Открыть на GitHub

Стратегия Three Soldiers Stochastic

Стратегия воспроизводит логику эксперта MetaTrader Expert_ABC_WS_Stoch.mq5, совмещая свечные модели разворота из трёх свечей со стохастическим осциллятором. Для покупки требуется бычий паттерн «Три белых солдата» и подтверждение от сигнальной линии стохастика в зоне перепроданности. Продажа открывается при формировании медвежьего паттерна «Три чёрные вороны» и сигнале стохастика в зоне перекупленности. Закрытие позиций выполняется по пересечению сигнальной линии заданных диапазонов.

Торговая логика

  1. Распознавание паттерна
    • Отслеживаются три последние завершённые свечи.
    • Three White Soldiers: все три свечи бычьи, и каждое закрытие выше предыдущего.
    • Three Black Crows: все три свечи медвежьи, и каждое закрытие ниже предыдущего.
  2. Подтверждение стохастиком
    • Рассчитывается стохастик с периодами %K = 47, %D = 9, Slowing = 13 (значения по умолчанию соответствуют исходному роботу).
    • Используется сигнальная линия (%D):
      • Покупка, если предыдущее значение ниже порога перепроданности (по умолчанию 30).
      • Продажа, если предыдущее значение выше порога перекупленности (по умолчанию 70).
  3. Условия выхода
    • Длинная позиция закрывается, когда сигнальная линия пересекает снизу вверх нижнюю или верхнюю границу (по умолчанию 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;
		}
	}
}