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
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.
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).
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;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class trendcapture_strategy(Strategy):
def __init__(self):
super(trendcapture_strategy, self).__init__()
self._ema_period = self.Param("EmaPeriod", 20).SetDisplay("EMA Period", "EMA lookback", "Indicators")
self._adx_period = self.Param("AdxPeriod", 14).SetDisplay("ADX Period", "ADX lookback", "Indicators")
self._adx_threshold = self.Param("AdxThreshold", 30.0).SetDisplay("ADX Threshold", "Minimum ADX for trending", "Levels")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))).SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_fast = 0.0; self._prev_slow = 0.0; self._has_prev = False
@property
def ema_period(self): return self._ema_period.Value
@property
def candle_type(self): return self._candle_type.Value
def OnReseted(self):
super(trendcapture_strategy, self).OnReseted()
self._prev_fast = 0.0; self._prev_slow = 0.0; self._has_prev = False
def OnStarted2(self, time):
super(trendcapture_strategy, self).OnStarted2(time)
self._has_prev = False
fast = ExponentialMovingAverage(); fast.Length = self.ema_period
slow = ExponentialMovingAverage(); slow.Length = self.ema_period * 3
sub = self.SubscribeCandles(self.candle_type)
sub.Bind(fast, slow, self.process_candle).Start()
def process_candle(self, candle, fast, slow):
if candle.State != CandleStates.Finished: return
f = float(fast); s = float(slow)
if not self._has_prev: self._prev_fast = f; self._prev_slow = s; self._has_prev = True; return
if self._prev_fast <= self._prev_slow and f > s and self.Position <= 0:
if self.Position < 0: self.BuyMarket()
self.BuyMarket()
elif self._prev_fast >= self._prev_slow and f < s and self.Position >= 0:
if self.Position > 0: self.SellMarket()
self.SellMarket()
self._prev_fast = f; self._prev_slow = s
def CreateClone(self): return trendcapture_strategy()