GitHub で見る

同期チャートの確認戦略

この戦略は、同じ金融商品の 2 つのローソク足フィードを監視することにより、元の MQL の「SyncCharts」ユーティリティのアイデアを反映しています。 両方のストリームが同じトレンド方向を確認した場合にのみ取引の決定を下します。マスター シリーズは参照チャートとして機能します (トレーダーが通常監視するもの)、フォロワー シリーズは補助チャート (たとえば、より速いタイムフレームや 代替集計)。市場に参入する前に両方のストリームを強制的に一致させることにより、システムは次のようなノイズをフィルタリングして除去します。 チャート間隔間の一時的な非同期。

この設定は、指数先物や流動的な通貨ペアなど、複数の時間枠のトレンド構造を示す商品で最も効果的に機能します。 取引が行われる前に両方のチャートが同時に動く必要があるため、誤ったシグナルが減少し、戦略が自然に制限されます。 時間枠が一致しない、または新しいローソク足が異なる瞬間に印刷される、混沌とした市場段階でのエクスポージャ。

詳細

  • エントリー基準:
    • ロング: マスターとフォロワーの両方の単純移動平均 (SMA) は、直近の完成したローソク足で上向きに傾斜しています。 これらのローソク足のタイムスタンプの差は同期許容値未満です。
    • 短い: 両方の SMA は下向きに傾斜しており、タイムスタンプの差は許容範囲内にあります。
  • 終了基準:
    • 時間の非同期: 最新のローソク足が許容誤差を超えて離れている場合、ポジションはフラット化されます。
    • トレンドの不一致: 一方の SMA が上昇し、他方が下落した場合、オープンポジションは直ちにクローズされます。
  • ストップ: 暗黙的なフラット化ロジックはソフト ストップとして機能します。個別のハード ストップは送信されません。
  • ロング/ショート: 両側が取引されます。
  • デフォルト値:
    • マスターキャンドル:5分のタイムフレーム。
    • フォロワーキャンドル:1分のタイムフレーム。
    • SMA 長さ: 両方のストリームで 20 ピリオド。
    • 同期許容範囲: ローソク足のオープン時間間の間隔は 15 秒です。
  • フィルター:
    • カテゴリ: トレンド確認/マルチタイムフレーム。
    • 方向: 双方向。
    • インジケーター: SMA (デュアル ストリーム)。
    • ストップ: 固定ストップはなく、チャートが発散すると自動的にフラット化されます。
    • 複雑さ: 中 (同期チェックを伴うマルチサブスクリプション)。
    • 時間枠: 設定可能 (デフォルトは日中)。
    • 季節性:なし。
    • ニューラルネットワーク: いいえ。
    • ダイバージェンス: 時間枠のダイバージェンスをフィルターとして使用します (価格のダイバージェンスではなく、合意が必要です)。
    • リスクレベル:確認が必要なため中程度。

仕組み

  1. 2 つのローソク足サブスクリプションが高レベルの StockSharp API 経由で作成されます。1 つはマスター チャート用、もう 1 つはフォロワー用です。
  2. 各フィードは同じ長さの SMA によって処理され、トレンド方向フラグ (SMA の値が上昇した場合は up) が生成されます。 前のローソク足、それ以外の場合は down)。
  3. 両方のローソク足が終了するたびに、戦略はそれらのタイムスタンプが十分に近いこと (絶対差が以下のものであること) を検証します。 設定された許容値)。
  4. チャートが同期し、両方のトレンドが上を向いている場合、戦略は買いになります (空売りを最初に閉じる)。両方のトレンドが下向きの場合、 空売りします(ロングがあれば最初にクローズします)。
  5. 同期の喪失やトレンドの不一致が発生した場合は、アカウントをチャートと一致させるために即座にフラット化がトリガーされます。 トレーダーの時計。

推奨される使用方法

  • 通常は相関する 2 つの異なる時間枠で同じ商品に適用します (例: 5 分と 1 分、または 1 時間と 1 時間)。 15分)。
  • わずかな遅延を伴うローソク足を出力する特殊なデータ ソースを使用する場合は、同期許容値を増やします。
  • ライブ取引に導入する場合は、外部リスクマネージャーまたはアドオン停止モジュールと組み合わせてください。
namespace StockSharp.Samples.Strategies;

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

/// <summary>
/// Sync Charts Confirmation strategy: dual SMA trend confirmation.
/// Uses fast and slow SMAs to confirm trend direction.
/// Buys when both SMAs trend up, sells when both trend down.
/// </summary>
public class SyncChartsConfirmationStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _signalCooldownCandles;
	private bool _wasBullish;
	private bool _hasPrevTrend;
	private int _candlesSinceTrade;

	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 SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }

	public SyncChartsConfirmationStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_fastPeriod = Param(nameof(FastPeriod), 10)
			.SetGreaterThanZero()
			.SetDisplay("Fast Period", "Fast SMA period", "Indicators");
		_slowPeriod = Param(nameof(SlowPeriod), 40)
			.SetGreaterThanZero()
			.SetDisplay("Slow Period", "Slow SMA period", "Indicators");
		_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
			.SetGreaterThanZero()
			.SetDisplay("Signal Cooldown", "Bars to wait between signals", "Trading");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_wasBullish = false;
		_hasPrevTrend = false;
		_candlesSinceTrade = SignalCooldownCandles;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_hasPrevTrend = false;
		_candlesSinceTrade = SignalCooldownCandles;
		var fast = new SimpleMovingAverage { Length = FastPeriod };
		var slow = new SimpleMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fast, slow, ProcessCandle).Start();
	}

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

		if (_candlesSinceTrade < SignalCooldownCandles)
			_candlesSinceTrade++;

		var isBullish = fast > slow;

		if (_hasPrevTrend && isBullish != _wasBullish && _candlesSinceTrade >= SignalCooldownCandles)
		{
			if (isBullish && Position <= 0)
			{
				BuyMarket();
				_candlesSinceTrade = 0;
			}
			else if (!isBullish && Position >= 0)
			{
				SellMarket();
				_candlesSinceTrade = 0;
			}
		}

		_wasBullish = isBullish;
		_hasPrevTrend = true;
	}
}