Puerto del MetaTrader asesor experto "Macd diver rsi mt4" al API de alto nivel de StockSharp.
Intercambia un solo símbolo usando filtros RSI combinados con MACD reconocimiento de divergencia para invertir el tiempo.
Sólo se puede abrir una posición de mercado a la vez; la estrategia espera el estado plano antes de emitir una nueva señal.
Lógica de señal
Cada vela terminada del período de tiempo seleccionado alimenta cuatro indicadores vinculados a la estrategia:
Dos instancias RelativeStrengthIndex independientes (para filtros de sobreventa y sobrecompra) muestrearon una barra hacia atrás.
Dos indicadores MovingAverageConvergenceDivergence con EMA rápido/lento configurable y longitudes de señal.
Configuración alcista
La barra anterior RSI debe estar por debajo del umbral de sobreventa configurable.
Los valores MACD más recientes deben formar una caída local por debajo de un umbral dinámico (equivalente a 3 pips en el instrumento actual).
Los datos históricos se escanean para localizar una caída anterior MACD y el mínimo asociado del precio. La divergencia se confirma cuando
el mínimo MACD sube mientras que el precio alcanza un mínimo más bajo (divergencia regular) o el mínimo MACD cae mientras el precio alcanza un mínimo más alto
bajo (divergencia oculta), que coincide con la lógica MQL original.
Cuando se confirma y la estrategia no tiene ninguna posición abierta, se envía una compra de mercado con configuraciones de riesgo y volumen específicas de la dirección.
La configuración bajista refleja las reglas alcistas con el filtro de sobrecompra RSI y los picos MACD. La divergencia se valida mediante
comparando los máximos anteriores con el actual.
Inmediatamente después de una entrada, la estrategia convierte las distancias de stop-loss y take-profit configuradas de pips a unidades de precio.
(respetando las reglas originales de formato de puntos) y las aplica a través de SetStopLoss / SetTakeProfit.
Parámetros
LowerRsiPeriod, LowerRsiThreshold: asignar a inp1_Lo_RSIperiod/inp1_Ro_Value.
BearishVolume, BearishStopLossPips, BearishTakeProfitPips – asignar a inp6_VolumeSize, inp6_StopLossPips, inp6_TakeProfitPips.
CandleType: fuente del período de tiempo para todos los cálculos.
Notas de implementación
El umbral de divergencia MACD se deriva del tamaño de punto actual del instrumento y equivale a 3 pips, lo que coincide con el valor predeterminado de 0,0003.
utilizado por la versión MQL.
La vela, MACD y el historial de precios se almacenan en listas limitadas (600 elementos) para reproducir las ventanas de escaneo de divergencia sin
Asignación de grandes matrices.
La estrategia utiliza SubscribeCandles(...).Bind(...) para actualizar todos los indicadores en una sola pasada y los procesos solo finalizan
velas, al igual que la ejecución original del bloque de una vez por barra.
Las distancias de pips se convierten en compensaciones de precio absoluto antes de llamar a SetStopLoss y SetTakeProfit, reproduciendo el
reglas de formato de puntos declaradas en la parte superior de la fuente MQL.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// MACD Divergence RSI strategy: RSI filter + MACD signal line crossover.
/// Buys when RSI below threshold and MACD crosses above signal.
/// Sells when RSI above threshold and MACD crosses below signal.
/// </summary>
public class MacdDivergenceRsiStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
private decimal _prevMacd;
private decimal _prevSignal;
private decimal _prevRsi;
private bool _hasPrev;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public MacdDivergenceRsiStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period", "Indicators");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevMacd = 0;
_prevSignal = 0;
_prevRsi = 0;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var macd = new MovingAverageConvergenceDivergenceSignal
{
Macd = { ShortMa = { Length = 12 }, LongMa = { Length = 26 } },
SignalMa = { Length = 9 }
};
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.BindEx(macd, rsi, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue macdValue, IIndicatorValue rsiValue)
{
if (candle.State != CandleStates.Finished) return;
if (!macdValue.IsFinal || !rsiValue.IsFinal) return;
if (macdValue is not MovingAverageConvergenceDivergenceSignalValue typed) return;
if (typed.Macd is not decimal macdMain || typed.Signal is not decimal signal) return;
var rsi = rsiValue.ToDecimal();
if (_hasPrev)
{
if (_prevMacd <= _prevSignal && macdMain > signal && rsi < 40 && Position <= 0)
BuyMarket();
else if (_prevMacd >= _prevSignal && macdMain < signal && rsi > 60 && Position >= 0)
SellMarket();
}
_prevMacd = macdMain;
_prevSignal = signal;
_prevRsi = rsi;
_hasPrev = true;
}
}
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 MovingAverageConvergenceDivergenceSignal, RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class macd_divergence_rsi_strategy(Strategy):
def __init__(self):
super(macd_divergence_rsi_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5)))
self._rsi_period = self.Param("RsiPeriod", 14)
self._prev_macd = 0.0
self._prev_signal = 0.0
self._prev_rsi = 0.0
self._has_prev = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def RsiPeriod(self):
return self._rsi_period.Value
@RsiPeriod.setter
def RsiPeriod(self, value):
self._rsi_period.Value = value
def OnReseted(self):
super(macd_divergence_rsi_strategy, self).OnReseted()
self._prev_macd = 0.0
self._prev_signal = 0.0
self._prev_rsi = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(macd_divergence_rsi_strategy, self).OnStarted2(time)
self._has_prev = False
macd = MovingAverageConvergenceDivergenceSignal()
macd.Macd.ShortMa.Length = 12
macd.Macd.LongMa.Length = 26
macd.SignalMa.Length = 9
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.BindEx(macd, rsi, self._process_candle).Start()
def _process_candle(self, candle, macd_value, rsi_value):
if candle.State != CandleStates.Finished:
return
if not macd_value.IsFinal or not rsi_value.IsFinal:
return
if macd_value.Macd is None or macd_value.Signal is None:
return
macd_main = float(macd_value.Macd)
signal = float(macd_value.Signal)
rsi_val = float(rsi_value)
if self._has_prev:
if self._prev_macd <= self._prev_signal and macd_main > signal and rsi_val < 40 and self.Position <= 0:
self.BuyMarket()
elif self._prev_macd >= self._prev_signal and macd_main < signal and rsi_val > 60 and self.Position >= 0:
self.SellMarket()
self._prev_macd = macd_main
self._prev_signal = signal
self._prev_rsi = rsi_val
self._has_prev = True
def CreateClone(self):
return macd_divergence_rsi_strategy()