A Estratégia de ADX MACD Deev é um port StockSharp do consultor especialista MetaTrader com o mesmo nome. Combina o sinal de força de tendência do Índice Direcional Médio (ADX) com a confirmação de momentum da Convergência/Divergência de Médias Móveis (MACD). A estratégia opera apenas quando ambos os indicadores concordam na direção do mercado e pode opcionalmente assegurar lucros através de trailing stops e saídas parciais de posição.
Como funciona
Preparação de indicadores
ADX é calculado com um período de médio configurável. A estratégia rastreia os valores mais recentes de ADX e requer que se movam consistentemente em uma direção antes de permitir uma negociação.
MACD usa EMAs rápidas, lentas e de sinal exponenciais configuráveis. O histograma e a linha de sinal devem mostrar conjuntamente um crescimento sustentado para comprados ou um declínio sustentado para vendidos.
Lógica de entrada
Entradas compradas: acionadas quando o histograma MACD excede o limiar MACD Minimum (pips), tanto o histograma MACD quanto a linha de sinal aumentam pelo número selecionado de barras, e ADX permanece acima da força necessária enquanto também sobe.
Entradas vendidas: acionadas quando o histograma MACD está abaixo do limiar negativo, tanto o histograma MACD quanto a linha de sinal declinam sobre o intervalo selecionado, e ADX permanece acima do mínimo enquanto decresce.
Apenas uma posição pode estar aberta por vez.
Gestão de risco
Os níveis iniciais de stop-loss e take-profit são colocados em unidades de preço derivadas do instrumento PriceStep e das distâncias de pip escolhidas.
Um trailing stop pode seguir posições rentáveis assim que o preço avança Trailing Stop + Trailing Step pips.
Quando Take Half Profit está habilitado, a estratégia fecha metade da posição atual no nível de take-profit e deixa o restante correr com o trailing stop.
Parâmetros
Grupo
Nome
Descrição
Trading
Order Volume
Volume de cada nova ordem de mercado.
Risco
Stop Loss (pips)
Deslocamento inicial do stop-loss desde a entrada.
Risco
Take Profit (pips)
Deslocamento inicial do take-profit desde a entrada.
Risco
Trailing Stop (pips)
Distância do trailing stop. Definir como zero para desabilitar o trailing.
Risco
Trailing Step (pips)
Movimento de preço adicional antes do trailing stop se mover novamente.
Risco
Take Half Profit
Habilita saída parcial quando o nível de take-profit é atingido.
Indicadores
ADX Period
Período de médio do ADX.
Indicadores
ADX Bars Interval
Número de barras ADX recentes que devem seguir uma tendência em uma direção.
Indicadores
ADX Minimum
Valor mínimo de ADX necessário para entradas.
Indicadores
MACD Fast EMA
Comprimento da EMA rápida usada pelo MACD.
Indicadores
MACD Slow EMA
Comprimento da EMA lenta usada pelo MACD.
Indicadores
MACD Signal EMA
Comprimento da EMA de sinal usada pelo MACD.
Indicadores
MACD Bars Interval
Número de barras MACD que devem se alinhar na mesma direção.
Indicadores
MACD Minimum (pips)
Magnitude mínima do MACD convertida para pips.
Geral
Candle Type
Tipo de vela ou período usado para cálculos.
Notas de uso
A estratégia requer instrumentos com um PriceStep válido. Se PriceStep for zero, os limiares baseados em pips revertem para valores brutos de MACD.
O arredondamento de volume para saídas parciais segue o VolumeStep do instrumento.
Ajustes do trailing stop são avaliados apenas em velas fechadas.
A estratégia usa bindings de API de alto nível (SubscribeCandles().BindEx(...)) e não depende de polling manual de valores de indicadores.
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class AdxMacdDeevStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _stopLossPoints;
private readonly StrategyParam<int> _takeProfitPoints;
private ExponentialMovingAverage _fast;
private ExponentialMovingAverage _slow;
private decimal _prevFast;
private decimal _prevSlow;
private decimal _entryPrice;
private int _cooldown;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }
public AdxMacdDeevStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 12).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
}
protected override void OnReseted()
{
base.OnReseted();
_fast = null; _slow = null;
_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_fast = new ExponentialMovingAverage { Length = FastPeriod };
_slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
subscription.Bind(_fast, _slow, ProcessCandle);
subscription.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished) return;
if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }
var close = candle.ClosePrice;
var step = Security?.PriceStep ?? 1m;
if (Position > 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
else if (Position < 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }
_prevFast = fastValue; _prevSlow = slowValue;
}
}
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 CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
from datatype_extensions import *
class adx_macd_deev_strategy(Strategy):
"""
ADX MACD Deev: dual EMA crossover with stop-loss/take-profit in price steps.
"""
def __init__(self):
super(adx_macd_deev_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 12) \
.SetGreaterThanZero() \
.SetDisplay("Fast Period", "Fast EMA period", "Indicator")
self._slow_period = self.Param("SlowPeriod", 50) \
.SetGreaterThanZero() \
.SetDisplay("Slow Period", "Slow EMA period", "Indicator")
self._stop_loss_points = self.Param("StopLossPoints", 200) \
.SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk")
self._take_profit_points = self.Param("TakeProfitPoints", 400) \
.SetDisplay("Take Profit", "Take-profit in price steps", "Risk")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
@property
def FastPeriod(self):
return self._fast_period.Value
@FastPeriod.setter
def FastPeriod(self, value):
self._fast_period.Value = value
@property
def SlowPeriod(self):
return self._slow_period.Value
@SlowPeriod.setter
def SlowPeriod(self, value):
self._slow_period.Value = value
@property
def StopLossPoints(self):
return self._stop_loss_points.Value
@StopLossPoints.setter
def StopLossPoints(self, value):
self._stop_loss_points.Value = value
@property
def TakeProfitPoints(self):
return self._take_profit_points.Value
@TakeProfitPoints.setter
def TakeProfitPoints(self, value):
self._take_profit_points.Value = value
def OnReseted(self):
super(adx_macd_deev_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
def OnStarted2(self, time):
super(adx_macd_deev_strategy, self).OnStarted2(time)
fast = ExponentialMovingAverage()
fast.Length = self.FastPeriod
slow = ExponentialMovingAverage()
slow.Length = self.SlowPeriod
subscription = self.SubscribeCandles(tf(5))
subscription.Bind(fast, slow, self.ProcessCandle).Start()
def ProcessCandle(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_fast = fast_value
self._prev_slow = slow_value
return
close = float(candle.ClosePrice)
step = 1.0
if self.Position > 0 and self._entry_price > 0:
if self.StopLossPoints > 0 and close <= self._entry_price - self.StopLossPoints * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_value
self._prev_slow = slow_value
return
if self.TakeProfitPoints > 0 and close >= self._entry_price + self.TakeProfitPoints * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_value
self._prev_slow = slow_value
return
elif self.Position < 0 and self._entry_price > 0:
if self.StopLossPoints > 0 and close >= self._entry_price + self.StopLossPoints * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_value
self._prev_slow = slow_value
return
if self.TakeProfitPoints > 0 and close <= self._entry_price - self.TakeProfitPoints * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_value
self._prev_slow = slow_value
return
if self._prev_fast <= self._prev_slow and fast_value > slow_value and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._entry_price = close
self._cooldown = 100
elif self._prev_fast >= self._prev_slow and fast_value < slow_value and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._entry_price = close
self._cooldown = 100
self._prev_fast = fast_value
self._prev_slow = slow_value
def CreateClone(self):
"""!! REQUIRED!! Creates a new instance of the strategy."""
return adx_macd_deev_strategy()