GitHub で見る
専門家によるAML MFI戦略
概要
エキスパート AML MFI 戦略 は、StockSharp の高レベル API を使用して、MetaTrader 5 エキスパート アドバイザー "Expert_AML_MFI" を複製します。 ミーティング ライン ローソク足パターンに焦点を当て、マネー フロー インデックス (MFI) オシレーターを使用してすべてのシグナルを検証します。この戦略は、MFI が売られすぎまたは買われすぎのしきい値を超えるたびに、必要なローソク足の統計を自動的に維持し、強気または弱気の反転を特定し、オープン ポジションを管理します。
取引ロジック
- ローソク足の準備 – この戦略は、選択した時間枠 (デフォルトでは H1) をサブスクライブし、最後の 2 つの完了したローソク足をローソク体の移動平均とともに保持します。平均本体サイズは、MT5 実装を反映して、ローソク本体の絶対サイズに適用される
SimpleMovingAverage を通じて計算されます。
- パターン検出 – 2 人の専門ヘルパーが 強気のミーティング ライン と 弱気のミーティング ラインを認識します。
- 強気のセットアップ: 長い弱気のローソク足に続いて、前の終値付近 (平均実体の 10% 以内) で閉じる長い強気のローソク足。
- 弱気のセットアップ: 長い強気のローソク足の後に、同様の終値を持つ長い弱気のローソク足が続きます。
- MFI 確認 – 以前の MFI 値は、ロングトレードの場合は強気のエントリーレベル (デフォルト 40) を下回るか、ショートトレードの場合は弱気のエントリーレベル (デフォルト 60) を上回る必要があります。
- ポジション管理 – 売られ過ぎ (30) と買われ過ぎ (70) レベルのクロスを検出するために、最後の 2 つの MFI 読み取り値が追跡されます。
- いずれかのレベルを超えるクロスはショートポジションから抜け出します。
- 売られすぎレベルを下回るクロス、または買われすぎレベルを上回るクロスはロングポジションから抜け出します。
- 注文執行 – 有効なパターンと 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;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import MoneyFlowIndex
from StockSharp.Algo.Strategies import Strategy
class expert_aml_mfi_strategy(Strategy):
def __init__(self):
super(expert_aml_mfi_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5)))
self._mfi_period = self.Param("MfiPeriod", 14)
self._mfi_low = self.Param("MfiLow", 40.0)
self._mfi_high = self.Param("MfiHigh", 60.0)
self._prev_candle = None
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def MfiPeriod(self):
return self._mfi_period.Value
@MfiPeriod.setter
def MfiPeriod(self, value):
self._mfi_period.Value = value
@property
def MfiLow(self):
return self._mfi_low.Value
@MfiLow.setter
def MfiLow(self, value):
self._mfi_low.Value = value
@property
def MfiHigh(self):
return self._mfi_high.Value
@MfiHigh.setter
def MfiHigh(self, value):
self._mfi_high.Value = value
def OnReseted(self):
super(expert_aml_mfi_strategy, self).OnReseted()
self._prev_candle = None
def OnStarted2(self, time):
super(expert_aml_mfi_strategy, self).OnStarted2(time)
self._prev_candle = None
mfi = MoneyFlowIndex()
mfi.Length = self.MfiPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(mfi, self._process_candle).Start()
def _process_candle(self, candle, mfi_value):
if candle.State != CandleStates.Finished:
return
mfi_val = float(mfi_value)
if self._prev_candle is not None:
avg_body = (abs(float(candle.ClosePrice) - float(candle.OpenPrice))
+ abs(float(self._prev_candle.ClosePrice) - float(self._prev_candle.OpenPrice))) / 2.0
if avg_body > 0:
prev_bearish = float(self._prev_candle.OpenPrice) > float(self._prev_candle.ClosePrice)
curr_bullish = float(candle.ClosePrice) > float(candle.OpenPrice)
closes_near = abs(float(candle.ClosePrice) - float(self._prev_candle.ClosePrice)) < avg_body * 0.3
if prev_bearish and curr_bullish and closes_near and mfi_val < self.MfiLow and self.Position <= 0:
self.BuyMarket()
prev_bullish = float(self._prev_candle.ClosePrice) > float(self._prev_candle.OpenPrice)
curr_bearish = float(candle.OpenPrice) > float(candle.ClosePrice)
closes_near2 = abs(float(candle.ClosePrice) - float(self._prev_candle.ClosePrice)) < avg_body * 0.3
if prev_bullish and curr_bearish and closes_near2 and mfi_val > self.MfiHigh and self.Position >= 0:
self.SellMarket()
self._prev_candle = candle
def CreateClone(self):
return expert_aml_mfi_strategy()