Открыть на GitHub

Стратегия Simple FX Crossover

Краткое описание

  • Высокоуровневая портированная версия эксперта MetaTrader 4 simplefx2.mq4 (Simple FX 2.0).
  • Торгует пересечением быстрой и медленной простых скользящих средних по закрытым свечам.
  • Держит только одну позицию и переворачивается при смене доминирующего тренда.

Логика торговли

  1. Формирует свечи выбранного таймфрейма.
  2. Рассчитывает две простые скользящие средние (быструю и медленную) по ценам закрытия свечей.
  3. Подтверждает бычий тренд, когда и текущая, и предыдущая свечи показывают, что быстрая SMA находится выше медленной. Медвежий тренд подтверждается, когда обе свечи показывают обратное соотношение.
  4. Если подтверждённый тренд отличается от сохранённого состояния, стратегия закрывает противоположную позицию и немедленно открывает рыночную сделку в направлении нового тренда с заданным объёмом.
  5. Дополнительно можно задать уровни стоп-лосса и тейк-профита в шагах цены; они реализуются через сервис защиты StockSharp и повторяют настройки из MT4.

Стратегия работает только с завершёнными свечами и не реагирует на внутрисвечные тики, что обеспечивает максимальное соответствие оригинальному эксперту. Для каждого входа в позицию в журнал записывается поясняющее сообщение.

Параметры

Имя Описание Значение по умолчанию Диапазон оптимизации
ShortPeriod Период быстрой простой скользящей средней. 50 10 → 150 шаг 5
LongPeriod Период медленной простой скользящей средней. 200 50 → 400 шаг 10
Volume Объём рыночной заявки при входе. 0.1 0.1 → 2 шаг 0.1
StopLossPoints Расстояние стоп-лосса в шагах цены (0 отключает). 0
TakeProfitPoints Расстояние тейк-профита в шагах цены (0 отключает). 0
CandleType Таймфрейм свечей для анализа. 1 час

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

  • Файл simplefx.dat больше не нужен: направление тренда хранится во внутреннем состоянии стратегии.
  • Параметры скольжения, комментария, magic number и цветов стрелок не перенесены, т.к. маршрутизация заявок в StockSharp устроена иначе.
  • Уровни стоп-лосса и тейк-профита задаются в шагах цены. При необходимости скорректируйте их под размер пункта у вашего брокера.
  • В любой момент времени открыта только одна позиция. Перед переворотом вызывается ClosePosition(), что гарантирует чистый переход между long и short.

Как использовать

  1. Выберите инструмент и настройте желаемый таймфрейм свечей.
  2. Отредактируйте периоды скользящих средних и параметры управления рисками.
  3. Запустите стратегию — она подпишется на свечи, будет отслеживать смену тренда и совершать рыночные сделки после подтверждённого пересечения на двух последовательных свечах.
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>
/// Simple FX crossover strategy.
/// Uses fast and slow SMA crossover for trend detection.
/// Buys on golden cross, sells on death cross.
/// </summary>
public class SimpleFxCrossoverStrategy : Strategy
{
	private readonly StrategyParam<int> _shortPeriod;
	private readonly StrategyParam<int> _longPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevShort;
	private decimal _prevLong;
	private bool _hasPrev;

	public int ShortPeriod { get => _shortPeriod.Value; set => _shortPeriod.Value = value; }
	public int LongPeriod { get => _longPeriod.Value; set => _longPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public SimpleFxCrossoverStrategy()
	{
		_shortPeriod = Param(nameof(ShortPeriod), 10)
			.SetDisplay("Fast SMA", "Fast SMA period", "Indicators");

		_longPeriod = Param(nameof(LongPeriod), 30)
			.SetDisplay("Slow SMA", "Slow SMA period", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevShort = 0m;
		_prevLong = 0m;
		_hasPrev = false;
	}

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

		_hasPrev = false;

		var fast = new SimpleMovingAverage { Length = ShortPeriod };
		var slow = new SimpleMovingAverage { Length = LongPeriod };

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

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

		if (!_hasPrev)
		{
			_prevShort = fast;
			_prevLong = slow;
			_hasPrev = true;
			return;
		}

		var crossUp = _prevShort <= _prevLong && fast > slow;
		var crossDown = _prevShort >= _prevLong && fast < slow;

		if (crossUp && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		else if (crossDown && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevShort = fast;
		_prevLong = slow;
	}
}