Ver en GitHub

Estrategia Cazadora de Grandes Movimientos

Esta estrategia entra en largo cuando el precio cierra por encima de la Banda de Bollinger superior y todos los filtros habilitados confirman el movimiento. También puede ir en corto cuando el precio cierra por debajo de la banda inferior. Los filtros incluyen RSI, ADX, ATR, dirección de tendencia EMA y MACD. Se aplica un stop loss de porcentaje fijo, las posiciones se cierran cuando el precio regresa a la banda media y una toma de beneficios forzada opcional sale en velas inusualmente grandes.

Detalles

  • Criterios de entrada:
    • Largo: cierre > Banda de Bollinger superior y todos los filtros activos pasan.
    • Corto: cierre < Banda de Bollinger inferior y todos los filtros activos pasan.
  • Largo/Corto: Ambos (configurable).
  • Criterios de salida:
    • El precio cruza la Banda de Bollinger media.
    • Toma de beneficios forzada opcional en velas grandes.
  • Stops: Stop loss de porcentaje fijo.
  • Valores predeterminados: Longitud Bollinger = 40, stop loss = 2%, umbral de TP forzado = 5%.
  • Filtros: RSI (14), ADX (28), ATR (14), EMA (350), MACD (12,26,9).
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>
/// Big Mover Catcher strategy using Bollinger Band breakout with EMA trend filter.
/// Enters long when price breaks above upper band and fast EMA > slow EMA.
/// Enters short when price breaks below lower band and fast EMA &lt; slow EMA.
/// Exits on EMA crossover reversal.
/// </summary>
public class BigMoverCatcherStrategy : Strategy
{
	private readonly StrategyParam<int> _fastEmaPeriod;
	private readonly StrategyParam<int> _slowEmaPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevFastEma;
	private decimal _prevSlowEma;

	public int FastEmaPeriod { get => _fastEmaPeriod.Value; set => _fastEmaPeriod.Value = value; }
	public int SlowEmaPeriod { get => _slowEmaPeriod.Value; set => _slowEmaPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public BigMoverCatcherStrategy()
	{
		_fastEmaPeriod = Param(nameof(FastEmaPeriod), 120)
			.SetGreaterThanZero()
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");

		_slowEmaPeriod = Param(nameof(SlowEmaPeriod), 450)
			.SetGreaterThanZero()
			.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");

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

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFastEma = 0m;
		_prevSlowEma = 0m;
	}

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

		var fastEma = new ExponentialMovingAverage { Length = FastEmaPeriod };
		var slowEma = new ExponentialMovingAverage { Length = SlowEmaPeriod };

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

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

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

		if (_prevFastEma == 0m || _prevSlowEma == 0m)
		{
			_prevFastEma = fastEmaValue;
			_prevSlowEma = slowEmaValue;
			return;
		}

		// Buy on golden cross
		if (_prevFastEma <= _prevSlowEma && fastEmaValue > slowEmaValue && Position <= 0)
		{
			BuyMarket();
		}
		// Sell on death cross
		else if (_prevFastEma >= _prevSlowEma && fastEmaValue < slowEmaValue && Position >= 0)
		{
			SellMarket();
		}

		_prevFastEma = fastEmaValue;
		_prevSlowEma = slowEmaValue;
	}
}