Ver en GitHub

Estrategia de cesta de comerciantes de divergencia

Descripción general

Esta estrategia es un puerto StockSharp del asesor experto "Divergence Trader" MetaTrader. Compara dos medias móviles simples. se calcula sobre fuentes de precios configurables y mide su diferencia (divergencia). Cuando la distancia entre lo rápido y lo lento promedio cae dentro de un corredor neutral, el algoritmo asume que el impulso está a punto de reanudarse y abre una posición en el dirección del sesgo predominante. La implementación utiliza sólo velas completadas de un período de tiempo seleccionado y se basa en el API de alto nivel con enlaces de indicadores.

Parámetros

  • Tamaño del lote: volumen de operaciones enviado con cada nueva posición. El valor está alineado con el paso de volumen del instrumento.
  • Período/precio rápido SMA: duración y fuente de precio para el promedio móvil rápido.
  • Período/precio lento SMA: duración y fuente de precio para el promedio móvil lento.
  • Umbral de compra: se requiere una divergencia positiva mínima antes de abrir una posición larga.
  • Umbral de permanencia fuera: divergencia máxima permitida para nuevas entradas; los valores fuera de este rango desactivan el comercio.
  • Take Profit (pips) – objetivo de ganancias expresado en pips. Deshabilitado cuando se establece en cero.
  • Stop Loss (pips) – tolerancia a la pérdida en pips. Deshabilitado cuando se establece en cero.
  • Trailing Stop (pips): distancia de seguimiento activada después de que la operación se vuelve rentable. Deshabilitado cuando es cero.
  • Activador/búfer de punto de equilibrio (pips): se requiere ganancia de pip antes de proteger la posición en el punto de equilibrio y un búfer opcional para compensar el punto de equilibrio del precio de entrada.
  • Beneficio de la cesta/Pérdida de la cesta: umbrales basados en el capital de la cuenta que aplanan todas las posiciones cuando se alcanzan. El control de pérdidas es deshabilitado de forma predeterminada.
  • Hora de inicio/hora de finalización: ventana de negociación en hora local. Cuando ambos valores son iguales la estrategia opera todo el día.
  • Tipo de vela: período de tiempo utilizado tanto para la generación de señales como para la gestión de riesgos.

Lógica de trading

  1. Suscríbase a la serie de velas configuradas y calcule las medias móviles simples rápidas y lentas.
  2. Trabaje solo con velas terminadas para evitar el ruido dentro de la barra y mantenerse cerca del comportamiento original EA.
  3. Realice un seguimiento de la divergencia (rápida menos lenta) calculada en la vela previamente terminada:
    • Si la divergencia es positiva y permanece entre el Umbral de compra y el Umbral de permanencia fuera, envíe una orden de compra de mercado.
    • Si la divergencia es negativa y su valor absoluto permanece dentro del corredor, envíe una orden de venta de mercado.
  4. Las operaciones se ignoran fuera del horario permitido o cuando la estrategia ya tiene una posición abierta.

Gestión de Puestos

  • Control de equilibrio: cuando la ganancia flotante alcanza el nivel de activación, la estrategia almacena un nivel de parada de equilibrio (opcionalmente desplazado por el buffer). Una vela que toca este nivel cierra la posición.
  • Trailing stop: una vez que el beneficio supera la distancia de seguimiento, el nivel de stop sigue el precio más favorable, siempre permaneciendo detrás de él por el número configurado de pips.
  • Take Profit / Stop Loss – salidas fijas calculadas a partir del precio de entrada en unidades de pips.
  • Protección de la cesta: el capital de la cartera se compara con los límites de pérdidas y ganancias configurados. Golpear cualquiera de los límites cierra la posición actual y cancela las órdenes activas, emulando la rutina "CloseEverything" de la versión MQL.

Notas de uso

  • El corredor de divergencia es simétrico: ampliar el umbral de permanencia permite que las operaciones permanezcan abiertas por más tiempo, mientras que lo estrecha aumenta la frecuencia de las señales.
  • Las opciones de fuente de precios corresponden a valores StockSharp CandlePrice, lo que permite utilizar valores de apertura, cierre, mediana o típico. precios como en MetaTrader.
  • La estrategia traza velas, tanto promedios móviles como órdenes ejecutadas en un área del gráfico para monitorear y depurar.
  • Las funciones de administración del dinero dependen de los datos de la cartera. Cuando se ejecuta en un sandbox sin estadísticas de cartera, los controles de la cesta se ignorado automáticamente.
using System;
using System.Linq;

using Ecng.Common;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Divergence-based strategy converted from the Divergence Trader MQL expert advisor.
/// Trades based on the divergence between fast and slow moving averages.
/// </summary>
public class DivergenceTraderBasketStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<decimal> _buyThreshold;
	private readonly StrategyParam<decimal> _stayOutThreshold;
	private readonly StrategyParam<DataType> _candleType;

	private decimal? _previousDifference;
	private decimal _entryPrice;

	public DivergenceTraderBasketStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 7)
			.SetDisplay("Fast SMA Period", "Length of the fast simple moving average.", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 88)
			.SetDisplay("Slow SMA Period", "Length of the slow simple moving average.", "Indicators");

		_buyThreshold = Param(nameof(BuyThreshold), 0.0001m)
			.SetDisplay("Buy Threshold", "Minimum divergence value required before buying.", "Signals");

		_stayOutThreshold = Param(nameof(StayOutThreshold), 1000m)
			.SetDisplay("Stay-Out Threshold", "Upper divergence limit that disables new entries.", "Signals");

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

	public int FastPeriod
	{
		get => _fastPeriod.Value;
		set => _fastPeriod.Value = value;
	}

	public int SlowPeriod
	{
		get => _slowPeriod.Value;
		set => _slowPeriod.Value = value;
	}

	public decimal BuyThreshold
	{
		get => _buyThreshold.Value;
		set => _buyThreshold.Value = value;
	}

	public decimal StayOutThreshold
	{
		get => _stayOutThreshold.Value;
		set => _stayOutThreshold.Value = value;
	}

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <inheritdoc />
	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_previousDifference = null;
		_entryPrice = 0;
	}

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

		_previousDifference = null;
		_entryPrice = 0;

		var fastMa = new SimpleMovingAverage { Length = FastPeriod };
		var slowMa = new SimpleMovingAverage { Length = SlowPeriod };

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

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

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

		var currentDiff = fastValue - slowValue;

		if (_previousDifference == null)
		{
			_previousDifference = currentDiff;
			return;
		}

		var prevDiff = _previousDifference.Value;
		_previousDifference = currentDiff;

		// Manage open position
		if (Position != 0)
		{
			// Exit on divergence sign change
			if (Position > 0 && currentDiff < 0)
			{
				SellMarket();
				_entryPrice = 0;
			}
			else if (Position < 0 && currentDiff > 0)
			{
				BuyMarket();
				_entryPrice = 0;
			}
			return;
		}

		// Entry logic: divergence crosses zero line
		if (currentDiff > 0 && prevDiff <= 0)
		{
			// Bullish divergence crossover
			BuyMarket();
			_entryPrice = candle.ClosePrice;
		}
		else if (currentDiff < 0 && prevDiff >= 0)
		{
			// Bearish divergence crossover
			SellMarket();
			_entryPrice = candle.ClosePrice;
		}
	}
}