GitHub で見る

テンプレートEAbyMarket戦略

概要

TemplateEAbyMarket は、オリジナルの MetaTrader 4 エキスパート アドバイザー TemplateEAbyMarket.mq4 の直接 StockSharp ポートです。この戦略では、移動平均収束発散 (MACD) 指標を使用して、運動量の変化を検出します。両方のコンポーネントが同じプラスまたはマイナスのゾーンにあるときに、MACD メイン ラインがシグナル ラインと交差すると、この戦略はクロスオーバーの方向に市場ポジションを開きます。手仕舞いは、組み込みの StartProtection ヘルパーを介して設定された保護注文 (利食いとストップロス) によってのみ管理されます。

StockSharp バージョンは、MQL プログラムの動作を維持しています。反対側のサイドを自動的にクローズしようとせず、新しいポジションのみをオープンします。ポジションが埋まると、取引は保護レベルまたは手動介入によって管理されます。

取引ロジック

  1. ユーザーが選択したローソク足のタイプを購読します (デフォルト: 15 分の時間枠)。
  2. 完成したキャンドルごとに MACD (デフォルトでは 12/26/9) を計算します。
  3. MACD のメイン ラインと信号ラインの相対位置を追跡して、クロスオーバー イベントを検出します。
    • 強気のセットアップ: 以前のローソク足はシグナルラインの下にメインラインがあり、現在のローソク足はシグナルラインの上にあるメインラインで終了し、両方のラインがゼロを上回っています。現在のエクスポージャーが MaxOrders * OrderVolume を下回る場合、OrderVolume の成行買い注文が送信されます。
    • 弱気のセットアップ: 以前のローソク足はシグナルラインの上にメインラインがあり、現在のローソク足はシグナルラインの下にあるメインラインで終了し、両方のラインはゼロを下回っています。 OrderVolume の成行売り注文は、同じエクスポージャ キャップに従って送信されます。
  4. 保護レベルの takeProfitstopLoss は起動時に一度有効になります。この戦略は反対のポジションを自動的に決済しません。リスクは保護モジュールまたはユーザーによって制御されます。

パラメーター

名前 説明
MacdFastPeriod MACD 計算のための高速な EMA の長さ。
MacdSlowPeriod MACD 計算の EMA の長さが遅いです。
MacdSignalPeriod MACD 計算用の信号 EMA の長さ。
CandleType インジケーターを供給するローソク足のタイプ (時間枠)。
OrderVolume 各成行注文で発注された数量。
MaxOrders 同時注文の最大数。OrderVolume の倍数で表されます。この戦略では、新しい注文を送信する前に abs(Position) < MaxOrders * OrderVolume をチェックします。
TakeProfitPoints 価格ポイントでの利食い距離。値 0 はテイクプロフィットを無効にします。
StopLossPoints 価格ポイントでのストップロス距離。値 0 はストップロスを無効にします。

注意事項

  • MQL バージョンのスリッページとマジック ナンバーの設定は、StockSharp では処理方法が異なるため、意図的に省略されています。
  • コネクタが適切な価格ステップのメタデータを提供することを確認します。 StartProtection は距離を商品価格ポイントで解釈します。
  • テンプレートは意図的に最小限に抑えられており、MaxOrders の制限を超える部分的な塗りつぶしやピラミッド エントリは管理しません。
namespace StockSharp.Samples.Strategies;

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

/// <summary>
/// Template EA by Market strategy: MACD histogram crossover with signal line.
/// </summary>
public class TemplateEAbyMarketStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _signalPeriod;

	private decimal _prevMacd;
	private decimal _prevSignal;
	private bool _hasPrev;

	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 int SignalPeriod { get => _signalPeriod.Value; set => _signalPeriod.Value = value; }

	public TemplateEAbyMarketStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_fastPeriod = Param(nameof(FastPeriod), 12)
			.SetGreaterThanZero()
			.SetDisplay("Fast Period", "MACD fast EMA", "Indicators");
		_slowPeriod = Param(nameof(SlowPeriod), 26)
			.SetGreaterThanZero()
			.SetDisplay("Slow Period", "MACD slow EMA", "Indicators");
		_signalPeriod = Param(nameof(SignalPeriod), 9)
			.SetGreaterThanZero()
			.SetDisplay("Signal Period", "MACD signal period", "Indicators");
	}

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

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_hasPrev = false;
		var macd = new MovingAverageConvergenceDivergenceSignal
		{
			Macd = { ShortMa = { Length = FastPeriod }, LongMa = { Length = SlowPeriod } },
			SignalMa = { Length = SignalPeriod }
		};
		var subscription = SubscribeCandles(CandleType);
		subscription.BindEx(macd, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, IIndicatorValue macdValue)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!macdValue.IsFinal) return;

		var v = (MovingAverageConvergenceDivergenceSignalValue)macdValue;
		if (v.Macd is not decimal macdLine || v.Signal is not decimal signal) return;

		if (_hasPrev)
		{
			var prevHist = _prevMacd - _prevSignal;
			var currHist = macdLine - signal;

			if (prevHist <= 0 && currHist > 0 && Position <= 0)
				BuyMarket();
			else if (prevHist >= 0 && currHist < 0 && Position >= 0)
				SellMarket();
		}

		_prevMacd = macdLine;
		_prevSignal = signal;
		_hasPrev = true;
	}
}