Ver no GitHub

MultiStrategyEA v1.2 (StockSharp Porta)

Visão geral

Esta estratégia é uma versão StockSharp de alto nível do consultor especialista MetaTrader MultiStrategyEA v1.2. O EA original agrega sete osciladores e gerencia múltiplas grades de pedidos. A versão StockSharp concentra-se no aspecto de geração de sinal e negocia uma única posição líquida que é impulsionada por um consenso entre os módulos do indicador. Gerenciamento de pedidos, perfis de gerenciamento de dinheiro, grades e recursos de recuperação do código MT5 são intencionalmente omitidos para manter a implementação alinhada com o API de alto nível de StockSharp e para manter a clareza.

Módulos

A estratégia avalia os seguintes módulos de indicadores no período selecionado:

  1. Oscilador de aceleração/desaceleração (AC) – Usa a diferença entre o Oscilador Awesome e seu SMA de 5 períodos. Requer que o valor atual exceda o limite AcLevel e aumente (ou diminua) em relação à leitura anterior.
  2. Índice Direcional Médio (ADX) – Confirma tendências quando a força de ADX está acima de AdxTrendLevel e o movimento direcional que domina também excede AdxDirectionalLevel.
  3. Awesome Oscillator (AO) – Detecta explosões de impulso quando o oscilador ultrapassa AoLevel e continua na mesma direção.
  4. DeMarker – Sinaliza possíveis reversões quando o oscilador sai dos territórios de sobrevenda (100 - DeMarkerThreshold) ou sobrecompra (DeMarkerThreshold).
  5. Índice de Força + Bandas Bollinger – Requer que o preço toque uma banda Bollinger enquanto o Índice de Força (escalonado na porta exatamente como no script MT5) confirma o impulso além de ForceConfirmationLevel. Um BandDistanceFilter opcional rejeita sinais quando a largura da banda, medida em pips, é muito estreita ou muito larga.
  6. Índice de Fluxo de Dinheiro (MFI) – Semelhante ao DeMarker; reage às zonas de sobrecompra e sobrevenda determinadas por MfiThreshold.
  7. MACD + Stochastic – Exige que MACD (MacdLevel) e Stochastic (StochasticLevel) confirmem o mesmo viés direcional. MACD deve estar acima/abaixo do nível e acima/abaixo de sua linha de sinal. Stochastic deve estar acima/abaixo do limite e acima/abaixo da linha de sinal.

Cada módulo contribui com um voto de compra, venda ou neutro com base na última vela finalizada.

Lógica de Consenso

  • Quando TradeAllStrategies é true (padrão), a estratégia espera até que pelo menos RequiredConfirmations votos de alta com zero votos de baixa apareçam antes de entrar comprado. A mesma lógica se aplica aos shorts.
  • Quando TradeAllStrategies é falso, um único voto de alta ou baixa é suficiente para negociar.
  • Se CloseInReverse estiver ativado, a estratégia fecha imediatamente uma posição oposta antes de abrir uma nova.

A implementação opera apenas uma posição agregada e não tenta recriar a escrituração de pedidos por módulo do EA original.

Gestão de risco

  • StopLossPips e TakeProfitPips são traduzidos em compensações de preço usando o PriceStep do instrumento. Para símbolos com 3 ou 5 dígitos decimais, o tamanho do pip é automaticamente multiplicado por 10, imitando o comportamento do pip FX.
  • Stops e alvos são verificados em cada vela finalizada usando os máximos/mínimos da vela. Quando qualquer um dos limites é atingido, toda a posição é fechada.

Diferenças do Expert Advisor MT5

  • Sem recursos de grade, martingale ou recuperação. O dimensionamento da posição é fixado por meio do parâmetro Volume.
  • Variantes de sinal próximo (opções CloseOrdersType no MT5) não são implementadas; as saídas dependem do stop-loss/take-profit global ou do comportamento opcional de reversão no sinal oposto.
  • A configuração do indicador em StockSharp reflete a ideia principal de cada módulo, mas suporta apenas a interpretação mais comum em vez das muitas enumerações de modo encontradas no script original.
  • Blocos de gerenciamento de dinheiro (lote automático, proteção de conta, avaliação de pip específica de símbolo) estão fora do escopo desta porta de alto nível.

Parâmetros

Parâmetro Descrição
CandleType Série de dados usada por cada módulo de indicador.
Volume Volume líquido negociado quando aparece um sinal de consenso.
TradeAllStrategies Permite votação por consenso; caso contrário, qualquer voto desencadeia uma negociação.
RequiredConfirmations Número de votos correspondentes de alta ou baixa necessários quando o consenso está habilitado.
CloseInReverse Feche uma posição existente antes de abrir o lado oposto.
StopLossPips / TakeProfitPips Stop protetor e meta de lucro medidos em pips.
UseAcModule, AcLevel Alternar e limite para o módulo Accelerator Oscillator.
UseAdxModule, AdxPeriod, AdxTrendLevel, AdxDirectionalLevel Configuração ADX.
UseAoModule, AoLevel Configuração impressionante do oscilador.
UseDeMarkerModule, DeMarkerPeriod, DeMarkerThreshold Configurações do oscilador DeMarker.
UseForceBollingerModule, BollingerPeriod, BollingerDeviation, ForceConfirmationLevel, BandDistanceFilter Índice de força + Bollinger configurações de filtro de banda.
UseMfiModule, MfiPeriod, MfiThreshold Configurações do índice de fluxo de dinheiro.
UseMacdStochasticModule, MacdFastPeriod, MacdSlowPeriod, MacdSignalPeriod, MacdLevel, StochasticPeriod, StochasticSignalPeriod, StochasticSlowing, StochasticLevel Configuração combinada MACD e Stochastic.

Notas de uso

  1. Anexe a estratégia a um instrumento com dados históricos suficientes para a formação de todos os indicadores.
  2. Configure o prazo e os limites do módulo para corresponder às condições de mercado desejadas. Os padrões replicam os valores usados ​​nas entradas MT5 EA.
  3. A lógica de consenso é sensível a quantos módulos estão ativos. Se você desabilitar módulos, considere diminuir RequiredConfirmations adequadamente.
  4. Como a estratégia negocia uma única posição líquida, ela é adequada para uso dentro de Designer, Runner ou outros ambientes StockSharp de alto nível sem roteamento adicional de portfólio.

Isenção de responsabilidade

Esta porta se concentra na paridade do sinal em vez de reproduzir toda a pilha de gerenciamento de risco e dinheiro do especialista MetaTrader original. A arquitetura simplificada facilita o teste, a extensão ou a integração em soluções baseadas em StockSharp, mas os resultados serão diferentes da versão MT5 quando recursos complexos (grades, lotes de recuperação, fechamentos parciais) forem o principal impulsionador de desempenho.

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();
		}
	}
}