UP3x1 Premium Strategy
The UP3x1 Premium Strategy is a C# port of the MetaTrader expert advisor up3x1_premium_v2M. It blends fast/slow EMA crossovers with wide-range candle filters and a daily context filter to capture momentum breakouts while keeping risk managed through fixed targets and trailing stops.
How It Works
Trend Detection
- Calculates two EMAs on the working timeframe (default 12 and 26 periods).
- Tracks the previous two EMA values to identify bullish or bearish crossovers similar to the MQL logic.
- Maintains a daily EMA to understand the broader bias.
Entry Logic
- Long setups trigger when any of the following occurs:
- The fast EMA crosses above the slow EMA and the previous two candle opens show upward progress.
- The prior candle forms a bullish wide-range bar whose body exceeds the configured body threshold.
- At midnight, if the previous daily candle closed notably lower than it opened (capitulation), a bounce signal is allowed.
- Price trades above the current daily EMA, favouring the long side.
- Short setups trigger when the mirror conditions hold (bearish EMA cross, wide bearish bar, or midnight reversal in the opposite direction).
- When both long and short triggers fire simultaneously, the strategy follows the prevailing EMA relationship to break the tie.
- Long setups trigger when any of the following occurs:
Exit Management
- An open position is closed when:
- The EMAs converge within ±0.1%, signalling a loss of directional conviction.
- Price touches the take-profit or stop-loss offsets defined in absolute price units.
- The trailing stop (if enabled) is pulled behind price and subsequently hit.
- An open position is closed when:
Position Handling
- Trades are opened only when the strategy is flat, matching the original EA behaviour.
- Volume is controlled via the
OrderVolumeparameter and applied to every market order.
Parameters
| Parameter | Description |
|---|---|
OrderVolume |
Order size in lots/contracts for every trade. |
FastEmaLength / SlowEmaLength |
Periods for the fast and slow EMAs on the working timeframe. |
DailyEmaLength |
Period for the EMA computed on the daily candles. |
TakeProfit |
Absolute profit target in price units (set to zero to disable). |
StopLoss |
Absolute stop distance in price units (set to zero to disable). |
TrailingStop |
Trailing distance that follows price once the move exceeds the threshold. |
RangeThreshold |
Minimum total range the previous candle must exceed to qualify as a wide bar. |
BodyThreshold |
Minimum candle body size that defines bullish/bearish thrust bars. |
DailyReversalThreshold |
Size of the previous daily reversal required during the midnight filter. |
CandleType |
Working timeframe for the main EMA and price logic. |
DailyCandleType |
Higher timeframe used for the daily EMA context. |
Usage Notes
- Defaults mimic the numeric constants found in the original EA (converted from point values to decimal price offsets).
- Adjust the price-based thresholds (
TakeProfit,StopLoss,TrailingStop, range/body thresholds) to match the tick size of the traded instrument. - The daily EMA filter replaces the unconditional long bias present in the MQL script, keeping trades aligned with the prevailing higher timeframe trend.
- Always backtest on historical data and forward test in a demo environment before enabling live trading.
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()