GitHub で見る

Exp X2MA Candle MM Recovery 戦略

概要

この戦略は、MetaTrader エキスパート Exp_X2MACandle_MMRec の C# 変換版です。元の X2MA カスタムインジケーターによって生成された2重に平滑化されたローソク足の色を観察し、ポジションをいつオープンまたはクローズするかを決定します。StockSharp バージョンは二重平滑化パイプラインを再現し、設定可能な数の最近の損失後に取引ボリュームを削減する軽量なマネーマネジメントレイヤーを維持します。

アルゴリズムは完了したローソク足のみを処理します。設定可能な時間軸を購読し、ローソク足の OHLC 値に2つの連鎖された移動平均を適用し、合成ローソク足の色(緑、グレー、赤)を導出し、ユーザーが選択可能なバーシフトによる色の遷移を使用してアクションをトリガーします。ロングトレードは色が強気から他の何かに変わったときにオープンされます。ショートトレードは対称的な条件に従います。ポジションエグジットは同じ色チェックと整合し、各サイドで個別に有効/無効にできます。

インジケーターロジック

  1. 各ローソク足は2回平滑化されます。両方のステージは異なる方法と長さを使用できます。
  2. 平滑化オプションは StockSharp インジケーターにマッピングされます:
    • SimpleSimpleMovingAverage
    • ExponentialExponentialMovingAverage
    • SmoothedSmoothedMovingAverage (RMA)
    • WeightedWeightedMovingAverage
    • JurikJurikMovingAverage(Phase パラメーターは利用可能な場合に適用されます)。
  3. 絶対的な始値/終値の差が GapPoints * Security.StepPrice を下回る場合、合成ローソク足のボディは平坦化されます。
  4. 色は次のように割り当てられます:始値 < 終値 → 2(強気)、始値 > 終値 → 0(弱気)、それ以外 → 1(ニュートラル)。
  5. シグナルはバー SignalBar + 1(デフォルト設定では2バー前)で評価されるため、完全なローソク足が色の変化を確認した後にのみ注文が送信されます。

マネーマネジメント

  • 元のエキスパートは、過去の取引統計を使用してロスの連続後にポジションサイズを動的に削減していました。StockSharp は MetaTrader の正確な履歴を公開していないため、このポートは最近のクローズされた取引の内部キューを維持します。
  • キューの長さは HistoryDepth によって制御され、ウィンドウ内で LossTrigger 以上の損失が検出されると、ボリュームは ReducedVolume にフォールバックします。
  • 戦略は手動エグジットがトリガーされたときのローソク足の終値を使用してトレード結果を記録します。MetaTrader バージョンのストップロス/テイクプロフィット注文は再現されません。必要に応じて StockSharp のリスクマネージャーを通じて独自の保護ルールを追加できます。

パラメーター

名前 説明
CandleType 平滑化と取引に使用されるローソク足の時間軸。
FirstMethod, FirstLength, FirstPhase 主要な平滑化方法、長さ、Jurik フェーズ。
SecondMethod, SecondLength, SecondPhase 副次的な平滑化方法、長さ、Jurik フェーズ。
GapPoints 価格ステップ単位のローソク足ボディ平坦化しきい値。
SignalBar 色バッファを読み取る際のシフト(0 = 最後の完了ローソク足)。
AllowLongEntry / AllowShortEntry ロングまたはショートポジションのオープンを有効化。
AllowLongExit / AllowShortExit ロングまたはショートポジションのクローズを有効化。
NormalVolume 標準注文サイズ(ロット、株式、契約)。
ReducedVolume 設定された損失数後に使用される注文サイズ。
HistoryDepth 損失について検査される最近のトレードの数(0は履歴追跡を無効化)。
LossTrigger 縮小ボリュームをアクティベートする損失カウント(0はスイッチを無効化)。

使用上の注意

  • 戦略は GetWorkingSecurities() によって返された単一のセキュリティで動作します。
  • シグナルとエグジットは重複した注文を避けるために完了したローソク足ごとに1回処理されます。
  • 履歴統計を保持しながらボリューム削減を無効にしたい場合は、ReducedVolumeNormalVolume と等しく設定します。
  • ポートはトレードを分類するためにローソク足の終値に依存しているため、スリッページや部分的な約定が発生した場合、損失カウンターは MetaTrader とわずかに異なる場合があります。ドキュメントは同様の動作を実現するためのパラメーター調整に役立つはずです。
  • MQL バージョンのストップとテイクプロフィットは自動的には再現されません。プラットフォームレベルの保護が必要な場合は StockSharp リスクマネージャー(StartProtection)を使用します。
using System;
using System.Collections.Generic;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

public class ExpX2MaCandleMmRecStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private decimal? _prevFast, _prevSlow;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }

	public ExpX2MaCandleMmRecStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
		_fastPeriod = Param(nameof(FastPeriod), 8).SetGreaterThanZero().SetDisplay("Fast WMA", "Fast WMA period", "Indicators");
		_slowPeriod = Param(nameof(SlowPeriod), 25).SetGreaterThanZero().SetDisplay("Slow WMA", "Slow WMA period", "Indicators");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFast = null;
		_prevSlow = null;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevFast = null; _prevSlow = null;
		var fast = new WeightedMovingAverage { Length = FastPeriod };
		var slow = new WeightedMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fast, slow, ProcessCandle).Start();
		var area = CreateChartArea();
		if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, fast); DrawIndicator(area, slow); DrawOwnTrades(area); }
	}

	private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!IsFormedAndOnlineAndAllowTrading()) { _prevFast = fast; _prevSlow = slow; return; }
		if (_prevFast == null || _prevSlow == null) { _prevFast = fast; _prevSlow = slow; return; }
		var prevAbove = _prevFast.Value > _prevSlow.Value;
		var currAbove = fast > slow;
		_prevFast = fast; _prevSlow = slow;
		if (!prevAbove && currAbove && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
		else if (prevAbove && !currAbove && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
	}
}