GitHub で見る

MultiStrategyEA v1.2 (StockSharp ポート)

概要

この戦略は、MetaTrader エキスパート アドバイザー MultiStrategyEA v1.2 の上位レベルの StockSharp 移植です。オリジナルの EA は 7 つのオシレーターを集約し、複数の注文グリッドを管理します。 StockSharp バージョンはシグナル生成の側面に焦点を当てており、インジケーター モジュール間のコンセンサスによって駆動される単一のネット ポジションを取引します。 MT5 コードの注文管理、資金管理プロファイル、グリッド、リカバリ機能は、実装を StockSharp の高レベルの API と整合させ、明確さを維持するために意図的に省略されています。

モジュール

この戦略は、選択した時間枠で次のインジケーター モジュールを評価します。

  1. 加速/減速オシレーター (AC) – Awesome Oscillator とその 5 周期 SMA の差を使用します。現在の値が AcLevel のしきい値を超え、前の読み取り値と比較して上昇 (または下降) する必要があります。
  2. 平均方向指数 (ADX) – ADX の強さが AdxTrendLevel を超え、支配的な方向の動きも AdxDirectionalLevel を超える場合の傾向を確認します。
  3. オーサム オシレーター (AO) – オシレーターが AoLevel を超えて同じ方向に進み続けるときの運動量のバーストを検出します。
  4. DeMarker – オシレーターが売られすぎ (100 - DeMarkerThreshold) または買われすぎ (DeMarkerThreshold) の領域を離れるときに反転の可能性をフラグします。
  5. フォース インデックス + Bollinger バンド – フォース インデックス (MT5 スクリプトと同じようにポート内で正確にスケーリング) が ForceConfirmationLevel を超える勢いを確認している間に、価格が Bollinger バンドに達する必要があります。オプションの BandDistanceFilter は、ピップ単位で測定される帯域幅が狭すぎるか広すぎる場合に信号を拒否します。
  6. マネー フロー インデックス (MFI) – DeMarker に似ています。 MfiThreshold によって決定される買われすぎゾーンと売られすぎゾーンに反応します。
  7. MACD + Stochastic – MACD (MacdLevel) と Stochastic (StochasticLevel) の両方が同じ方向の偏りを確認することを要求します。 MACD は、そのレベルの上/下、および信号線の上/下にある必要があります。 Stochastic はしきい値を上回るか下回るか、信号線を上回るか下回る必要があります。

各モジュールは、最後に完成したローソク足に基づいて、買い売り、または中立の投票に貢献します。

コンセンサスロジック

  • TradeAllStrategiestrue (デフォルト) の場合、戦略はロングに入る前に、少なくとも RequiredConfirmations 件の強気票と 0 の弱気票が表示されるまで待機します。同じロジックがショートにも反映されます。
  • TradeAllStrategiesfalse の場合、取引には 1 つの強気または弱気の投票で十分です。
  • CloseInReverse が有効な場合、ストラテジーは新しいポジションをオープンする前に、反対のポジションを直ちにクローズします。

この実装は 1 つの集約ポジションのみを操作し、元の EA のモジュールごとの注文簿記を再作成しようとはしません。

リスク管理

  • StopLossPipsTakeProfitPips は、商品の PriceStep を使用して価格オフセットに変換されます。 10 進数が 3 桁または 5 桁のシンボルの場合、pip サイズは自動的に 10 倍になり、FX の pip 動作を模倣します。
  • ストップとターゲットは、ローソクの高値/安値を使用して、完成したローソクごとにチェックされます。いずれかのしきい値に達すると、ポジション全体がクローズされます。

MT5エキスパートアドバイザーとの違い

  • グリッド、マーチンゲール、回復機能はありません。ポジションのサイジングは、Volume パラメータによって固定されます。
  • クローズシグナルバリアント (MT5 の CloseOrdersType オプション) は実装されていません。エグジットは、グローバルなストップロス/テイクプロフィット、またはオプションの逆シグナル動作に依存します。
  • StockSharp のインジケーター構成は各モジュールの主なアイデアを反映していますが、元のスクリプトにある多くのモード列挙ではなく、最も一般的な解釈のみをサポートしています。
  • 資金管理ブロック (自動ロット、アカウント保護、シンボル固有の PIP 評価) は、この高レベル ポートの範囲外です。

パラメーター

パラメータ 説明
CandleType すべてのインジケーター モジュールで使用されるデータ シリーズ。
Volume コンセンサスシグナルが現れたときの純取引高。
TradeAllStrategies コンセンサス投票を有効にします。それ以外の場合は、任意の 1 票が取引のトリガーとなります。
RequiredConfirmations コンセンサスが有効な場合に必要な、一致する強気投票または弱気投票の数。
CloseInReverse 反対側をオープンする前に、既存のポジションをクローズします。
StopLossPips / TakeProfitPips ピップ単位で測定されるプロテクティブストップと利益目標。
UseAcModule, AcLevel Accelerator Oscillator モジュールのトグルとしきい値。
UseAdxModule, AdxPeriod, AdxTrendLevel, AdxDirectionalLevel ADX 構成。
UseAoModule, AoLevel 素晴らしいオシレーター構成。
UseDeMarkerModule, DeMarkerPeriod, DeMarkerThreshold DeMarker オシレーターの設定。
UseForceBollingerModule, BollingerPeriod, BollingerDeviation, ForceConfirmationLevel, BandDistanceFilter インデックス + Bollinger バンド フィルター設定を強制します。
UseMfiModule, MfiPeriod, MfiThreshold マネーフローインデックスの設定。
UseMacdStochasticModule, MacdFastPeriod, MacdSlowPeriod, MacdSignalPeriod, MacdLevel, StochasticPeriod, StochasticSignalPeriod, StochasticSlowing, StochasticLevel MACD と Stochastic のコンボ構成。

使用上の注意

  1. すべての指標を形成するのに十分な履歴データを備えた商品に戦略を添付します。
  2. 希望する市場状況に合わせてタイムフレームとモジュールのしきい値を設定します。デフォルトは、MT5 EA 入力で使用される値を複製します。
  3. コンセンサス ロジックは、アクティブなモジュールの数に影響されます。モジュールを無効にする場合は、それに応じて RequiredConfirmations を下げることを検討してください。
  4. この戦略は単一のネット ポジションを取引するため、追加のポートフォリオ ルーティングなしで、デザイナー、ランナー、またはその他の StockSharp の高レベル環境内での使用に適しています。

免責事項

この移植は、元の MetaTrader 専門家のリスクと資金管理スタック全体を再現するのではなく、信号のパリティに焦点を当てています。簡素化されたアーキテクチャにより、StockSharp ベースのソリューションへのテスト、拡張、統合が容易になりますが、複雑な機能 (グリッド、回収ロット、部分的なクローズ) が主なパフォーマンスの要因である場合、結果は MT5 バージョンとは異なります。

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