Ver no GitHub

Anands Strategy

This breakout system sets the trade direction using the previous day's candle. If the prior close is above that day's high the strategy looks for longs, while a close below the low turns it bearish. On the 15‑minute timeframe it watches the last two completed candles. A long position opens when the previous candle closes above the high from two bars ago. A short position opens when the previous close falls below the low from two bars back.

Details

  • Entry Criteria:
    • Previous day close above/below its range sets bullish/bearish bias.
    • Long: prior 15m close > high two bars ago.
    • Short: prior 15m close < low two bars ago.
  • Long/Short: Both sides.
  • Exit Criteria: Not defined, reverse signal closes.
  • Stops: Suggested at opposite side of the breakout bar.
  • Default Values:
    • CandleType = 15 minute
  • Filters:
    • Category: Breakout
    • Direction: Both
    • Indicators: Candles
    • Stops: Optional
    • Complexity: Low
    • Timeframe: Intraday
    • Seasonality: No
    • Neural networks: No
    • Divergence: No
    • Risk level: Medium
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;
	}
}