GitHub で見る

eInTradePanel戦略

eInTradePanel戦略は、元のMetaTraderトレードパネルのワークフローを自動化します。同じ8つの注文モード(両方向でのマーケット、ストップ、リミット、ストップリミット)を可能にしながら、現在のスプレッドとボラティリティに敏感なATR推定値からトリガー、エントリー、ストップロス、テイクプロフィット距離を自動的に計算します。保護注文はローソク足の監視を通じてシミュレートされるため、SL/TP注文の添付をサポートしないデータベンダーでも戦略を使用できます。

ハイライト

  • 注文モード – Buy、Sell、Buy/Sell Stop、Buy/Sell Limit、Buy/Sell Stop-Limitから選択します。ストップリミット注文は価格がトリガー距離に達すると発動し、次にリミットエントリーを送信します。
  • 動的な距離 – 保留レベル、トリガー、ストップ、ターゲットは現在のスプレッドまたはATR由来の合成スプレッド(ATR × AtrFactor)の大きい方に比例します。ATRが準備できていない場合、設定可能なベースティック距離が使用されます。
  • ボラティリティ適応 – ATRの長さは元のパネル(55)に従うため、オフセットは追加調整なしに市場の変化に反応します。
  • 注文の有効期限 – オプションのキャンセルウィンドウと最小存続時間の強制(デフォルト11分)により、古い保留注文をブックから排除します。
  • リスク管理 – すべてのオープンポジションは閉じたローソク足ごとに監視され、高値/安値が計算されたストップまたはターゲットを突き抜けるとポジションはマーケット価格でクローズされます。
  • クォート認識 – 戦略はより正確なオフセット計算のためにオーダーブックを購読して最良の買値/売値を取得し、深度が利用できない場合はローソク足のクローズにフォールバックします。

パラメーター

名前 説明
Volume すべてのエントリーに使用される注文サイズ。
Mode エントリーモード(マーケット、ストップ、リミット、ストップリミット)。
Candle Type ATRおよびローソク足ベースの実行チェックに使用される集計。
Base Ticks ATRデータが利用できない場合の最小ティック距離。
Pending Multiplier 保留注文オフセットのためのベースティック距離に適用される乗数。
Trigger Multiplier ストップリミットトリガー距離のための追加乗数。
Stop Multiplier ストップロス距離の乗数(無効にするには0に設定)。
Take Multiplier テイクプロフィット距離の乗数(無効にするには0に設定)。
Use ATR すべての距離のATRベースのスケーリングを有効にします。
ATR Factor スケーリング時に合成スプレッドとして扱われるATRの割合。
Expiration 保留注文がキャンセルされるまでの分数(0はGTCを維持)。
Min Expiration 分単位の最小保留存続時間、パネルの保護機能を反映。

取引ロジック

  1. データ準備 – 戦略は設定されたローソク足タイプを購読し、55期間のATRを更新し続けます。オーダーブックのスナップショットが最後に確認された買値/売値を更新します。
  2. 距離計算 – 完成したローソク足ごとにATRとスプレッドからベースティック距離を再計算し、選択されたモードに従って保留、トリガー、ストップ、テイクプロフィット価格を導出します。
  3. 注文提出
    • マーケットモードは戦略がフラットな間、次の完成したローソク足で即座に実行されます。
    • ストップとリミットモードは対応する保留注文を配置し、オプションで有効期限ウィンドウ後にキャンセルします。
    • ストップリミットモードはローソク足の高値/安値でトリガー価格が印刷されるまで待機し、次にリミットエントリーを送信します。
  4. ポジション監視 – ポジションがオープンになったら、戦略は完成したローソク足のストップまたはターゲット違反をチェックし、いずれかのレベルが違反された場合はポジションをマーケット価格でクローズします。
  5. 状態リセット – 戦略がフラットでアクティブな注文がない場合、次のローソク足で新しいトレードを準備できるようにレベルを再計算します。

このアプローチは手動パネルを反映しながら、StockSharpのハイレベルAPIと非同期注文フローとの互換性を維持します。

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>
/// EInTradePanel strategy. Uses ATR breakout for entries.
/// </summary>
public class EInTradePanelStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _atrPeriod;
	private readonly StrategyParam<decimal> _multiplier;
	private decimal? _prevClose;
	private decimal? _prevAtr;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int AtrPeriod { get => _atrPeriod.Value; set => _atrPeriod.Value = value; }
	public decimal Multiplier { get => _multiplier.Value; set => _multiplier.Value = value; }

	public EInTradePanelStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
		_atrPeriod = Param(nameof(AtrPeriod), 14).SetGreaterThanZero().SetDisplay("ATR Period", "ATR lookback", "Indicators");
		_multiplier = Param(nameof(Multiplier), 1.5m).SetDisplay("Multiplier", "ATR multiplier for breakout", "Indicators");
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevClose = null;
		_prevAtr = null;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevClose = null; _prevAtr = null;
		var atr = new AverageTrueRange { Length = AtrPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(atr, ProcessCandle).Start();
		var area = CreateChartArea();
		if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, atr); DrawOwnTrades(area); }
	}

	private void ProcessCandle(ICandleMessage candle, decimal atrVal)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!IsFormedAndOnlineAndAllowTrading()) { _prevClose = candle.ClosePrice; _prevAtr = atrVal; return; }
		if (_prevClose == null || _prevAtr == null) { _prevClose = candle.ClosePrice; _prevAtr = atrVal; return; }
		var threshold = _prevAtr.Value * Multiplier;
		var diff = candle.ClosePrice - _prevClose.Value;
		if (diff > threshold && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
		else if (diff < -threshold && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
		_prevClose = candle.ClosePrice; _prevAtr = atrVal;
	}
}