Стратегия воспроизводит логику эксперта MetaTrader Expert_ABC_WS_Stoch.mq5, совмещая свечные модели разворота из трёх свечей со стохастическим осциллятором. Для покупки требуется бычий паттерн «Три белых солдата» и подтверждение от сигнальной линии стохастика в зоне перепроданности. Продажа открывается при формировании медвежьего паттерна «Три чёрные вороны» и сигнале стохастика в зоне перекупленности. Закрытие позиций выполняется по пересечению сигнальной линии заданных диапазонов.
Торговая логика
Распознавание паттерна
Отслеживаются три последние завершённые свечи.
Three White Soldiers: все три свечи бычьи, и каждое закрытие выше предыдущего.
Three Black Crows: все три свечи медвежьи, и каждое закрытие ниже предыдущего.
Подтверждение стохастиком
Рассчитывается стохастик с периодами %K = 47, %D = 9, Slowing = 13 (значения по умолчанию соответствуют исходному роботу).
Используется сигнальная линия (%D):
Покупка, если предыдущее значение ниже порога перепроданности (по умолчанию 30).
Продажа, если предыдущее значение выше порога перекупленности (по умолчанию 70).
Условия выхода
Длинная позиция закрывается, когда сигнальная линия пересекает снизу вверх нижнюю или верхнюю границу (по умолчанию 20 и 80).
Короткая позиция закрывается, когда сигнальная линия пересекает сверху вниз те же границы.
Для фиксации пересечений используются предыдущее и пред-предыдущее значения сигнальной линии.
Параметры
Параметр
Значение по умолчанию
Описание
CandleType
Таймфрейм 1 час
Таймфрейм свечей для анализа.
StochKPeriod
47
Период расчёта %K.
StochDPeriod
9
Длина усреднения сигнальной линии.
StochSlowing
13
Дополнительное сглаживание %K.
OversoldLevel
30
Граница перепроданности для подтверждения покупки.
OverboughtLevel
70
Граница перекупленности для подтверждения продажи.
ExitLowerLevel
20
Нижняя граница для выхода из длинной позиции.
ExitUpperLevel
80
Верхняя граница для выхода из короткой позиции.
Все числовые параметры имеют диапазоны оптимизации и могут настраиваться в Strategy Designer без изменения кода.
Управление ордерами
При появлении встречного сигнала стратегия реверсирует позицию, добавляя модуль текущего объёма к параметру Volume.
Метод StartProtection() активирует встроенный контроль рисков платформы; явные стоп-лоссы и тейк-профиты по умолчанию не задаются.
Визуализация
При запуске в Strategy Designer отображаются:
Свечи выбранного инструмента и таймфрейма.
Стохастический осциллятор с заданными параметрами.
Маркеры сделок для наглядного анализа входов и выходов.
Рекомендации по использованию
Убедитесь, что по инструменту доступно достаточное количество истории для прогрева индикатора.
При реальной торговле добавьте дополнительные фильтры (волатильность, торговые сессии, фундаментальные события).
Пороговые уровни вынесены в параметры, что упрощает эксперименты с подтверждающими диапазонами.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Three Soldiers Stochastic strategy: detects three consecutive bullish/bearish candles
/// confirmed by RSI levels.
/// </summary>
public class ThreeSoldiersStochasticStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<int> _signalCooldownCandles;
private int _bullCount;
private int _bearCount;
private int _candlesSinceTrade;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }
public ThreeSoldiersStochasticStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period for confirmation", "Indicators");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_bullCount = 0;
_bearCount = 0;
_candlesSinceTrade = SignalCooldownCandles;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_bullCount = 0;
_bearCount = 0;
_candlesSinceTrade = SignalCooldownCandles;
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(rsi, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal rsi)
{
if (candle.State != CandleStates.Finished) return;
if (_candlesSinceTrade < SignalCooldownCandles)
_candlesSinceTrade++;
if (candle.ClosePrice > candle.OpenPrice)
{
_bullCount++;
_bearCount = 0;
}
else if (candle.ClosePrice < candle.OpenPrice)
{
_bearCount++;
_bullCount = 0;
}
else
{
_bullCount = 0;
_bearCount = 0;
}
if (_bullCount >= 3 && rsi < 65 && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_bullCount = 0;
_candlesSinceTrade = 0;
}
else if (_bearCount >= 3 && rsi > 35 && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
SellMarket();
_bearCount = 0;
_candlesSinceTrade = 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.Indicators import RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class three_soldiers_stochastic_strategy(Strategy):
def __init__(self):
super(three_soldiers_stochastic_strategy, self).__init__()
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "RSI period for confirmation", "Indicators")
self._signal_cooldown = self.Param("SignalCooldownCandles", 6) \
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading")
self._rsi = None
self._bull_count = 0
self._bear_count = 0
self._candles_since_trade = 0
@property
def rsi_period(self):
return self._rsi_period.Value
@property
def signal_cooldown(self):
return self._signal_cooldown.Value
def OnReseted(self):
super(three_soldiers_stochastic_strategy, self).OnReseted()
self._rsi = None
self._bull_count = 0
self._bear_count = 0
self._candles_since_trade = self.signal_cooldown
def OnStarted2(self, time):
super(three_soldiers_stochastic_strategy, self).OnStarted2(time)
self._rsi = RelativeStrengthIndex()
self._rsi.Length = self.rsi_period
self._bull_count = 0
self._bear_count = 0
self._candles_since_trade = self.signal_cooldown
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(60)))
subscription.Bind(self._rsi, self._process_candle)
subscription.Start()
def _process_candle(self, candle, rsi_value):
if candle.State != CandleStates.Finished:
return
if not self._rsi.IsFormed:
return
rsi_val = float(rsi_value)
if self._candles_since_trade < self.signal_cooldown:
self._candles_since_trade += 1
close = float(candle.ClosePrice)
open_p = float(candle.OpenPrice)
if close > open_p:
self._bull_count += 1
self._bear_count = 0
elif close < open_p:
self._bear_count += 1
self._bull_count = 0
else:
self._bull_count = 0
self._bear_count = 0
if self._bull_count >= 3 and rsi_val < 65.0 and self.Position <= 0 and self._candles_since_trade >= self.signal_cooldown:
self.BuyMarket()
self._bull_count = 0
self._candles_since_trade = 0
elif self._bear_count >= 3 and rsi_val > 35.0 and self.Position >= 0 and self._candles_since_trade >= self.signal_cooldown:
self.SellMarket()
self._bear_count = 0
self._candles_since_trade = 0
def CreateClone(self):
return three_soldiers_stochastic_strategy()