Открыть на GitHub

Стратегия Escape

Данная стратегия торгует на основе простых скользящих средних от цен открытия свечей. Сравнивается последняя закрытая 5‑минутная свеча с двумя средними, вычисленными по ценам открытия:

  • Быстрая SMA (4 периода) – используется для открытия коротких позиций.
  • Медленная SMA (5 периодов) – используется для открытия длинных позиций.

Принцип работы

  1. На каждой завершённой 5‑минутной свече обновляются две SMA по цене открытия.
  2. При отсутствии позиции:
    • Вход в покупку, если закрытие ниже медленной SMA.
    • Вход в продажу, если закрытие выше быстрой SMA.
  3. После входа устанавливаются фиксированные уровни stop‑loss и take‑profit, измеренные в ценовых единицах.
  4. Позиция закрывается при достижении любого уровня.

Стратегия использует высокоуровневый API StockSharp и предназначена для демонстрации.

Параметры

Имя Описание Значение по умолчанию
FastLength Период быстрой SMA. 4
SlowLength Период медленной SMA. 5
TakeProfitLong Дистанция take‑profit для длинных сделок. 25
TakeProfitShort Дистанция take‑profit для коротких сделок. 26
StopLossLong Дистанция stop‑loss для длинных сделок. 25
StopLossShort Дистанция stop‑loss для коротких сделок. 3
CandleType Тип используемых свечей. TimeFrame(5m)

Все параметры могут быть оптимизированы через оптимизатор StockSharp.

using System;
using System.Linq;
using System.Collections.Generic;

using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Simple strategy based on SMA of open prices and previous close comparison.
/// Buys when the previous close is below the slow SMA.
/// Sells short when the previous close is above the fast SMA.
/// Uses fixed take profit and stop loss levels for both directions.
/// </summary>
public class EscapeStrategy : Strategy
{
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<decimal> _takeProfitLong;
	private readonly StrategyParam<decimal> _takeProfitShort;
	private readonly StrategyParam<decimal> _stopLossLong;
	private readonly StrategyParam<decimal> _stopLossShort;
	private readonly StrategyParam<DataType> _candleType;

	private SimpleMovingAverage _fastMa;
	private SimpleMovingAverage _slowMa;
	private bool _initialized;
	private decimal _previousClose;
	private decimal _previousFast;
	private decimal _previousSlow;

	/// <summary>
	/// Length of fast SMA.
	/// </summary>
	public int FastLength
	{
		get => _fastLength.Value;
		set => _fastLength.Value = value;
	}

	/// <summary>
	/// Length of slow SMA.
	/// </summary>
	public int SlowLength
	{
		get => _slowLength.Value;
		set => _slowLength.Value = value;
	}

	/// <summary>
	/// Take profit distance for long positions in price units.
	/// </summary>
	public decimal TakeProfitLong
	{
		get => _takeProfitLong.Value;
		set => _takeProfitLong.Value = value;
	}

	/// <summary>
	/// Take profit distance for short positions in price units.
	/// </summary>
	public decimal TakeProfitShort
	{
		get => _takeProfitShort.Value;
		set => _takeProfitShort.Value = value;
	}

	/// <summary>
	/// Stop loss distance for long positions in price units.
	/// </summary>
	public decimal StopLossLong
	{
		get => _stopLossLong.Value;
		set => _stopLossLong.Value = value;
	}

	/// <summary>
	/// Stop loss distance for short positions in price units.
	/// </summary>
	public decimal StopLossShort
	{
		get => _stopLossShort.Value;
		set => _stopLossShort.Value = value;
	}

	/// <summary>
	/// Candle type to analyze.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public EscapeStrategy()
	{
		_fastLength = Param(nameof(FastLength), 4)
			.SetDisplay("Fast SMA Length", "Length of fast SMA", "Parameters")
			.SetGreaterThanZero()
			;

		_slowLength = Param(nameof(SlowLength), 5)
			.SetDisplay("Slow SMA Length", "Length of slow SMA", "Parameters")
			.SetGreaterThanZero()
			;

		_takeProfitLong = Param(nameof(TakeProfitLong), 25m)
			.SetDisplay("Take Profit Long", "Take profit for long trades", "Trading")
			.SetGreaterThanZero();

		_takeProfitShort = Param(nameof(TakeProfitShort), 26m)
			.SetDisplay("Take Profit Short", "Take profit for short trades", "Trading")
			.SetGreaterThanZero();

		_stopLossLong = Param(nameof(StopLossLong), 25m)
			.SetDisplay("Stop Loss Long", "Stop loss for long trades", "Trading")
			.SetGreaterThanZero();

		_stopLossShort = Param(nameof(StopLossShort), 3m)
			.SetDisplay("Stop Loss Short", "Stop loss for short trades", "Trading")
			.SetGreaterThanZero();

		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe for candles", "General");
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_fastMa = null;
		_slowMa = null;
		_initialized = false;
		_previousClose = 0m;
		_previousFast = 0m;
		_previousSlow = 0m;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_fastMa = new SMA { Length = FastLength };
		_slowMa = new SMA { Length = SlowLength };

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

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

		StartProtection(
			takeProfit: new Unit(2, UnitTypes.Percent),
			stopLoss: new Unit(1, UnitTypes.Percent)
		);
	}

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

		var fast = _fastMa!.Process(new DecimalIndicatorValue(_fastMa, candle.OpenPrice, candle.OpenTime) { IsFinal = true }).ToDecimal();
		var slow = _slowMa!.Process(new DecimalIndicatorValue(_slowMa, candle.OpenPrice, candle.OpenTime) { IsFinal = true }).ToDecimal();

		if (!_initialized)
		{
			_initialized = true;
			_previousClose = candle.ClosePrice;
			_previousFast = fast;
			_previousSlow = slow;
			return;
		}

		var close = candle.ClosePrice;
		var buySignal = _previousClose >= _previousSlow && close < slow;
		var sellSignal = _previousClose <= _previousFast && close > fast;

		if (Position == 0)
		{
			if (buySignal)
				BuyMarket();
			else if (sellSignal)
				SellMarket();
		}

		_previousClose = close;
		_previousFast = fast;
		_previousSlow = slow;
	}
}