GitHub で見る

EXP FIBO ZZ 戦略

概要

EXP FIBO ZZ 戦略は、MetaTrader 4 Expert Advisor EXP_FIBO_ZZ_V1en の C# ポートです。オリジナルのブレイクアウトを再現します ロジック: 最後に確認されたジグザグ コリドーを監視し、スイング高値の上に買いストップを配置し、スイング安値の下に売りストップを配置します。 Fibonacci ベースのストップロス注文とテイクプロフィット注文を添付します。 StockSharp バージョンは、すべての構成可能な入力を公開します。 StrategyParam オブジェクトを使用し、広範な検証を追加し、残高ベースのリスクを含む元の資金管理オプションを維持します サイジングと損益分岐点の調整。

取引ロジック

  1. データの準備

    • この戦略は、設定された CandleType (デフォルト: 1 分ローソク足) をサブスクライブし、シリーズを HighestZigZagDepth に等しい長さの Lowest インジケーター。
    • 軽量の ZigZag 検出器は、最新の 3 つのピボット価格を追跡します。新しいピボットは、次の場合にのみ登録されます。
      • ローソク足の高値/安値はインジケーターの出力と同じです。
      • 前回の転換点から少なくとも ZigZagBackstep バーが経過しました。
      • 現在のピボットからの価格偏差が ZigZagDeviationPips を超えています (MetaTrader ピップで表されます)。
  2. コリドーの検証

    • 3 つのピボットが使用可能になると、最も古い 2 つのピボットがコリドーを定義します。コリドーの高さが次の範囲にある場合にのみ取引が続行されます。 MinCorridorPipsMaxCorridorPips、および最新のピボットは、小さなブローカー スタイルのバッファーを備えてバンド内に厳密に配置されます。
    • ユーザーが指定した取引ウィンドウ (StartHour/StartMinuteStopHour/StopMinute) の外では、すべての未決注文がキャンセルされます。
  3. 注文の発注

    • 売買ストップ価格は、コリドー境界プラス/マイナス EntryOffsetPips として計算されます。
    • ストップロス距離は corridor * FiboStopLoss / 100 に等しい。利食い距離は MetaTrader の式に従います corridor * (FiboTakeProfit / 100 - 1) は負の値がゼロにクランプされます。
    • 注文を出す前に、ストラテジーは取引量を計算します。 RiskPercent > 0 の場合、コードは選択した資本を乗算します ソース(UseBalanceForRisktrueの場合は資本、それ以外の場合は資本からブロックマージンを差し引いたもの)をリスクパーセンテージで割ります。 参考価格による結果です。ボリュームは取引所ロット グリッドにスナップされ、取引所制限にクリップされます。いつ 必要な情報が利用できない場合、アルゴリズムは FixedVolume にフォールバックします。
    • アクティブなエントリー注文は、目標価格または数量が変更されるたびに変更されます。それ以外の場合は、新しい注文が送信されます。
  4. ポジション管理

    • ポジションがオープンするとすぐに、アルゴリズムは反対の未決注文をキャンセルし、保護注文を登録します。
      • 事前に計算された距離での SellStop/BuyStop 経由のストップロス。
      • SellLimit/BuyLimit 経由のオプションのテイクプロフィット。
    • オプションの損益分岐点モジュール (EnableBreakEven) は、元の MovingInWL ルーチンを反映しています。積み上げた後は ストップ利益の BreakEvenTriggerPips がエントリー価格プラス/マイナス BreakEvenOffsetPips に移動され、少なくとも保証されます 繰り返しの調整を防ぎながら、わずかなゲインを実現します。
  5. セッションメンテナンス

    • 取引ウィンドウを終了するか、ポジションをフラット化すると、未処理の保留注文またはプロテクション注文がキャンセルされます。方法 OnStopped は、戦略が終了したときにすべての注文もクリアします。

パラメーター

名前 説明 デフォルト 注意事項
CandleType ZigZag ピボットの構築に使用されるデータ シリーズ。 1m TimeFrame() あらゆる StockSharp キャンドル タイプをサポートします。
ZigZagDepth ジグザグ スイング間のローソクの最小数。 12 MT4 ExtDepth 入力と一致します。
ZigZagDeviationPips 新しいピボットを受け入れるまでの最小偏差 (MetaTrader ピップ単位)。 5 ミラー ExtDeviation
ZigZagBackstep ジグザグが再び反転できるようになるまでの最小バー数。 3 ExtBackstep と同等。
EntryOffsetPips 逆指値注文を出すときにコリドーの上下に追加される距離 (ピップ)。 5 ミラー n_pips
MinCorridorPips コリドー サイズの下限。 20 ミラー Min_Corridor
MaxCorridorPips コリドー サイズの上限。 100 ミラー Max_Corridor
FiboStopLoss Fibonacci 比率をコリドーに適用して、ストップロス距離を導き出します。 61.8 ミラー Fibo_StopLoss
FiboTakeProfit Fibonacci 比率はテイクプロフィットターゲットの計算に適用されます。 161.8 ミラー Fibo_TakeProfit
StartHour / StartMinute 許可された取引セッションの開始。 00:01 注文は期間外にキャンセルされます。
StopHour / StopMinute 取引セッションの終了。 23:59 真夜中を含む夜間セッションをサポートします。
UseBalanceForRisk リスクのサイジングには、株式 (true) または利用可能な現金 (false) を選択します。 true ミラー Choice_method
RiskPercent 次の取引に割り当てられる資本の割合。 1 リスクベースのサイジングを無効にするには、0 に設定します。
FixedVolume リスクサイジングが無効または利用できない場合に使用されるロットサイズ。 0.1 Lots 入力をミラーリングします。
EnableBreakEven 損益分岐点調整を有効にします。 true ミラー MovingInWL
BreakEvenTriggerPips ストップを移動する前に必要な利益 (pips)。 13 ミラー LevelProfit
BreakEvenOffsetPips 損益分岐点に適用されるオフセット (ピップ単位)。 2 ミラー LevelWLoss
DrawCorridorLevels アクティブなコリドーをチャート上にプロットします。 false オプションの線描画フラグをミラーリングします。

実装メモ

  • Pip 変換は、3 桁および 5 桁の外国為替記号の場合、PriceStep を 10 倍することで、MetaTrader の規則を尊重します。
  • 注文価格と数量は、取引所メタデータ (PriceStepVolumeStepMinVolumeMaxVolume)。
  • ポートフォリオデータまたは参照価格が欠落している場合、リスクサイジングは適切にフォールバックし、戦略が引き続き機能することを保証します。 設定された固定ロット。
  • 損益分岐点ルーチンは、取引ごとに 1 回だけ保護ストップをキャンセルして再登録し、ストップを超えてストップを設定することはありません。 エントリー価格。
  • DrawCorridorLevels が有効な場合、戦略は現在のピボットの高値ピボットと低値ピボットの間に垂直セグメントを描画します。 コリドーにより、取引範囲を素早く視覚的に確認できます。

MetaTrader バージョンとの違い

  • MT4 スクリプトのチャート オブジェクト、サウンド、画面コメントは省略されました。 StockSharp のロギングとチャートのプリミティブは、 同じニーズ。
  • リスクサイジングでは、MarketInfo のマージン値の代わりにポートフォリオの資産と最新の既知の価格が使用されます。これらの詳細はブローカーによって決定されるためです。 特定のものであり、プラットフォームに依存しない方法で使用できません。
  • 注文管理では、手動チケットの代わりに高レベルの StockSharp API (BuyStopSellStopSellLimitBuyLimit) を使用します 取り扱い。動作は同等のままですが、必要な定型コードは少なくなります。
  • ZigZag 検出器は、組み込みインジケーターを使用して深度/偏差/バックステップ ロジックを再実装し、互換性を維持します。 StockSharp のストリーミング キャンドル モデル。
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Exp Fibo ZZ: Fibonacci-style breakout using high/low channel with ATR stops.
/// </summary>
public class ExpFiboZzStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _channelLength;
	private readonly StrategyParam<int> _atrLength;
	private readonly StrategyParam<int> _emaLength;

	private decimal _entryPrice;
	private decimal _prevHigh;
	private decimal _prevLow;
	private readonly decimal[] _highs = new decimal[15];
	private readonly decimal[] _lows = new decimal[15];
	private int _barCount;

	public ExpFiboZzStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe.", "General");

		_channelLength = Param(nameof(ChannelLength), 15)
			.SetDisplay("Channel", "N-bar channel lookback.", "Indicators");

		_atrLength = Param(nameof(AtrLength), 14)
			.SetDisplay("ATR Length", "ATR period.", "Indicators");

		_emaLength = Param(nameof(EmaLength), 50)
			.SetDisplay("EMA Length", "Trend filter.", "Indicators");
	}

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public int ChannelLength
	{
		get => _channelLength.Value;
		set => _channelLength.Value = value;
	}

	public int AtrLength
	{
		get => _atrLength.Value;
		set => _atrLength.Value = value;
	}

	public int EmaLength
	{
		get => _emaLength.Value;
		set => _emaLength.Value = value;
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_entryPrice = 0;
		_barCount = 0;
		_prevHigh = 0;
		_prevLow = 0;
		Array.Clear(_highs, 0, _highs.Length);
		Array.Clear(_lows, 0, _lows.Length);
	}

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

		_entryPrice = 0;
		_barCount = 0;
		_prevHigh = 0;
		_prevLow = 0;

		var atr = new AverageTrueRange { Length = AtrLength };
		var ema = new ExponentialMovingAverage { Length = EmaLength };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(atr, ema, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, ema);
			DrawOwnTrades(area);
		}
	}

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

		var len = Math.Min(ChannelLength, _highs.Length);
		var idx = _barCount % len;
		_highs[idx] = candle.HighPrice;
		_lows[idx] = candle.LowPrice;
		_barCount++;

		if (_barCount < len || atrVal <= 0)
			return;

		var high = decimal.MinValue;
		var low = decimal.MaxValue;
		for (var i = 0; i < len; i++)
		{
			if (_highs[i] > high) high = _highs[i];
			if (_lows[i] < low) low = _lows[i];
		}

		var close = candle.ClosePrice;

		if (_prevHigh == 0 || _prevLow == 0)
		{
			_prevHigh = high;
			_prevLow = low;
			return;
		}

		if (Position > 0)
		{
			if (close >= _entryPrice + atrVal * 3m || close <= _entryPrice - atrVal * 1.5m)
			{
				SellMarket();
				_entryPrice = 0;
			}
		}
		else if (Position < 0)
		{
			if (close <= _entryPrice - atrVal * 3m || close >= _entryPrice + atrVal * 1.5m)
			{
				BuyMarket();
				_entryPrice = 0;
			}
		}

		if (Position == 0)
		{
			if (close > _prevHigh && close > emaVal)
			{
				_entryPrice = close;
				BuyMarket();
			}
			else if (close < _prevLow && close < emaVal)
			{
				_entryPrice = close;
				SellMarket();
			}
		}

		_prevHigh = high;
		_prevLow = low;
	}
}