Ver en GitHub

Estrategia de Cuadrícula Aeron Robot

Esta estrategia implementa un sistema de cobertura basado en cuadrícula inspirado en el asesor experto AeronRobot. Coloca órdenes de compra y venta en intervalos de precio predefinidos y aumenta el volumen de la posición después de cada nueva orden. El enfoque busca capturar pequeñas oscilaciones de precio mientras controla el riesgo mediante take-profit, stop-loss y límites de operaciones configurables.

La estrategia trabaja con posiciones largas y cortas. Cuando el precio se mueve en pasos definidos por el parámetro Gap, se abre una nueva orden con volumen multiplicado por LotsFactor. Los beneficios se aseguran cuando el precio regresa TakeProfit puntos, y las pérdidas se cortan si el movimiento alcanza StopLoss puntos. La bandera Hedging permite mantener posiciones en ambos lados simultáneamente.

Detalles

  • Criterios de entrada:
    • Largo: el precio cae Gap puntos desde el último precio de compra.
    • Corto: el precio sube Gap puntos desde el último precio de venta.
  • Gestión de volumen: el volumen de cada nueva orden se multiplica por LotsFactor.
  • Criterios de salida:
    • las posiciones de un lado se cierran cuando el beneficio supera los puntos TakeProfit.
    • las posiciones de un lado se cierran cuando la pérdida supera los puntos StopLoss.
  • Parámetros:
    • FirstLot – volumen inicial de la orden.
    • LotsFactor – multiplicador para las órdenes siguientes.
    • Gap – distancia base entre niveles de cuadrícula en puntos.
    • GapFactor – multiplicador que expande el intervalo después de cada operación.
    • MaxTrades – número máximo de operaciones por lado.
    • Hedging – permitir posiciones largas y cortas simultáneas.
    • TakeProfit – objetivo en puntos.
    • StopLoss – límite protector en puntos.
    • CandleType – marco temporal de velas usado para el procesamiento.
  • Largo/Corto: ambos.
  • Filtros:
    • Categoría: Cuadrícula / Reversión a la media
    • Dirección: Ambos
    • Indicadores: Ninguno
    • Stops: Sí
    • Complejidad: Intermedio
    • Marco temporal: Corto plazo
    • Estacionalidad: No
    • Redes neuronales: No
    • Divergencia: No
    • Nivel de riesgo: Alto
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>
/// EMA crossover strategy (converted from grid).
/// </summary>
public class AeronRobotStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevFast;
	private decimal _prevSlow;
	private bool _hasPrev;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public AeronRobotStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 12)
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 26)
			.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
		=> [(Security, CandleType)];

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFast = 0;
		_prevSlow = 0;
		_hasPrev = false;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };

		SubscribeCandles(CandleType).Bind(fast, slow, ProcessCandle).Start();
	}

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

		if (!_hasPrev)
		{
			_prevFast = fastVal;
			_prevSlow = slowVal;
			_hasPrev = true;
			return;
		}

		var crossUp = _prevFast <= _prevSlow && fastVal > slowVal;
		var crossDown = _prevFast >= _prevSlow && fastVal < slowVal;

		if (crossUp && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
		}
		else if (crossDown && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
		}

		_prevFast = fastVal;
		_prevSlow = slowVal;
	}
}