Ver no GitHub

Estratégia de Escape

Esta estratégia opera com base em médias móveis simples dos preços de abertura das velas. Ela compara o fechamento mais recente de 5 minutos com duas médias móveis calculadas sobre o preço de abertura:

  • SMA rápida (4 períodos) – usada como limiar para entradas vendidas.
  • SMA lenta (5 períodos) – usada como limiar para entradas compradas.

Como funciona

  1. Em cada vela de 5 minutos concluída, a estratégia atualiza duas SMAs do preço de abertura das velas.
  2. Se não houver posição ativa:
    • Entrar comprado quando o último fechamento estiver abaixo da SMA lenta.
    • Entrar vendido quando o último fechamento estiver acima da SMA rápida.
  3. Após entrar em uma posição, a estratégia define níveis fixos de stop-loss e take-profit medidos em unidades de preço.
  4. A posição é fechada quando o take-profit ou stop-loss é atingido.

A lógica usa a API de alto nível do StockSharp e é destinada a fins educativos.

Parâmetros

Nome Descrição Padrão
FastLength Período da SMA rápida. 4
SlowLength Período da SMA lenta. 5
TakeProfitLong Distância de take-profit para trades comprados em unidades de preço. 25
TakeProfitShort Distância de take-profit para trades vendidos em unidades de preço. 26
StopLossLong Distância de stop-loss para trades comprados em unidades de preço. 25
StopLossShort Distância de stop-loss para trades vendidos em unidades de preço. 3
CandleType Tipo de vela usado para análise. TimeFrame(5m)

Todos os parâmetros podem ser otimizados pelo otimizador do 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;
	}
}