GitHub で見る

FX-CHAOSスカルプMT4戦略

概要

FX-CHAOS Scalp MT4 戦略は、素晴らしいオシレーター フィルターとフラクタルに基づいて構築された ZigZag レベルを組み合わせた MetaTrader 4 エキスパート アドバイザの直接ポートです。 StockSharp バージョンは、元のシステムのマルチタイムフレーム設計を維持しています。時間足ローソク足は取引シグナルを生成し、日足ローソク足はより高い時間枠のバイアスを提供します。 2 つの埋め込みトラッカーは、5 本のローソク足パターンをスキャンし、スイングの高値と安値を交互に記録することにより、「Fractals のジグザグ」インジケーターを再構築します。

取引ワークフロー

  1. データ収集
    • 時間ごとのローソク足は、主要な実行ロジックとリスク管理に役立ちます。
    • 毎日のローソク足は、トレンドフィルターとして使用される長期的なジグザグスイングを更新します。
    • オーサム オシレーター (5、34) は、ハイレベル インジケーター API を通じて時間系列で評価されます。
  2. ジグザグ再構築
    • 完成したキャンドルはすべて、スライド式の 5 要素窓に保管されます。
    • 中央のローソク足が上昇フラクタルを形成すると、トラッカーはローソク足の高さを最新のスイングとして保存し、方向を「上昇」に切り替えます。ダウン フラクタルは、低音に対しても同じことを行います。
    • 同じ方向への連続したスイングは、MT4 インジケーターのバッファー ロジックを模倣して、新しい極値がより顕著な場合にのみ置き換えられます。
  3. 信号検出
    • ブレイクアウト バッファは、元のコードにある 2*Point パディングを反映して、前の時間の高値/安値に 2 つの価格ステップ オフセットを追加します。
    • ロングエントリーの場合、ローソク足はバッファーされた高値より下で開き、その上で閉じ、最新の時間足ジグザグスイングより下に留まり、最新の日足スイングより上で閉じ、オーサムオシレーターをマイナスに保つ必要があります。
    • 短いエントリは、バッファされた下位、上位のジグザグ レベル、および正のオシレーター値を使用して条件を反映します。
  4. 注文の実行と競合の解決
    • 新しい注文が送信される前に反対のポジションがクローズされるため、この戦略ではロングとショートの同時取引が維持されることはありません。
    • 約定された終値は、後続のローソク足のストップロスとテイクプロフィットの距離を導き出すために保存されます。

リスク管理

  • ストップロスとテイクプロフィットのしきい値はオプションです。 0 の値は、対応するルールを無効にします。
  • 終了した各ローソク足の終わりに、戦略はローソク足の範囲が設定されたストップまたはターゲットに触れたかどうかを確認し、レベルを突破した場合はポジションを閉じます。
  • 逆のブレイクアウトが現れると、まずポジションが清算され、その後、単一ポジションのルールを維持するために、同じローソク足で新しい取引が送信されます。

パラメーター

名前 説明
Volume すべての成行注文に適用されるロット単位の取引量。
Stop Loss (pts) 保護停止までのポイント単位の距離。証券価格ステップを乗算します。無効にするには、0 に設定します。
Take Profit (pts) 利益目標までの距離 (ポイント単位)。価格ステップを乗算します。無効にするには、0 に設定します。
Breakout Buffer ブレイクアウトをテストする前に、前のローソク足の極値に追加のポイントが追加されます。デフォルト値はMT4で使用される2*Pointクッションを再現します。
Spread (pts) エントリーが MT4 の 2*Point + spread を反映するように、購入シグナルのブレイクアウトしきい値に追加されるポイント単位の平均スプレッド。
Trading Candle エントリに使用される主な時間枠 (デフォルトは 1 時間)。
Daily Candle ZigZag フィルターに使用されるより長い時間枠 (デフォルトは 1 日)。

実装メモ

  • この戦略は、リポジトリのガイドラインを尊重し、インジケーター バッファーを直接操作することを避けるために、高レベルの SubscribeCandles API および BindEx に依存しています。
  • Security.PriceStep から取得した価格ステップは、ポイントで表現されたパラメータ値を絶対価格距離に変換するために使用されます。機器にステップが欠けている場合、コードは 1 に戻ります。
  • どちらの ZigZag トラッカーも OnReseted にリセットされ、最初のスイングを決定するのに十分なローソク足が蓄積されるまで取引を一時停止します。これにより、歴史的コンテキストが欠落している場合の時期尚早なエントリが防止されます。
  • チャートのレンダリングでは、時間足のローソク足、オーサム オシレーター、および戦略トレードが描画され、StockSharp の実装と MT4 テンプレートの比較に役立ちます。
using System;

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

namespace StockSharp.Samples.Strategies;

public class FxChaosScalpMt4Strategy : Strategy
{
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<int> _momentumPeriod;
	private readonly StrategyParam<int> _cooldownCandles;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevMom;
	private bool _hasPrev;
	private int _cooldownRemaining;

	public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
	public int MomentumPeriod { get => _momentumPeriod.Value; set => _momentumPeriod.Value = value; }
	public int CooldownCandles { get => _cooldownCandles.Value; set => _cooldownCandles.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public FxChaosScalpMt4Strategy()
	{
		_emaPeriod = Param(nameof(EmaPeriod), 14).SetDisplay("EMA Period", "EMA filter", "Indicators");
		_momentumPeriod = Param(nameof(MomentumPeriod), 10).SetDisplay("Momentum", "Momentum period", "Indicators");
		_cooldownCandles = Param(nameof(CooldownCandles), 200).SetDisplay("Cooldown", "Candles between signals", "General");
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevMom = default;
		_hasPrev = default;
		_cooldownRemaining = default;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevMom = 0;
		_hasPrev = false;
		_cooldownRemaining = 0;

		var ema = new ExponentialMovingAverage { Length = EmaPeriod };
		var mom = new Momentum { Length = MomentumPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(ema, mom, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal ema, decimal mom)
	{
		if (candle.State != CandleStates.Finished) return;
		var close = candle.ClosePrice;
		if (!_hasPrev) { _prevMom = mom; _hasPrev = true; return; }

		if (_cooldownRemaining > 0)
		{
			_cooldownRemaining--;
			_prevMom = mom;
			return;
		}

		if (close > ema && _prevMom <= 0 && mom > 0 && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
			_cooldownRemaining = CooldownCandles;
		}
		else if (close < ema && _prevMom >= 0 && mom < 0 && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
			_cooldownRemaining = CooldownCandles;
		}
		_prevMom = mom;
	}
}