コンテンツにスキップ

cBotのライフサイクル

この記事と付随するビデオでは、コード構造をステップスルーし、cTrader cBotのイベントとライフサイクルの背後にあるロジックを説明します。

念のため、cTraderのAlgoアプリケーションでcBotにアクセスできます。 新しいcBotを作成するには、新しいcBotボタンをクリックするか、下に表示されるドロップダウンからこのオプションを選択します。

基本的なテンプレートを解釈

新しいcBotを作成した後、コードエディタウィンドウに次の基本的な構造が表示されます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.None)]
    public class NewcBot : Robot
    {
        [Parameter(DefaultValue = "Hello world!")]
        public string Message { get; set; }

        protected override void OnStart()
        {
            // To learn more about cTrader Algo visit our Help Center:
            // https://help.ctrader.com/ctrader-algo

            Print(Message);
        }

        protected override void OnTick()
        {
            // Handle price updates here
        }

        protected override void OnStop()
        {
            // Handle cBot stop here
        }
    }
}

基本的なテンプレートには3つのイベントのみが表示されていることに注意してください。これらのイベントは、OnStart()OnTick()OnStop()メソッドによって処理されます。 後で説明するために、2つの追加メソッド(OnBar()OnException())を追加し、それらがどのように機能するかを説明します。まず、OnStart()メソッドについて説明します。

OnStart()メソッドを使用

OnStart()メソッドは、cBotが最初に起動したときにトリガーされます。 このメソッドは、cBotで使用する予定の変数(インジケーター、カウンター、イベントハンドラー、タイマーなど)を初期化するために使用されます。

注意

初期コードテンプレートには、cBotが起動したときにログにメッセージを出力するコードステートメントがすでに含まれています。 ご覧のとおり、cBotにはMessageパラメーターがあり、OnStart()メソッドはこのパラメーターの値をPrint()メソッドに渡します。

TradeアプリケーションでcBotインスタンスを起動し、ログタブを開いて結果を確認することで、OnStart()メソッドがどのように機能するかを示すことができます。

また、いつでもcBotを停止し、パラメータータブでMessageパラメーターの値を変更して、インスタンスを再起動することもできます。 起動時に、新しいメッセージがログに出力されます。

OnTick()メソッドを使用

OnTick()メソッドは、シンボルの売値または買値が変わるたびにトリガーされます。 このメソッド内では、通常、ポジションのエントリーとイグジットの条件、および新しいティックデータが到着したときに実行する必要があるその他の補助機能をプログラムできます。

OnTick()メソッドに次のコードを追加して、ログにメッセージを出力するようにします。

1
Print("OnTick. Bid: ", Symbol.Bid, ", Ask: ", Symbol.Ask);

以下に示すように、cBotは価格が変わるたびに売値と買値をログに出力します。

OnBar()メソッドを使用

OnBar()メソッドはデフォルトのcBotコードテンプレートには含まれていないため、次のコードスニペットを追加して追加します。

1
2
3
4
protected override void OnBar() 
{
    Print("OnBar");
}

OnBar()メソッドは、cBotがアタッチされているチャートに新しいバーまたはキャンドルが描画されるたびにトリガーされます。 OnTick()メソッドと同様に、OnBar()メソッドを使用して、ポジションのエントリーとイグジットの条件、および各新しいバーの形成時に実行する必要があるその他のロジックをプログラムできます。

OnBar()メソッドがどのようにトリガーされるか

H1チャートがある場合、新しいバーは1時間ごとに形成されるため、OnBar()メソッドは1時間に1回呼び出されます。 m1チャートがある場合、同じメソッドは1分ごとに呼び出されます。

OnBar()メソッドは、新しいバー/キャンドルごとに「OnBar」を出力します。 その動作をデモンストレーションするために、cBotをm1チャートにアタッチし、ログを見てみます。

OnStop()メソッドを使用

OnStop()メソッドは、ユーザーまたはコードによってcBotが停止したときに呼び出されます。 これが発生すると、OnStop()メソッド内のコードが実行されます。 これは、ポジションをクローズするなどの最終操作を実行するために使用できます。

OnStop()メソッドに次のコードを追加します。いつものように、cBotは停止時にMessageパラメーターの値を出力します。

1
Print(Message);

以下のスクリーンショットでは、cBotのインスタンスを起動して停止し、その動作をデモンストレーションします。

OnException()メソッドを使用する

OnException()メソッドは、未処理の例外をキャプチャしてフォールトトレランスを提供し、それらをどのように処理するかを決定できるようにします。 これはデフォルトのコードテンプレートには含まれていないため、以下のスニペットを使用して自分で追加します。

1
2
3
4
protected override void OnException(Exception exception) 
{
    Print("Ooops, unhandled exception! No worries, cBot still alive");            
}

OnException()メソッドをトリガーするために、存在しない取引の情報にアクセスしようとしたときに発生する例外をキャプチャするコードを書きます。 以下のコードをOnStart()メソッドに追加します。

1
ExecuteMarketOrder(TradeType.Buy, SymbolName, 1000, "my label");

OnStart()メソッドに書いたコードは、以下の設定可能なパラメータで成行注文を実行します。

  • 取引タイプは買い注文になります。
  • 取引は、cBotがアタッチされているチャートの現在の通貨ペアで実行されます。
  • 注文の取引高は1,000単位です。
  • 注文に付与されるユニークなラベルは「my label」です。

また、以下のコードをOnTick()メソッドに追加します。

1
2
3
var position = Positions.Find("my label");
if (Positions.Find("my label") != null) Print("PositionId: ", position.Id);
Print("Message below");

OnTick()メソッドに書いたコードは、OnStart()メソッドで開かれたポジションをラベル名「my label」を使用して見つけます。

同じラベルでポジションが見つかった場合、オープン取引のポジションIDをログに出力します。 また、次のコード行が実行される際に「Message below」という別のメッセージを出力します。

cBotが起動し、OnTick()メソッドが呼び出され、注文が見つかった場合、cBotは注文IDをログに出力し、注文IDの後に「Message below」メッセージを出力します。

ご覧の通り、例外は発生せず、cBotは完璧に仕事をこなします。

しかし、ここでcBotによって開かれたポジションを手動で決済し、例外が確実に発生するようにコードを少し変更します。 OnStart()メソッドで、注文ラベルを「cTrader」に変更します。 OnTick()メソッドで、「my label」ラベルを持つポジションが存在するかどうかをチェックする条件をコメントアウトします。

これがcBotの最終的なコードです。このコードは常に例外をトリガーします。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.None)]
    public class LifecycleTest : Robot
    {
        [Parameter(DefaultValue = "cTrader rocks!")]
        public string Message { get; set; }

        protected override void OnStart()
        {
            ExecuteMarketOrder(TradeType.Buy, SymbolName, 1000, "cTrader");
        }

        protected override void OnTick()
        {
            var position = Positions.Find("my label");
            //if (Positions.Find("my label") != null) 
            Print("PositionId: ", position.Id);
            Print("Message below");
        }

        protected override void OnStop()
        {
            Print(Message);
        }

        protected override void OnException(Exception exception) 
        {
            Print("Ooops, unhandled exception! No worries, cBot still alive");            
        }
    }
}

cBotを再度実行して、何が起こるか見てみましょう。

起こったことは、cBotが起動したときに新しい成行注文が作成されたことです。 この注文に付与されたラベルは"cTrader"でした。 OnTick()メソッドで、コードはmy labelのラベルを持つポジションを取得しようとし、条件付きのコード行をコメントアウトしたため、 ポジションIDをログに出力しようとしました。

これにより、以前のバージョンのcTraderではcBotが停止する例外エラーが発生しましたが、新しいOnException()メソッドを使用することで、これをキャプチャしてエラーを処理できるようになりました。 cBotは実行を続け、エラーをログに記録して修正できるようになります。

概要

cBotのライフサイクルは、OnStart()OnTick()OnStop()OnBar()OnException()メソッドを介して処理できるいくつかの主要なイベントで構成されています。 主要なイベントに対するcBotの応答をカスタマイズすることで、アルゴリズムが期待通りに動作することを保証できます。