cTraderにおける並行注文の実行

cTraderの特徴の一つは、注文を実行する際に同期プログラミングと非同期プログラミングの両方を使用できることです。同期プログラミングを使用して、注文の実行結果を待ってから次の処理を進める必要がある戦略を実装することができます。一方、非同期プログラミングは、複数の注文を同時に送信する高速戦略を作成するのに最適です。

このビデオと対応する記事では、同期実行と非同期実行の違いを説明し、これらのアプローチを使用して新しい注文を行う方法を示します。

同期 vs 非同期注文実行

基本フロー

同期注文実行は、シンプルな図を使って説明できます。新しい注文を同期的に行う場合、cBotは他の指示を実行する前に1つの注文が実行されるのを待つ必要があります。つまり、cTraderはサーバーに注文を送り、応答を待ってから次のコード行の実行を開始します。

 
 
 
注文 1、100 ms
注文 2、70 ms
注文 3、80 ms
後続の指示

上記の注文を同期的に行う場合、cBotは注文 3の後の指示に進む前に合計250 msを費やす必要があります。

一方、非同期実行を使用すると、cTraderはサーバーからの応答を期待せずに複数の注文を並行して送信できます。非同期プログラミングを使用することで、複数の注文を実行するために必要な総時間を最小限に抑えることができます。

 
注文
 
 
注文 3、80 ms
注文 1、100 ms
注文 2、70 ms
後続の指示

上記の図では、すべての注文がまったく同時に送信されており、cBotはそれらの実行結果を待つことなく後続の指示に進んでいます。

コード例

同期実行がどのように機能するかをコードを使用して説明できます。

1
2
3
4
5
6
7
8
9
protected override void OnStart()
{
    for (int i = 0; i < 10; i++)
    {
        ExecuteMarketOrder(TradeType.Buy, SymbolName, 1000);
        Print("注文送信済み");
        Print("ポジション数:" + Positions.Count); 
    }
}

このコードを含むcBotを実行すると、ログにはポジション数が各ポジションの実行後にのみ増加していることが表示されます。このコードは、次の注文の実行要求を送信する前に各注文の実行を待機しています。

非同期注文実行に変更するには、ExecuteMarketOrderAsyncメソッドを使用できます。

1
2
3
4
5
6
7
8
9
protected override void OnStart()
{
    for (int i = 0; i < 10; i++)
    {
        ExecuteMarketOrderAsync(TradeType.Buy, SymbolName, 1000);
        Print("注文送信済み");
        Print("ポジション数:" + Positions.Count); 
    }
}

また、Positions.Openedイベントをリッスンするためのイベントハンドラを追加します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
protected override void OnStart()
{
    Positions.Opened += Positions_Opened;
    for (int i = 0; i < 10; i++)
    {
        ExecuteMarketOrderAsync(TradeType.Buy, SymbolName, 1000, PositionOpened);
        Print("注文送信済み");
        Print("ポジション数:" + Positions.Count); 
    }
}

イベントハンドラでは、ポジションが開いたときにログにメッセージと現在のポジション数を表示します。

このコードを含むcBotを実行し、ログを確認すると、すべての注文が送信され、前の指示の結果を受け取ることなく送信されたことがわかります。ポジションカウンタはずっと0のままでした。確認はすべての注文がサーバーに送信された数ミリ秒後にログに表示されました。

コールバック注文の使用

次に、非同期実行のもう一つの重要な機能であるコールバックメソッドの使用を示します。注文実行が完了したときに呼び出されるコールバックメソッドを実装します。Positions.Openedイベントのハンドラを削除し、注文実行が完了したことを確認するコールバックメソッドを実装します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private void TradeExecuted(TradeResult tradeResult)
{
    if (tradeResult.IsSuccessful)
    {
        Print("取引成功。ポジションが開かれました。");
    }
    else
    {
        Print("取引失敗。ポジションが開かれませんでした。");
    }
}

次に、このメソッドをExecuteMarketOrderAsyncメソッドの引数として渡します。

1
ExecuteMarketOrderAsync(TradeType.Buy, SymbolName, 1000, TradeExecuted);

以前のアプローチとは対照的に、コールバックメソッドは取引が成功したかどうかに関係なく呼び出されます。つまり、成功しなかった取引についても通知され、それに応じて対処することができます。

非同期実行のステータスの監視

cTraderは、非同期取引のステータスを追跡するための使いやすいツールも提供しています。ExecuteMarketOrderAsyncメソッドは、注文がまだ実行中かどうかについての情報を含むTradeOperationオブジェクトを返します。

新しいフィールドを宣言することから始めます。

1
TradeOperation _tradeOperation;

次に、forループを削除し、注文実行の結果を新しいフィールドに代入します。

1
_tradeOperation = ExecuteMarketOrderAsync(TradeType.Buy, SymbolName, 1000, TradeExecuted);

また、cBotにタイマーを追加します。このタイマーは、100ミリ秒ごとに操作のステータスを確認します。

1
2
Timer.TimerTick += Timer_TimerTick;
Timer.Start(new System.TimeSpan(0, 0, 0, 0, 100));

操作がまだ実行中の場合、タイマーはこれをログに表示します。

1
2
3
4
5
6
7
8
private void Timer_TimerTick()
{
    Print("Tick");
    if (_tradeOperation != null)
    {
        Print("取引操作が実行中です: " + _tradeOperation.IsExecuting);
    }
}

cBotがビルドされると、デモアカウントでの動作をテストできます。ログでは、タイマーが非同期実行のステータスについて定期的に更新を表示するはずです。

まとめ

非同期実行は、注文の自動配置を同期プログラミングと比較してはるかに高速にする強力なツールです。ただし、取引の結果を知る必要がある場合は、同期実行を使用することもできます。非同期実行は、複数の注文を遅延なく並行して送信する必要がある場合に最適です。

私たちのYouTubeチャンネルに登録する

目次

このページについて