Стратегия N Candles v5
Обзор
Стратегия N Candles v5 ищет последовательности из одинаковых свечей и открывает сделку в их направлении, как только найден необходимый отрезок. Оригинальная версия на MQL, написанная Владимиром Карпутовым, перенесена на высокоуровневый API StockSharp. Логика работает только с закрытыми свечами и может применяться на любом таймфрейме, по умолчанию используется часовой.
Торговая логика
- После закрытия свечи она классифицируется как бычья (close > open), медвежья (close < open) или нейтральная (close = open).
- Последовательные бычьи свечи увеличивают счётчик бычьей серии и обнуляют медвежий счётчик, и наоборот. Нейтральные свечи сбрасывают оба счётчика.
- Когда счётчик бычьей серии достигает
CandlesCount, а текущая позиция отсутствует или открыта в шорт, стратегия покупает по рынку. Сначала закрывается шортовая позиция, затем добавляется объёмTradeVolumeдля открытия лонга. - Когда счётчик медвежьей серии достигает
CandlesCount, а позиция отсутствует или открыта в лонг, стратегия продаёт по рынку. Сначала закрывается лонг, затем открывается шорт. - Входы выполняются только внутри торгового окна между
StartHourиEndHour, если активирован флагUseTradingHours. При этом защита позиции (тейк, стоп, трейлинг) продолжает работать вне торгового окна. - Объём позиции ограничивается параметром
MaxNetVolume, что повторяет защиту от чрезмерного увеличения позиции в исходном MQL-скрипте.
Управление рисками
- Тейк-профит / стоп-лосс – задаются в пунктах и автоматически переводятся в абсолютные цены через шаг цены инструмента. Значение 0 отключает уровень.
- Трейлинг-стоп – активируется после движения цены на
TrailingStopPipsпунктов от цены входа. После активации стоп подтягивается при каждом дополнительном продвижении наTrailingStepPipsпунктов. - Торговая сессия – параметр
UseTradingHoursвключает фильтр по часам. Вне окна стратегия не открывает новые позиции, но продолжает сопровождать существующие. - Ограничение объёма – модуль позиции не превышает
MaxNetVolume.
Параметры
| Параметр | Описание | Значение по умолчанию |
|---|---|---|
TradeVolume |
Объём заявки при входе. | 1 |
CandlesCount |
Количество подряд идущих одинаковых свечей для сигнала. | 3 |
TakeProfitPips |
Дистанция тейк-профита в пунктах (0 отключает). | 50 |
StopLossPips |
Дистанция стоп-лосса в пунктах (0 отключает). | 50 |
TrailingStopPips |
Сдвиг, активирующий трейлинг-стоп (0 отключает). | 10 |
TrailingStepPips |
Дополнительное движение, необходимое для подтягивания трейлинга. | 4 |
UseTradingHours |
Флаг включения фильтра по времени. | true |
StartHour |
Начальный час (0–23), когда разрешены новые входы. | 11 |
EndHour |
Конечный час (0–23), когда разрешены новые входы. | 18 |
MaxNetVolume |
Максимальный модуль позиции. | 2 |
CandleType |
Тип свечей для анализа. По умолчанию часовые. | TimeSpan.FromHours(1) |
Рекомендации по использованию
- Стратегия подписывается на свечи через
SubscribeCandlesи может работать с любыми инструментами, предоставляющими свечные ряды. - Так как логика основана на закрытых барах, стратегия хорошо подходит для внутридневной и более высокой периодичности, где шум между закрытиями менее значим.
- Подбирайте значения тейк-профита, стоп-лосса и трейлинга с учётом шага цены конкретного инструмента и текущего спреда.
- Перед запуском на инструментах с широкими или плавающими спредами проверяйте параметры трейлинга, чтобы избежать ложных срабатываний.
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()