GitHub で見る

初日の開始 MACD ヒストグラム戦略

概要

この戦略は、MetaTrader のエキスパート「2 1000 1 0.7% 0.5 500lev st」を再現するもので、新しい取引日の開始時に取引を入力し、MACD ヒストグラムの傾きで方向をフィルタリングします。このシステムは時間足ローソク足用に設計されており、元の MQL 設定から変換された固定資金管理パラメータに依存しています。

取引ロジック

  • この戦略は、時間ごとのローソク足を監視し、新しい日ごとに最初のローソク足を検出します。
  • 前日の最も最近完了した 2 つのローソク足の MACD ヒストグラムを評価します。
  • ヒストグラムがこれら 2 本のバーの間で下落した場合、システムは新しい日の最初のローソク足でロングポジションをオープンします。
  • ヒストグラムが増加した場合は、代わりにショートポジションをオープンします。
  • 一度にアクティブにできるポジションは 1 つだけです。反対のシグナルは、新しい方向を開始する前に現在の取引を終了します。

リスク管理

  • 初期ストップロス距離: 875 ポイント (商品価格ステップを乗算して価格に換算)。
  • テイクプロフィットディスタンス:510ポイント。
  • トレーリングストップ距離: 2172 ポイント。ストップはエントリー以降に到達した最高値(ロング)または最低(ショート)価格に従い、値が厳しくなると最初のストップを上書きします。
  • 元の損益分岐点オプションは無効になっていたため、ここでは省略されました。

パラメーター

名前 説明 デフォルト
CandleType 戦略で使用されるローソク足シリーズ (デフォルトでは時間ごと)。 1時間キャンドル
MacdFastPeriod MACD の短い EMA 期間。 58
MacdSlowPeriod MACDのEMA期間が遅いです。 195
MacdSignalPeriod MACD の信号線期間。 183
StopLossPoints インスツルメントポイントで表されるストップロス距離。 875
TakeProfitPoints テイクプロフィット距離(ポイント単位)。 510
TrailingStopPoints トレーリングストップの距離 (ポイント単位)。 2172

注意事項

  • この戦略は、ソースエキスパートの「前のバー値を使用」オプションを反映して、バー内先読みを回避するために完了したローソク足のみを使用します。
  • トレーリングおよび固定エグジットは内部で処理されるため、ストップの二重処理を防ぐために追加のポートフォリオ保護は無効のままにしておく必要があります。
  • このロジックでは、ブローカーが標準のポイント定義 (価格ステップ) を使用していることを前提としています。インストゥルメントが異なるティック サイズを使用する場合は、パラメータを調整します。
namespace StockSharp.Samples.Strategies;

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

/// <summary>
/// Day Opening MACD Histogram strategy: MACD histogram direction.
/// Buys when MACD histogram turns positive, sells when turns negative.
/// </summary>
public class DayOpeningMacdHistogramStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _signalPeriod;
	private readonly StrategyParam<int> _signalCooldownCandles;

	private decimal _prevHistogram;
	private int _candlesSinceTrade;
	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 int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }

	public DayOpeningMacdHistogramStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_fastPeriod = Param(nameof(FastPeriod), 12)
			.SetGreaterThanZero()
			.SetDisplay("MACD Fast", "MACD fast EMA period", "Indicators");
		_slowPeriod = Param(nameof(SlowPeriod), 26)
			.SetGreaterThanZero()
			.SetDisplay("MACD Slow", "MACD slow EMA period", "Indicators");
		_signalPeriod = Param(nameof(SignalPeriod), 9)
			.SetGreaterThanZero()
			.SetDisplay("Signal Period", "MACD signal period", "Indicators");
		_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 4)
			.SetGreaterThanZero()
			.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevHistogram = 0;
		_candlesSinceTrade = SignalCooldownCandles;
		_hasPrev = false;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevHistogram = 0;
		_candlesSinceTrade = SignalCooldownCandles;
		_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;

		if (_candlesSinceTrade < SignalCooldownCandles)
			_candlesSinceTrade++;

		if (macdValue is not MovingAverageConvergenceDivergenceSignalValue typed) return;
		if (typed.Macd is not decimal macdMain || typed.Signal is not decimal signal) return;

		var histogram = macdMain - signal;

		if (_hasPrev)
		{
			if (_prevHistogram <= 0 && histogram > 0 && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				BuyMarket();
				_candlesSinceTrade = 0;
			}
			else if (_prevHistogram >= 0 && histogram < 0 && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				SellMarket();
				_candlesSinceTrade = 0;
			}
		}

		_prevHistogram = histogram;
		_hasPrev = true;
	}
}