GitHub で見る

Myfriend 外国為替商品戦略

Myfriend Forex Instruments Strategy は、2006 年の「MyFriend」MetaTrader エキスパートを再現しています。毎日のピボットレベル、Donchian チャネルの拡大、終値から測定される短期と長期のモメンタムスプレッドを組み合わせて、30 分足のローソク足で EUR/USD を取引します。システムは、幅広い実体で日次ピボットを貫通するローソク足、または突然の Donchian 幅の拡大を探します。これらのインパルスの 1 つが日中のモメンタム バイアスと一致すると、戦略は事前に定義された保護レベルで単一のポジションをオープンします。

取引ロジック

  1. 日次ピボット マップ – 前日の高値、安値、終値により、古典的なピボット ラダー (PivotR1S1) が構築されます。これらのレベルは取引セッション全体を通じて変化せず、予想される取引範囲を定義します。
  2. モメンタムパルス – 終値の 2 つの単純移動平均 (3 期間と 9 期間) により、短期/長期のモメンタム スプレッドが形成されます。 MetaTrader "MP" 計算を模倣するためにスプレッドに 1000 を乗算し、強気圧力か弱気圧力のどちらが優勢であるかを決定します。
  3. ブレイクアウトフィルター
    • ピボットスラスト: ローソク足が 12 ポイントを超える実体でピボットを横切って閉じ、次のローソク足が同じ方向に閉じた後、戦略は潜在的な取引のフラグを立てます。
    • Donchian の拡張: 16 期間の Donchian チャネルが R1 - S1 の範囲を超えて広がり、その方向が価格変動と一致した場合にも、シグナルがトリガーされます。
  4. 注文管理 – 一度に許可されるポジションは 1 つだけです。ロングエントリーでは、前のローソク足の安値からバッファーを差し引いた値をストップとして使用し、固定の 70 ポイントのテイクプロフィットを使用します。短いエントリは、前の高値とバッファーを使用してこのロジックを反映します。
  5. 撤退戦略
    • 時間ベースのエグジット: エントリー後の 3 番目と 4 番目のローソク足の間で、最後の閉じたバーがポジションに対して 3 ポイント移動した場合、取引は早期に終了します。
    • トレーリングストップ: オープン利益が 5 ポイントを超え、Donchian 境界が取引に有利に動き続けると、ストップはチャネルに沿ってプラス/マイナス 1 ポイントのバッファーで追跡されます。
    • ハードターゲット: 計算されたストップまたはテイクプロフィットに価格が触れた場合、ポジションは直ちにクローズされます。

パラメーター

名前 説明 デフォルト
BaseVolume 新しい取引ごとに使用される注文量。 1
TakeProfitPoints エントリーからのテイクプロフィットまでの距離(MetaTrader ポイント)。 70
StopLossBufferPoints 保護ストップのために前のローソク足の極値を超えて追加された追加のバッファー。 13
ChannelPeriod Donchian チャネル期間は幅拡張テストとトレーリングに使用されます。 16
UseTrailingStop Donchian ベースのトレーリングストップを有効または無効にします。 true
TrailingStartPoints トレーリングストップが引き締められる前に必要なオープン利益(ポイント)。 5
TrailingBufferPoints トレーリング時に Donchian 境界に適用されるバッファ (ポイント)。 1
UseTimeClose 3 ~ 4 キャンドル拒否出口を有効にします。 true
CandleType プライマリローソク足タイプ (デフォルトの 30 分の時間枠)。 M30
DailyCandleType ピボット レベルを再構築するために使用される毎日のローソク足タイプ。 D1

注意事項

  • この戦略は、元の専門家を反映して、EUR/USD および 30 分足のローソク足向けに設計されています。金融商品や時間枠が異なると、パラメーターの調整が必要になる場合があります。
  • ポイントベースのパラメータは、機器の PriceStep に依存します。市場データによって提供されない場合、戦略は単価の増加に戻ります。
  • ソース アルゴリズムの MetaTrader の動作と一致する、完了したローソク足のみが処理されます。
using System;
using System.Collections.Generic;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// MyFriend Forex strategy - Donchian channel breakout with SMA momentum filter.
/// Buys when close breaks above upper Donchian and fast SMA > slow SMA.
/// Sells when close breaks below lower Donchian and fast SMA less than slow SMA.
/// </summary>
public class MyfriendForexInstrumentsStrategy : Strategy
{
	private readonly StrategyParam<int> _channelPeriod;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevClose;
	private decimal _prevUpper;
	private decimal _prevLower;
	private bool _hasPrev;

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

	public MyfriendForexInstrumentsStrategy()
	{
		_channelPeriod = Param(nameof(ChannelPeriod), 16)
			.SetDisplay("Channel Period", "Donchian channel period", "Indicators");

		_fastPeriod = Param(nameof(FastPeriod), 3)
			.SetDisplay("Fast SMA", "Fast SMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 9)
			.SetDisplay("Slow SMA", "Slow SMA period", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevClose = 0m;
		_prevUpper = 0m;
		_prevLower = 0m;
		_hasPrev = false;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_hasPrev = false;

		var highest = new Highest { Length = ChannelPeriod };
		var lowest = new Lowest { Length = ChannelPeriod };
		var fastSma = new SimpleMovingAverage { Length = FastPeriod };
		var slowSma = new SimpleMovingAverage { Length = SlowPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(highest, lowest, fastSma, slowSma, ProcessCandle)
			.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal high, decimal low, decimal fast, decimal slow)
	{
		if (candle.State != CandleStates.Finished)
			return;

		var close = candle.ClosePrice;

		if (!_hasPrev)
		{
			_prevClose = close;
			_prevUpper = high;
			_prevLower = low;
			_hasPrev = true;
			return;
		}

		// Breakout above channel with bullish momentum
		if (_prevClose <= _prevUpper && close > high && fast > slow && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Breakout below channel with bearish momentum
		else if (_prevClose >= _prevLower && close < low && fast < slow && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}
		// Mean reversion: close crosses midpoint
		else
		{
			var mid = (high + low) / 2m;
			var prevMid = (_prevUpper + _prevLower) / 2m;

			if (_prevClose <= prevMid && close > mid && fast > slow && Position <= 0)
			{
				if (Position < 0)
					BuyMarket();
				BuyMarket();
			}
			else if (_prevClose >= prevMid && close < mid && fast < slow && Position >= 0)
			{
				if (Position > 0)
					SellMarket();
				SellMarket();
			}
		}

		_prevClose = close;
		_prevUpper = high;
		_prevLower = low;
	}
}