Открыть на GitHub

Стратегия Iin MA Signal

Общее описание

Стратегия полностью воспроизводит логику советника Iin MA Signal для MQL5. Она отслеживает пересечения быстрой и медленной скользящих средних и реагирует на свечу, указанную параметром SignalBar, что соответствует чтению буферов индикатора в оригинале. При бычьем пересечении можно открыть длинную позицию и при необходимости закрыть короткую, при медвежьем — открыть шорт и закрыть лонг. Защитные ордера устанавливаются через механизм защиты позиций StockSharp.

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

  1. Подписка на свечи типа CandleType (по умолчанию — часовой таймфрейм).
  2. Построение двух скользящих средних с параметрами FastMaType/FastPeriod и SlowMaType/SlowPeriod. Поддерживаются типы SMA, EMA, SMMA (RMA) и LWMA — все варианты из исходного MQL-кода.
  3. Хранение компактного окна значений MA, чтобы оценивать пересечение на свече с индексом SignalBar и предыдущей свече.
  4. Фиксация бычьего сигнала, когда на предыдущей свече быстрая MA была ниже медленной, а на сигнальной свече оказалась выше, при условии, что предыдущий тренд не был бычьим. Аналогично определяется медвежий сигнал.
  5. После каждого пересечения обновляется внутренний флаг тренда (аналог переменной trend в индикаторе), чтобы избежать повторных входов на одной и той же серии данных.
  6. Когда метод IsFormedAndOnlineAndAllowTrading() разрешает торговлю, стратегия выставляет рыночные ордера согласно включённым флагам входа/выхода.

Правила входа

  • Покупка: выполняется при бычьем пересечении, если AllowLongEntries = true, а текущая позиция отсутствует или открыта в шорт. При активном флаге CloseShortOnSignal сперва закрывается короткая позиция.
  • Продажа: выполняется при медвежьем пересечении, если AllowShortEntries = true, а позиция отсутствует или открыта в лонг. Флаг CloseLongOnSignal позволяет сначала закрыть длинную позицию.

Правила выхода

  • Противоположные сигналы закрывают позиции в зависимости от переключателей CloseLongOnSignal и CloseShortOnSignal.
  • Если StopLossPoints или TakeProfitPoints больше нуля, вызывается StartProtection, которая выставляет стоп-лосс и тейк-профит на заданном абсолютном расстоянии и использует рыночные заявки.

Параметры

Параметр Описание Значение по умолчанию
CandleType Тип свечей, используемых в расчётах. Часовой таймфрейм
FastPeriod Период быстрой скользящей средней. 10
FastMaType Тип быстрой MA (Sma, Ema, Smma, Lwma). Ema
SlowPeriod Период медленной скользящей средней. 22
SlowMaType Тип медленной MA (Sma, Ema, Smma, Lwma). Sma
SignalBar Количество завершённых свечей назад, где должен возникнуть сигнал. 1
AllowLongEntries Разрешить входы в лонг. true
AllowShortEntries Разрешить входы в шорт. true
CloseLongOnSignal Закрывать лонг при появлении медвежьего сигнала. true
CloseShortOnSignal Закрывать шорт при появлении бычьего сигнала. true
StopLossPoints Абсолютное расстояние стоп-лосса (0 — отключено). 1000
TakeProfitPoints Абсолютное расстояние тейк-профита (0 — отключено). 2000

Особенности реализации

  • Используется только высокоуровневый API StockSharp: SubscribeCandles и Bind обеспечивают получение значений индикаторов без ручной работы с историей.
  • Фабричный метод CreateMa сопоставляет значения enum с готовыми индикаторами StockSharp, поэтому дополнительные расчёты не требуются.
  • Буфер из SignalBar + 2 значений достаточно компактен и воссоздаёт логику чтения буферов индикатора из MQL.
  • Защитные ордера активируются только при ненулевых значениях стопа или профита, что повторяет опциональный блок управления капиталом в оригинале.
  • Комментарии в коде приведены на английском языке в соответствии с требованиями репозитория.

Использование

  1. Соберите решение (dotnet build AlgoTrading.sln), чтобы скомпилировать новую стратегию.
  2. Создайте экземпляр IinMaSignalStrategy, настройте параметры и назначьте коннектор/инструмент/портфель перед запуском.
  3. При необходимости подключите стратегию к графику, чтобы видеть обе скользящие и выполненные сделки.
  4. Оптимизируйте периоды MA, величину SignalBar и параметры риска под конкретный рынок.

Отличия от оригинального советника MQL

  • Вместо ручного чтения буферов используется связка подписки и биндинга индикаторов.
  • Функции управления позицией из TradeAlgorithms.mqh заменены вызовом StartProtection, обеспечивающим эквивалентные стопы и цели.
  • По умолчанию стратегия избегает хеджирования: новая позиция не откроется, пока не закрыта противоположная (если только соответствующий флаг закрытия не выключен).
  • Для визуализации применяются стандартные методы StockSharp, стрелочные буферы индикатора не воспроизводятся.
using System;
using System.Collections.Generic;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Iin MA Signal strategy. Uses fast/slow SMA crossover.
/// </summary>
public class IinMaSignalStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;

	private decimal? _prevFast;
	private decimal? _prevSlow;

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public int FastPeriod
	{
		get => _fastPeriod.Value;
		set => _fastPeriod.Value = value;
	}

	public int SlowPeriod
	{
		get => _slowPeriod.Value;
		set => _slowPeriod.Value = value;
	}

	public IinMaSignalStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe", "General");

		_fastPeriod = Param(nameof(FastPeriod), 7)
			.SetGreaterThanZero()
			.SetDisplay("Fast SMA", "Fast SMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 21)
			.SetGreaterThanZero()
			.SetDisplay("Slow SMA", "Slow SMA period", "Indicators");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFast = null;
		_prevSlow = null;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_prevFast = null;
		_prevSlow = null;

		var fast = new SimpleMovingAverage { Length = FastPeriod };
		var slow = new SimpleMovingAverage { Length = SlowPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fast, slow, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, fast);
			DrawIndicator(area, slow);
			DrawOwnTrades(area);
		}
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastVal, decimal slowVal)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!IsFormedAndOnlineAndAllowTrading())
		{
			_prevFast = fastVal;
			_prevSlow = slowVal;
			return;
		}

		if (_prevFast == null || _prevSlow == null)
		{
			_prevFast = fastVal;
			_prevSlow = slowVal;
			return;
		}

		var prevAbove = _prevFast.Value > _prevSlow.Value;
		var currAbove = fastVal > slowVal;

		_prevFast = fastVal;
		_prevSlow = slowVal;

		if (!prevAbove && currAbove && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		else if (prevAbove && !currAbove && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}
	}
}