Estrategia N Candles v5
Descripción General
La estrategia N Candles v5 busca rachas de velas idénticas y abre una operación en la misma dirección tan pronto como aparece la racha requerida. La implementación MQL original de Vladimir Karputov ha sido traducida a la API de alto nivel de StockSharp. La estrategia opera únicamente en velas cerradas y puede ejecutarse en cualquier marco temporal, siendo las velas de una hora el valor predeterminado para la versión de StockSharp.
Lógica de Trading
- Cuando una vela cierra, la estrategia la clasifica como alcista (cierre por encima de apertura), bajista (cierre por debajo de apertura) o neutral (cierre igual a apertura).
- Las velas alcistas consecutivas aumentan el contador de racha alcista mientras reinician el contador bajista, y viceversa para las velas bajistas. Las velas neutrales reinician ambos contadores.
- Si el contador de racha alcista alcanza el valor configurado de
CandlesCounty la posición neta actual es plana o corta, la estrategia envía una compra a mercado. La exposición corta se cubre primero y luego se añade elTradeVolumeconfigurado para establecer una posición largo. - Si el contador de racha bajista alcanza
CandlesCounty la posición es plana o larga, la estrategia vende a mercado, cubriendo primero cualquier exposición larga antes de entrar corto. - Las operaciones solo se abren dentro de la ventana opcional de sesión de trading
definida por
StartHouryEndHour. Las acciones de protección (take profit, stop loss y trailing) continúan operando fuera de la sesión para garantizar que las posiciones se gestionen de forma segura. - La estrategia se niega a aumentar la exposición más allá de
MaxNetVolume, reflejando la salvaguarda de volumen de la versión MQL.
Gestión de Riesgo
- Take Profit / Stop Loss – expresados en pips y convertidos a distancias de precio absolutas usando el paso de precio del instrumento. Ambos niveles son opcionales y pueden desactivarse estableciendo el valor correspondiente en cero.
- Trailing Stop – se activa después de que el precio avanza
TrailingStopPipsdesde el precio de entrada. Una vez activo, el stop se ajusta cada vez que el precio se mueve unTrailingStepPipsadicional en la dirección de la operación. - Filtro de Sesión –
UseTradingHourshabilita el filtro de hora de inicio y fin, impidiendo nuevas entradas fuera de la ventana seleccionada mientras permite que la gestión de riesgo cierre posiciones. - Volumen Neto Máximo – la posición absoluta (larga o corta) nunca puede superar
MaxNetVolume.
Parámetros
| Parámetro | Descripción | Por defecto |
|---|---|---|
TradeVolume |
Tamaño de orden usado para nuevas entradas. | 1 |
CandlesCount |
Número de velas idénticas consecutivas requeridas para una señal. | 3 |
TakeProfitPips |
Distancia del take profit en pips (0 desactiva). | 50 |
StopLossPips |
Distancia del stop loss en pips (0 desactiva). | 50 |
TrailingStopPips |
Distancia que activa el trailing stop (0 desactiva). | 10 |
TrailingStepPips |
Progreso adicional requerido antes de ajustar el trailing stop. | 4 |
UseTradingHours |
Habilita el filtro de horas de trading. | true |
StartHour |
Primera hora (0–23) cuando se permiten nuevas posiciones. | 11 |
EndHour |
Última hora (0–23) cuando se permiten nuevas posiciones. | 18 |
MaxNetVolume |
Tamaño máximo absoluto de posición permitido. | 2 |
CandleType |
Tipo de datos de vela a analizar. Por defecto velas de 1 hora. | TimeSpan.FromHours(1) |
Notas de Uso
- La estrategia se suscribe a datos de velas a través de la API de alto nivel
SubscribeCandlesy funciona con cualquier instrumento que proporcione series de velas. - Dado que la lógica se basa en barras completadas, es más adecuada para marcos temporales intradía o superiores donde el ruido de mercado entre cierres es menos impactante.
- Ajuste la configuración de riesgo basada en pips según el tamaño del tick del instrumento.
- Al desplegar en instrumentos con diferencias de spread significativas, verifique los parámetros del trailing stop para que no sea activado por una ampliación normal del spread.
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>
/// Detects a sequence of identical candles and opens trades in the same direction.
/// Implements optional take profit, stop loss, trailing stop and trading hour filter.
/// </summary>
public class NCandlesV5Strategy : Strategy
{
private readonly StrategyParam<int> _candlesCount;
private readonly StrategyParam<decimal> _takeProfitPips;
private readonly StrategyParam<decimal> _stopLossPips;
private readonly StrategyParam<decimal> _trailingStopPips;
private readonly StrategyParam<decimal> _trailingStepPips;
private readonly StrategyParam<bool> _useTradingHours;
private readonly StrategyParam<int> _startHour;
private readonly StrategyParam<int> _endHour;
private readonly StrategyParam<decimal> _volumeParam;
private readonly StrategyParam<decimal> _maxNetVolume;
private readonly StrategyParam<DataType> _candleType;
private int _bullishCount;
private int _bearishCount;
private decimal? _longEntryPrice;
private decimal? _longTakeProfit;
private decimal? _longStopLoss;
private decimal? _longTrailingStop;
private decimal? _shortEntryPrice;
private decimal? _shortTakeProfit;
private decimal? _shortStopLoss;
private decimal? _shortTrailingStop;
/// <summary>
/// Initializes a new instance of <see cref="NCandlesV5Strategy"/>.
/// </summary>
public NCandlesV5Strategy()
{
_volumeParam = Param(nameof(TradeVolume), 1m)
.SetDisplay("Trade Volume", "Order volume for entries", "Trading")
.SetGreaterThanZero();
_candlesCount = Param(nameof(CandlesCount), 3)
.SetDisplay("Candles Count", "Number of identical candles required", "General")
.SetGreaterThanZero();
_takeProfitPips = Param(nameof(TakeProfitPips), 50m)
.SetDisplay("Take Profit (pips)", "Take profit distance in pips", "Risk");
_stopLossPips = Param(nameof(StopLossPips), 50m)
.SetDisplay("Stop Loss (pips)", "Stop loss distance in pips", "Risk");
_trailingStopPips = Param(nameof(TrailingStopPips), 10m)
.SetDisplay("Trailing Stop (pips)", "Trailing stop activation distance", "Risk");
_trailingStepPips = Param(nameof(TrailingStepPips), 4m)
.SetDisplay("Trailing Step (pips)", "Increment required to tighten trailing stop", "Risk");
_useTradingHours = Param(nameof(UseTradingHours), true)
.SetDisplay("Use Trading Hours", "Enable trading session filter", "Trading");
_startHour = Param(nameof(StartHour), 11)
.SetRange(0, 23)
.SetDisplay("Start Hour", "Hour when trading is allowed to start", "Trading");
_endHour = Param(nameof(EndHour), 18)
.SetRange(0, 23)
.SetDisplay("End Hour", "Hour when trading is allowed to stop", "Trading");
_maxNetVolume = Param(nameof(MaxNetVolume), 2m)
.SetDisplay("Max Net Volume", "Maximum absolute net position", "Risk")
.SetGreaterThanZero();
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to analyze", "General");
Volume = _volumeParam.Value;
}
/// <summary>
/// Trade volume used for new entries.
/// </summary>
public decimal TradeVolume
{
get => _volumeParam.Value;
set
{
_volumeParam.Value = value;
Volume = value;
}
}
/// <summary>
/// Number of consecutive identical candles required for a signal.
/// </summary>
public int CandlesCount
{
get => _candlesCount.Value;
set => _candlesCount.Value = value;
}
/// <summary>
/// Take profit distance in pips.
/// </summary>
public decimal TakeProfitPips
{
get => _takeProfitPips.Value;
set => _takeProfitPips.Value = value;
}
/// <summary>
/// Stop loss distance in pips.
/// </summary>
public decimal StopLossPips
{
get => _stopLossPips.Value;
set => _stopLossPips.Value = value;
}
/// <summary>
/// Trailing stop activation distance in pips.
/// </summary>
public decimal TrailingStopPips
{
get => _trailingStopPips.Value;
set => _trailingStopPips.Value = value;
}
/// <summary>
/// Trailing step distance in pips.
/// </summary>
public decimal TrailingStepPips
{
get => _trailingStepPips.Value;
set => _trailingStepPips.Value = value;
}
/// <summary>
/// Enables the trading hour filter.
/// </summary>
public bool UseTradingHours
{
get => _useTradingHours.Value;
set => _useTradingHours.Value = value;
}
/// <summary>
/// First hour of the allowed trading window.
/// </summary>
public int StartHour
{
get => _startHour.Value;
set => _startHour.Value = value;
}
/// <summary>
/// Last hour of the allowed trading window.
/// </summary>
public int EndHour
{
get => _endHour.Value;
set => _endHour.Value = value;
}
/// <summary>
/// Maximum absolute net position allowed.
/// </summary>
public decimal MaxNetVolume
{
get => _maxNetVolume.Value;
set => _maxNetVolume.Value = value;
}
/// <summary>
/// Candle type used for pattern detection.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
Volume = TradeVolume;
ResetState();
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
if (UseTradingHours && StartHour >= EndHour)
throw new InvalidOperationException("Start hour must be less than end hour when trading hours filter is enabled.");
Volume = TradeVolume;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
// Work only with completed candles to avoid premature signals.
if (candle.State != CandleStates.Finished)
return;
// Refresh trailing and exit logic before looking for new opportunities.
UpdateRiskManagement(candle);
var direction = GetDirection(candle);
// Track bullish and bearish streak length.
if (direction == 1)
{
_bullishCount++;
_bearishCount = 0;
}
else if (direction == -1)
{
_bearishCount++;
_bullishCount = 0;
}
else
{
_bullishCount = 0;
_bearishCount = 0;
}
var tradingAllowed = !UseTradingHours || (candle.OpenTime.Hour >= StartHour && candle.OpenTime.Hour <= EndHour);
// Skip entries outside the configured session window.
if (!tradingAllowed)
return;
var volume = TradeVolume;
if (volume <= 0m)
return;
var step = Security?.PriceStep ?? 1m;
// Use instrument price step to translate pip distances to absolute prices.
if (_bullishCount >= CandlesCount && Position <= 0m)
{
// Enter long after detecting the required number of bullish candles in a row.
var orderVolume = volume + Math.Max(0m, -Position);
if (orderVolume > 0m && Math.Abs(Position + orderVolume) <= MaxNetVolume)
{
BuyMarket();
SetupLongState(candle, step);
}
ResetCounters();
}
else if (_bearishCount >= CandlesCount && Position >= 0m)
{
// Enter short after detecting the required number of bearish candles in a row.
var orderVolume = volume + Math.Max(0m, Position);
if (orderVolume > 0m && Math.Abs(Position - orderVolume) <= MaxNetVolume)
{
SellMarket();
SetupShortState(candle, step);
}
ResetCounters();
}
}
private void UpdateRiskManagement(ICandleMessage candle)
{
if (Position > 0m)
{
ManageLongPosition(candle);
}
else
{
ClearLongState();
}
if (Position < 0m)
{
ManageShortPosition(candle);
}
else
{
ClearShortState();
}
}
private void ManageLongPosition(ICandleMessage candle)
{
if (_longEntryPrice is null)
// Capture entry price if it was not stored yet (for example after restart).
_longEntryPrice = candle.ClosePrice;
var step = Security?.PriceStep ?? 1m;
var close = candle.ClosePrice;
var high = candle.HighPrice;
var low = candle.LowPrice;
var trailingDistance = TrailingStopPips > 0m ? TrailingStopPips * step : 0m;
var trailingStep = TrailingStepPips > 0m ? TrailingStepPips * step : 0m;
if (TrailingStopPips > 0m && _longEntryPrice is decimal entry)
{
// Update trailing stop level according to the latest candle.
if (_longTrailingStop is null)
{
if (close - trailingDistance > entry)
_longTrailingStop = entry;
}
else
{
var newLevel = close - trailingDistance;
if (newLevel - trailingStep > _longTrailingStop)
_longTrailingStop = newLevel;
}
}
else
{
_longTrailingStop = null;
}
var exitVolume = Position > 0m ? Position : 0m;
var closed = false;
// Exit the long position when any protective target is triggered.
if (!closed && _longTakeProfit is decimal takeProfit && high >= takeProfit)
{
if (exitVolume > 0m)
SellMarket();
closed = true;
}
if (!closed && _longStopLoss is decimal stopLoss && low <= stopLoss)
{
if (exitVolume > 0m)
SellMarket();
closed = true;
}
if (!closed && _longTrailingStop is decimal trailingStop && low <= trailingStop)
{
if (exitVolume > 0m)
SellMarket();
closed = true;
}
if (closed)
ClearLongState();
}
private void ManageShortPosition(ICandleMessage candle)
{
if (_shortEntryPrice is null)
// Capture entry price if it was not stored yet (for example after restart).
_shortEntryPrice = candle.ClosePrice;
var step = Security?.PriceStep ?? 1m;
var close = candle.ClosePrice;
var high = candle.HighPrice;
var low = candle.LowPrice;
var trailingDistance = TrailingStopPips > 0m ? TrailingStopPips * step : 0m;
var trailingStep = TrailingStepPips > 0m ? TrailingStepPips * step : 0m;
if (TrailingStopPips > 0m && _shortEntryPrice is decimal entry)
{
// Update trailing stop level for the active short position.
if (_shortTrailingStop is null)
{
if (close + trailingDistance < entry)
_shortTrailingStop = entry;
}
else
{
var newLevel = close + trailingDistance;
if (newLevel + trailingStep < _shortTrailingStop)
_shortTrailingStop = newLevel;
}
}
else
{
_shortTrailingStop = null;
}
var exitVolume = Position < 0m ? -Position : 0m;
var closed = false;
// Exit the short position when any protective target is triggered.
if (!closed && _shortTakeProfit is decimal takeProfit && low <= takeProfit)
{
if (exitVolume > 0m)
BuyMarket();
closed = true;
}
if (!closed && _shortStopLoss is decimal stopLoss && high >= stopLoss)
{
if (exitVolume > 0m)
BuyMarket();
closed = true;
}
if (!closed && _shortTrailingStop is decimal trailingStop && high >= trailingStop)
{
if (exitVolume > 0m)
BuyMarket();
closed = true;
}
if (closed)
ClearShortState();
}
private static int GetDirection(ICandleMessage candle)
{
if (candle.ClosePrice > candle.OpenPrice)
return 1;
if (candle.ClosePrice < candle.OpenPrice)
return -1;
return 0;
}
private void SetupLongState(ICandleMessage candle, decimal step)
{
var entryPrice = candle.ClosePrice;
// Store reference levels for long-side risk management.
_longEntryPrice = entryPrice;
_longTakeProfit = TakeProfitPips > 0m ? entryPrice + TakeProfitPips * step : null;
_longStopLoss = StopLossPips > 0m ? entryPrice - StopLossPips * step : null;
_longTrailingStop = null;
ClearShortState();
}
private void SetupShortState(ICandleMessage candle, decimal step)
{
var entryPrice = candle.ClosePrice;
// Store reference levels for short-side risk management.
_shortEntryPrice = entryPrice;
_shortTakeProfit = TakeProfitPips > 0m ? entryPrice - TakeProfitPips * step : null;
_shortStopLoss = StopLossPips > 0m ? entryPrice + StopLossPips * step : null;
_shortTrailingStop = null;
ClearLongState();
}
private void ClearLongState()
{
_longEntryPrice = null;
_longTakeProfit = null;
_longStopLoss = null;
_longTrailingStop = null;
}
private void ClearShortState()
{
_shortEntryPrice = null;
_shortTakeProfit = null;
_shortStopLoss = null;
_shortTrailingStop = null;
}
private void ResetState()
{
ResetCounters();
ClearLongState();
ClearShortState();
}
private void ResetCounters()
{
_bullishCount = 0;
_bearishCount = 0;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Strategies import Strategy
class n_candles_v5_strategy(Strategy):
"""N Candles v5: trades after N consecutive same-direction candles with SL/TP/trailing."""
def __init__(self):
super(n_candles_v5_strategy, self).__init__()
self._volume_param = self.Param("TradeVolume", 1.0) \
.SetGreaterThanZero() \
.SetDisplay("Trade Volume", "Order volume for entries", "Trading")
self._candles_count = self.Param("CandlesCount", 3) \
.SetGreaterThanZero() \
.SetDisplay("Candles Count", "Number of identical candles required", "General")
self._take_profit_pips = self.Param("TakeProfitPips", 50.0) \
.SetDisplay("Take Profit (pips)", "Take profit distance in pips", "Risk")
self._stop_loss_pips = self.Param("StopLossPips", 50.0) \
.SetDisplay("Stop Loss (pips)", "Stop loss distance in pips", "Risk")
self._trailing_stop_pips = self.Param("TrailingStopPips", 10.0) \
.SetDisplay("Trailing Stop (pips)", "Trailing stop activation distance", "Risk")
self._trailing_step_pips = self.Param("TrailingStepPips", 4.0) \
.SetDisplay("Trailing Step (pips)", "Increment required to tighten trailing stop", "Risk")
self._use_trading_hours = self.Param("UseTradingHours", True) \
.SetDisplay("Use Trading Hours", "Enable trading session filter", "Trading")
self._start_hour = self.Param("StartHour", 11) \
.SetDisplay("Start Hour", "Hour when trading is allowed to start", "Trading")
self._end_hour = self.Param("EndHour", 18) \
.SetDisplay("End Hour", "Hour when trading is allowed to stop", "Trading")
self._max_net_volume = self.Param("MaxNetVolume", 2.0) \
.SetGreaterThanZero() \
.SetDisplay("Max Net Volume", "Maximum absolute net position", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles to analyze", "General")
self._bullish_count = 0
self._bearish_count = 0
self._long_entry_price = None
self._long_take_profit = None
self._long_stop_loss = None
self._long_trailing_stop = None
self._short_entry_price = None
self._short_take_profit = None
self._short_stop_loss = None
self._short_trailing_stop = None
@property
def TradeVolume(self):
return float(self._volume_param.Value)
@property
def CandlesCount(self):
return int(self._candles_count.Value)
@property
def TakeProfitPips(self):
return float(self._take_profit_pips.Value)
@property
def StopLossPips(self):
return float(self._stop_loss_pips.Value)
@property
def TrailingStopPips(self):
return float(self._trailing_stop_pips.Value)
@property
def TrailingStepPips(self):
return float(self._trailing_step_pips.Value)
@property
def UseTradingHours(self):
return self._use_trading_hours.Value
@property
def StartHour(self):
return int(self._start_hour.Value)
@property
def EndHour(self):
return int(self._end_hour.Value)
@property
def MaxNetVolume(self):
return float(self._max_net_volume.Value)
@property
def CandleType(self):
return self._candle_type.Value
def OnStarted2(self, time):
super(n_candles_v5_strategy, self).OnStarted2(time)
self._bullish_count = 0
self._bearish_count = 0
self._clear_long_state()
self._clear_short_state()
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
open_p = float(candle.OpenPrice)
h = float(candle.HighPrice)
lo = float(candle.LowPrice)
self._update_risk_management(candle)
# Determine direction
if close > open_p:
direction = 1
elif close < open_p:
direction = -1
else:
direction = 0
if direction == 1:
self._bullish_count += 1
self._bearish_count = 0
elif direction == -1:
self._bearish_count += 1
self._bullish_count = 0
else:
self._bullish_count = 0
self._bearish_count = 0
trading_allowed = not self.UseTradingHours or (candle.OpenTime.Hour >= self.StartHour and candle.OpenTime.Hour <= self.EndHour)
if not trading_allowed:
return
volume = self.TradeVolume
if volume <= 0:
return
sec = self.Security
step = float(sec.PriceStep) if sec is not None and sec.PriceStep is not None else 1.0
if self._bullish_count >= self.CandlesCount and self.Position <= 0:
order_volume = volume + max(0.0, -self.Position)
if order_volume > 0 and abs(self.Position + order_volume) <= self.MaxNetVolume:
self.BuyMarket()
self._setup_long_state(candle, step)
self._reset_counters()
elif self._bearish_count >= self.CandlesCount and self.Position >= 0:
order_volume = volume + max(0.0, self.Position)
if order_volume > 0 and abs(self.Position - order_volume) <= self.MaxNetVolume:
self.SellMarket()
self._setup_short_state(candle, step)
self._reset_counters()
def _update_risk_management(self, candle):
if self.Position > 0:
self._manage_long_position(candle)
else:
self._clear_long_state()
if self.Position < 0:
self._manage_short_position(candle)
else:
self._clear_short_state()
def _manage_long_position(self, candle):
if self._long_entry_price is None:
self._long_entry_price = float(candle.ClosePrice)
sec = self.Security
step = float(sec.PriceStep) if sec is not None and sec.PriceStep is not None else 1.0
close = float(candle.ClosePrice)
h = float(candle.HighPrice)
lo = float(candle.LowPrice)
trailing_distance = self.TrailingStopPips * step if self.TrailingStopPips > 0 else 0.0
trailing_step = self.TrailingStepPips * step if self.TrailingStepPips > 0 else 0.0
if self.TrailingStopPips > 0 and self._long_entry_price is not None:
entry = self._long_entry_price
if self._long_trailing_stop is None:
if close - trailing_distance > entry:
self._long_trailing_stop = entry
else:
new_level = close - trailing_distance
if new_level - trailing_step > self._long_trailing_stop:
self._long_trailing_stop = new_level
else:
self._long_trailing_stop = None
closed = False
if not closed and self._long_take_profit is not None and h >= self._long_take_profit:
if self.Position > 0:
self.SellMarket()
closed = True
if not closed and self._long_stop_loss is not None and lo <= self._long_stop_loss:
if self.Position > 0:
self.SellMarket()
closed = True
if not closed and self._long_trailing_stop is not None and lo <= self._long_trailing_stop:
if self.Position > 0:
self.SellMarket()
closed = True
if closed:
self._clear_long_state()
def _manage_short_position(self, candle):
if self._short_entry_price is None:
self._short_entry_price = float(candle.ClosePrice)
sec = self.Security
step = float(sec.PriceStep) if sec is not None and sec.PriceStep is not None else 1.0
close = float(candle.ClosePrice)
h = float(candle.HighPrice)
lo = float(candle.LowPrice)
trailing_distance = self.TrailingStopPips * step if self.TrailingStopPips > 0 else 0.0
trailing_step = self.TrailingStepPips * step if self.TrailingStepPips > 0 else 0.0
if self.TrailingStopPips > 0 and self._short_entry_price is not None:
entry = self._short_entry_price
if self._short_trailing_stop is None:
if close + trailing_distance < entry:
self._short_trailing_stop = entry
else:
new_level = close + trailing_distance
if new_level + trailing_step < self._short_trailing_stop:
self._short_trailing_stop = new_level
else:
self._short_trailing_stop = None
closed = False
if not closed and self._short_take_profit is not None and lo <= self._short_take_profit:
if self.Position < 0:
self.BuyMarket()
closed = True
if not closed and self._short_stop_loss is not None and h >= self._short_stop_loss:
if self.Position < 0:
self.BuyMarket()
closed = True
if not closed and self._short_trailing_stop is not None and h >= self._short_trailing_stop:
if self.Position < 0:
self.BuyMarket()
closed = True
if closed:
self._clear_short_state()
def _setup_long_state(self, candle, step):
entry_price = float(candle.ClosePrice)
self._long_entry_price = entry_price
self._long_take_profit = entry_price + self.TakeProfitPips * step if self.TakeProfitPips > 0 else None
self._long_stop_loss = entry_price - self.StopLossPips * step if self.StopLossPips > 0 else None
self._long_trailing_stop = None
self._clear_short_state()
def _setup_short_state(self, candle, step):
entry_price = float(candle.ClosePrice)
self._short_entry_price = entry_price
self._short_take_profit = entry_price - self.TakeProfitPips * step if self.TakeProfitPips > 0 else None
self._short_stop_loss = entry_price + self.StopLossPips * step if self.StopLossPips > 0 else None
self._short_trailing_stop = None
self._clear_long_state()
def _clear_long_state(self):
self._long_entry_price = None
self._long_take_profit = None
self._long_stop_loss = None
self._long_trailing_stop = None
def _clear_short_state(self):
self._short_entry_price = None
self._short_take_profit = None
self._short_stop_loss = None
self._short_trailing_stop = None
def _reset_counters(self):
self._bullish_count = 0
self._bearish_count = 0
def OnReseted(self):
super(n_candles_v5_strategy, self).OnReseted()
self._bullish_count = 0
self._bearish_count = 0
self._clear_long_state()
self._clear_short_state()
def CreateClone(self):
return n_candles_v5_strategy()