GitHub で見る

MFIレベルクロス戦略

この戦略はMoney Flow Index(MFI)オシレーターを使用して買われすぎと売られすぎの状態を識別します。MFIが事前定義された閾値レベルをクロスするとき、戦略はポジションをエントリーまたは反転させます。選択されたトレンドモードに応じて、クロスの方向または反対方向で動作できます。

デフォルト設定は4時間ローソク足を監視し、14期間のMFIを評価します。MFIが下限閾値を下回るとロングポジションをオープンし、上限閾値を上回るとショートポジションをオープンします。"Against"モードに設定すると、エントリーロジックが逆転し、インジケーター方向に逆らって取引します。

リスク管理はエントリー価格からのパーセンテージで表される組み込みのストップロスとテイクプロフィットパラメーターを通じて処理されます。

詳細

  • エントリー条件:
    • Trend Mode: Direct:
      • ロング: 前のMFI > 低レベル、現在のMFI ≤ 低レベル。
      • ショート: 前のMFI < 高レベル、現在のMFI ≥ 高レベル。
    • Trend Mode: Against:
      • ロング: 前のMFI < 高レベル、現在のMFI ≥ 高レベル。
      • ショート: 前のMFI > 低レベル、現在のMFI ≤ 低レベル。
  • ロング/ショート: 両方向。
  • エグジット条件: 反対のシグナルが現れるとポジションが反転され、または保護モジュールによってクローズされます。
  • ストップ: ストップロスとテイクプロフィットはエントリー価格からのパーセントで表されます。
  • デフォルト値:
    • Candle Type = 4時間ローソク足。
    • MFI Period = 14。
    • Low Level = 40。
    • High Level = 60。
    • Stop Loss % = 1。
    • Take Profit % = 2。
  • フィルター:
    • カテゴリ: オシレーター
    • 方向: 設定可能
    • インジケーター: Money Flow Index
    • ストップ: はい
    • 複雑さ: 基本
    • 時間軸: 中期
    • 季節性: いいえ
    • ニューラルネットワーク: いいえ
    • ダイバージェンス: いいえ
    • リスクレベル: 中

注記

この実装はStockSharpの高レベルAPIに依存しています。ローソク足データを購読し、MFIインジケーターを直接バインドし、クロス条件が満たされたときに成行注文を実行します。ポジション保護は起動時に一度初期化され、リスクを自動的に管理します。

using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Money Flow Index based strategy that opens positions when the indicator crosses predefined levels.
/// The strategy can trade in the direction of the crossing or in the opposite direction based on Trend Mode.
/// </summary>
public class MfiLevelCrossStrategy : Strategy
{
	public enum TrendModes
	{
		Direct,
		Against
	}

	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _mfiPeriod;
	private readonly StrategyParam<decimal> _lowLevel;
	private readonly StrategyParam<decimal> _highLevel;
	private readonly StrategyParam<TrendModes> _trend;
	private readonly StrategyParam<decimal> _stopLossPercent;
	private readonly StrategyParam<decimal> _takeProfitPercent;

	private decimal _prevMfi;
	private bool _isFirst;

	/// <summary>
	/// Candle type used by the strategy.
	/// </summary>
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	/// <summary>
	/// Period for the Money Flow Index indicator.
	/// </summary>
	public int MfiPeriod { get => _mfiPeriod.Value; set => _mfiPeriod.Value = value; }

	/// <summary>
	/// Oversold threshold for the MFI.
	/// </summary>
	public decimal LowLevel { get => _lowLevel.Value; set => _lowLevel.Value = value; }

	/// <summary>
	/// Overbought threshold for the MFI.
	/// </summary>
	public decimal HighLevel { get => _highLevel.Value; set => _highLevel.Value = value; }

	/// <summary>
	/// Trading mode selection.
	/// </summary>
	public TrendModes Trend { get => _trend.Value; set => _trend.Value = value; }

	/// <summary>
	/// Stop loss in percent from entry price.
	/// </summary>
	public decimal StopLossPercent { get => _stopLossPercent.Value; set => _stopLossPercent.Value = value; }

	/// <summary>
	/// Take profit in percent from entry price.
	/// </summary>
	public decimal TakeProfitPercent { get => _takeProfitPercent.Value; set => _takeProfitPercent.Value = value; }

	/// <summary>
	/// Initializes a new instance of the <see cref="MfiLevelCrossStrategy"/>.
	/// </summary>
	public MfiLevelCrossStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe of candles used", "General");

		_mfiPeriod = Param(nameof(MfiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("MFI Period", "Period of the Money Flow Index indicator", "Indicator");

		_lowLevel = Param(nameof(LowLevel), 30m)
			.SetRange(0m, 100m)
			.SetDisplay("Low Level", "Oversold threshold for MFI", "Signal");

		_highLevel = Param(nameof(HighLevel), 70m)
			.SetRange(0m, 100m)
			.SetDisplay("High Level", "Overbought threshold for MFI", "Signal");

		_trend = Param(nameof(Trend), TrendModes.Direct)
			.SetDisplay("Trend Mode", "Trade with trend (Direct) or against it (Against)", "Signal");

		_stopLossPercent = Param(nameof(StopLossPercent), 1m)
			.SetRange(0m, 100m)
			.SetDisplay("Stop Loss %", "Stop loss as percent from entry price", "Risk");

		_takeProfitPercent = Param(nameof(TakeProfitPercent), 2m)
			.SetRange(0m, 100m)
			.SetDisplay("Take Profit %", "Take profit as percent from entry price", "Risk");
	}

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_prevMfi = 0m;
		_isFirst = true;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		StartProtection(
			new Unit(TakeProfitPercent, UnitTypes.Percent),
			new Unit(StopLossPercent, UnitTypes.Percent));

		var mfi = new MoneyFlowIndex { Length = MfiPeriod };

		var subscription = SubscribeCandles(CandleType);

		subscription
			.Bind(mfi, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, mfi);
			DrawOwnTrades(area);
		}
	}

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

		if (_isFirst)
		{
			_prevMfi = mfiValue;
			_isFirst = false;
			return;
		}

		var crossBelowLow = _prevMfi > LowLevel && mfiValue <= LowLevel;
		var crossAboveHigh = _prevMfi < HighLevel && mfiValue >= HighLevel;

		if (Trend == TrendModes.Direct)
		{
			if (crossBelowLow && Position <= 0)
				BuyMarket();
			else if (crossAboveHigh && Position >= 0)
				SellMarket();
		}
		else
		{
			if (crossBelowLow && Position >= 0)
				SellMarket();
			else if (crossAboveHigh && Position <= 0)
				BuyMarket();
		}

		_prevMfi = mfiValue;
	}
}