Открыть на GitHub

Стратегия MACross

Стратегия переносит логику эксперта MQL/34176/MACross.mq4 на высокоуровневый API StockSharp. Она торгует один инструмент по пересечению скользящих средних и сохраняет все защитные механизмы, выраженные в пунктах и капитале счёта.

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

  1. На выбранном типе свечей строятся две простые скользящие средние (SMA):
    • FastPeriod — быстрый фильтр, мгновенно реагирующий на цену.
    • SlowPeriod — медленный фильтр, показывающий базовый тренд.
  2. После закрытия каждой свечи сравниваются значения SMA:
    • Пересечение вверх (быстрая выше медленной) открывает длинную позицию. При наличии шорта он закрывается перед новым входом.
    • Пересечение вниз (быстрая ниже медленной) открывает короткую позицию после закрытия лонга.
  3. Любой вход выполняется рыночным объёмом LotSize, который дополнительно подгоняется под биржевые ограничения (VolumeStep, MinVolume, MaxVolume).
  4. После открытия позиции стратегия отслеживает два уровня управления риском, заданных в пунктах. Размер пункта определяется по Security.Decimals (или PriceStep, если количество знаков неизвестно):
    • TakeProfitPips — дистанция до цели по прибыли. Достижение уровня приводит к рыночному выходу.
    • StopLossPips — расстояние защитного стопа. Его пробой немедленно закрывает позицию.
  5. Порог MinEquity позволяет приостановить появление новых сделок. Если текущая стоимость портфеля падает ниже заданного уровня, стратегия продолжает сопровождать открытую позицию, но не инициирует новые входы.

Вся логика работает только на закрытых свечах, что полностью соответствует оригинальному эксперту, проверявшему условия после формирования нового бара.

Визуализация

При наличии панели графика отображаются:

  • Свечи выбранного таймфрейма.
  • Быстрая и медленная SMA.
  • Собственные сделки стратегии, показывающие точки входа и выхода.

Параметры

Название Тип Значение по умолчанию Описание
FastPeriod int 8 Длина быстрой SMA, определяющей сигналы на вход.
SlowPeriod int 20 Длина медленной SMA, задающей направление тренда.
TakeProfitPips decimal 20 Дистанция до цели по прибыли в пунктах. Размер пункта вычисляется автоматически.
StopLossPips decimal 20 Расстояние защитного стопа в пунктах. Использует ту же формулу пункта, что и тейк-профит.
LotSize decimal 1 Базовый объём заявки. Перед отправкой округляется к допустимому значению.
MinEquity decimal 100 Минимальный капитал счёта. При падении ниже порога новые входы блокируются.
CandleType DataType TimeSpan.FromMinutes(1).TimeFrame() Свечной ряд, по которому считаются SMA и принимаются решения.

Отличия от версии MQL

  • В MQL-реализации стоп и тейк передавались в OrderSend равными нулю. В StockSharp-версии выходы выполняются вручную при достижении ценовых уровней на закрытии свечей.
  • Проверка капитала (cekMinEquity) теперь использует Portfolio.CurrentValue и Portfolio.BeginValue вместо AccountEquity(), сохраняя ту же логику порога.
  • Определение размера пункта повторяет функцию GetPipPoint: для двух- и трёхзнаковых котировок берётся 0.01, для четырёх- и пятизнаковых — 0.0001, иначе используется PriceStep.

Стратегия готова к оптимизации по всем параметрам и интегрируется с механизмами визуализации и риск-менеджмента StockSharp.

namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// MA Cross strategy: SMA crossover.
/// Buys when fast SMA crosses above slow SMA, sells on cross below.
/// </summary>
public class MacrossStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;

	private decimal _prevFast;
	private decimal _prevSlow;
	private bool _hasPrev;

	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 MacrossStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_fastPeriod = Param(nameof(FastPeriod), 10)
			.SetGreaterThanZero()
			.SetDisplay("Fast SMA", "Fast SMA period", "Indicators");
		_slowPeriod = Param(nameof(SlowPeriod), 30)
			.SetGreaterThanZero()
			.SetDisplay("Slow SMA", "Slow SMA period", "Indicators");
	}

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

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevFast = 0;
		_prevSlow = 0;
		_hasPrev = false;
		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fast, slow, ProcessCandle).Start();
	}

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

		if (_hasPrev)
		{
			if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
				BuyMarket();
			else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
				SellMarket();
		}
		else
		{
			if (fastValue > slowValue && Position <= 0)
				BuyMarket();
			else if (fastValue < slowValue && Position >= 0)
				SellMarket();
		}

		_prevFast = fastValue;
		_prevSlow = slowValue;
		_hasPrev = true;
	}
}