TradingLab Best MACD Strategy
This strategy replicates the MetaTrader expert advisor "TradingLab_Best_MACD_Strategy" using StockSharp's high-level API. It combines moving average structure, MACD crossovers, and dynamic support/resistance checks to open directional trades that align with momentum and recent price reactions.
Core Logic
- Candle Source – Uses the configurable
CandleTypeparameter to subscribe to finished candles. Only completed candles generate trading decisions. - Trend Filter – A 200-period simple moving average defines the prevailing trend. Long trades require the close to remain above the average, while short trades require the close to remain below it.
- Support and Resistance Box – A 20-period highest/lowest window emulates the "Box" custom indicator. Touching the previous resistance or support level arms short or long setups for a limited number of candles controlled by
SignalValidity. - MACD Crossovers – A standard MACD (12, 26, 9 by default) must cross its signal line on the previous candle and stay on the required side of the zero line. Each valid crossover keeps its signal alive for
SignalValiditycandles, mirroring the countdown logic from the source EA. - Entry Timing – A position opens when both the MACD and the corresponding support/resistance touch are still valid, and at least one of them triggered on the current candle.
- Exit Logic – Upon entry, dynamic stop-loss and take-profit targets are calculated relative to the moving average distance. The take-profit distance is
RiskRewardMultipliertimes the adjusted distance used for the stop. Protective exits monitor subsequent candles and callClosePosition()once price breaches the stored levels.
Parameters
| Parameter | Description |
|---|---|
OrderVolume |
Fixed volume sent with every market order. |
SignalValidity |
Number of candles that keep MACD and support/resistance triggers active. |
MaLength |
Period of the simple moving average trend filter. |
BoxPeriod |
Lookback length for the highest/lowest box that tracks recent resistance and support. |
MacdFastLength, MacdSlowLength, MacdSignalLength |
MACD fast, slow, and signal periods. |
StopDistancePoints |
Distance from the moving average to the stop-loss, expressed in MetaTrader-style points (multiplied by the symbol price step). |
RiskRewardMultiplier |
Multiplier applied to the adjusted MA distance to produce the take-profit target. |
CandleType |
Data type describing the candle series to subscribe to (default: 1 hour time frame). |
Notes
- The support and resistance detection follows the original idea by watching whether the previous candle breaks the 20-period highest/lowest levels. Each touch restarts the validity counters.
- Stops and targets are recomputed for every new entry and are checked against the high/low of each finished candle to mimic MetaTrader's intrabar monitoring in a deterministic way.
- Protective management relies on the instrument
PriceStep. If an instrument reports a zero step, a fallback of 0.0001 is used.
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;
public class TradingLabBestMacdStrategy : Strategy
{
private readonly StrategyParam<decimal> _orderVolume;
private readonly StrategyParam<int> _signalValidity;
private readonly StrategyParam<int> _maLength;
private readonly StrategyParam<int> _boxPeriod;
private readonly StrategyParam<int> _macdFastLength;
private readonly StrategyParam<int> _macdSlowLength;
private readonly StrategyParam<int> _macdSignalLength;
private readonly StrategyParam<decimal> _stopDistancePoints;
private readonly StrategyParam<decimal> _riskRewardMultiplier;
private readonly StrategyParam<DataType> _candleType;
private SimpleMovingAverage _sma;
private Highest _highest;
private Lowest _lowest;
private MovingAverageConvergenceDivergenceSignal _macd;
private int _resistanceCounter;
private int _supportCounter;
private int _macdDownCounter;
private int _macdUpCounter;
private decimal? _prevMacdMain;
private decimal? _prevMacdSignal;
private decimal? _plannedStop;
private decimal? _plannedTake;
private Sides? _plannedSide;
private decimal? _activeStop;
private decimal? _activeTake;
private Sides? _activeSide;
private decimal? _previousHigh;
private decimal? _previousLow;
private bool _hasPreviousCandle;
/// <summary>
/// Initializes a new instance of <see cref="TradingLabBestMacdStrategy"/>.
/// </summary>
public TradingLabBestMacdStrategy()
{
_orderVolume = Param(nameof(OrderVolume), 1m)
.SetDisplay("Order Volume", "Fixed volume sent with each market order", "Risk")
;
_signalValidity = Param(nameof(SignalValidity), 7)
.SetGreaterThanZero()
.SetDisplay("Signal Validity", "Number of candles a MACD or box trigger remains active", "Filters")
;
_maLength = Param(nameof(MaLength), 20)
.SetGreaterThanZero()
.SetDisplay("MA Length", "Simple moving average period used as the trend filter", "Filters")
;
_boxPeriod = Param(nameof(BoxPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("Box Period", "Lookback length for the support/resistance box", "Filters")
;
_macdFastLength = Param(nameof(MacdFastLength), 12)
.SetGreaterThanZero()
.SetDisplay("MACD Fast Length", "Fast EMA length for MACD", "Indicators")
;
_macdSlowLength = Param(nameof(MacdSlowLength), 26)
.SetGreaterThanZero()
.SetDisplay("MACD Slow Length", "Slow EMA length for MACD", "Indicators")
;
_macdSignalLength = Param(nameof(MacdSignalLength), 9)
.SetGreaterThanZero()
.SetDisplay("MACD Signal Length", "Signal line length for MACD", "Indicators")
;
_stopDistancePoints = Param(nameof(StopDistancePoints), 50m)
.SetGreaterThanZero()
.SetDisplay("Stop Distance (points)", "Protective stop distance from the moving average expressed in points", "Risk")
;
_riskRewardMultiplier = Param(nameof(RiskRewardMultiplier), 1.5m)
.SetGreaterThanZero()
.SetDisplay("Risk-Reward Multiplier", "Multiplier applied to derive the take-profit distance", "Risk")
;
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Data type used to subscribe for candles", "General")
;
}
/// <summary>
/// Fixed volume sent with every market order.
/// </summary>
public decimal OrderVolume
{
get => _orderVolume.Value;
set => _orderVolume.Value = value;
}
/// <summary>
/// Number of candles that keep MACD and support/resistance triggers active.
/// </summary>
public int SignalValidity
{
get => _signalValidity.Value;
set => _signalValidity.Value = value;
}
/// <summary>
/// Period for the simple moving average trend filter.
/// </summary>
public int MaLength
{
get => _maLength.Value;
set => _maLength.Value = value;
}
/// <summary>
/// Lookback length for the support/resistance box.
/// </summary>
public int BoxPeriod
{
get => _boxPeriod.Value;
set => _boxPeriod.Value = value;
}
/// <summary>
/// Fast EMA length used by MACD.
/// </summary>
public int MacdFastLength
{
get => _macdFastLength.Value;
set => _macdFastLength.Value = value;
}
/// <summary>
/// Slow EMA length used by MACD.
/// </summary>
public int MacdSlowLength
{
get => _macdSlowLength.Value;
set => _macdSlowLength.Value = value;
}
/// <summary>
/// Signal line length used by MACD.
/// </summary>
public int MacdSignalLength
{
get => _macdSignalLength.Value;
set => _macdSignalLength.Value = value;
}
/// <summary>
/// Protective stop distance measured in MetaTrader points.
/// </summary>
public decimal StopDistancePoints
{
get => _stopDistancePoints.Value;
set => _stopDistancePoints.Value = value;
}
/// <summary>
/// Multiplier applied to the adjusted moving-average distance to build the take-profit target.
/// </summary>
public decimal RiskRewardMultiplier
{
get => _riskRewardMultiplier.Value;
set => _riskRewardMultiplier.Value = value;
}
/// <summary>
/// Candle data type used to subscribe for historical bars.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_sma = null;
_highest = null;
_lowest = null;
_macd = null;
_resistanceCounter = 0;
_supportCounter = 0;
_macdDownCounter = 0;
_macdUpCounter = 0;
_prevMacdMain = null;
_prevMacdSignal = null;
_plannedStop = null;
_plannedTake = null;
_plannedSide = null;
_activeStop = null;
_activeTake = null;
_activeSide = null;
_previousHigh = null;
_previousLow = null;
_hasPreviousCandle = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
// Configure the indicators that replicate the MetaTrader calculations.
_sma = new SimpleMovingAverage { Length = MaLength };
_highest = new Highest { Length = BoxPeriod };
_lowest = new Lowest { Length = BoxPeriod };
_macd = new MovingAverageConvergenceDivergenceSignal { Macd = { ShortMa = { Length = MacdFastLength }, LongMa = { Length = MacdSlowLength } }, SignalMa = { Length = MacdSignalLength } };
// Subscribe to the configured candle stream and bind indicator outputs to the handler.
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(new IIndicator[] { _sma, _highest, _lowest, _macd }, ProcessCandle)
.Start();
// removed StartProtection
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue[] values)
{
if (candle.State != CandleStates.Finished)
return;
// Manage trailing exits before analysing new signals.
CheckProtectiveLevels(candle);
if (values.Length != 4)
{
UpdatePreviousCandle(candle, null, null);
return;
}
var smaValue = values[0].ToDecimal();
var resistanceValue = values[1].ToDecimal();
var supportValue = values[2].ToDecimal();
if (values[3] is not IMovingAverageConvergenceDivergenceSignalValue macdValue)
{
UpdatePreviousCandle(candle, null, null);
return;
}
var macdMain = macdValue.Macd;
var macdSignal = macdValue.Signal;
if (!_sma.IsFormed || !_highest.IsFormed || !_lowest.IsFormed || !_macd.IsFormed)
{
UpdatePreviousCandle(candle, macdMain, macdSignal);
return;
}
// Decrease counters that track how many candles each signal remains active.
if (_resistanceCounter > 0)
_resistanceCounter--;
if (_supportCounter > 0)
_supportCounter--;
if (_macdDownCounter > 0)
_macdDownCounter--;
if (_macdUpCounter > 0)
_macdUpCounter--;
var point = GetPointValue();
if (_hasPreviousCandle)
{
// Detect fresh touches of the synthetic resistance/support levels.
if (_previousHigh.HasValue && resistanceValue > 0m && _previousHigh.Value > resistanceValue)
{
_resistanceCounter = SignalValidity;
}
if (_previousLow.HasValue && supportValue > 0m && _previousLow.Value < supportValue)
{
_supportCounter = SignalValidity;
}
}
if (_prevMacdMain.HasValue && _prevMacdSignal.HasValue)
{
// Track MACD crossovers relative to the zero line.
if (macdMain < macdSignal && _prevMacdMain.Value > _prevMacdSignal.Value && macdMain > 0m)
{
_macdDownCounter = SignalValidity;
}
if (macdMain > macdSignal && _prevMacdMain.Value < _prevMacdSignal.Value && macdMain < 0m)
{
_macdUpCounter = SignalValidity;
}
}
var volume = OrderVolume;
if (volume > 0m)
{
// Evaluate entry conditions once both the MACD and box counters are armed.
var longSignalActive = _macdUpCounter > 0 && candle.ClosePrice > smaValue;
var longTriggeredNow = true;
if (longSignalActive && longTriggeredNow && Position <= 0)
{
var stopOffset = StopDistancePoints * point;
var adjustedDistance = candle.ClosePrice - smaValue + stopOffset;
if (adjustedDistance > 0m)
{
_plannedStop = smaValue - stopOffset;
_plannedTake = candle.ClosePrice + adjustedDistance * RiskRewardMultiplier;
_plannedSide = Sides.Buy;
BuyMarket(volume);
}
}
var shortSignalActive = _macdDownCounter > 0 && candle.ClosePrice < smaValue;
var shortTriggeredNow = true;
if (shortSignalActive && shortTriggeredNow && Position >= 0)
{
var stopOffset = StopDistancePoints * point;
var adjustedDistance = smaValue - candle.ClosePrice + stopOffset;
if (adjustedDistance > 0m)
{
_plannedStop = smaValue + stopOffset;
_plannedTake = candle.ClosePrice - adjustedDistance * RiskRewardMultiplier;
_plannedSide = Sides.Sell;
SellMarket(volume);
}
}
}
UpdatePreviousCandle(candle, macdMain, macdSignal);
}
private void CheckProtectiveLevels(ICandleMessage candle)
{
if (_activeSide == null || Position == 0)
return;
// Close the position if price violates the stored stop-loss or take-profit.
if (_activeSide == Sides.Buy && Position > 0)
{
if (_activeStop.HasValue && candle.LowPrice <= _activeStop.Value)
{
ClearPlannedLevels();
ClearActiveLevels();
ClosePosition();
return;
}
if (_activeTake.HasValue && candle.HighPrice >= _activeTake.Value)
{
ClearPlannedLevels();
ClearActiveLevels();
ClosePosition();
return;
}
}
else if (_activeSide == Sides.Sell && Position < 0)
{
if (_activeStop.HasValue && candle.HighPrice >= _activeStop.Value)
{
ClearPlannedLevels();
ClearActiveLevels();
ClosePosition();
return;
}
if (_activeTake.HasValue && candle.LowPrice <= _activeTake.Value)
{
ClearPlannedLevels();
ClearActiveLevels();
ClosePosition();
}
}
}
private void UpdatePreviousCandle(ICandleMessage candle, decimal? macdMain, decimal? macdSignal)
{
_previousHigh = candle.HighPrice;
_previousLow = candle.LowPrice;
_hasPreviousCandle = true;
_prevMacdMain = macdMain;
_prevMacdSignal = macdSignal;
}
private decimal GetPointValue()
{
var step = Security?.PriceStep ?? 0m;
if (step <= 0m)
return 0.0001m;
return step;
}
private void ClosePosition()
{
if (Position > 0)
SellMarket(Position);
else if (Position < 0)
BuyMarket(Math.Abs(Position));
}
private void ClearPlannedLevels()
{
_plannedStop = null;
_plannedTake = null;
_plannedSide = null;
}
private void ClearActiveLevels()
{
_activeStop = null;
_activeTake = null;
_activeSide = null;
}
/// <inheritdoc />
protected override void OnOwnTradeReceived(MyTrade trade)
{
base.OnOwnTradeReceived(trade);
if (trade.Order?.Security != Security)
return;
if (Position == 0)
{
ClearActiveLevels();
ClearPlannedLevels();
return;
}
if (Position > 0)
{
if (_plannedSide == Sides.Buy)
{
_activeStop = _plannedStop;
_activeTake = _plannedTake;
_activeSide = Sides.Buy;
ClearPlannedLevels();
}
else
{
_activeSide = Sides.Buy;
}
}
else if (Position < 0)
{
if (_plannedSide == Sides.Sell)
{
_activeStop = _plannedStop;
_activeTake = _plannedTake;
_activeSide = Sides.Sell;
ClearPlannedLevels();
}
else
{
_activeSide = Sides.Sell;
}
}
}
}
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
from StockSharp.Algo.Indicators import (
SimpleMovingAverage, Highest, Lowest, MovingAverageConvergenceDivergenceSignal
)
from StockSharp.Algo.Strategies import Strategy
class trading_lab_best_macd_strategy(Strategy):
"""MACD + SMA trend + Highest/Lowest box with signal validity counters and virtual SL/TP."""
def __init__(self):
super(trading_lab_best_macd_strategy, self).__init__()
self._order_volume = self.Param("OrderVolume", 1.0) \
.SetDisplay("Order Volume", "Fixed volume sent with each market order", "Risk")
self._signal_validity = self.Param("SignalValidity", 7) \
.SetGreaterThanZero() \
.SetDisplay("Signal Validity", "Number of candles a MACD or box trigger remains active", "Filters")
self._ma_length = self.Param("MaLength", 20) \
.SetGreaterThanZero() \
.SetDisplay("MA Length", "Simple moving average period used as the trend filter", "Filters")
self._box_period = self.Param("BoxPeriod", 20) \
.SetGreaterThanZero() \
.SetDisplay("Box Period", "Lookback length for the support/resistance box", "Filters")
self._macd_fast_length = self.Param("MacdFastLength", 12) \
.SetGreaterThanZero() \
.SetDisplay("MACD Fast Length", "Fast EMA length for MACD", "Indicators")
self._macd_slow_length = self.Param("MacdSlowLength", 26) \
.SetGreaterThanZero() \
.SetDisplay("MACD Slow Length", "Slow EMA length for MACD", "Indicators")
self._macd_signal_length = self.Param("MacdSignalLength", 9) \
.SetGreaterThanZero() \
.SetDisplay("MACD Signal Length", "Signal line length for MACD", "Indicators")
self._stop_distance_points = self.Param("StopDistancePoints", 50.0) \
.SetGreaterThanZero() \
.SetDisplay("Stop Distance (points)", "Protective stop distance from the moving average", "Risk")
self._risk_reward_multiplier = self.Param("RiskRewardMultiplier", 1.5) \
.SetGreaterThanZero() \
.SetDisplay("Risk-Reward Multiplier", "Multiplier applied to derive the take-profit distance", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Data type used to subscribe for candles", "General")
self._sma = None
self._highest = None
self._lowest = None
self._macd = None
self._resistance_counter = 0
self._support_counter = 0
self._macd_down_counter = 0
self._macd_up_counter = 0
self._prev_macd_main = None
self._prev_macd_signal = None
self._planned_stop = None
self._planned_take = None
self._planned_side = None
self._active_stop = None
self._active_take = None
self._active_side = None
self._previous_high = None
self._previous_low = None
self._has_previous_candle = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def OrderVolume(self):
return self._order_volume.Value
@property
def SignalValidity(self):
return self._signal_validity.Value
@property
def MaLength(self):
return self._ma_length.Value
@property
def BoxPeriod(self):
return self._box_period.Value
@property
def MacdFastLength(self):
return self._macd_fast_length.Value
@property
def MacdSlowLength(self):
return self._macd_slow_length.Value
@property
def MacdSignalLength(self):
return self._macd_signal_length.Value
@property
def StopDistancePoints(self):
return self._stop_distance_points.Value
@property
def RiskRewardMultiplier(self):
return self._risk_reward_multiplier.Value
def OnReseted(self):
super(trading_lab_best_macd_strategy, self).OnReseted()
self._sma = None
self._highest = None
self._lowest = None
self._macd = None
self._resistance_counter = 0
self._support_counter = 0
self._macd_down_counter = 0
self._macd_up_counter = 0
self._prev_macd_main = None
self._prev_macd_signal = None
self._planned_stop = None
self._planned_take = None
self._planned_side = None
self._active_stop = None
self._active_take = None
self._active_side = None
self._previous_high = None
self._previous_low = None
self._has_previous_candle = False
def OnStarted2(self, time):
super(trading_lab_best_macd_strategy, self).OnStarted2(time)
self._sma = SimpleMovingAverage()
self._sma.Length = self.MaLength
self._highest = Highest()
self._highest.Length = self.BoxPeriod
self._lowest = Lowest()
self._lowest.Length = self.BoxPeriod
self._macd = MovingAverageConvergenceDivergenceSignal()
self._macd.Macd.ShortMa.Length = self.MacdFastLength
self._macd.Macd.LongMa.Length = self.MacdSlowLength
self._macd.SignalMa.Length = self.MacdSignalLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.BindEx(self._sma, self._highest, self._lowest, self._macd, self._process_candle).Start()
def _process_candle(self, candle, sma_val, highest_val, lowest_val, macd_val):
if candle.State != CandleStates.Finished:
return
self._check_protective_levels(candle)
sma_value = float(sma_val)
resistance_value = float(highest_val)
support_value = float(lowest_val)
macd_main_raw = macd_val.Macd
macd_signal_raw = macd_val.Signal
if macd_main_raw is None or macd_signal_raw is None:
self._update_previous_candle(candle, None, None)
return
macd_main = float(macd_main_raw)
macd_signal = float(macd_signal_raw)
if not self._sma.IsFormed or not self._highest.IsFormed or \
not self._lowest.IsFormed or not self._macd.IsFormed:
self._update_previous_candle(candle, macd_main, macd_signal)
return
if self._resistance_counter > 0:
self._resistance_counter -= 1
if self._support_counter > 0:
self._support_counter -= 1
if self._macd_down_counter > 0:
self._macd_down_counter -= 1
if self._macd_up_counter > 0:
self._macd_up_counter -= 1
point = self._get_point_value()
if self._has_previous_candle:
if self._previous_high is not None and resistance_value > 0 and self._previous_high > resistance_value:
self._resistance_counter = self.SignalValidity
if self._previous_low is not None and support_value > 0 and self._previous_low < support_value:
self._support_counter = self.SignalValidity
if self._prev_macd_main is not None and self._prev_macd_signal is not None:
if macd_main < macd_signal and self._prev_macd_main > self._prev_macd_signal and macd_main > 0:
self._macd_down_counter = self.SignalValidity
if macd_main > macd_signal and self._prev_macd_main < self._prev_macd_signal and macd_main < 0:
self._macd_up_counter = self.SignalValidity
volume = float(self.OrderVolume)
close = float(candle.ClosePrice)
if volume > 0:
long_signal_active = self._macd_up_counter > 0 and close > sma_value
if long_signal_active and self.Position <= 0:
stop_offset = float(self.StopDistancePoints) * point
adjusted_distance = close - sma_value + stop_offset
if adjusted_distance > 0:
self._planned_stop = sma_value - stop_offset
self._planned_take = close + adjusted_distance * float(self.RiskRewardMultiplier)
self._planned_side = 1
self.BuyMarket(volume)
self._activate_planned_levels(1)
short_signal_active = self._macd_down_counter > 0 and close < sma_value
if short_signal_active and self.Position >= 0:
stop_offset = float(self.StopDistancePoints) * point
adjusted_distance = sma_value - close + stop_offset
if adjusted_distance > 0:
self._planned_stop = sma_value + stop_offset
self._planned_take = close - adjusted_distance * float(self.RiskRewardMultiplier)
self._planned_side = -1
self.SellMarket(volume)
self._activate_planned_levels(-1)
self._update_previous_candle(candle, macd_main, macd_signal)
def _activate_planned_levels(self, direction):
if direction == 1 and self._planned_side == 1:
self._active_stop = self._planned_stop
self._active_take = self._planned_take
self._active_side = 1
elif direction == -1 and self._planned_side == -1:
self._active_stop = self._planned_stop
self._active_take = self._planned_take
self._active_side = -1
self._planned_stop = None
self._planned_take = None
self._planned_side = None
def _check_protective_levels(self, candle):
if self._active_side is None or self.Position == 0:
return
if self._active_side == 1 and self.Position > 0:
if self._active_stop is not None and float(candle.LowPrice) <= self._active_stop:
self._clear_planned_levels()
self._clear_active_levels()
self._close_position()
return
if self._active_take is not None and float(candle.HighPrice) >= self._active_take:
self._clear_planned_levels()
self._clear_active_levels()
self._close_position()
return
elif self._active_side == -1 and self.Position < 0:
if self._active_stop is not None and float(candle.HighPrice) >= self._active_stop:
self._clear_planned_levels()
self._clear_active_levels()
self._close_position()
return
if self._active_take is not None and float(candle.LowPrice) <= self._active_take:
self._clear_planned_levels()
self._clear_active_levels()
self._close_position()
def _update_previous_candle(self, candle, macd_main, macd_signal):
self._previous_high = float(candle.HighPrice)
self._previous_low = float(candle.LowPrice)
self._has_previous_candle = True
self._prev_macd_main = macd_main
self._prev_macd_signal = macd_signal
def _get_point_value(self):
if self.Security is not None and self.Security.PriceStep is not None:
step = float(self.Security.PriceStep)
if step > 0:
return step
return 0.0001
def _close_position(self):
if self.Position > 0:
self.SellMarket(self.Position)
elif self.Position < 0:
self.BuyMarket(abs(self.Position))
def _clear_planned_levels(self):
self._planned_stop = None
self._planned_take = None
self._planned_side = None
def _clear_active_levels(self):
self._active_stop = None
self._active_take = None
self._active_side = None
def CreateClone(self):
return trading_lab_best_macd_strategy()