GitHub で見る

専門家によるAML MFI戦略

概要

エキスパート AML MFI 戦略 は、StockSharp の高レベル API を使用して、MetaTrader 5 エキスパート アドバイザー "Expert_AML_MFI" を複製します。 ミーティング ライン ローソク足パターンに焦点を当て、マネー フロー インデックス (MFI) オシレーターを使用してすべてのシグナルを検証します。この戦略は、MFI が売られすぎまたは買われすぎのしきい値を超えるたびに、必要なローソク足の統計を自動的に維持し、強気または弱気の反転を特定し、オープン ポジションを管理します。

取引ロジック

  1. ローソク足の準備 – この戦略は、選択した時間枠 (デフォルトでは H1) をサブスクライブし、最後の 2 つの完了したローソク足をローソク体の移動平均とともに保持します。平均本体サイズは、MT5 実装を反映して、ローソク本体の絶対サイズに適用される SimpleMovingAverage を通じて計算されます。
  2. パターン検出 – 2 人の専門ヘルパーが 強気のミーティング ライン弱気のミーティング ラインを認識します。
    • 強気のセットアップ: 長い弱気のローソク足に続いて、前の終値付近 (平均実体の 10% 以内) で閉じる長い強気のローソク足。
    • 弱気のセットアップ: 長い強気のローソク足の後に、同様の終値を持つ長い弱気のローソク足が続きます。
  3. MFI 確認 – 以前の MFI 値は、ロングトレードの場合は強気のエントリーレベル (デフォルト 40) を下回るか、ショートトレードの場合は弱気のエントリーレベル (デフォルト 60) を上回る必要があります。
  4. ポジション管理 – 売られ過ぎ (30) と買われ過ぎ (70) レベルのクロスを検出するために、最後の 2 つの MFI 読み取り値が追跡されます。
    • いずれかのレベルを超えるクロスはショートポジションから抜け出します。
    • 売られすぎレベルを下回るクロス、または買われすぎレベルを上回るクロスはロングポジションから抜け出します。
  5. 注文執行 – 有効なパターンと MFI 確認が発生すると、戦略は反対のエクスポージャーをクローズし、設定された基本ボリュームで市場に新しいポジションをオープンします。

パラメーター

名前 説明 デフォルト
CandleType キャンドルのサブスクリプションに使用される時間枠。 1時間枠
MfiPeriod MFI オシレーターのバーの数。 12
BodyAveragePeriod 平均身体サイズを計算するためのウィンドウの長さ。 4
BullishEntryLevel 強気エントリーに許可される最大 MFI 値。 40
BearishEntryLevel 弱気エントリーに必要な最小 MFI 値。 60
OversoldLevel 売られすぎレベルは出口シグナルに使用されます。 30
OverboughtLevel 買われすぎレベルは出口シグナルに使用されます。 70
TradeVolume 新しい取引に適用される基本注文量。 1

StrategyParam ラッパーのおかげで、すべてのパラメータは StockSharp デザイナー内で直接最適化できます。

インジケーターとビジュアル

  • マネー フロー インデックス – 確認のためにキャンドル サブスクリプションにバインドされ、チャート エリアが利用可能な場合にチャートに表示されます。
  • ローソク体の単純移動平均 – 内部使用のみ。MT5 の平均実体の計算を再現します。

注意事項

  • この戦略は、組み込みの位置保護機能を有効にするために、StartProtection() を 1 回呼び出します。
  • 取引コマンドは、BuyMarket ヘルパーと SellMarket ヘルパーを使用して、新しいポジションを開く前に現在のポジションをフラットにし、MetaTrader エキスパート アドバイザーの動作と一致します。
  • プロジェクト要件に従って Python ポートは提供されません。
namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// Meeting Lines + MFI strategy.
/// Buys on bullish meeting lines with low MFI, sells on bearish meeting lines with high MFI.
/// </summary>
public class ExpertAmlMfiStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _mfiPeriod;
	private readonly StrategyParam<decimal> _mfiLow;
	private readonly StrategyParam<decimal> _mfiHigh;

	private ICandleMessage _prevCandle;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int MfiPeriod { get => _mfiPeriod.Value; set => _mfiPeriod.Value = value; }
	public decimal MfiLow { get => _mfiLow.Value; set => _mfiLow.Value = value; }
	public decimal MfiHigh { get => _mfiHigh.Value; set => _mfiHigh.Value = value; }

	public ExpertAmlMfiStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_mfiPeriod = Param(nameof(MfiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("MFI Period", "MFI period", "Indicators");
		_mfiLow = Param(nameof(MfiLow), 40m)
			.SetDisplay("MFI Low", "MFI level for bullish entry", "Signals");
		_mfiHigh = Param(nameof(MfiHigh), 60m)
			.SetDisplay("MFI High", "MFI level for bearish entry", "Signals");
	}

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

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevCandle = null;
		var mfi = new MoneyFlowIndex { Length = MfiPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(mfi, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal mfiValue)
	{
		if (candle.State != CandleStates.Finished) return;

		if (_prevCandle != null)
		{
			var avgBody = (Math.Abs(candle.ClosePrice - candle.OpenPrice) +
						   Math.Abs(_prevCandle.ClosePrice - _prevCandle.OpenPrice)) / 2m;

			if (avgBody > 0)
			{
				var prevBearish = _prevCandle.OpenPrice > _prevCandle.ClosePrice;
				var currBullish = candle.ClosePrice > candle.OpenPrice;
				var closesNear = Math.Abs(candle.ClosePrice - _prevCandle.ClosePrice) < avgBody * 0.3m;

				if (prevBearish && currBullish && closesNear && mfiValue < MfiLow && Position <= 0)
					BuyMarket();

				var prevBullish = _prevCandle.ClosePrice > _prevCandle.OpenPrice;
				var currBearish = candle.OpenPrice > candle.ClosePrice;
				var closesNear2 = Math.Abs(candle.ClosePrice - _prevCandle.ClosePrice) < avgBody * 0.3m;

				if (prevBullish && currBearish && closesNear2 && mfiValue > MfiHigh && Position >= 0)
					SellMarket();
			}
		}

		_prevCandle = candle;
	}
}