A ADX Simple Trend Strategy é uma versão direta do clássico MetaTrader consultor especialista "ADX Simple". Ele segue a direção do Índice Direcional Médio (ADX) comparando os indicadores de movimento direcional positivo e negativo (DI+ e DI-) e exigindo que a linha principal ADX suba antes de abrir qualquer negociação. A versão StockSharp mantém a natureza minimalista do sistema original enquanto o adapta a padrões e controles de risco API de alto nível.
Pilha de Indicadores
Índice direcional médio (ADX) com período configurável (padrão 25).
Fornece a linha ADX principal usada para confirmar a força da tendência.
Fornece valores DI+ e DI- que definem o domínio de alta ou baixa.
O período pode ser selecionado por meio de CandleType (o padrão é velas de 15 minutos).
Geração de Sinal
Entrada longa
Aguarde uma vela finalizada e um valor ADX finalizado.
Confirme se DI+ está acima de DI- na mesma barra.
Exige que a linha principal ADX seja estritamente maior que seu valor anterior (a tendência é de fortalecimento).
Se não existir nenhuma posição aberta, envie uma ordem de compra a mercado usando o volume da estratégia.
Entrada curta
Aguarde uma vela terminada e uma leitura finalizada de ADX.
Confirme se DI- está acima de DI+.
Exija que a linha principal ADX seja maior que seu valor anterior.
Se estiver estável, envie uma ordem de venda a mercado com o volume da estratégia.
Sair da lógica
Fechar Longo: Quando DI- cruza acima de DI+ (o impulso da tendência se torna de baixa).
Fechar Short: Quando DI+ cruza acima de DI- (o impulso da tendência se torna de alta).
A verificação de inclinação ADX não é necessária para saídas, espelhando o EA original que fechou posições imediatamente após um cruzamento DI.
Gerenciamento de posição
A estratégia é sempre plana, longa ou curta; nunca mantém posições simultâneas em ambas as direções.
As ordens de mercado são dimensionadas usando a propriedade integrada Strategy.Volume (padrão 1). Ajuste esta propriedade ao configurar a instância da estratégia para corresponder ao tamanho do seu instrumento.
Não há ordens automáticas de stop-loss ou take-profit. O risco deve ser controlado externamente ou modificando a estratégia.
Parâmetros
Parâmetro
Tipo
Padrão
Descrição
AdxPeriod
int
25
Comprimento de lookback para cálculos ADX, DI+ e DI-.
CandleType
DataType
Período de 15 minutos
Assinatura de velas usada para conduzir cálculos de indicadores.
Diferenças da versão original MQL
Gestão de dinheiro: os lotes originais EA redimensionados com base no saldo da conta; a estratégia StockSharp usa Strategy.Volume e deixa o gerenciamento de capital para o ambiente de hospedagem.
Acompanhamento de pedidos: em vez de iterar por meio de pools de pedidos MetaTrader, StockSharp depende do valor Position integrado.
Tratamento de dados: a estratégia ignora velas inacabadas e negocia apenas com dados finalizados.
Os ganchos de registro e visualização estão disponíveis por meio dos auxiliares CreateChartArea, DrawCandles e DrawIndicator para facilitar a depuração.
Diretrizes de uso
Anexe a estratégia a um instrumento com movimento de tendência suficiente (por exemplo, principais FX ou índices).
Defina o tipo de vela desejado e o comprimento ADX através de parâmetros antes de iniciar a estratégia.
Opcionalmente, ative o gerenciamento de risco em nível de portfólio (stop-outs, limites de saque) por meio do aplicativo de hospedagem.
Monitore os cruzamentos DI e a inclinação ADX no visualizador de gráfico para verificar o comportamento.
Estendendo a Estratégia
Adicione filtros de volatilidade (ATR, desvio padrão) para evitar condições de baixa volatilidade.
Apresente a automação de stop-loss/take-profit chamando StartProtection ou lógica de pedido personalizada em ProcessCandle.
Combine com filtros de prazo mais altos assinando fluxos de velas adicionais.
Esta documentação tem como objetivo fornecer uma visão abrangente da estratégia de tendência simples do ADX para que você possa implantá-la e estendê-la com segurança dentro da estrutura do 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()