Ver en GitHub

3874 Estrategia de captura de tendencias

Descripción general

La Estrategia de captura de tendencias es una versión StockSharp de alto nivel del MetaTrader asesor experto MQL/7772/Trendcapture.mq4. El EA original observa la dirección de la tendencia Parabolic SAR y espera a que un entorno ADX débil ingrese a nuevas posiciones. Después de cada operación cerrada, decide si mantiene o cambia la dirección de la operación dependiendo de la ganancia obtenida, y una vez que una posición abierta gana algunos puntos, tira del stop hasta el punto de equilibrio.

Este puerto mantiene el comportamiento intacto y depende de los asistentes de pedidos y los enlaces de indicadores de StockSharp. Todas las señales se procesan en velas completas de un período de tiempo configurable.

Lógica de trading

  1. Configuración del indicador
    • Parabolic SAR (ParabolicSar) con paso y límite de aceleración configurables.
    • Índice direccional promedio (AverageDirectionalIndex) para el valor de fuerza de la tendencia principal.
  2. Selección de entrada
    • Sólo se puede abrir una posición a la vez.
    • Se permite una entrada larga cuando:
      • La dirección deseada (derivada de la última operación cerrada) apunta a la compra.
      • La vela actual cierra por encima del valor SAR.
      • La línea principal ADX está debajo de 20, lo que indica el régimen de alcance requerido por el código original.
    • Una entrada corta refleja las reglas (la dirección deseada apunta a la venta, precio de cierre por debajo de SAR, ADX por debajo de 20).
  3. Gestión de salida
    • Cada vez que se ejecuta, la estrategia envía órdenes de limitación de pérdidas y toma de ganancias a distancias StopLossPoints y TakeProfitPoints (convertidas a través del paso del precio del valor).
    • Cuando el beneficio flotante alcanza GuardPoints, el stop activo se vuelve a emitir al precio de entrada para fijar un suelo de equilibrio.
    • Las operaciones cerradas activan una actualización de dirección: las operaciones rentables mantienen el mismo sesgo, las operaciones perdedoras o planas lo invierten, reproduciendo la verificación OrderProfit() del experto.

Parámetros

Parámetro Descripción Predeterminado
CandleType Tipo de datos de vela utilizado para los cálculos del indicador. plazo de 1 hora
SarStep Factor de aceleración inicial de Parabolic SAR. 0.02
SarMax Factor de aceleración máximo para Parabolic SAR. 0.2
AdxPeriod Período de suavizado de ADX. 14
TakeProfitPoints Distancia de obtención de beneficios expresada en incrementos de precio. 180
StopLossPoints Distancia de stop-loss expresada en pasos de precio. 50
GuardPoints Umbral de beneficio (en pasos de precio) requerido antes de mover el tope al punto de equilibrio. 5
MaximumRisk factor de escala de volumen; 0.03 reproduce el tamaño del lote original. 0.03

Notas de uso

  • Asegúrese de que el valor seleccionado exponga PriceStep (o al menos MinStep) para que las distancias de puntos se conviertan en valores de precios correctamente.
  • La propiedad base Volume representa el tamaño de lote utilizado cuando MaximumRisk es igual a 0.03. Al aumentar el factor de riesgo, el volumen enviado se escala proporcionalmente.
  • Debido a que EA cotiza en el mercado e inmediatamente coloca órdenes de protección, no quedan entradas pendientes en el libro cuando la estrategia está inactiva.
  • La guardia de equilibrio cancela y vuelve a emitir el stop de protección al precio de entrada; esto refleja la llamada OrderModify original que movió el stop-loss al punto de equilibrio.

Archivos

  • CS/TrendcaptureStrategy.cs – implementación StockSharp de alto nivel de Trendcapture EA.
  • README_zh.md – Traducción al chino de este documento.
  • README_ru.md – Traducción al ruso de este documento.
using System;
using System.Collections.Generic;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Trendcapture strategy - EMA trend with ADX strength filter.
/// Buys when close is above EMA and ADX indicates trending.
/// Sells when close is below EMA and ADX indicates trending.
/// </summary>
public class TrendcaptureStrategy : Strategy
{
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<int> _adxPeriod;
	private readonly StrategyParam<decimal> _adxThreshold;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevClose;
	private decimal _prevEma;
	private bool _hasPrev;

	public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
	public int AdxPeriod { get => _adxPeriod.Value; set => _adxPeriod.Value = value; }
	public decimal AdxThreshold { get => _adxThreshold.Value; set => _adxThreshold.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public TrendcaptureStrategy()
	{
		_emaPeriod = Param(nameof(EmaPeriod), 20)
			.SetDisplay("EMA Period", "EMA lookback", "Indicators");
		_adxPeriod = Param(nameof(AdxPeriod), 14)
			.SetDisplay("ADX Period", "ADX lookback", "Indicators");
		_adxThreshold = Param(nameof(AdxThreshold), 30m)
			.SetDisplay("ADX Threshold", "Minimum ADX for trending", "Levels");
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
	protected override void OnReseted() { base.OnReseted(); _prevClose = 0m; _prevEma = 0m; _hasPrev = false; }

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

		var fast = new ExponentialMovingAverage { Length = EmaPeriod };
		var slow = new ExponentialMovingAverage { Length = EmaPeriod * 3 };

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

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

		if (!_hasPrev) { _prevClose = fast; _prevEma = slow; _hasPrev = true; return; }

		if (_prevClose <= _prevEma && fast > slow && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
		}
		else if (_prevClose >= _prevEma && fast < slow && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
		}

		_prevClose = fast; _prevEma = slow;
	}
}