Ver en GitHub

Estrategia Anands

Este sistema de ruptura establece la dirección de la operación usando la vela del día anterior. Si el cierre previo está por encima del máximo de ese día, la estrategia busca largos, mientras que un cierre por debajo del mínimo la vuelve bajista. En el marco temporal de 15 minutos observa las últimas dos velas completadas. Se abre una posición larga cuando la vela anterior cierra por encima del máximo de dos barras atrás. Se abre una posición corta cuando el cierre anterior cae por debajo del mínimo de dos barras atrás.

Detalles

  • Criterios de entrada:
    • El cierre del día anterior por encima/por debajo de su rango establece el sesgo alcista/bajista.
    • Largo: cierre previo de 15m > máximo de dos barras atrás.
    • Corto: cierre previo de 15m < mínimo de dos barras atrás.
  • Largo/Corto: Ambos lados.
  • Criterios de salida: No definidos, la señal inversa cierra.
  • Stops: Sugerido en el lado opuesto de la barra de ruptura.
  • Valores predeterminados:
    • CandleType = 15 minutos
  • Filtros:
    • Categoría: Ruptura
    • Dirección: Ambos
    • Indicadores: Velas
    • Stops: Opcional
    • Complejidad: Bajo
    • Marco temporal: Intradía
    • Estacionalidad: No
    • Redes neuronales: No
    • Divergencia: No
    • Nivel de riesgo: Medio
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>
/// Anand's breakout strategy based on short-term trend and price level breakouts.
/// Uses EMA for trend and breakout of previous candle high/low for entry.
/// </summary>
public class AnandsStrategy : Strategy
{
	private readonly StrategyParam<int> _emaLength;
	private readonly StrategyParam<int> _cooldownBars;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevHigh;
	private decimal _prevLow;
	private int _barIndex;
	private int _lastTradeBar;

	/// <summary>
	/// EMA period for trend filter.
	/// </summary>
	public int EmaLength
	{
		get => _emaLength.Value;
		set => _emaLength.Value = value;
	}

	/// <summary>
	/// Cooldown bars between trades.
	/// </summary>
	public int CooldownBars
	{
		get => _cooldownBars.Value;
		set => _cooldownBars.Value = value;
	}

	/// <summary>
	/// Trading candle type.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <summary>
	/// Constructor.
	/// </summary>
	public AnandsStrategy()
	{
		_emaLength = Param(nameof(EmaLength), 5)
			.SetDisplay("EMA Length", "EMA trend filter period", "Indicator");

		_cooldownBars = Param(nameof(CooldownBars), 10)
			.SetDisplay("Cooldown Bars", "Bars between trades", "Trading");

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

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevHigh = 0;
		_prevLow = 0;
		_barIndex = 0;
		_lastTradeBar = -100;
	}

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

		var ema = new ExponentialMovingAverage { Length = EmaLength };

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

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

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

		_barIndex++;

		if (_prevHigh == 0 || _prevLow == 0)
		{
			_prevHigh = candle.HighPrice;
			_prevLow = candle.LowPrice;
			return;
		}

		var cooldownOk = _barIndex - _lastTradeBar > CooldownBars;
		var upTrend = candle.ClosePrice > emaValue;
		var downTrend = candle.ClosePrice < emaValue;

		// Breakout above previous candle high in uptrend
		if (upTrend && candle.ClosePrice > _prevHigh && Position <= 0 && cooldownOk)
		{
			BuyMarket();
			_lastTradeBar = _barIndex;
		}
		// Breakout below previous candle low in downtrend
		else if (downTrend && candle.ClosePrice < _prevLow && Position >= 0 && cooldownOk)
		{
			SellMarket();
			_lastTradeBar = _barIndex;
		}

		_prevHigh = candle.HighPrice;
		_prevLow = candle.LowPrice;
	}
}