GitHub で見る

タイムド・バイオーダー戦略

概要

タイムド・バイオーダー戦略は、1秒タイマーによって駆動される成行買い注文のストリームを送信するMetaTraderのエキスパートアドバイザーbuy_order.mq4を複製します。StockSharpポートは同じ取引リズムを維持します:タイマーが現在の分内の期待される秒と一致するまで待機し、次の注文を送信します。事前定義された数の執行後、戦略は自動的に停止します。

この実装は手動ループの代わりにStockSharpの高レベルTimerサービスに依存しています。市場インジケーターやキャンドルサブスクリプションは不要で、ロジックを決定論的かつ時間指向にしています。

コアロジック

  1. 戦略が開始すると、StartProtection()を介してリスク保護をアクティブにし、設定されたインターバル(デフォルト:1秒)でタイマーを開始します。
  2. 各タイマーコールバックは、戦略がオンラインで取引許可されているかどうか、および現在の取引所の秒がシーケンスの期待値と一致するかどうかを確認します。
  3. すべてのチェックが成功した場合、戦略は設定されたボリュームで成行買い注文を送信します。
  4. このプロセスは目標注文数が送信されるまで繰り返され、その後戦略は停止します。

秒の同期動作は元のMQLエキスパートを反映します:最初の注文は秒の成分がゼロに達したときのみ送信され、その後の各注文は次の秒の値に結びついています。

パラメーター

名前 デフォルト 説明
OrderVolume decimal 0.01 各成行買い注文の数量。値が正でない場合、バリデーションガードが戦略を停止します。
OrdersToPlace int 60 停止前に送信する連続買い注文の総数。
Interval TimeSpan 1s タイマーコールバック間の遅延。1秒に設定するとMQLのタイミングを最もよく再現しますが、実験のために他の値も可能です。

すべてのパラメーターはStockSharpのStrategyParam<T>オブジェクトを通じて公開されているため、UIツールから最適化または設定できます。

実行フロー

  • 初期化OnReseted()でカウンターをリセットすることで、再起動または再最適化時にクリーンな状態を確保します。
  • 開始OnStarted()でタイマーが開始し、カウンターがリセットされます;保護はライフサイクルごとに1回有効化されます。
  • タイマーティックOnTimer()メソッドがシーケンシングチェックを実行し、送信注文をログに記録し、最後の注文が送信されたときに戦略を停止します。
  • 完了 – ヘルパーCompleteStrategy()が重複したシャットダウンの試みを防ぎ、Stop()をちょうど1回呼び出します。

変換に関する注意

  • MQL関数EventSetTimer(1)Timer.Start(TimeSpan.FromSeconds(1), OnTimer)にマッピングされます。
  • MetaTraderで使用される注文コメントとマジックナンバーはStockSharpに直接の対応がないため、進捗を追跡するためにロギングが使用されます。
  • 戦略はタイマートリガーをカウントする代わりに秒の成分を一致させることで「1分に60注文」の概念を維持します。

使用のヒント

  1. 戦略を開始する前に目的のセキュリティとポートフォリオを割り当ててください。
  2. OrderVolumeをインストゥルメントのロットサイズとブローカーのルールに合わせて調整してください。
  3. 少ない注文が必要な場合はOrdersToPlaceを減らしてください;秒ベースのペーシングを完全に無効にするには、Intervalを任意の値に設定し、コードから秒の一致を削除してください(高度な変更)。
  4. ログ出力を監視して注文の送信を追跡し、タイマーのアライメントが期待どおりに動作することを確認してください。

制限事項

  • 戦略は買いのみ行います;手動による介入またはブローカーが管理する保護ストップ以外の退出ロジックはありません。
  • 注文の配置は接続とオペレーティングシステムが提供するタイマーサービスの精度によって制限されます;大きな遅延はシーケンスを同期ずれにする可能性があります。

ファイル

  • CS/TimedBuyOrderStrategy.cs – メインのC#実装。
  • README_zh.md – 中国語ドキュメント。
  • README_ru.md – ロシア語ドキュメント。

プロジェクトの指示に従い、Pythonポートは意図的に省略されています;必要な場合は後で作成してください。

namespace StockSharp.Samples.Strategies;

using System;

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

/// <summary>
/// Strategy that submits a sequence of market buy orders on each candle close.
/// After a configurable number of orders have been placed, it stops.
/// </summary>
public class TimedBuyOrderStrategy : Strategy
{
	private readonly StrategyParam<int> _ordersToPlace;
	private readonly StrategyParam<DataType> _candleType;

	private int _ordersPlaced;

	/// <summary>
	/// Initializes a new instance of the <see cref="TimedBuyOrderStrategy"/> class.
	/// </summary>
	public TimedBuyOrderStrategy()
	{
		_ordersToPlace = Param(nameof(OrdersToPlace), 60)
			.SetGreaterThanZero()
			.SetDisplay("Orders To Place", "Number of sequential buy orders before stopping", "Trading");

		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle type", "Candle type for strategy calculation.", "General");
	}

	/// <summary>
	/// Total number of buy orders to submit before the strategy stops.
	/// </summary>
	public int OrdersToPlace
	{
		get => _ordersToPlace.Value;
		set => _ordersToPlace.Value = value;
	}

	/// <summary>
	/// Candle type.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

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

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_ordersPlaced = 0;

		var sma = new SMA { Length = 5 };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(sma, OnProcess)
			.Start();
	}

	private void OnProcess(ICandleMessage candle, decimal smaValue)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		if (_ordersPlaced >= OrdersToPlace)
			return;

		BuyMarket();

		_ordersPlaced++;
	}
}