ADX Estrategia cruzada DI del sistema
Descripción general
La estrategia del sistema ADX es la StockSharp conversión del MetaTrader 4 expertos ADX_System.mq4. El EA original compara el
Índice direccional promedio (ADX) con sus componentes +DI y -DI en las dos velas completadas más recientes. Cuando la línea +DI
sube por encima del valor ADX el sistema quiere que sea largo; cuando la línea -DI supera el valor ADX, quiere ser corta. el
El puerto StockSharp reproduce este comportamiento almacenando los valores del indicador de las dos velas terminadas anteriores para que la lógica
refleja las llamadas iADX(..., shift=1/2) utilizadas en el código MetaTrader.
Sólo puede haber una posición abierta a la vez. La estrategia envía órdenes de mercado para entradas y salidas, igualando el billete único.
lógica de MetaTrader cuentas de compensación. La gestión de riesgos refleja el asesor experto original: toma de ganancias fija y stop-loss
Los niveles se expresan en puntos en relación con el precio de entrada promedio, y un trailing stop opcional puede asegurar ganancias una vez que el
la posición evoluciona favorablemente.
Lógica comercial
- Suscríbase al período de tiempo configurado (
CandleType) y procese solo velas terminadas para evitar decisiones dentro de la barra.
- Alimente un indicador
AverageDirectionalIndex con los datos de la vela y espere hasta que el indicador proporcione sus ADX, +DI y -DI.
valores.
- Almacene en caché las lecturas del indicador de las dos velas terminadas más recientes para que la estrategia pueda hacer referencia a las velas "actuales" y
valores "anteriores" exactamente iguales a la implementación MetaTrader.
- Entrada larga: si el ADX (
shift = 2) más antiguo está por debajo del ADX (shift = 1) más reciente, el +DI más antiguo está por debajo del más antiguo
ADX, y el +DI más reciente está por encima del ADX más reciente, envíe una orden de compra de mercado.
- Entrada breve: si aparecen las mismas condiciones para el componente -DI (antiguo -DI debajo del antiguo ADX, nuevo -DI encima del nuevo ADX), envíe un
orden de venta de mercado.
- Salida larga: cierra la posición larga cuando el ADX comienza a caer y +DI vuelve a cruzar por debajo de él, cuando el valor configurado
se alcanza la toma de ganancias o el stop-loss, o cuando se supera el trailing stop.
- Salida corta: refleja la lógica de salida larga usando -DI junto con los controles de riesgo.
- Actualice el historial del indicador en caché después de cada vela para que la siguiente señal utilice el último par
shift = 1/2.
Gestión de riesgos
TakeProfitPoints y StopLossPoints describen distancias en puntos de estilo MetaTrader. Se convierten a unidades de precio reales.
usando Security.PriceStep cuando esté disponible; de lo contrario, el valor bruto se trata como un delta de precio absoluto.
- El trailing stop (
TrailingStopPoints) se activa solo después de que la posición gana al menos la distancia configurada desde el
precio de entrada. Una vez activo, se mueve en dirección a la ganancia y cierra la posición cuando el precio cruza el nivel final.
- Todas las salidas (inversión de indicador, toma de ganancias, stop-loss, trailing stop) utilizan órdenes de mercado, por lo que la posición se aplana.
inmediatamente, imitando el comportamiento
OrderClose de la fuente EA.
Parámetros
| Nombre |
Tipo |
Predeterminado |
Descripción |
CandleType |
DataType |
marco de tiempo de 1 minuto |
Plazo primario procesado por la estrategia. |
AdxPeriod |
int |
14 |
Número de velas utilizadas para calcular los componentes ADX y DI. |
TradeVolume |
decimal |
1 |
Tamaño de lote utilizado para cada orden de mercado. |
TakeProfitPoints |
decimal |
100 |
Distancia de obtención de beneficios en puntos respecto al precio de entrada. |
StopLossPoints |
decimal |
30 |
Distancia del stop-loss en puntos con respecto al precio de entrada. |
TrailingStopPoints |
decimal |
0 |
Distancia de trailing-stop opcional en puntos. Establezca en cero para desactivar el seguimiento. |
- MetaTrader gestiona tickets individuales mientras que StockSharp trabaja con una única posición neta. Por lo tanto, la conversión cierra el
posición actual antes de emitir una nueva orden de entrada cuando la señal cambia.
- El EA original se basó en
Point para convertir puntos en distancias de precios. El puerto StockSharp usa Security.PriceStep cuando
es conocido; de lo contrario, la distancia se trata como unidades de precio bruto, por lo que es posible que deba ajustar los valores predeterminados para los instrumentos con
pasos de precios no convencionales.
- MetaTrader aplica paradas dinámicas modificando el orden existente. StockSharp cierra la posición con una orden de mercado cuando el
Se viola el trailing stop, que es funcionalmente equivalente pero más simple dentro del modelo de compensación.
Consejos de uso
- Asegúrese de que el volumen de la estrategia (
TradeVolume) se alinee con el paso del lote del instrumento. El constructor también asigna este valor a
Strategy.Volume, por lo que los métodos auxiliares utilizan el tamaño comercial esperado.
- Aumente
TakeProfitPoints y StopLossPoints si opera con instrumentos con rangos promedio más grandes o incrementos de precios más pequeños.
- Agregue la estrategia a un gráfico para visualizar las velas, el indicador ADX y las operaciones ejecutadas, lo que ayuda a verificar esas señales.
ocurre exactamente cuando +DI o -DI cruza por encima de la línea ADX.
Indicadores
AverageDirectionalIndex (proporciona ADX junto con los componentes +DI y -DI).
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// ADX System DI Cross: trend-following using dual EMA crossover
/// (proxy for +DI/-DI cross) with ATR-based volatility filter.
/// </summary>
public class AdxSystemDiCrossStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastLength;
private readonly StrategyParam<int> _slowLength;
private readonly StrategyParam<int> _atrLength;
private readonly StrategyParam<decimal> _atrThreshold;
private decimal _prevFast;
private decimal _prevSlow;
private decimal _entryPrice;
public AdxSystemDiCrossStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame())
.SetDisplay("Candle Type", "Timeframe.", "General");
_fastLength = Param(nameof(FastLength), 10)
.SetDisplay("Fast EMA", "Fast EMA period (proxy for +DI).", "Indicators");
_slowLength = Param(nameof(SlowLength), 20)
.SetDisplay("Slow EMA", "Slow EMA period (proxy for -DI).", "Indicators");
_atrLength = Param(nameof(AtrLength), 14)
.SetDisplay("ATR Length", "ATR period for trend strength.", "Indicators");
_atrThreshold = Param(nameof(AtrThreshold), 50m)
.SetDisplay("ATR Threshold", "Min ATR value for entry.", "Indicators");
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int FastLength
{
get => _fastLength.Value;
set => _fastLength.Value = value;
}
public int SlowLength
{
get => _slowLength.Value;
set => _slowLength.Value = value;
}
public int AtrLength
{
get => _atrLength.Value;
set => _atrLength.Value = value;
}
public decimal AtrThreshold
{
get => _atrThreshold.Value;
set => _atrThreshold.Value = value;
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0;
_prevSlow = 0;
_entryPrice = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fast = new ExponentialMovingAverage { Length = FastLength };
var slow = new ExponentialMovingAverage { Length = SlowLength };
var atr = new AverageTrueRange { Length = AtrLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, atr, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fast);
DrawIndicator(area, slow);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal fastVal, decimal slowVal, decimal atrVal)
{
if (candle.State != CandleStates.Finished)
return;
if (_prevFast == 0 || _prevSlow == 0)
{
_prevFast = fastVal;
_prevSlow = slowVal;
return;
}
var bullishCross = _prevFast <= _prevSlow && fastVal > slowVal;
var bearishCross = _prevFast >= _prevSlow && fastVal < slowVal;
// Exit on opposite cross
if (Position > 0 && bearishCross)
{
SellMarket();
_entryPrice = 0;
}
else if (Position < 0 && bullishCross)
{
BuyMarket();
_entryPrice = 0;
}
// Entry on cross + volatility filter
if (Position == 0 && atrVal >= AtrThreshold)
{
if (bullishCross)
{
_entryPrice = candle.ClosePrice;
BuyMarket();
}
else if (bearishCross)
{
_entryPrice = candle.ClosePrice;
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.Indicators import ExponentialMovingAverage, AverageTrueRange
from StockSharp.Algo.Strategies import Strategy
class adx_system_di_cross_strategy(Strategy):
"""
ADX System DI Cross: trend-following using dual EMA crossover
(proxy for +DI/-DI cross) with ATR-based volatility filter.
"""
def __init__(self):
super(adx_system_di_cross_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(15))) \
.SetDisplay("Candle Type", "Timeframe.", "General")
self._fast_length = self.Param("FastLength", 10) \
.SetDisplay("Fast EMA", "Fast EMA period (proxy for +DI).", "Indicators")
self._slow_length = self.Param("SlowLength", 20) \
.SetDisplay("Slow EMA", "Slow EMA period (proxy for -DI).", "Indicators")
self._atr_length = self.Param("AtrLength", 14) \
.SetDisplay("ATR Length", "ATR period for trend strength.", "Indicators")
self._atr_threshold = self.Param("AtrThreshold", 50.0) \
.SetDisplay("ATR Threshold", "Min ATR value for entry.", "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
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def FastLength(self):
return self._fast_length.Value
@FastLength.setter
def FastLength(self, value):
self._fast_length.Value = value
@property
def SlowLength(self):
return self._slow_length.Value
@SlowLength.setter
def SlowLength(self, value):
self._slow_length.Value = value
@property
def AtrLength(self):
return self._atr_length.Value
@AtrLength.setter
def AtrLength(self, value):
self._atr_length.Value = value
@property
def AtrThreshold(self):
return self._atr_threshold.Value
@AtrThreshold.setter
def AtrThreshold(self, value):
self._atr_threshold.Value = value
def OnReseted(self):
super(adx_system_di_cross_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
def OnStarted2(self, time):
super(adx_system_di_cross_strategy, self).OnStarted2(time)
fast = ExponentialMovingAverage()
fast.Length = self.FastLength
slow = ExponentialMovingAverage()
slow.Length = self.SlowLength
atr = AverageTrueRange()
atr.Length = self.AtrLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast, slow, atr, self.ProcessCandle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast)
self.DrawIndicator(area, slow)
self.DrawOwnTrades(area)
def ProcessCandle(self, candle, fast_val, slow_val, atr_val):
if candle.State != CandleStates.Finished:
return
if self._prev_fast == 0 or self._prev_slow == 0:
self._prev_fast = fast_val
self._prev_slow = slow_val
return
bullish_cross = self._prev_fast <= self._prev_slow and fast_val > slow_val
bearish_cross = self._prev_fast >= self._prev_slow and fast_val < slow_val
# Exit on opposite cross
if self.Position > 0 and bearish_cross:
self.SellMarket()
self._entry_price = 0.0
elif self.Position < 0 and bullish_cross:
self.BuyMarket()
self._entry_price = 0.0
# Entry on cross + volatility filter
if self.Position == 0 and atr_val >= self.AtrThreshold:
if bullish_cross:
self._entry_price = float(candle.ClosePrice)
self.BuyMarket()
elif bearish_cross:
self._entry_price = float(candle.ClosePrice)
self.SellMarket()
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
"""!! REQUIRED!! Creates a new instance of the strategy."""
return adx_system_di_cross_strategy()