La mejor estrategia MACD de TradingLab
Esta estrategia replica el asesor experto de MetaTrader "TradingLab_Best_MACD_Strategy" utilizando el API de alto nivel de StockSharp. Combina una estructura de media móvil, cruces MACD y comprobaciones dinámicas de soporte/resistencia para abrir operaciones direccionales que se alinean con el impulso y las reacciones recientes de los precios.
Lógica principal
- Fuente de velas: utiliza el parámetro configurable
CandleTypepara suscribirse a velas terminadas. Sólo las velas completadas generan decisiones comerciales. - Filtro de tendencias: una media móvil simple de 200 períodos define la tendencia predominante. Las operaciones largas requieren que el cierre se mantenga por encima del promedio, mientras que las operaciones cortas requieren que el cierre se mantenga por debajo de él.
- Cuadro de soporte y resistencia: una ventana más alta/más baja de 20 períodos emula el indicador personalizado "Cuadro". Tocar la resistencia o el nivel de soporte anterior genera configuraciones cortas o largas para un número limitado de velas controladas por
SignalValidity. - MACD Cruces: un MACD estándar (12, 26, 9 por defecto) debe cruzar su línea de señal en la vela anterior y permanecer en el lado requerido de la línea cero. Cada cruce válido mantiene viva su señal durante
SignalValidityvelas, reflejando la lógica de cuenta regresiva de la fuente EA. - Momento de entrada: se abre una posición cuando tanto el MACD como el toque de soporte/resistencia correspondiente siguen siendo válidos, y al menos uno de ellos se activa en la vela actual.
- Lógica de salida: al entrar, los objetivos dinámicos de stop-loss y take-profit se calculan en relación con la distancia promedio móvil. La distancia de obtención de beneficios es
RiskRewardMultiplierveces la distancia ajustada utilizada para la parada. Las salidas protectoras monitorean las velas posteriores y llaman aClosePosition()una vez que el precio supera los niveles almacenados.
Parámetros
| Parámetro | Descripción |
|---|---|
OrderVolume |
Volumen fijo enviado con cada orden de mercado. |
SignalValidity |
Número de velas que mantienen activos MACD y activadores de soporte/resistencia. |
MaLength |
Período del filtro de tendencia de media móvil simple. |
BoxPeriod |
Longitud retrospectiva del cuadro más alto/más bajo que rastrea la resistencia y el soporte recientes. |
MacdFastLength, MacdSlowLength, MacdSignalLength |
MACD períodos rápido, lento y de señal. |
StopDistancePoints |
Distancia desde la media móvil hasta el stop-loss, expresada en puntos estilo MetaTrader (multiplicados por el paso del precio del símbolo). |
RiskRewardMultiplier |
Multiplicador aplicado a la distancia MA ajustada para producir el objetivo de obtención de beneficios. |
CandleType |
Tipo de datos que describe la serie de velas a la que suscribirse (predeterminado: período de 1 hora). |
Notas
- La detección de soporte y resistencia sigue la idea original al observar si la vela anterior rompe los niveles más alto/más bajo de los 20 períodos. Cada toque reinicia los contadores de validez.
- Las paradas y los objetivos se vuelven a calcular para cada nueva entrada y se comparan con el máximo/mínimo de cada vela terminada para imitar el monitoreo intrabar de MetaTrader de manera determinista.
- La gestión protectora se basa en el instrumento
PriceStep. Si un instrumento informa un paso cero, se utiliza un retroceso de 0,0001.
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()