A estratégia Exp Digital MACD recria o comportamento do consultor especialista original do MetaTrader 5 "Exp_Digital_MACD" dentro do framework StockSharp. O sistema escuta candles completados de um período dedicado e reage à posição relativa e inclinação de um oscilador estilo MACD. Quatro modos de operação reproduzem as regras de decisão do código fonte:
Breakdown – opera transições da linha zero do oscilador.
MACD Twist – observa uma reversão na inclinação da linha MACD.
Signal Twist – usa a curva da linha de sinal em si como confirmação.
MACD Disposition – procura pelo histograma MACD cruzar acima ou abaixo de sua linha de sinal.
Como o StockSharp não fornece o filtro proprietário "Digital MACD", a estratégia emprega o indicador padrão MovingAverageConvergenceDivergenceSignal. Os valores padrão (EMA rápida 12, EMA lenta 26, sinal 5) aproximam a configuração original onde o comprimento de suavização do sinal era igual a cinco. A estratégia processa apenas candles finalizados e mantém um histórico deslizante curto em campos privados para espelhar o comportamento SignalBar = 1 da implementação MQL.
Parâmetros
Mode – seleciona um dos quatro algoritmos de trading descritos acima. Padrão: MacdTwist.
FastPeriod – comprimento da EMA rápida usada pelo MACD. Padrão: 12.
SlowPeriod – comprimento da EMA lenta usada pelo MACD. Padrão: 26.
SignalPeriod – comprimento da EMA de suavização do sinal. Padrão: 5 para corresponder ao consultor especialista original.
CandleType – período para a assinatura de candle. Padrão: candles de 4h.
OrderVolume – número de contratos ou lotes enviados em cada ordem de mercado.
StopLossPoints / TakeProfitPoints – compensações de proteção expressas em passos de preço do ativo. São ativadas quando o ativo expõe um valor Step válido; definir como zero para desabilitar.
EnableLongEntry / EnableShortEntry – alternadores que permitem ou proíbem a abertura de novas posições compradas ou vendidas.
EnableLongExit / EnableShortExit – alternadores que permitem à estratégia fechar posições existentes na direção correspondente.
Lógica de trading
O algoritmo trabalha sobre o valor de fechamento de cada candle:
Breakdown: Se o valor MACD de duas barras atrás estava acima de zero, a estratégia opcionalmente fecha posições vendidas e abre uma operação comprada quando a barra seguinte cai de volta a zero ou abaixo. Inversamente, quando o MACD de duas barras atrás estava abaixo de zero, o sistema fecha comprados e abre vendidos se a barra seguinte sobe para a linha zero ou acima. Isso espelha a lógica contrária à linha zero no consultor especialista.
MACD Twist: Acompanha três leituras sequenciais de MACD. Um sinal comprado aparece quando a linha forma um mínimo local (value[2] > value[1] e value[0] > value[1]). Um máximo local gera um sinal vendido. As saídas seguem o twist oposto.
Signal Twist: Aplica a mesma detecção de ponto de viragem ao buffer da linha de sinal.
MACD Disposition: Trabalha com os buffers MACD e de sinal. Se o MACD anteriormente estava acima da linha de sinal mas a observação seguinte cai de volta para ela ou abaixo, a estratégia entra comprada e fecha vendidas. A transição oposta leva a entradas vendidas e saídas compradas.
Cada entrada usa uma ordem de mercado com tamanho OrderVolume + |posição atual| para que uma reversão feche a exposição existente e estabeleça uma nova posição em uma única instrução. Sinais de saída emitem ordens de mercado que apenas aplainam a posição aberta.
Gerenciamento de risco
StartProtection é habilitado uma vez que a estratégia inicia. Quando StopLossPoints ou TakeProfitPoints estão definidos acima de zero e o passo do ativo é conhecido, as ordens de proteção correspondentes são configuradas em termos absolutos de preço. Manter os parâmetros em zero desabilita a proteção automática.
Notas de implementação
A estratégia avalia apenas o candle completado mais recente, equivalente a SignalBar = 1 na versão MQL.
A implementação de MACD do StockSharp difere do Digital MACD proprietário. Os usuários podem ajustar os comprimentos de EMA para aproximar melhor o comportamento original se desejado.
Todos os comentários dentro do arquivo fonte C# são fornecidos em inglês conforme solicitado.
Uso
Anexar a estratégia a um portfólio e um ativo que fornece o período de candle necessário.
Ajustar os parâmetros para corresponder ao símbolo desejado e às características de volatilidade.
Iniciar a estratégia; ela se inscreverá automaticamente nos candles configurados, processará os valores MACD e colocará ordens de mercado de acordo com o modo selecionado.
Monitorar os logs ou a saída gráfica opcional para acompanhar os valores do indicador e as mudanças de posição.
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>
/// Digital MACD strategy using fast/slow EMA crossover (MACD concept).
/// Trades on MACD line zero crossovers.
/// </summary>
public class ExpDigitalMacdStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private decimal? _prevMacd;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int FastPeriod
{
get => _fastPeriod.Value;
set => _fastPeriod.Value = value;
}
public int SlowPeriod
{
get => _slowPeriod.Value;
set => _slowPeriod.Value = value;
}
public ExpDigitalMacdStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 12)
.SetGreaterThanZero()
.SetDisplay("Fast Period", "Fast EMA for MACD", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 26)
.SetGreaterThanZero()
.SetDisplay("Slow Period", "Slow EMA for MACD", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevMacd = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevMacd = null;
var fastEma = new ExponentialMovingAverage { Length = FastPeriod };
var slowEma = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastEma, slowEma, 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 fast, decimal slow)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevMacd = fast - slow;
return;
}
var macd = fast - slow;
if (_prevMacd == null)
{
_prevMacd = macd;
return;
}
// MACD crosses above zero → buy
if (_prevMacd.Value <= 0 && macd > 0)
{
if (Position < 0)
BuyMarket();
if (Position <= 0)
BuyMarket();
}
// MACD crosses below zero → sell
else if (_prevMacd.Value >= 0 && macd < 0)
{
if (Position > 0)
SellMarket();
if (Position >= 0)
SellMarket();
}
_prevMacd = macd;
}
}
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 exp_digital_macd_strategy(Strategy):
def __init__(self):
super(exp_digital_macd_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._fast_period = self.Param("FastPeriod", 12) \
.SetDisplay("Fast Period", "Fast EMA for MACD", "Indicators")
self._slow_period = self.Param("SlowPeriod", 26) \
.SetDisplay("Slow Period", "Slow EMA for MACD", "Indicators")
self._prev_macd = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def FastPeriod(self):
return self._fast_period.Value
@property
def SlowPeriod(self):
return self._slow_period.Value
def OnReseted(self):
super(exp_digital_macd_strategy, self).OnReseted()
self._prev_macd = None
def OnStarted2(self, time):
super(exp_digital_macd_strategy, self).OnStarted2(time)
self._prev_macd = None
fast_ema = ExponentialMovingAverage()
fast_ema.Length = self.FastPeriod
slow_ema = ExponentialMovingAverage()
slow_ema.Length = self.SlowPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast_ema, slow_ema, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast_ema)
self.DrawIndicator(area, slow_ema)
self.DrawOwnTrades(area)
def _on_process(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fv = float(fast_value)
sv = float(slow_value)
macd = fv - sv
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_macd = macd
return
if self._prev_macd is None:
self._prev_macd = macd
return
# MACD crosses above zero
if self._prev_macd <= 0 and macd > 0:
if self.Position < 0:
self.BuyMarket()
if self.Position <= 0:
self.BuyMarket()
# MACD crosses below zero
elif self._prev_macd >= 0 and macd < 0:
if self.Position > 0:
self.SellMarket()
if self.Position >= 0:
self.SellMarket()
self._prev_macd = macd
def CreateClone(self):
return exp_digital_macd_strategy()