Открыть на GitHub

Стратегия X Trader V3

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

Подробности

  • Условия входа:
    • SMA медианной цены с периодом Ma1Period пересекает SMA с периодом Ma2Period сверху вниз и остаётся ниже две свечи ⇒ покупка при AllowBuy.
    • SMA медианной цены с периодом Ma1Period пересекает SMA с периодом Ma2Period снизу вверх и остаётся выше две свечи ⇒ продажа при AllowSell.
    • Время свечи между StartTime и EndTime.
  • Направление: Лонг и шорт.
  • Условия выхода:
    • Обратное пересечение при включённом CloseOnReverseSignal.
  • Стопы:
    • Опциональные тейк-профит и стоп-лосс в тиках через TakeProfitTicks и StopLossTicks.
  • Параметры по умолчанию:
    • Ma1Period = 16
    • Ma2Period = 1
    • TakeProfitTicks = 150
    • StopLossTicks = 100
  • Фильтры:
    • Категория: Пересечение
    • Направление: Оба
    • Индикаторы: SMA
    • Стопы: Опционально
    • Сложность: Низкая
    • Таймфрейм: Любой
    • Сезонность: Нет
    • Нейросети: Нет
    • Дивергенция: Нет
    • Уровень риска: Средний
using System;
using System.Collections.Generic;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// X Trader V3 strategy based on EMA crossover.
/// </summary>
public class XTraderV3Strategy : 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 XTraderV3Strategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe", "General");

		_fastPeriod = Param(nameof(FastPeriod), 12)
			.SetGreaterThanZero()
			.SetDisplay("Fast Period", "Fast EMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 26)
			.SetGreaterThanZero()
			.SetDisplay("Slow Period", "Slow EMA period", "Indicators");
	}

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

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

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

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

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

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

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

		var crossUp = _prevFast <= _prevSlow && fastVal > slowVal;
		var crossDown = _prevFast >= _prevSlow && fastVal < slowVal;

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

		_prevFast = fastVal;
		_prevSlow = slowVal;
	}
}