MultiStrategyEA v1.2 (puerto StockSharp)
Descripción general
Esta estrategia es una versión StockSharp de alto nivel del asesor experto MetaTrader MultiStrategyEA v1.2. El EA original agrega siete osciladores y gestiona múltiples cuadrículas de órdenes. La versión StockSharp se centra en el aspecto de generación de señales y comercializa una única posición neta impulsada por un consenso entre los módulos de indicadores. La gestión de pedidos, los perfiles de gestión de dinero, las cuadrículas y las funciones de recuperación del código MT5 se omiten intencionalmente para mantener la implementación alineada con el nivel alto API de StockSharp y para mantener la claridad.
Módulos
La estrategia evalúa los siguientes módulos de indicadores en el marco temporal seleccionado:
- Oscilador de aceleración/deceleración (AC): utiliza la diferencia entre el Awesome Oscillator y su SMA de 5 períodos. Requiere que el valor actual supere el umbral
AcLevel y aumente (o disminuya) en relación con la lectura anterior.
- Índice direccional promedio (ADX): confirma las tendencias cuando la fuerza de ADX está por encima de
AdxTrendLevel y el movimiento direccional que domina también supera AdxDirectionalLevel.
- Awesome Oscillator (AO): detecta ráfagas de impulso cuando el oscilador cruza más allá de
AoLevel y continúa en la misma dirección.
- DeMarker: señala posibles reversiones cuando el oscilador abandona territorios de sobreventa (
100 - DeMarkerThreshold) o sobrecompra (DeMarkerThreshold).
- Índice de fuerza + Bollinger bandas: requiere que el precio toque una banda Bollinger, mientras que el índice de fuerza (escalado en el puerto exactamente como en el script MT5) confirma el impulso más allá de
ForceConfirmationLevel. Un BandDistanceFilter opcional rechaza señales cuando el ancho de banda, medido en pips, es demasiado estrecho o demasiado ancho.
- Índice de flujo de dinero (IMF) – Similar a DeMarker; reacciona a las zonas de sobrecompra y sobreventa determinadas por
MfiThreshold.
- MACD + Stochastic: exige que tanto MACD (
MacdLevel) como Stochastic (StochasticLevel) confirmen el mismo sesgo direccional. MACD debe estar por encima/por debajo del nivel y por encima/por debajo de su línea de señal. Stochastic debe estar por encima/por debajo del umbral y por encima/por debajo de la línea de señal.
Cada módulo aporta un voto de compra, venta o neutral según la última vela terminada.
Lógica del consenso
- Cuando
TradeAllStrategies es verdadero (predeterminado), la estrategia espera hasta que aparezcan al menos RequiredConfirmations votos alcistas con cero votos bajistas antes de entrar en largo. La misma lógica se refleja en los pantalones cortos.
- Cuando
TradeAllStrategies es falso, un solo voto alcista o bajista es suficiente para operar.
- Si
CloseInReverse está habilitado, la estrategia cierra inmediatamente una posición opuesta antes de abrir una nueva.
La implementación opera solo una posición agregada y no intenta recrear la contabilidad de pedidos por módulo del EA original.
Gestión del riesgo
StopLossPips y TakeProfitPips se traducen en compensaciones de precios utilizando el PriceStep del instrumento. Para símbolos con 3 o 5 dígitos decimales, el tamaño del pip se multiplica automáticamente por 10, imitando el comportamiento de los pips de FX.
- Las paradas y los objetivos se verifican en cada vela terminada utilizando máximos y mínimos de velas. Cuando se alcanza cualquiera de los umbrales, se cierra toda la posición.
Diferencias con el Asesor Experto MT5
- Sin funciones de cuadrícula, martingala o recuperación. El tamaño de la posición se fija mediante el parámetro
Volume.
- Las variantes de señal de cierre (opciones
CloseOrdersType en MT5) no están implementadas; las salidas se basan en un stop-loss/take-profit global o en el comportamiento opcional de inversión de señal opuesta.
- La configuración del indicador en StockSharp refleja la idea principal de cada módulo, pero solo admite la interpretación más común en lugar de las muchas enumeraciones de modos que se encuentran en el script original.
- Los bloques de administración de dinero (lote automático, protección de cuenta, valoración de pips de símbolos específicos) están fuera del alcance de esta portabilidad de alto nivel.
Parámetros
| Parámetro |
Descripción |
CandleType |
Serie de datos utilizados por cada módulo indicador. |
Volume |
Volumen neto negociado cuando aparece una señal de consenso. |
TradeAllStrategies |
Permite la votación por consenso; de lo contrario, cualquier voto desencadena un intercambio. |
RequiredConfirmations |
Número de votos coincidentes alcistas o bajistas necesarios cuando se habilita el consenso. |
CloseInReverse |
Cierre una posición existente antes de abrir el lado opuesto. |
StopLossPips / TakeProfitPips |
Stop protector y objetivo de ganancias medidos en pips. |
UseAcModule, AcLevel |
Alternancia y umbral para el módulo Accelerator Oscillator. |
UseAdxModule, AdxPeriod, AdxTrendLevel, AdxDirectionalLevel |
Configuración ADX. |
UseAoModule, AoLevel |
Impresionante configuración del oscilador. |
UseDeMarkerModule, DeMarkerPeriod, DeMarkerThreshold |
Configuración del oscilador DeMarker. |
UseForceBollingerModule, BollingerPeriod, BollingerDeviation, ForceConfirmationLevel, BandDistanceFilter |
Índice de fuerza + Bollinger configuración del filtro de banda. |
UseMfiModule, MfiPeriod, MfiThreshold |
Configuración del índice de flujo de dinero. |
UseMacdStochasticModule, MacdFastPeriod, MacdSlowPeriod, MacdSignalPeriod, MacdLevel, StochasticPeriod, StochasticSignalPeriod, StochasticSlowing, StochasticLevel |
Configuración combinada MACD y Stochastic. |
Notas de uso
- Adjunte la estrategia a un instrumento con suficientes datos históricos para que se formen todos los indicadores.
- Configure los umbrales de plazo y módulo para que coincidan con las condiciones de mercado deseadas. Los valores predeterminados replican los valores utilizados en las entradas MT5 EA.
- La lógica de consenso es sensible a cuántos módulos están activos. Si desactiva los módulos, considere reducir
RequiredConfirmations en consecuencia.
- Debido a que la estrategia negocia una única posición neta, es adecuada para su uso dentro de Designer, Runner u otros StockSharp entornos de alto nivel sin enrutamiento de cartera adicional.
Descargo de responsabilidad
Este puerto se centra en la paridad de señales en lugar de reproducir toda la pila de gestión de riesgos y dinero del experto original MetaTrader. La arquitectura simplificada hace que sea más fácil probar, ampliar o integrar en soluciones basadas en StockSharp, pero los resultados diferirán de la versión MT5 cuando las funciones complejas (cuadrículas, lotes de recuperación, cierres parciales) eran el principal impulsor del rendimiento.
namespace StockSharp.Samples.Strategies;
using System;
using StockSharp.Algo;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Simplified port of the MetaTrader expert advisor "MultiStrategyEA v1.2".
/// Combines multiple oscillators (RSI, Stochastic, MACD, Bollinger, ADX)
/// and requires a configurable number of bullish or bearish confirmations before entering a trade.
/// </summary>
public class MultiEaV12Strategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _requiredConfirmations;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<decimal> _rsiUpper;
private readonly StrategyParam<decimal> _rsiLower;
private readonly StrategyParam<int> _stochKPeriod;
private readonly StrategyParam<int> _stochDPeriod;
private readonly StrategyParam<decimal> _stochUpper;
private readonly StrategyParam<decimal> _stochLower;
private readonly StrategyParam<int> _bollingerPeriod;
private readonly StrategyParam<decimal> _bollingerDeviation;
private readonly StrategyParam<int> _adxPeriod;
private readonly StrategyParam<decimal> _adxTrendLevel;
private readonly StrategyParam<int> _macdFast;
private readonly StrategyParam<int> _macdSlow;
private readonly StrategyParam<int> _macdSignal;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int RequiredConfirmations { get => _requiredConfirmations.Value; set => _requiredConfirmations.Value = value; }
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public decimal RsiUpper { get => _rsiUpper.Value; set => _rsiUpper.Value = value; }
public decimal RsiLower { get => _rsiLower.Value; set => _rsiLower.Value = value; }
public int StochKPeriod { get => _stochKPeriod.Value; set => _stochKPeriod.Value = value; }
public int StochDPeriod { get => _stochDPeriod.Value; set => _stochDPeriod.Value = value; }
public decimal StochUpper { get => _stochUpper.Value; set => _stochUpper.Value = value; }
public decimal StochLower { get => _stochLower.Value; set => _stochLower.Value = value; }
public int BollingerPeriod { get => _bollingerPeriod.Value; set => _bollingerPeriod.Value = value; }
public decimal BollingerDeviation { get => _bollingerDeviation.Value; set => _bollingerDeviation.Value = value; }
public int AdxPeriod { get => _adxPeriod.Value; set => _adxPeriod.Value = value; }
public decimal AdxTrendLevel { get => _adxTrendLevel.Value; set => _adxTrendLevel.Value = value; }
public int MacdFast { get => _macdFast.Value; set => _macdFast.Value = value; }
public int MacdSlow { get => _macdSlow.Value; set => _macdSlow.Value = value; }
public int MacdSignal { get => _macdSignal.Value; set => _macdSignal.Value = value; }
public MultiEaV12Strategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_requiredConfirmations = Param(nameof(RequiredConfirmations), 3)
.SetDisplay("Required Confirmations", "Number of modules required for entry", "Consensus");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetDisplay("RSI Period", "RSI length", "RSI");
_rsiUpper = Param(nameof(RsiUpper), 65m)
.SetDisplay("RSI Upper", "Overbought level", "RSI");
_rsiLower = Param(nameof(RsiLower), 35m)
.SetDisplay("RSI Lower", "Oversold level", "RSI");
_stochKPeriod = Param(nameof(StochKPeriod), 10)
.SetDisplay("Stochastic %K", "%K period", "Stochastic");
_stochDPeriod = Param(nameof(StochDPeriod), 3)
.SetDisplay("Stochastic %D", "%D period", "Stochastic");
_stochUpper = Param(nameof(StochUpper), 70m)
.SetDisplay("Stoch Upper", "Overbought", "Stochastic");
_stochLower = Param(nameof(StochLower), 30m)
.SetDisplay("Stoch Lower", "Oversold", "Stochastic");
_bollingerPeriod = Param(nameof(BollingerPeriod), 20)
.SetDisplay("Bollinger Period", "BB length", "Bollinger");
_bollingerDeviation = Param(nameof(BollingerDeviation), 2m)
.SetDisplay("Bollinger Deviation", "BB width", "Bollinger");
_adxPeriod = Param(nameof(AdxPeriod), 14)
.SetDisplay("ADX Period", "ADX length", "ADX");
_adxTrendLevel = Param(nameof(AdxTrendLevel), 20m)
.SetDisplay("ADX Trend Level", "Min ADX for trend", "ADX");
_macdFast = Param(nameof(MacdFast), 12)
.SetDisplay("MACD Fast", "Fast EMA period", "MACD");
_macdSlow = Param(nameof(MacdSlow), 26)
.SetDisplay("MACD Slow", "Slow EMA period", "MACD");
_macdSignal = Param(nameof(MacdSignal), 9)
.SetDisplay("MACD Signal", "Signal line period", "MACD");
}
/// <inheritdoc />
public override System.Collections.Generic.IEnumerable<(StockSharp.BusinessEntities.Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var stochastic = new StochasticOscillator();
stochastic.K.Length = StochKPeriod;
stochastic.D.Length = StochDPeriod;
var bollinger = new BollingerBands { Length = BollingerPeriod, Width = BollingerDeviation };
var adx = new AverageDirectionalIndex { Length = AdxPeriod };
var macd = new MovingAverageConvergenceDivergenceSignal();
macd.Macd.ShortMa.Length = MacdFast;
macd.Macd.LongMa.Length = MacdSlow;
macd.SignalMa.Length = MacdSignal;
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(rsi, stochastic, bollinger, adx, macd, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, bollinger);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue rsiVal, IIndicatorValue stochVal, IIndicatorValue bbVal, IIndicatorValue adxVal, IIndicatorValue macdVal)
{
if (candle.State != CandleStates.Finished)
return;
if (!rsiVal.IsFinal || !stochVal.IsFinal || !bbVal.IsFinal || !adxVal.IsFinal || !macdVal.IsFinal)
return;
if (!rsiVal.IsFormed || !stochVal.IsFormed || !bbVal.IsFormed || !adxVal.IsFormed || !macdVal.IsFormed)
return;
var rsi = rsiVal.GetValue<decimal>();
var stoch = (StochasticOscillatorValue)stochVal;
var stochK = stoch.K ?? 50m;
var bb = (BollingerBandsValue)bbVal;
var bbUpper = bb.UpBand ?? candle.ClosePrice;
var bbLower = bb.LowBand ?? candle.ClosePrice;
var adxTyped = (AverageDirectionalIndexValue)adxVal;
var adxMain = adxTyped.MovingAverage ?? 0m;
var adxPlus = adxTyped.Dx.Plus ?? 0m;
var adxMinus = adxTyped.Dx.Minus ?? 0m;
var macdTyped = (MovingAverageConvergenceDivergenceSignalValue)macdVal;
var macdLine = macdTyped.Macd ?? 0m;
var macdSignalLine = macdTyped.Signal ?? 0m;
var close = candle.ClosePrice;
// Count bullish and bearish signals from each module
var bullish = 0;
var bearish = 0;
// Module 1: RSI
if (rsi < RsiLower) bullish++;
else if (rsi > RsiUpper) bearish++;
// Module 2: Stochastic
if (stochK < StochLower) bullish++;
else if (stochK > StochUpper) bearish++;
// Module 3: Bollinger Bands
if (close <= bbLower) bullish++;
else if (close >= bbUpper) bearish++;
// Module 4: ADX directional
if (adxMain >= AdxTrendLevel)
{
if (adxPlus > adxMinus) bullish++;
else if (adxMinus > adxPlus) bearish++;
}
// Module 5: MACD
if (macdLine > macdSignalLine && macdLine > 0) bullish++;
else if (macdLine < macdSignalLine && macdLine < 0) bearish++;
var minConfirmations = RequiredConfirmations;
// Enter on consensus
if (bullish >= minConfirmations && bearish == 0 && Position <= 0)
{
BuyMarket();
}
else if (bearish >= minConfirmations && bullish == 0 && Position >= 0)
{
SellMarket();
}
// Exit when consensus breaks
else if (Position > 0 && bearish >= 2)
{
SellMarket();
}
else if (Position < 0 && bullish >= 2)
{
BuyMarket();
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import (
RelativeStrengthIndex, StochasticOscillator, BollingerBands,
AverageDirectionalIndex, MovingAverageConvergenceDivergenceSignal
)
from StockSharp.Algo.Strategies import Strategy
class multi_ea_v12_strategy(Strategy):
"""5-indicator consensus strategy (RSI, Stochastic, Bollinger, ADX, MACD)."""
def __init__(self):
super(multi_ea_v12_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._required_confirmations = self.Param("RequiredConfirmations", 3) \
.SetDisplay("Required Confirmations", "Number of modules required for entry", "Consensus")
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "RSI length", "RSI")
self._rsi_upper = self.Param("RsiUpper", 65.0) \
.SetDisplay("RSI Upper", "Overbought level", "RSI")
self._rsi_lower = self.Param("RsiLower", 35.0) \
.SetDisplay("RSI Lower", "Oversold level", "RSI")
self._stoch_k_period = self.Param("StochKPeriod", 10) \
.SetDisplay("Stochastic %K", "%K period", "Stochastic")
self._stoch_d_period = self.Param("StochDPeriod", 3) \
.SetDisplay("Stochastic %D", "%D period", "Stochastic")
self._stoch_upper = self.Param("StochUpper", 70.0) \
.SetDisplay("Stoch Upper", "Overbought", "Stochastic")
self._stoch_lower = self.Param("StochLower", 30.0) \
.SetDisplay("Stoch Lower", "Oversold", "Stochastic")
self._bollinger_period = self.Param("BollingerPeriod", 20) \
.SetDisplay("Bollinger Period", "BB length", "Bollinger")
self._bollinger_deviation = self.Param("BollingerDeviation", 2.0) \
.SetDisplay("Bollinger Deviation", "BB width", "Bollinger")
self._adx_period = self.Param("AdxPeriod", 14) \
.SetDisplay("ADX Period", "ADX length", "ADX")
self._adx_trend_level = self.Param("AdxTrendLevel", 20.0) \
.SetDisplay("ADX Trend Level", "Min ADX for trend", "ADX")
self._macd_fast = self.Param("MacdFast", 12) \
.SetDisplay("MACD Fast", "Fast EMA period", "MACD")
self._macd_slow = self.Param("MacdSlow", 26) \
.SetDisplay("MACD Slow", "Slow EMA period", "MACD")
self._macd_signal = self.Param("MacdSignal", 9) \
.SetDisplay("MACD Signal", "Signal line period", "MACD")
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def RequiredConfirmations(self):
return self._required_confirmations.Value
@property
def RsiPeriod(self):
return self._rsi_period.Value
@property
def RsiUpper(self):
return self._rsi_upper.Value
@property
def RsiLower(self):
return self._rsi_lower.Value
@property
def StochKPeriod(self):
return self._stoch_k_period.Value
@property
def StochDPeriod(self):
return self._stoch_d_period.Value
@property
def StochUpper(self):
return self._stoch_upper.Value
@property
def StochLower(self):
return self._stoch_lower.Value
@property
def BollingerPeriod(self):
return self._bollinger_period.Value
@property
def BollingerDeviation(self):
return self._bollinger_deviation.Value
@property
def AdxPeriod(self):
return self._adx_period.Value
@property
def AdxTrendLevel(self):
return self._adx_trend_level.Value
@property
def MacdFast(self):
return self._macd_fast.Value
@property
def MacdSlow(self):
return self._macd_slow.Value
@property
def MacdSignal(self):
return self._macd_signal.Value
def OnStarted2(self, time):
super(multi_ea_v12_strategy, self).OnStarted2(time)
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiPeriod
stochastic = StochasticOscillator()
stochastic.K.Length = self.StochKPeriod
stochastic.D.Length = self.StochDPeriod
bollinger = BollingerBands()
bollinger.Length = self.BollingerPeriod
bollinger.Width = float(self.BollingerDeviation)
adx = AverageDirectionalIndex()
adx.Length = self.AdxPeriod
macd = MovingAverageConvergenceDivergenceSignal()
macd.Macd.ShortMa.Length = self.MacdFast
macd.Macd.LongMa.Length = self.MacdSlow
macd.SignalMa.Length = self.MacdSignal
subscription = self.SubscribeCandles(self.CandleType)
subscription.BindEx(rsi, stochastic, bollinger, adx, macd, self._process_candle).Start()
def _process_candle(self, candle, rsi_val, stoch_val, bb_val, adx_val, macd_val):
if candle.State != CandleStates.Finished:
return
if not rsi_val.IsFormed or not stoch_val.IsFormed or not bb_val.IsFormed or \
not adx_val.IsFormed or not macd_val.IsFormed:
return
rsi = float(rsi_val)
stoch_k_raw = stoch_val.K
stoch_k = float(stoch_k_raw) if stoch_k_raw is not None else 50.0
bb_upper_raw = bb_val.UpBand
bb_lower_raw = bb_val.LowBand
bb_upper = float(bb_upper_raw) if bb_upper_raw is not None else float(candle.ClosePrice)
bb_lower = float(bb_lower_raw) if bb_lower_raw is not None else float(candle.ClosePrice)
adx_ma_raw = adx_val.MovingAverage
adx_main = float(adx_ma_raw) if adx_ma_raw is not None else 0.0
adx_plus_raw = adx_val.Dx.Plus
adx_minus_raw = adx_val.Dx.Minus
adx_plus = float(adx_plus_raw) if adx_plus_raw is not None else 0.0
adx_minus = float(adx_minus_raw) if adx_minus_raw is not None else 0.0
macd_line_raw = macd_val.Macd
macd_signal_raw = macd_val.Signal
macd_line = float(macd_line_raw) if macd_line_raw is not None else 0.0
macd_signal_line = float(macd_signal_raw) if macd_signal_raw is not None else 0.0
close = float(candle.ClosePrice)
bullish = 0
bearish = 0
# Module 1: RSI
if rsi < float(self.RsiLower):
bullish += 1
elif rsi > float(self.RsiUpper):
bearish += 1
# Module 2: Stochastic
if stoch_k < float(self.StochLower):
bullish += 1
elif stoch_k > float(self.StochUpper):
bearish += 1
# Module 3: Bollinger Bands
if close <= bb_lower:
bullish += 1
elif close >= bb_upper:
bearish += 1
# Module 4: ADX directional
if adx_main >= float(self.AdxTrendLevel):
if adx_plus > adx_minus:
bullish += 1
elif adx_minus > adx_plus:
bearish += 1
# Module 5: MACD
if macd_line > macd_signal_line and macd_line > 0:
bullish += 1
elif macd_line < macd_signal_line and macd_line < 0:
bearish += 1
min_confirmations = self.RequiredConfirmations
# Enter on consensus
if bullish >= min_confirmations and bearish == 0 and self.Position <= 0:
self.BuyMarket()
elif bearish >= min_confirmations and bullish == 0 and self.Position >= 0:
self.SellMarket()
# Exit when consensus breaks
elif self.Position > 0 and bearish >= 2:
self.SellMarket()
elif self.Position < 0 and bullish >= 2:
self.BuyMarket()
def CreateClone(self):
return multi_ea_v12_strategy()