Esta estratégia recria o consultor especialista MetaTrader 5 "Divergência EA pip sl tp" na estrutura StockSharp. O algoritmo procura divergências clássicas entre a ação do preço e o histograma MACD e, em seguida, valida o sinal com um filtro oscilador Stochastic de sobrecompra/sobrevenda antes de abrir negociações de reversão.
Lógica de negociação
Assine as velas do período principal selecionadas pelo parâmetro CandleType.
Calcule o histograma MACD (MACD line - Signal line) e os valores Stochastic %K/%D em cada vela concluída.
Acompanhe os dois últimos máximos e mínimos dos valores de preço e histograma.
Divergência de baixa: uma nova máxima de preço mais alta acompanhada por um pico de histograma MACD mais baixo e Stochastic %K acima de StochasticUpperLevel aciona uma posição curta ou reverte uma posição comprada existente.
Divergência de alta: uma nova mínima de preço mais baixa com um fundo de histograma MACD mais alto e %K abaixo de StochasticLowerLevel abre ou reverte para uma posição longa.
As proteções opcionais TakeProfitSteps e StopLossSteps são convertidas em unidades de passo StockSharp e ativadas uma vez quando a estratégia é iniciada.
Notas de implementação
Construído com StockSharp API de alto nível usando uma única assinatura de vela vinculada aos indicadores MovingAverageConvergenceDivergenceSignal e StochasticOscillator.
Mantém o estado de divergência sem chamar ajudantes do indicador GetValue, obedecendo às diretrizes de conversão.
A integração do gráfico exibe velas de preço, MACD e Stochastic linhas quando uma área do gráfico está disponível.
As posições são invertidas adicionando o tamanho absoluto da posição atual à base Volume, garantindo mudanças de direção imediatas após divergências confirmadas.
Parâmetros
Parâmetro
Descrição
Padrão
CandleType
Prazo usado para cálculos de divergência.
Velas de 1 hora
MacdFastLength, MacdSlowLength, MacdSignalLength
MACD EMA comprimentos replicando as entradas originais EA.
26/12/9
MacdDivergenceThreshold
Diferença mínima do histograma entre oscilações consecutivas necessária para confirmar a divergência.
0,0005
StochasticLength
Período %K rápido do oscilador Stochastic.
50
StochasticSlowK, StochasticSlowD
Comprimentos de suavização %K/%D adicionais espelhando a configuração EA.
9/9
StochasticUpperLevel, StochasticLowerLevel
Filtros de sobrecompra e sobrevenda validando configurações de baixa/alta.
80/20
TakeProfitSteps, StopLossSteps
Distâncias de proteção opcionais expressas em etapas de preço (0 desativa o nível).
50
Uso
Anexe a estratégia a um conector StockSharp com uma segurança que suporte o período de tempo selecionado.
Configure o tamanho da posição através da propriedade base Volume e ajuste as configurações do indicador conforme desejado.
Inicie a estratégia - os pedidos serão gerados automaticamente sempre que a divergência e as condições Stochastic forem satisfeitas.
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Simplified from "Divergence MACD Stochastic" MetaTrader expert.
/// Uses MACD histogram divergence (price vs histogram) with RSI confirmation.
/// MACD is computed manually from two EMAs.
/// </summary>
public class DivergenceMacdStochasticStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _macdFast;
private readonly StrategyParam<int> _macdSlow;
private readonly StrategyParam<int> _rsiPeriod;
// Manual EMA for MACD
private decimal _fastEma;
private decimal _slowEma;
private bool _emaInitialized;
private int _barCount;
private decimal _fastMultiplier;
private decimal _slowMultiplier;
private readonly decimal[] _macdWindow = new decimal[DivergenceLookback];
private readonly decimal[] _priceWindow = new decimal[DivergenceLookback];
private int _windowCount;
private int _windowIndex;
private const int DivergenceLookback = 10;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int MacdFast
{
get => _macdFast.Value;
set => _macdFast.Value = value;
}
public int MacdSlow
{
get => _macdSlow.Value;
set => _macdSlow.Value = value;
}
public int RsiPeriod
{
get => _rsiPeriod.Value;
set => _rsiPeriod.Value = value;
}
public DivergenceMacdStochasticStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for divergence detection", "General");
_macdFast = Param(nameof(MacdFast), 20)
.SetGreaterThanZero()
.SetDisplay("MACD Fast", "Fast EMA length", "Indicators");
_macdSlow = Param(nameof(MacdSlow), 50)
.SetGreaterThanZero()
.SetDisplay("MACD Slow", "Slow EMA length", "Indicators");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period for confirmation", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_windowCount = 0;
_windowIndex = 0;
_emaInitialized = false;
_barCount = 0;
_fastMultiplier = 2m / (MacdFast + 1);
_slowMultiplier = 2m / (MacdSlow + 1);
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
var close = candle.ClosePrice;
_barCount++;
// Manual EMA computation
if (!_emaInitialized)
{
_fastEma = close;
_slowEma = close;
_emaInitialized = true;
}
else
{
_fastEma = close * _fastMultiplier + _fastEma * (1 - _fastMultiplier);
_slowEma = close * _slowMultiplier + _slowEma * (1 - _slowMultiplier);
}
if (_barCount < MacdSlow)
return;
var macdLine = _fastEma - _slowEma;
_macdWindow[_windowIndex] = macdLine;
_priceWindow[_windowIndex] = close;
_windowIndex = (_windowIndex + 1) % DivergenceLookback;
if (_windowCount < DivergenceLookback)
_windowCount++;
if (_windowCount < DivergenceLookback)
return;
var volume = Volume;
if (volume <= 0)
volume = 1;
var oldestIndex = _windowIndex;
var newestIndex = (_windowIndex + DivergenceLookback - 1) % DivergenceLookback;
var oldMacd = _macdWindow[oldestIndex];
var newMacd = _macdWindow[newestIndex];
var oldPrice = _priceWindow[oldestIndex];
var newPrice = _priceWindow[newestIndex];
var minPriceMove = oldPrice * 0.005m;
// Bullish divergence: price makes lower low but MACD makes higher low.
var bullishDiv = newPrice < oldPrice - minPriceMove && newMacd > oldMacd;
// Bearish divergence: price makes higher high but MACD makes lower high.
var bearishDiv = newPrice > oldPrice + minPriceMove && newMacd < oldMacd;
if (bullishDiv)
{
if (Position <= 0)
BuyMarket(Position < 0 ? Math.Abs(Position) + volume : volume);
}
else if (bearishDiv)
{
if (Position >= 0)
SellMarket(Position > 0 ? Math.Abs(Position) + volume : volume);
}
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_fastEma = 0;
_slowEma = 0;
_emaInitialized = false;
_barCount = 0;
_fastMultiplier = 0;
_slowMultiplier = 0;
Array.Clear(_macdWindow, 0, _macdWindow.Length);
Array.Clear(_priceWindow, 0, _priceWindow.Length);
_windowCount = 0;
_windowIndex = 0;
}
}
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
class divergence_macd_stochastic_strategy(Strategy):
DIVERGENCE_LOOKBACK = 10
def __init__(self):
super(divergence_macd_stochastic_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._macd_fast = self.Param("MacdFast", 20)
self._macd_slow = self.Param("MacdSlow", 50)
self._fast_ema = 0.0
self._slow_ema = 0.0
self._ema_initialized = False
self._bar_count = 0
self._fast_multiplier = 0.0
self._slow_multiplier = 0.0
self._macd_window = []
self._price_window = []
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def MacdFast(self):
return self._macd_fast.Value
@MacdFast.setter
def MacdFast(self, value):
self._macd_fast.Value = value
@property
def MacdSlow(self):
return self._macd_slow.Value
@MacdSlow.setter
def MacdSlow(self, value):
self._macd_slow.Value = value
def OnReseted(self):
super(divergence_macd_stochastic_strategy, self).OnReseted()
self._fast_ema = 0.0
self._slow_ema = 0.0
self._ema_initialized = False
self._bar_count = 0
self._macd_window = []
self._price_window = []
def OnStarted2(self, time):
super(divergence_macd_stochastic_strategy, self).OnStarted2(time)
self._fast_ema = 0.0
self._slow_ema = 0.0
self._ema_initialized = False
self._bar_count = 0
self._fast_multiplier = 2.0 / (self.MacdFast + 1)
self._slow_multiplier = 2.0 / (self.MacdSlow + 1)
self._macd_window = []
self._price_window = []
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._process_candle).Start()
def _process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
self._bar_count += 1
if not self._ema_initialized:
self._fast_ema = close
self._slow_ema = close
self._ema_initialized = True
else:
self._fast_ema = close * self._fast_multiplier + self._fast_ema * (1 - self._fast_multiplier)
self._slow_ema = close * self._slow_multiplier + self._slow_ema * (1 - self._slow_multiplier)
if self._bar_count < self.MacdSlow:
return
macd_line = self._fast_ema - self._slow_ema
self._macd_window.append(macd_line)
self._price_window.append(close)
while len(self._macd_window) > self.DIVERGENCE_LOOKBACK:
self._macd_window.pop(0)
self._price_window.pop(0)
if len(self._macd_window) < self.DIVERGENCE_LOOKBACK:
return
old_macd = self._macd_window[0]
new_macd = self._macd_window[-1]
old_price = self._price_window[0]
new_price = self._price_window[-1]
min_price_move = old_price * 0.005
# Bullish divergence: price makes lower low but MACD makes higher low
bullish_div = new_price < old_price - min_price_move and new_macd > old_macd
# Bearish divergence: price makes higher high but MACD makes lower high
bearish_div = new_price > old_price + min_price_move and new_macd < old_macd
if bullish_div:
if self.Position <= 0:
self.BuyMarket()
elif bearish_div:
if self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return divergence_macd_stochastic_strategy()