UP3x1 Premium戦略
UP3x1 Premium戦略はMetaTraderのエキスパートアドバイザーup3x1_premium_v2MのC#ポートです。速い/遅いEMAクロスオーバーとワイドレンジのローソク足フィルター、日次コンテキストフィルターを組み合わせ、固定ターゲットとトレーリングストップによりリスクを管理しながらモメンタムブレイクアウトを捉えます。
機能の説明
トレンド検出
- 作業時間軸で2本のEMAを計算します(デフォルトは12期間と26期間)。
- MQLロジックと同様に強気または弱気のクロスオーバーを識別するために、前の2つのEMA値を追跡します。
- より広いバイアスを把握するために日次EMAを維持します。
エントリーロジック
- 以下のいずれかが発生した場合にロングセットアップがトリガーされます:
- 速いEMAが遅いEMAを上方クロスし、前の2本のローソク足の始値が上昇傾向を示す。
- 前のローソク足が、設定されたボディしきい値を超えるボディを持つ強気のワイドレンジバーを形成する。
- 午前0時に、前の日足ローソク足が始値より著しく低く終値した場合(投げ売り)、バウンスシグナルが許可される。
- 価格が現在の日次EMAより高く取引されており、ロングサイドを優先する。
- ショートセットアップは、ミラー条件が成立すると(弱気EMAクロス、ワイド弱気バー、または反対方向の午前0時のリバーサル)トリガーされます。
- ロングとショートの両方のトリガーが同時に発火した場合、戦略は優勢なEMAの関係に従って判断します。
- 以下のいずれかが発生した場合にロングセットアップがトリガーされます:
エグジット管理
- 以下の場合にオープンポジションが閉じられます:
- EMAが±0.1%以内に収束し、方向性の確信の喪失を示す。
- 価格が絶対価格単位で定義されたテイクプロフィットまたはストップロスオフセットに触れる。
- トレーリングストップ(有効な場合)が価格の後ろに引かれ、その後ヒットする。
- 以下の場合にオープンポジションが閉じられます:
ポジション処理
- 元のEAの動作と一致させるため、戦略がフラットの時のみトレードが開かれます。
- ボリュームは
OrderVolumeパラメーターで制御され、すべての成行注文に適用されます。
パラメーター
| パラメーター | 説明 |
|---|---|
OrderVolume |
各トレードの注文サイズ(ロット/コントラクト)。 |
FastEmaLength / SlowEmaLength |
作業時間軸での速い・遅いEMAの期間。 |
DailyEmaLength |
日足ローソク足で計算されるEMAの期間。 |
TakeProfit |
価格単位での絶対利益目標(無効にするにはゼロに設定)。 |
StopLoss |
価格単位での絶対ストップ距離(無効にするにはゼロに設定)。 |
TrailingStop |
動きがしきい値を超えたら価格に追従するトレーリング距離。 |
RangeThreshold |
ワイドバーとして認定されるために前のローソク足が超えなければならない最小総レンジ。 |
BodyThreshold |
強気/弱気スラストバーを定義する最小ローソク足ボディサイズ。 |
DailyReversalThreshold |
午前0時フィルター中に必要な前日のリバーサルのサイズ。 |
CandleType |
メインEMAと価格ロジックのための作業時間軸。 |
DailyCandleType |
日次EMAコンテキストに使用される上位時間軸。 |
使用上の注意
- デフォルトは元のEAで見つかった数値定数を模倣しています(ポイント値から小数価格オフセットに変換)。
- 取引するインストゥルメントのティックサイズに合わせて、価格ベースのしきい値(
TakeProfit、StopLoss、TrailingStop、レンジ/ボディしきい値)を調整してください。 - 日次EMAフィルターはMLQスクリプトに存在する無条件のロングバイアスを置き換え、優勢な上位時間軸トレンドに合わせてトレードを保ちます。
- ライブ取引を有効にする前に、常に過去のデータでバックテストし、デモ環境でフォワードテストしてください。
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Port of the UP3x1 Premium expert advisor that relies on EMA momentum with daily context.
/// </summary>
public class Up3x1PremiumStrategy : Strategy
{
private readonly StrategyParam<decimal> _orderVolume;
private readonly StrategyParam<int> _fastEmaLength;
private readonly StrategyParam<int> _slowEmaLength;
private readonly StrategyParam<int> _dailyEmaLength;
private readonly StrategyParam<decimal> _takeProfit;
private readonly StrategyParam<decimal> _stopLoss;
private readonly StrategyParam<decimal> _trailingStop;
private readonly StrategyParam<decimal> _rangeThreshold;
private readonly StrategyParam<decimal> _bodyThreshold;
private readonly StrategyParam<decimal> _dailyReversalThreshold;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<DataType> _dailyCandleType;
private decimal? _fastPrev;
private decimal? _fastPrev2;
private decimal? _slowPrev;
private decimal? _slowPrev2;
private ICandleMessage _prevCandle;
private ICandleMessage _prevPrevCandle;
private decimal? _dailyEmaValue;
private decimal? _prevDailyOpen;
private decimal? _prevDailyClose;
private decimal? _entryPrice;
private decimal? _stopPrice;
private decimal? _takeProfitPrice;
private decimal? _trailingStopPrice;
public Up3x1PremiumStrategy()
{
_orderVolume = Param(nameof(OrderVolume), 1m)
.SetGreaterThanZero()
.SetDisplay("Order Volume", "Volume for each trade", "Trading")
;
_fastEmaLength = Param(nameof(FastEmaLength), 12)
.SetGreaterThanZero()
.SetDisplay("Fast EMA Length", "Length of the fast EMA", "Indicators")
;
_slowEmaLength = Param(nameof(SlowEmaLength), 26)
.SetGreaterThanZero()
.SetDisplay("Slow EMA Length", "Length of the slow EMA", "Indicators")
;
_dailyEmaLength = Param(nameof(DailyEmaLength), 10)
.SetGreaterThanZero()
.SetDisplay("Daily EMA Length", "EMA length for the daily trend filter", "Indicators")
;
_takeProfit = Param(nameof(TakeProfit), 0.015m)
.SetNotNegative()
.SetDisplay("Take Profit", "Absolute take profit distance", "Risk")
;
_stopLoss = Param(nameof(StopLoss), 0.01m)
.SetNotNegative()
.SetDisplay("Stop Loss", "Absolute stop loss distance", "Risk")
;
_trailingStop = Param(nameof(TrailingStop), 0.001m)
.SetNotNegative()
.SetDisplay("Trailing Stop", "Distance for trailing stop updates", "Risk")
;
_rangeThreshold = Param(nameof(RangeThreshold), 0.006m)
.SetNotNegative()
.SetDisplay("Range Threshold", "Minimum candle range to qualify as wide", "Filters")
;
_bodyThreshold = Param(nameof(BodyThreshold), 0.005m)
.SetNotNegative()
.SetDisplay("Body Threshold", "Minimum candle body for momentum", "Filters")
;
_dailyReversalThreshold = Param(nameof(DailyReversalThreshold), 0.006m)
.SetNotNegative()
.SetDisplay("Daily Reversal Threshold", "Minimum prior day reversal size", "Filters")
;
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Primary working timeframe", "General");
_dailyCandleType = Param(nameof(DailyCandleType), TimeSpan.FromDays(1).TimeFrame())
.SetDisplay("Daily Candle Type", "Higher timeframe for daily context", "General");
}
/// <summary>
/// Trade volume expressed in security lots.
/// </summary>
public decimal OrderVolume
{
get => _orderVolume.Value;
set => _orderVolume.Value = value;
}
/// <summary>
/// Length of the fast EMA on the working timeframe.
/// </summary>
public int FastEmaLength
{
get => _fastEmaLength.Value;
set => _fastEmaLength.Value = value;
}
/// <summary>
/// Length of the slow EMA on the working timeframe.
/// </summary>
public int SlowEmaLength
{
get => _slowEmaLength.Value;
set => _slowEmaLength.Value = value;
}
/// <summary>
/// Length of the EMA used on the daily candles.
/// </summary>
public int DailyEmaLength
{
get => _dailyEmaLength.Value;
set => _dailyEmaLength.Value = value;
}
/// <summary>
/// Absolute take profit expressed in price units.
/// </summary>
public decimal TakeProfit
{
get => _takeProfit.Value;
set => _takeProfit.Value = value;
}
/// <summary>
/// Absolute stop loss expressed in price units.
/// </summary>
public decimal StopLoss
{
get => _stopLoss.Value;
set => _stopLoss.Value = value;
}
/// <summary>
/// Distance used for trailing stop updates.
/// </summary>
public decimal TrailingStop
{
get => _trailingStop.Value;
set => _trailingStop.Value = value;
}
/// <summary>
/// Minimum candle range that activates the momentum filter.
/// </summary>
public decimal RangeThreshold
{
get => _rangeThreshold.Value;
set => _rangeThreshold.Value = value;
}
/// <summary>
/// Minimum candle body needed to qualify as a thrust.
/// </summary>
public decimal BodyThreshold
{
get => _bodyThreshold.Value;
set => _bodyThreshold.Value = value;
}
/// <summary>
/// Size of the prior daily reversal required during the midnight check.
/// </summary>
public decimal DailyReversalThreshold
{
get => _dailyReversalThreshold.Value;
set => _dailyReversalThreshold.Value = value;
}
/// <summary>
/// Working timeframe for the main signals.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Higher timeframe used for the daily EMA filter.
/// </summary>
public DataType DailyCandleType
{
get => _dailyCandleType.Value;
set => _dailyCandleType.Value = value;
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType), (Security, DailyCandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_fastPrev = null;
_fastPrev2 = null;
_slowPrev = null;
_slowPrev2 = null;
_prevCandle = null;
_prevPrevCandle = null;
_dailyEmaValue = null;
_prevDailyOpen = null;
_prevDailyClose = null;
ClearTradeLevels();
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
Volume = OrderVolume;
// Create EMA indicators for the working timeframe.
var fastEma = new EMA { Length = FastEmaLength };
var slowEma = new EMA { Length = SlowEmaLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastEma, slowEma, ProcessCandle)
.Start();
// Daily subscription provides the higher timeframe confirmation.
var dailyEma = new EMA { Length = DailyEmaLength };
var dailySubscription = SubscribeCandles(DailyCandleType);
dailySubscription
.Bind(dailyEma, ProcessDailyCandle)
.Start();
StartProtection(null, null);
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fastEma);
DrawIndicator(area, slowEma);
DrawOwnTrades(area);
}
}
private void ProcessDailyCandle(ICandleMessage candle, decimal emaValue)
{
if (candle.State != CandleStates.Finished)
return;
// Store the latest completed daily information for intraday decisions.
_dailyEmaValue = emaValue;
_prevDailyOpen = candle.OpenPrice;
_prevDailyClose = candle.ClosePrice;
}
private void ProcessCandle(ICandleMessage candle, decimal fastEma, decimal slowEma)
{
if (candle.State != CandleStates.Finished)
return;
// Manage an existing position before looking for fresh entries.
ManageOpenPosition(candle);
var haveHistory = _prevCandle != null && _prevPrevCandle != null &&
_fastPrev.HasValue && _fastPrev2.HasValue && _slowPrev.HasValue && _slowPrev2.HasValue;
if (Position == 0m && haveHistory && IsFormedAndOnlineAndAllowTrading())
{
var bullishCross = _fastPrev2.Value < _slowPrev2.Value && _fastPrev.Value > _slowPrev.Value &&
_prevPrevCandle.OpenPrice < _prevCandle.OpenPrice;
var wideBullish = (_prevCandle.HighPrice - _prevCandle.LowPrice) > RangeThreshold &&
_prevCandle.ClosePrice > _prevCandle.OpenPrice &&
(_prevCandle.ClosePrice - _prevCandle.OpenPrice) > BodyThreshold;
var midnight = candle.OpenTime.Hour == 0;
var dailyBounce = midnight &&
_prevDailyOpen is decimal dayOpen &&
_prevDailyClose is decimal dayClose &&
dayOpen > dayClose &&
(dayOpen - dayClose) > DailyReversalThreshold;
var priceAboveDaily = _dailyEmaValue is decimal daily && candle.ClosePrice >= daily;
var longSignal = bullishCross || wideBullish || dailyBounce || priceAboveDaily;
var bearishCross = _fastPrev2.Value > _slowPrev2.Value && _fastPrev.Value < _slowPrev.Value &&
_prevPrevCandle.OpenPrice > _prevCandle.OpenPrice;
var wideBearish = (_prevCandle.HighPrice - _prevCandle.LowPrice) > RangeThreshold &&
_prevCandle.OpenPrice > _prevCandle.ClosePrice &&
(_prevCandle.OpenPrice - _prevCandle.ClosePrice) > BodyThreshold;
var midnightSell = midnight &&
_prevDailyOpen is decimal dayOpenSell &&
_prevDailyClose is decimal dayCloseSell &&
dayOpenSell < dayCloseSell &&
(dayCloseSell - dayOpenSell) > DailyReversalThreshold;
var shortSignal = bearishCross || wideBearish || midnightSell;
if (longSignal && shortSignal)
{
// Break ties with the latest EMA relationship.
if (_fastPrev.Value >= _slowPrev.Value)
shortSignal = false;
else
longSignal = false;
}
if (longSignal && OrderVolume > 0m)
{
BuyMarket();
_entryPrice = candle.ClosePrice;
_stopPrice = StopLoss > 0m ? _entryPrice - StopLoss : null;
_takeProfitPrice = TakeProfit > 0m ? _entryPrice + TakeProfit : null;
_trailingStopPrice = TrailingStop > 0m ? _entryPrice - TrailingStop : null;
}
else if (shortSignal && OrderVolume > 0m)
{
SellMarket();
_entryPrice = candle.ClosePrice;
_stopPrice = StopLoss > 0m ? _entryPrice + StopLoss : null;
_takeProfitPrice = TakeProfit > 0m ? _entryPrice - TakeProfit : null;
_trailingStopPrice = TrailingStop > 0m ? _entryPrice + TrailingStop : null;
}
}
// Preserve history to mimic the MQL index-based access pattern.
_prevPrevCandle = _prevCandle;
_prevCandle = candle;
_fastPrev2 = _fastPrev;
_fastPrev = fastEma;
_slowPrev2 = _slowPrev;
_slowPrev = slowEma;
}
private void ManageOpenPosition(ICandleMessage candle)
{
if (Position > 0m)
{
UpdateTrailingStopForLong(candle);
var exit = AreEmaNear(_fastPrev, _slowPrev);
if (!exit && _takeProfitPrice is decimal tp && candle.HighPrice >= tp)
exit = true;
if (!exit && _stopPrice is decimal sl && candle.LowPrice <= sl)
exit = true;
if (!exit && _trailingStopPrice is decimal trail && candle.LowPrice <= trail)
exit = true;
if (exit)
{
SellMarket();
ClearTradeLevels();
}
}
else if (Position < 0m)
{
UpdateTrailingStopForShort(candle);
var exit = AreEmaNear(_fastPrev, _slowPrev);
if (!exit && _takeProfitPrice is decimal tp && candle.LowPrice <= tp)
exit = true;
if (!exit && _stopPrice is decimal sl && candle.HighPrice >= sl)
exit = true;
if (!exit && _trailingStopPrice is decimal trail && candle.HighPrice >= trail)
exit = true;
if (exit)
{
BuyMarket();
ClearTradeLevels();
}
}
}
private void UpdateTrailingStopForLong(ICandleMessage candle)
{
if (TrailingStop <= 0m || _entryPrice is not decimal entry)
return;
var move = candle.HighPrice - entry;
if (move < TrailingStop)
return;
var newStop = candle.HighPrice - TrailingStop;
if (_trailingStopPrice is null || newStop > _trailingStopPrice)
_trailingStopPrice = newStop;
}
private void UpdateTrailingStopForShort(ICandleMessage candle)
{
if (TrailingStop <= 0m || _entryPrice is not decimal entry)
return;
var move = entry - candle.LowPrice;
if (move < TrailingStop)
return;
var newStop = candle.LowPrice + TrailingStop;
if (_trailingStopPrice is null || newStop < _trailingStopPrice)
_trailingStopPrice = newStop;
}
private static bool AreEmaNear(decimal? fast, decimal? slow)
{
if (fast is not decimal fastValue || slow is not decimal slowValue)
return false;
if (slowValue == 0m)
return false;
var diff = Math.Abs(fastValue - slowValue);
return diff <= Math.Abs(slowValue) * 0.001m;
}
private void ClearTradeLevels()
{
_entryPrice = null;
_stopPrice = null;
_takeProfitPrice = null;
_trailingStopPrice = null;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates, Unit, UnitTypes
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class up3x1_premium_strategy(Strategy):
def __init__(self):
super(up3x1_premium_strategy, self).__init__()
self._order_volume = self.Param("OrderVolume", 1.0)
self._fast_ema_length = self.Param("FastEmaLength", 12)
self._slow_ema_length = self.Param("SlowEmaLength", 26)
self._take_profit = self.Param("TakeProfit", 0.015)
self._stop_loss = self.Param("StopLoss", 0.01)
self._trailing_stop = self.Param("TrailingStop", 0.001)
self._range_threshold = self.Param("RangeThreshold", 0.006)
self._body_threshold = self.Param("BodyThreshold", 0.005)
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4)))
self._fast_prev = None
self._fast_prev2 = None
self._slow_prev = None
self._slow_prev2 = None
self._prev_candle_open = None
self._prev_candle_close = None
self._prev_candle_high = None
self._prev_candle_low = None
self._prev_prev_candle_open = None
self._entry_price = None
self._stop_price = None
self._take_profit_price = None
self._trailing_stop_price = None
@property
def OrderVolume(self):
return self._order_volume.Value
@OrderVolume.setter
def OrderVolume(self, value):
self._order_volume.Value = value
@property
def FastEmaLength(self):
return self._fast_ema_length.Value
@FastEmaLength.setter
def FastEmaLength(self, value):
self._fast_ema_length.Value = value
@property
def SlowEmaLength(self):
return self._slow_ema_length.Value
@SlowEmaLength.setter
def SlowEmaLength(self, value):
self._slow_ema_length.Value = value
@property
def TakeProfit(self):
return self._take_profit.Value
@TakeProfit.setter
def TakeProfit(self, value):
self._take_profit.Value = value
@property
def StopLoss(self):
return self._stop_loss.Value
@StopLoss.setter
def StopLoss(self, value):
self._stop_loss.Value = value
@property
def TrailingStop(self):
return self._trailing_stop.Value
@TrailingStop.setter
def TrailingStop(self, value):
self._trailing_stop.Value = value
@property
def RangeThreshold(self):
return self._range_threshold.Value
@RangeThreshold.setter
def RangeThreshold(self, value):
self._range_threshold.Value = value
@property
def BodyThreshold(self):
return self._body_threshold.Value
@BodyThreshold.setter
def BodyThreshold(self, value):
self._body_threshold.Value = value
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
def OnStarted2(self, time):
super(up3x1_premium_strategy, self).OnStarted2(time)
self._fast_prev = None
self._fast_prev2 = None
self._slow_prev = None
self._slow_prev2 = None
self._prev_candle_open = None
self._prev_candle_close = None
self._prev_candle_high = None
self._prev_candle_low = None
self._prev_prev_candle_open = None
self._entry_price = None
self._stop_price = None
self._take_profit_price = None
self._trailing_stop_price = None
fast_ema = ExponentialMovingAverage()
fast_ema.Length = self.FastEmaLength
slow_ema = ExponentialMovingAverage()
slow_ema.Length = self.SlowEmaLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast_ema, slow_ema, self.ProcessCandle).Start()
self.StartProtection(
Unit(2000.0, UnitTypes.Absolute),
Unit(1000.0, UnitTypes.Absolute))
def ProcessCandle(self, candle, fast_ema_val, slow_ema_val):
if candle.State != CandleStates.Finished:
return
fast_val = float(fast_ema_val)
slow_val = float(slow_ema_val)
close = float(candle.ClosePrice)
high = float(candle.HighPrice)
low = float(candle.LowPrice)
open_price = float(candle.OpenPrice)
self._manage_open_position(candle)
have_history = (self._prev_candle_open is not None and
self._prev_prev_candle_open is not None and
self._fast_prev is not None and self._fast_prev2 is not None and
self._slow_prev is not None and self._slow_prev2 is not None)
tp = float(self.TakeProfit)
sl = float(self.StopLoss)
trail = float(self.TrailingStop)
range_th = float(self.RangeThreshold)
body_th = float(self.BodyThreshold)
if self.Position == 0 and have_history:
bullish_cross = (self._fast_prev2 < self._slow_prev2 and
self._fast_prev > self._slow_prev and
self._prev_prev_candle_open < self._prev_candle_open)
wide_bullish = (self._prev_candle_high is not None and
self._prev_candle_low is not None and
(self._prev_candle_high - self._prev_candle_low) > range_th and
self._prev_candle_close > self._prev_candle_open and
(self._prev_candle_close - self._prev_candle_open) > body_th)
long_signal = bullish_cross or wide_bullish
bearish_cross = (self._fast_prev2 > self._slow_prev2 and
self._fast_prev < self._slow_prev and
self._prev_prev_candle_open > self._prev_candle_open)
wide_bearish = (self._prev_candle_high is not None and
self._prev_candle_low is not None and
(self._prev_candle_high - self._prev_candle_low) > range_th and
self._prev_candle_open > self._prev_candle_close and
(self._prev_candle_open - self._prev_candle_close) > body_th)
short_signal = bearish_cross or wide_bearish
if long_signal and short_signal:
if self._fast_prev >= self._slow_prev:
short_signal = False
else:
long_signal = False
if long_signal:
self.BuyMarket()
self._entry_price = close
self._stop_price = close - sl if sl > 0.0 else None
self._take_profit_price = close + tp if tp > 0.0 else None
self._trailing_stop_price = close - trail if trail > 0.0 else None
elif short_signal:
self.SellMarket()
self._entry_price = close
self._stop_price = close + sl if sl > 0.0 else None
self._take_profit_price = close - tp if tp > 0.0 else None
self._trailing_stop_price = close + trail if trail > 0.0 else None
self._prev_prev_candle_open = self._prev_candle_open
self._prev_candle_open = open_price
self._prev_candle_close = close
self._prev_candle_high = high
self._prev_candle_low = low
self._fast_prev2 = self._fast_prev
self._fast_prev = fast_val
self._slow_prev2 = self._slow_prev
self._slow_prev = slow_val
def _manage_open_position(self, candle):
high = float(candle.HighPrice)
low = float(candle.LowPrice)
trail = float(self.TrailingStop)
if self.Position > 0:
if trail > 0.0 and self._entry_price is not None:
move = high - self._entry_price
if move >= trail:
new_stop = high - trail
if self._trailing_stop_price is None or new_stop > self._trailing_stop_price:
self._trailing_stop_price = new_stop
do_exit = False
if self._take_profit_price is not None and high >= self._take_profit_price:
do_exit = True
if not do_exit and self._stop_price is not None and low <= self._stop_price:
do_exit = True
if not do_exit and self._trailing_stop_price is not None and low <= self._trailing_stop_price:
do_exit = True
if not do_exit and self._are_ema_near():
do_exit = True
if do_exit:
self.SellMarket()
self._clear_trade_levels()
elif self.Position < 0:
if trail > 0.0 and self._entry_price is not None:
move = self._entry_price - low
if move >= trail:
new_stop = low + trail
if self._trailing_stop_price is None or new_stop < self._trailing_stop_price:
self._trailing_stop_price = new_stop
do_exit = False
if self._take_profit_price is not None and low <= self._take_profit_price:
do_exit = True
if not do_exit and self._stop_price is not None and high >= self._stop_price:
do_exit = True
if not do_exit and self._trailing_stop_price is not None and high >= self._trailing_stop_price:
do_exit = True
if not do_exit and self._are_ema_near():
do_exit = True
if do_exit:
self.BuyMarket()
self._clear_trade_levels()
def _are_ema_near(self):
if self._fast_prev is None or self._slow_prev is None:
return False
if self._slow_prev == 0.0:
return False
diff = abs(self._fast_prev - self._slow_prev)
return diff <= abs(self._slow_prev) * 0.001
def _clear_trade_levels(self):
self._entry_price = None
self._stop_price = None
self._take_profit_price = None
self._trailing_stop_price = None
def OnReseted(self):
super(up3x1_premium_strategy, self).OnReseted()
self._fast_prev = None
self._fast_prev2 = None
self._slow_prev = None
self._slow_prev2 = None
self._prev_candle_open = None
self._prev_candle_close = None
self._prev_candle_high = None
self._prev_candle_low = None
self._prev_prev_candle_open = None
self._clear_trade_levels()
def CreateClone(self):
return up3x1_premium_strategy()