GitHub で見る

OverHedgeV2 グリッド戦略

この戦略はStockSharpの高レベルAPIでMetaTraderのOverHedge V2エキスパートアドバイザーを複製します。高速EMAと低速EMAの方向に従ってヘッジされたグリッドを構築し、動的なトンネル内でロングとショートの注文を交互に配置します。ポジションは幾何学的なロット進行に従って追加され、集約された未実現利益が設定された目標に達すると、バスケット全体が清算されます。

取引ロジック

  • トレンドフィルター: 8期間EMAが21期間EMAから少なくともMinDistancePips乖離している必要があります。フィルターは各サイクルの最初の取引の方向を決定します。
  • グリッドトンネル: トンネルの幅は現在のスプレッドを2倍にしたものに価格単位に変換したTunnelWidthPipsを加えたものです。サイクルが開始したら反対側のトリガーを定義します。
  • 注文の交互配置: 最初の3つのポジションはトレンド方向に開かれます。その後、アルゴリズムは同じトンネルアンカーを参照として使用しながら、エクスポージャーをヘッジするために側面を切り替えます。
  • ロットのエスカレーション: 各後続注文はStartVolumeから始まり、前のボリュームにBaseMultiplierを乗算します。サイズは銘柄のボリューム制約に合わせられます。
  • サイクル終了: 銘柄ロットあたりの純未実現利益がMinProfitTargetPipsを超え、バスケット総利益がProfitTargetPipsを超えると、戦略はすべてのオープンポジションを閉じてステートをリセットします。
  • 手動シャットダウン: ShutdownGridtrueに設定すると、残りのポジションが閉じられ、オフに切り替えるまで新しい注文が防止されます。

エントリー条件

ロングエントリー

  • トレンドフィルターが上昇トレンドを示している(EMA_short - EMA_long > MinDistancePips)。
  • Askプライスが現在の買いアンカー以上。
  • 戦略がシャットダウンモードでなく、バスケットが利益目標に達していない。

ショートエントリー

  • トレンドフィルターが下降トレンドを示している(EMA_long - EMA_short > MinDistancePips)。
  • Askプライスが現在の売りアンカー以下。
  • シャットダウンフラグがfalseで、バスケット利益目標にまだ達していない。

決済管理

  • 利益決済: 未実現バスケット利益がProfitTargetPipsを満たし、各オープン側がロットあたり少なくともMinProfitTargetPipsを獲得していると、すべてのポジションが成行で閉じられます。
  • 緊急決済: ShutdownGridtrueに設定すると、すべてのオープンエクスポージャーが即座に閉じられます。

インジケーターとデータ

  • 設定されたローソク足シリーズで計算された8期間EMA(高速)と21期間EMA(低速)。
  • レベル1サブスクリプションは、トンネルを構築してリアルタイムスプレッドとエントリー条件を比較するために最良のbid/askを追跡するために使用されます。

パラメーター

パラメーター 説明
StartVolume サイクル内の最初の注文の初期ボリューム。
BaseMultiplier 各後続注文のボリュームに適用される幾何学的乗数。
TunnelWidthPips 現在のスプレッドの2倍に追加される追加トンネル幅(pip単位)。
ProfitTargetPips 価格距離に変換されたpip単位のバスケット利益目標。
MinProfitTargetPips バスケットが閉じる前の各側の最小有利な動き。
ShortEmaPeriod 方向確認に使用される高速EMAの期間。
LongEmaPeriod 方向確認に使用される低速EMAの期間。
MinDistancePips トレンドを宣言するために必要な最小EMA分離。
CandleType EMAと取引ループを供給するローソク足の時間軸。
ShutdownGrid 清算を強制して新しい取引をブロックするブールスイッチ。

実践的な注意事項

  • デフォルトのローソク足期間は1時間です;元のEAで使用された時間軸に合わせて調整してください。
  • 戦略は最良のbid/askデータに依存しています;ライブ取引またはバックテスト中にレベル1の相場を提供してください。
  • StockSharpは銘柄ごとのネットポジションを維持するため、交互の買いと売りは独立したヘッジされたチケットを保持する代わりにネットエクスポージャーを減らすか反転させますが、バスケットロジックは意図された利益取得を模倣しています。
  • 生成されたトンネルとロットスケーリングが取引する市場に一致するように、常に銘柄固有のボリュームステップとティックサイズを確認してください。
using System;
using System.Collections.Generic;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Grid hedging strategy based on EMA crossover direction.
/// Opens positions on EMA trend, reverses on direction change.
/// </summary>
public class OverHedgeV2Strategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _shortEmaPeriod;
	private readonly StrategyParam<int> _longEmaPeriod;

	private int _prevSignal;

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

	public int ShortEmaPeriod
	{
		get => _shortEmaPeriod.Value;
		set => _shortEmaPeriod.Value = value;
	}

	public int LongEmaPeriod
	{
		get => _longEmaPeriod.Value;
		set => _longEmaPeriod.Value = value;
	}

	public OverHedgeV2Strategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");

		_shortEmaPeriod = Param(nameof(ShortEmaPeriod), 8)
			.SetGreaterThanZero()
			.SetDisplay("Short EMA", "Fast EMA length", "Indicators");

		_longEmaPeriod = Param(nameof(LongEmaPeriod), 21)
			.SetGreaterThanZero()
			.SetDisplay("Long EMA", "Slow EMA length", "Indicators");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

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

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

		_prevSignal = 0;

		var shortEma = new ExponentialMovingAverage { Length = ShortEmaPeriod };
		var longEma = new ExponentialMovingAverage { Length = LongEmaPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(shortEma, longEma, ProcessCandle)
			.Start();

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

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

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		var signal = shortEma > longEma ? 1 : shortEma < longEma ? -1 : _prevSignal;

		if (signal == _prevSignal)
			return;

		var oldSignal = _prevSignal;
		_prevSignal = signal;

		if (signal == 1 && oldSignal <= 0)
		{
			if (Position < 0)
				BuyMarket();
			if (Position <= 0)
				BuyMarket();
		}
		else if (signal == -1 && oldSignal >= 0)
		{
			if (Position > 0)
				SellMarket();
			if (Position >= 0)
				SellMarket();
		}
	}
}