La ADX Estrategia de tendencias simple es una adaptación directa del clásico asesor experto MetaTrader "ADX Simple". Sigue la dirección del índice direccional promedio (ADX) comparando los indicadores de movimiento direccional positivo y negativo (DI+ y DI-) y exigiendo que la línea principal ADX aumente antes de abrir cualquier operación. La versión StockSharp mantiene la naturaleza minimalista del sistema original al tiempo que lo adapta a patrones y controles de riesgo de alto nivel API.
Pila de indicadores
Índice direccional promedio (ADX) con período configurable (predeterminado 25).
Proporciona la línea principal ADX utilizada para confirmar la fuerza de la tendencia.
Proporciona valores DI+ y DI- que definen el dominio alcista o bajista.
El plazo se puede seleccionar hasta CandleType (el valor predeterminado es velas de 15 minutos).
Generación de señal
Entrada larga
Espere una vela terminada y un valor ADX finalizado.
Confirme que DI+ esté encima de DI- en la misma barra.
Requerir que la línea principal ADX sea estrictamente mayor que su valor anterior (la tendencia se está fortaleciendo).
Si no existe ninguna posición abierta, envíe una orden de compra de mercado utilizando el volumen de la estrategia.
Entrada corta
Espere una vela terminada y una lectura finalizada de ADX.
Confirme que DI- esté por encima de DI+.
Requerir que la línea principal ADX sea mayor que su valor anterior.
Si es plano, envíe una orden de venta de mercado con el volumen de la estrategia.
Salir de la lógica
Cerrar en Largo: Cuando DI- cruza por encima de DI+ (el impulso de la tendencia se vuelve bajista).
Cerrar en corto: Cuando DI+ cruza por encima de DI- (el impulso de la tendencia se vuelve alcista).
La verificación de pendiente ADX no es necesaria para las salidas, lo que refleja la EA original que cerró posiciones inmediatamente después de un cruce DI.
Gestión de Puestos
La estrategia siempre es plana, larga o corta; nunca ocupa posiciones simultáneas en ambas direcciones.
Las órdenes de mercado se dimensionan utilizando la propiedad incorporada Strategy.Volume (predeterminada 1). Ajuste esta propiedad al configurar la instancia de estrategia para que coincida con el tamaño de su instrumento.
No existen órdenes automáticas de stop-loss o take-profit. El riesgo debe controlarse externamente o modificando la estrategia.
Parámetros
Parámetro
Tipo
Predeterminado
Descripción
AdxPeriod
int
25
Longitud retrospectiva para cálculos ADX, DI+ y DI-.
CandleType
DataType
plazo de 15 minutos
Suscripción de vela utilizada para impulsar los cálculos de indicadores.
Diferencias con la versión original MQL
Gestión del dinero: los EA lotes originales redimensionados según el saldo de la cuenta; la estrategia StockSharp utiliza Strategy.Volume y deja la gestión del capital al entorno de alojamiento.
Seguimiento de pedidos: en lugar de iterar a través de MetaTrader grupos de pedidos, StockSharp se basa en el valor integrado Position.
Manejo de datos: la estrategia ignora las velas inacabadas y solo opera con datos finalizados.
Los enlaces de registro y visualización están disponibles a través de los ayudantes CreateChartArea, DrawCandles y DrawIndicator para facilitar la depuración.
Pautas de uso
Adjunte la estrategia a un instrumento con suficiente movimiento de tendencia (por ejemplo, índices o divisas principales).
Establezca el tipo de vela deseado y la longitud ADX mediante parámetros antes de comenzar la estrategia.
Opcionalmente, habilite la gestión de riesgos a nivel de cartera (stop-outs, límites de reducción) a través de la aplicación de alojamiento.
Supervise los cruces de DI y la pendiente ADX en el visualizador de gráficos para verificar el comportamiento.
Ampliando la estrategia
Agregue filtros de volatilidad (ATR, desviación estándar) para evitar condiciones de baja volatilidad.
Introduzca la automatización de stop-loss/take-profit llamando a StartProtection o una lógica de orden personalizada en ProcessCandle.
Combínelo con filtros de períodos de tiempo más altos suscribiéndose a flujos de velas adicionales.
Esta documentación tiene como objetivo proporcionar una vista completa de la ADX Estrategia de tendencia simple para que pueda implementarla y ampliarla de forma segura dentro del marco StockSharp.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// ADX Simple: Trend following with EMA crossover and ATR momentum filter.
/// </summary>
public class AdxSimpleStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastEmaLength;
private readonly StrategyParam<int> _slowEmaLength;
private readonly StrategyParam<int> _atrLength;
private decimal _prevFast;
private decimal _prevSlow;
private decimal _entryPrice;
public AdxSimpleStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(2).TimeFrame())
.SetDisplay("Candle Type", "Timeframe.", "General");
_fastEmaLength = Param(nameof(FastEmaLength), 10)
.SetDisplay("Fast EMA", "Fast EMA period.", "Indicators");
_slowEmaLength = Param(nameof(SlowEmaLength), 30)
.SetDisplay("Slow EMA", "Slow EMA period.", "Indicators");
_atrLength = Param(nameof(AtrLength), 14)
.SetDisplay("ATR Length", "ATR period.", "Indicators");
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int FastEmaLength
{
get => _fastEmaLength.Value;
set => _fastEmaLength.Value = value;
}
public int SlowEmaLength
{
get => _slowEmaLength.Value;
set => _slowEmaLength.Value = value;
}
public int AtrLength
{
get => _atrLength.Value;
set => _atrLength.Value = value;
}
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0;
_prevSlow = 0;
_entryPrice = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fastEma = new ExponentialMovingAverage { Length = FastEmaLength };
var slowEma = new ExponentialMovingAverage { Length = SlowEmaLength };
var atr = new AverageTrueRange { Length = AtrLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastEma, slowEma, atr, 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 fastVal, decimal slowVal, decimal atrVal)
{
if (candle.State != CandleStates.Finished)
return;
if (_prevFast == 0 || _prevSlow == 0 || atrVal <= 0)
{
_prevFast = fastVal;
_prevSlow = slowVal;
return;
}
var close = candle.ClosePrice;
if (Position > 0)
{
if (fastVal < slowVal && _prevFast >= _prevSlow)
{
SellMarket();
_entryPrice = 0;
}
else if (close <= _entryPrice - atrVal * 2m)
{
SellMarket();
_entryPrice = 0;
}
}
else if (Position < 0)
{
if (fastVal > slowVal && _prevFast <= _prevSlow)
{
BuyMarket();
_entryPrice = 0;
}
else if (close >= _entryPrice + atrVal * 2m)
{
BuyMarket();
_entryPrice = 0;
}
}
if (Position == 0)
{
if (fastVal > slowVal && _prevFast <= _prevSlow)
{
_entryPrice = close;
BuyMarket();
}
else if (fastVal < slowVal && _prevFast >= _prevSlow)
{
_entryPrice = close;
SellMarket();
}
}
_prevFast = fastVal;
_prevSlow = slowVal;
}
}
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.Strategies import Strategy
from StockSharp.Algo.Indicators import ExponentialMovingAverage, AverageTrueRange
class adx_simple_strategy(Strategy):
def __init__(self):
super(adx_simple_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(2))) \
.SetDisplay("Candle Type", "Timeframe.", "General")
self._fast_ema_length = self.Param("FastEmaLength", 10) \
.SetDisplay("Fast EMA", "Fast EMA period.", "Indicators")
self._slow_ema_length = self.Param("SlowEmaLength", 30) \
.SetDisplay("Slow EMA", "Slow EMA period.", "Indicators")
self._atr_length = self.Param("AtrLength", 14) \
.SetDisplay("ATR Length", "ATR period.", "Indicators")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
@property
def CandleType(self):
return self._candle_type.Value
@property
def FastEmaLength(self):
return self._fast_ema_length.Value
@property
def SlowEmaLength(self):
return self._slow_ema_length.Value
@property
def AtrLength(self):
return self._atr_length.Value
def OnStarted2(self, time):
super(adx_simple_strategy, self).OnStarted2(time)
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._fast_ema = ExponentialMovingAverage()
self._fast_ema.Length = self.FastEmaLength
self._slow_ema = ExponentialMovingAverage()
self._slow_ema.Length = self.SlowEmaLength
self._atr = AverageTrueRange()
self._atr.Length = self.AtrLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._fast_ema, self._slow_ema, self._atr, self.ProcessCandle).Start()
def ProcessCandle(self, candle, fast_val, slow_val, atr_val):
if candle.State != CandleStates.Finished:
return
fv = float(fast_val)
sv = float(slow_val)
av = float(atr_val)
if self._prev_fast == 0 or self._prev_slow == 0 or av <= 0:
self._prev_fast = fv
self._prev_slow = sv
return
close = float(candle.ClosePrice)
if self.Position > 0:
if fv < sv and self._prev_fast >= self._prev_slow:
self.SellMarket()
self._entry_price = 0.0
elif close <= self._entry_price - av * 2.0:
self.SellMarket()
self._entry_price = 0.0
elif self.Position < 0:
if fv > sv and self._prev_fast <= self._prev_slow:
self.BuyMarket()
self._entry_price = 0.0
elif close >= self._entry_price + av * 2.0:
self.BuyMarket()
self._entry_price = 0.0
if self.Position == 0:
if fv > sv and self._prev_fast <= self._prev_slow:
self._entry_price = close
self.BuyMarket()
elif fv < sv and self._prev_fast >= self._prev_slow:
self._entry_price = close
self.SellMarket()
self._prev_fast = fv
self._prev_slow = sv
def OnReseted(self):
super(adx_simple_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
def CreateClone(self):
return adx_simple_strategy()