コンテンツにスキップ

cBotコードサンプル

このページでは、取引ボットの作成やアルゴリズムの開発のためのいくつかのPythonおよびC#コード例を提供しています。 以下のcBotは、いかなる金融リターンも保証するものではありません。 ライブ口座でインスタンスをデプロイする前に、必ずcBotをバックテストし、カスタマイズしてください。

cBotサンプルリポジトリ

さまざまな自動化戦略や取引スタイルのための実行可能なテンプレートを含む包括的なcBotコードサンプルは、GitHubのPythonおよびC#リポジトリで利用可能です。

同期操作

このセクションのすべてのcBotは操作を同期して実行します

マーケットオーダーの実行

  • 成功した操作を実行するシンプルなcBot

    以下の取引ボットは、起動時にマーケットオーダーを作成し、結果をresult変数に保存します。

    注文の実行が成功した場合、エントリー価格がログに出力されます。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    [Robot()]
    public class Sample_cBot : Robot
    {
        protected override void OnStart()
        {
            var result = ExecuteMarketOrder(TradeType.Buy, SymbolName, 10000);
    
            if (result.IsSuccessful)
            {
                var position = result.Position;
                Print("Position entry price is {0}", position.EntryPrice);
            }
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    class Sample_cBot():
        def on_start(self):
            result = api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, 10000)
    
            if result.IsSuccessful:
                position = result.Position
                api.Print(f"Position entry price is {position.EntryPrice}")
    

    ログ出力

    • cBot "New cBot"がEURUSD、h1で正常に開始されました。
    • 10000 EURUSDの買いマーケットオーダーを実行中
    • 10000 EURUSDの買いマーケットオーダーの実行が成功しました、ポジションPID14576001
    • ポジションのエントリー価格は1.19067です
  • カスタマイズ可能なパラメータを持つシンプルなcBot

    さまざまなcBotプロパティを宣言する際に、[Parameter()]宣言を使用して、それらをカスタマイズ可能なパラメータに変換できます。 cBotの新しいインスタンスが起動されると、あなた(または他のユーザー)はこれらにカスタム値を割り当てることができます。

    以下の例を考えてみてください。

    1
    2
    [Parameter("SMA Period", DefaultValue = 14)]
    public int SmaPeriod { get; set; }
    

    注意

    Python cBotは、.csファイルで宣言されたカスタマイズ可能なパラメータを使用します。

    1
    2
    [Parameter("SMA Period", DefaultValue = 14)]
    public int SmaPeriod { get; set; }
    

    上記の例では、以下の特性を定義しています:

    • パラメータの名前。 これは、cTrader UIに表示されます("SMA Period")。
    • ユーザーによって変更されない限り、すべての新しいインスタンスに適用されるパラメータのデフォルト値(DefaultValue = 14)。

    以下のコードでは、SmaPeriodプロパティを実際の取引ボットで使用する方法を示しています。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class SamplecBotReferenceSMA : Robot
    {
        [Parameter("Source")]
        public DataSeries Source { get; set; }
    
        [Parameter("SMA Period", DefaultValue = 14)]
        public int SmaPeriod { get; set; }
    
        private SampleSMA sma;
    
        protected override void OnStart()
        {
            sma = Indicators.GetIndicator<SampleSMA>(Source, SmaPeriod);
        }
    
        protected override void OnTick()
        {
            Print("{0}", sma.Result.LastValue);
        }
    }
    

    注意

    Python cBotは、.csファイルで宣言されたカスタマイズ可能なパラメータを使用します。

    1
    2
    3
    4
    5
    6
    class Sample_cBot():
        def on_start(self):
            self.sma = api.Indicators.GetIndicator<SampleSMA>(api.Source, api.SmaPeriod)
    
        def on_tick(self):
            api.Print(f"{self.sma.Result.LastValue}")
    

    私たちのボットは、カスタマイズ可能なSmaPeriodプロパティを取り、起動時にその値をIndicators.GetIndicator<SampleSMA>()メソッドに渡します。 このメソッドは、指定された期間の単純移動平均値を返します。

    cBotインスタンスを作成する際に、すべての調整可能なパラメータをインスタンス追加ウィンドウで設定できます。

    起動すると、cBotは各ティックでの最後の単純移動平均値を通知します。

    ログ出力

    • cBotインスタンス[Sample cBot Reference SMA, EURUSD, h1]が開始されました。
    • 0.975685714285714
    • 0.975681428571429
    • 0.97568
    • cBotインスタンス[Sample cBot Reference SMA, EURUSD, h1]がユーザーによって停止されました。
  • より多くの引数でマーケットオーダーを実行

    前の例では、ExecuteMarketOrder()メソッドに最小限の引数を渡しました。 それらは、取引タイプ(TradeType.Buy)、シンボル(Symbol)、およびボリューム(-1)でした。

    ExecuteMarketOrder()メソッドは、LabelStopLossTakeProfitCommentなどの追加の引数で呼び出すことができます。 以下の例では、ラベル("order 1")、損切り保護メカニズム(10)、および利食いレベル(10)を指定しています。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    [Robot(TimeZone = TimeZones.UTC)]
    public class Sample_cBot : Robot
    {
        protected override void OnStart()
        {
            var result = ExecuteMarketOrder(TradeType.Buy, SymbolName, 10000, "order 1", 10, 10);
    
            if (result.IsSuccessful)
            {
                var position = result.Position;
                Print("Position entry price is {0}", position.EntryPrice);
                Print("Position SL price is {0}", position.StopLoss);
            }
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    class Sample_cBot():
        def on_start(self):
            result = api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, 10000, "order 1", 10, 10)
    
            if result.IsSuccessful:
                position = result.Position
                api.Print(f"Position entry price is {position.EntryPrice}")
                api.Print(f"Position SL price is {position.StopLoss}")
    

    ログ出力

    • cBot "New cBot"がEURUSD、h1で正常に開始されました。
    • 10000 EURUSDの買いマーケットオーダーを実行中(SL: 10, TP: 10)
    • 10000 EURUSDの買いマーケットオーダーの実行が成功しました、ポジションPID14576098
    • ポジションのエントリー価格は1.1896です
    • ポジションのSL価格は1.1886です

ポジションの変更

以下の例では、注文が実行されたときに利食い値(10)のみを追加します。 その後、ポジションを変更して損切りを追加します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
[Robot()]
public class SamplecBbot : Robot
{
    protected override void OnStart()
    {
        var result = ExecuteMarketOrder(TradeType.Buy, SymbolName, 10000,
                                "order 1", null, 10);
        if (result.IsSuccessful)
        {
            var position = result.Position;
            Print("Position SL price is {0}", position.StopLoss);

            var stopLoss = position.EntryPrice - 10*Symbol.PipSize;
            ModifyPosition(position, stopLoss, position.TakeProfit);

            Print("New Position SL price is {0}", position.StopLoss);

        }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class Sample_cBot():
    def on_start(self):
        result = api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, 10000, "order 1", None, 10)

        if result.IsSuccessful:
            position = result.Position
            api.Print(f"Position SL price is {position.StopLoss}")
            stopLoss = position.EntryPrice - 10 * api.Symbol.PipSize
            api.ModifyPosition(position, stopLoss, position.TakeProfit)
            api.Print(f"New Position SL price is {position.StopLoss}")

ログ出力

ポジションのクローズ

  • 完全クローズの実行

    以下のコードサンプルは、マーケットオーダーを実行します。 結果のポジションの総利益が特定の値(null && position.GrossProfit > 10)を超える場合、そのポジションはクローズされます。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    [Robot()]
    public class Sample_cBot : Robot
    {
        protected override void OnStart()
        {
            ExecuteMarketOrder(TradeType.Buy, SymbolName, 10000, "myLabel");
        }
    
        protected override void OnTick()
        {
            var position = Positions.Find("myLabel");
            if (position != null && position.GrossProfit > 10)
            {
                ClosePosition(position);
                Stop();
            }
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Sample_cBot():
        def on_start(self):
            api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, 10000, "myLabel")
    
        def on_tick(self):
            position = api.Positions.Find("myLabel")
            if position is not None and position.GrossProfit > 10:
                api.ClosePosition(position)
                api.Stop()
    

    ログ出力

    • cBot "New cBot"がEURUSD、h1で正常に開始されました。
    • 10000 EURUSDの買いマーケットオーダーを実行中
    • 10000 EURUSDの買いマーケットオーダーの実行が成功しました、ポジションPID14576180
  • 部分クローズの実行

    前の例を変更して、同じラベル("myLabel")を持つ2つのマーケットオーダーを作成します。 新しいバーごとに、取引ボットはこれらの注文のうちの1つを正確に半分クローズしますが、そのボリュームが20,000以上の場合のみです。

    また、Positions.FindAll()メソッドを使用します。 これは、反復処理できるポジションのリストを返します。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    [Robot()]
    public class Sample_cBot : Robot
    {
        protected override void OnStart()
        {
            ExecuteMarketOrder(TradeType.Buy, SymbolName, 20000, "myLabel");
            ExecuteMarketOrder(TradeType.Buy, SymbolName, 30000, "myLabel");
        }
    
        protected override void OnBar()
        {
            var positions = Positions.FindAll("myLabel", SymbolName, TradeType.Buy);
    
            foreach (var position in positions)
            {
                if (position.VolumeInUnits >= 20000)
                {
                    ClosePosition(position, 15000);
                }
            }
        }
    }
    
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    class Sample_cBot():
        def on_start(self):
            api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, 20000, "myLabel")
            api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, 30000, "myLabel")
    
        def on_tick(self):
            positions = api.Positions.FindAll("myLabel", api.SymbolName, TradeType.Buy)
            for position in positions:
                if position.VolumeInUnits >= 20000:
                    api.ClosePosition(position, 15000)
    

    ログ出力

    • cBot "New cBot"がEURUSD、h1で正常に開始されました。
    • 20000 EURUSDの買いマーケットオーダーを実行中
    • 20000 EURUSDの買いマーケットオーダーの実行が成功しました、ポジションPID14579299
    • 30000 EURUSDの買いマーケットオーダーを実行中
    • 30000 EURUSDの買いマーケットオーダーの実行が成功しました、ポジションPID14579300

予約注文の作成

  • 指値注文と逆指値注文の作成

    指値注文と逆指値注文は予約注文です。それにもかかわらず、マーケットオーダーと同様に作成されます。 ただし、指値注文と逆指値注文を作成する際には、ターゲット価格を指定する必要があり、マーケットレンジはありません。

    このcBotは、2つの指値注文と1つの逆指値注文を作成します。 その後、注文を反復処理し、ラベルとIDをログに出力します。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    [Robot()]
    public class Sample_cBot : Robot
    {
        protected override void OnStart()
        {
            PlaceLimitOrder(TradeType.Buy, SymbolName, 10000, Symbol.Bid, "myLimitOrder");
            PlaceLimitOrder(TradeType.Buy, SymbolName, 20000, Symbol.Bid-2*Symbol.PipSize,
                    "myLimitOrder");
            PlaceStopOrder(TradeType.Buy, SymbolName, 10000, Symbol.Ask, "myStopOrder");
    
            foreach (var pendingOrder in PendingOrders)
            {
                Print("Order placed with label {0}, id {1}", pendingOrder.Label, pendingOrder.Id);
            }
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    class Sample_cBot():
        def on_start(self):
            api.PlaceLimitOrder(TradeType.Buy, api.SymbolName, 10000, api.Symbol.Bid, "myLimitOrder")
            api.PlaceLimitOrder(TradeType.Buy, api.SymbolName, 20000, api.Symbol.Bid - 2 * api.Symbol.PipSize, "myLimitOrder")
            api.PlaceStopOrder(TradeType.Buy, api.SymbolName, 10000, api.Symbol.Ask, "myStopOrder")
    
            for pendingOrder in api.PendingOrders:
                Print(f"Order placed with label {pendingOrder.Label}, id {pendingOrder.Id}")
    

    ログ出力

    • cBot "New cBot"がEURUSD、h1で正常に開始されました。
    • 10000 EURUSDの買い指値注文を実行中(価格: 1.19036)
    • 10000 EURUSDの買い指値注文の実行が成功しました、予約注文OID25220794
    • 20000 EURUSDの買い指値注文を実行中(価格: 1.19017)
    • 20000 EURUSDの買い指値注文の実行が成功しました、予約注文OID25220795
    • 10000 EURUSDの買い逆指値注文を実行中(価格: 1.19040)
    • 10000 EURUSDの買い逆指値注文の実行が成功しました、予約注文OID25220796
    • ラベルmyLimitOrder、ID25220794の注文が実行されました
    • ラベルmyLimitOrder、ID25220795の注文が実行されました
    • ラベルmyStopOrder、ID25220796の注文が実行されました
  • より多くのパラメータで予約注文を作成

    成行注文の場合と同様に、注文ラベル、各種保護メカニズム、注文の有効期限日を指定し、コメントを提供することもできます。

     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
    [Robot()]
    public class Sample_cBot : Robot
    {
        protected override void OnStart()
        {
            var midnight = Server.Time.AddDays(1).Date;
    
            PlaceLimitOrder(TradeType.Buy, SymbolName, 10000, Symbol.Bid, "mySample_cBot", 10, null, midnight, "First");
    
            PlaceStopOrder(TradeType.Buy, SymbolName, 10000, Symbol.Ask, "mySample_cBot", 10, 10, null, "Second");
    
            foreach (var order in PendingOrders)
            {
                var sl = order.StopLoss == null ? "" : "SL: " + order.StopLoss;
                var tp = order.TakeProfit == null ? "" : " TP: " + order.TakeProfit;
    
                var text = string.Format("{0} {1}", sl, tp);
    
                if (order.OrderType == PendingOrderType.Limit)
                    Print(order.Comment + " Limit Order " + text);
                else
                    Print(order.Comment + " Stop Order " + text);
            }
        }
    }
    
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    class Sample_cBot():
        def on_start(self):
            midnight = api.Server.Time.AddDays(1).Date
    
            api.PlaceLimitOrder(TradeType.Buy, api.SymbolName, 10000, api.Symbol.Bid, "mySample_cBot", 10, None, midnight, "First")
            api.PlaceStopOrder(TradeType.Buy, api.SymbolName, 10000, api.Symbol.Ask, "mySample_cBot", 10, 10, None, "Second")
    
            for order in api.PendingOrders:
                sl = "" if order.StopLoss is None else f"SL: {order.StopLoss}"
                tp = "" if order.TakeProfit is None else f"TP: {order.TakeProfit}"
    
                api.Print(f"{order.Comment} {order.OrderType} Order {sl} {tp}")
    

    ログ出力

    • cBot "New cBot"がEURUSD、h1で正常に開始されました。
    • 買い指値注文を実行 10000 EURUSD (価格: 1.19049, 損切り: 10, 有効期限: 2018/05/12 00:00:00)
    • 買い指値注文を実行 10000 EURUSD (価格: 1.19049, 損切り: 10, 有効期限: 2018/05/12 00:00:00) 成功, 予約注文 OID25220807
    • 買い逆指値注文を実行 10000 EURUSD (価格: 1.19053, 損切り: 10, 利食い: 10)
    • 買い逆指値注文を実行 10000 EURUSD (価格: 1.19053, 損切り: 10, 利食い: 10) 成功, 予約注文 OID25220808
    • 指値注文
    • 最初の指値注文 損切り: 1.18949
    • 2番目の逆指値注文 損切り: 1.18953 利食い: 1.19153

予約注文を変更

予約注文のいくつかの特性を変更することが可能です。

以下の例は、予約注文の目標価格、保護レベル、または有効期限日時を変更する方法を示しています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[Robot()]
public class Sample_cBot : Robot
{
    protected override void OnStart()
    {
        var price = Symbol.Ask + 10 * Symbol.PipSize;
        var expiry = Server.Time.AddHours(12);
        PlaceStopOrder(TradeType.Buy, SymbolName, 10000, price, "myLabel", 10, 10, expiry);
    }

    protected override void OnBar()
    {
        foreach (var order in PendingOrders)
        {
            if (order.Label == "myLabel")
            {
                double newPrice = Symbol.Ask + 5 * Symbol.PipSize;
                ModifyPendingOrder(order, newPrice, order.StopLossPips,
                                                            order.TakeProfitPips, order.ExpirationTime);
            }
        }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class Sample_cBot():
    def on_start(self):
        price = api.Symbol.Ask + 10 * api.Symbol.PipSize
        expiry = Server.Time.AddHours(12)

        api.PlaceStopOrder(TradeType.Buy, api.SymbolName, 10000, price, "myLabel", 10, 10, expiry)

    def on_bar(self):
        for order in api.PendingOrders:
            if order.Label == "myLabel":
                newPrice = api.Symbol.Ask + 5 * api.Symbol.PipSize
                api.ModifyPendingOrder(order, newPrice, order.StopLossPips, order.TakeProfitPips, order.ExpirationTime)

ログ出力

予約注文をキャンセル

注文をキャンセルするための構文は CancelPendingOrder(order) で、orderPendingOrder 型です。

以下の例は、ラベル "myLabel" を持つすべての注文をキャンセルする方法を示しています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
[Robot()]
public class Sample_cBot : Robot
{
    protected override void OnTick()
    {
        foreach (var order in PendingOrders)
        {
            if (order.Label == "myLabel")
            {
                CancelPendingOrder(order);
            }
        }
    }
}
1
2
3
4
5
class Sample_cBot():
    def on_tick(self):
        for order in api.PendingOrders:
            if order.Label == "myLabel":
                api.CancelPendingOrder(order)

ポジションのイベント

さまざまな取引操作に関連するイベントを購読することが可能です。 例えば、ポジションが開かれたかどうかをテストするために、すべての Position オブジェクトが開かれたときに発生するイベントを購読します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
[Robot()]
public class Sample_cBot : Robot
{
    protected override void OnStart()
    {
        Positions.Opened += PositionsOnOpened;
        ExecuteMarketOrder(TradeType.Buy, Symbol, 10000, "myLabel", 10, 10);
    }

    private void PositionsOnOpened(PositionOpenedEventArgs args)
    {
        var pos = args.Position;
        Print("Position opened at {0}", pos.EntryPrice);
    }
}
1
2
3
4
5
6
7
8
class Sample_cBot():
    def on_start(self):
        api.Positions.Opened += self.on_position_opened
        api.ExecuteMarketOrder(TradeType.Buy, api.Symbol, 10000, "myLabel", 10, 10)

    def on_position_opened(self, args):
        pos = args.Position
        api.Print(f"Position opened at {pos.EntryPrice}")

ログ出力

同様に、ポジションが閉じられるたびに発生するイベントを購読することも可能です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
[Robot()]
public class Sample_cBot : Robot
{
    protected override void OnStart()
    {
        Positions.Closed += PositionsOnClosed;
        ExecuteMarketOrder(TradeType.Buy, Symbol, 10000, "myLabel", 10, 10);
    }

    protected override void OnBar()
    {
        var position = Positions.Find("myLabel");
        if (position != null)
            ClosePosition(position);
    }

    private void PositionsOnClosed(PositionClosedEventArgs args)
    {
        var pos = args.Position;
        Print("Position closed with {0} profit", pos.GrossProfit);
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class Sample_cBot():
    def on_start(self):
        api.Positions.Closed += self.on_position_closed
        api.ExecuteMarketOrder(TradeType.Buy, api.Symbol, 10000, "myLabel", 10, 10)

    def on_bar(self):
        position = api.Positions.Find("myLabel")

        if position is not None:
            api.ClosePosition(position);            

    def on_position_closed(self, args):
        pos = args.Position
        api.Print(f"Position closed with {pos.GrossProfit} profit")

ログ出力

座標変換

以下のcBotは、チャート上で右クリックするだけで適切な方向に指値注文を実行できるようにします。 これは、マウスのY座標をチャートのY座標(シンボルの場合、シンボルの価格に対応)に変換することで実現されます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
[Robot(AccessRights = AccessRights.None)]
public class CoordinatesConverter : Robot
{
    protected override void OnStart()
    {
        Chart.MouseUp += Chart_MouseUp;
    }

    private void Chart_MouseUp(ChartMouseEventArgs obj)
    {
        var desiredPrice = Chart.YToYValue(obj.MouseY);
        var desiredTradeType = desiredPrice > Symbol.Bid ? TradeType.Sell : TradeType.Buy;
        PlaceLimitOrder(desiredTradeType, SymbolName, 10000, desiredPrice);
    }
}
1
2
3
4
5
6
7
8
class Sample_cBot():
    def on_start(self):
        api.Chart.MouseUp += self.on_chart_mouse_up        

    def on_chart_mouse_up(self, args):
        desiredPrice = api.Chart.YToYValue(args.MouseY)
        desiredTradeType = TradeType.Sell if desiredPrice > api.Symbol.Bid else TradeType.Buy
        api.PlaceLimitOrder(desiredTradeType, api.SymbolName, 10000, desiredPrice)

非同期実行

上記のコードサンプルは、同期実行を使用して取引ロボットを実装するように設計されています。 C#とPythonはどちらも非同期操作をサポートしており、cBotが同じ時間枠内で複数のアクションを実行できるようにします。

成行注文を非同期で実行

非同期メソッドの構文は同期メソッドの構文と似ています。 同じタイプの引数を受け取りますが、戻り値の型は TradeResult ではなく TradeOperation です。

  • 基本的な非同期操作

    以下のcBotは、非同期操作がどのように機能するかを示しています。 成行注文が作成され、次の条件でcBotは操作が実行中かどうかを確認します。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    [Robot()]
    public class Sample_cBot : Robot
    {
        protected override void OnStart()
        {
            var operation = ExecuteMarketOrderAsync(TradeType.Buy, SymbolName, 10000);
    
            if (operation.IsExecuting)
            {
                Print("Operation Is Executing");
            }
        }
    }
    
    1
    2
    3
    4
    5
    6
    class Sample_cBot():
        def on_start(self):
            operation = api.ExecuteMarketOrderAsync(TradeType.Buy, api.SymbolName, 10000)
    
            if operation.IsExecuting:
                api.Print("Operation Is Executing")
    

    ログ出力

    • cBot "New cBot"がEURUSD、h1で正常に開始されました。
    • 成行注文を実行 10000 EURUSD
    • 操作が実行中
    • 成行注文を実行 10000 EURUSD 成功, ポジション PID14579532
  • 注文を実行

    次の例は、同期メソッドと非同期メソッドの違いを強調しています。

    cBotは、非同期メソッドを呼び出した直後に操作が実行中かどうかを確認します。 その後、同期メソッドを呼び出した後にも再度確認します。 これらのアクションのログ出力は異なります。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    [Robot()]
    public class Sample_cBot : Robot
    {
        protected override void OnStart()
        {
            var operation = ExecuteMarketOrderAsync(TradeType.Buy, SymbolName, 10000);
            Print(operation.IsExecuting ? "Operation Is Executing" : "Operation executed");
            ExecuteMarketOrder(TradeType.Buy, SymbolName, 20000);
            Print(operation.IsExecuting ? "Operation Is Executing" : "Operation executed");
        }
    }
    
    1
    2
    3
    4
    5
    6
    class Sample_cBot():
        def on_start(self):
            operation = api.ExecuteMarketOrderAsync(TradeType.Buy, api.SymbolName, 10000)
            api.Print("Operation Is Executing" if operation.IsExecuting else "Operation executed")
            api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, 20000)
            api.Print("Operation Is Executing" if operation.IsExecuting else "Operation executed")
    

    ログ出力

    • cBot "New cBot"がEURUSD、h1で正常に開始されました。
    • 成行注文を実行 10000 EURUSD
    • 操作が実行中
    • 成行注文を実行 20000 EURUSD
    • 成行注文を実行 10000 EURUSD 成功, ポジション PID14579541
    • 成行注文を実行 20000 EURUSD 成功, ポジション PID14579542
    • 操作が実行されました
  • より多くのパラメータで注文を実行

    以下のcBotは、ラベル ("myLabel")、保護レベル (10, 10)、シンボル (SymbolName)、および取引高 (10000) を指定して注文を実行します。

    この例には、Positions コレクションと FindAll() メソッドも含まれています。 Find()FindAll() を使用して、同じラベル、シンボル、および取引タイプを持つポジションを見つけることができます。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    [Robot()]
    public class Sample_cBot : Robot
    {
        protected override void OnStart()
        {
            ExecuteMarketOrderAsync(TradeType.Buy, SymbolName, 10000, "myLabel", 10, 10);
        }
        protected override void OnTick()
        {
            var positions = Positions.FindAll("myLabel", SymbolName, TradeType.Buy);
    
            if (positions.Length == 0)
                return;
    
            foreach (var position in positions)
                Print("Buy at {0} SL {1}", position.EntryPrice, position.StopLoss);
    
            Stop();
        }
    }
    
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    class Sample_cBot():
        def on_start(self):
            api.ExecuteMarketOrderAsync(TradeType.Buy, api.SymbolName, 10000, "myLabel", 10, 10)
    
        def on_tick(self):
            positions = api.Positions.FindAll("myLabel", api.SymbolName, TradeType.Buy)
    
            if positions.Length == 0:
                return
    
            for position in positions:
                api.Print(f"Buy at {position.EntryPrice} SL {position.StopLoss}")
    
            api.Stop()            
    

    ログ出力

    • cBot "New cBot"がEURUSD、h1で正常に開始されました。
    • 成行注文を実行 10000 EURUSD (損切り: 10, 利食い: 10)
    • 成行注文を実行 10000 EURUSD (損切り: 10, 利食い: 10) 成功, ポジション PID14579719
    • 1.19087 で買い 損切り null
    • 1.19357 で買い 損切り 1.19257
    • cBot "New cBot" が EURUSD, h1 で停止されました。

ポジションを非同期で変更

以下のcBotは、成行注文を実行し、その後新しく開かれたポジションを変更します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
[Robot()]
public class Sample_cBot : Robot
{
    protected override void OnStart()
    {
        ExecuteMarketOrderAsync(TradeType.Buy, SymbolName, 10000, "myLabel", null, 10);
    }

    protected override void OnTick()
    {
        Position myPosition = Positions.Find("myLabel");
        if (myPosition != null && myPosition.StopLoss == null)
        {
            double stopLoss = Symbol.Bid - 10 * Symbol.PipSize;
            ModifyPositionAsync(myPosition, stopLoss, myPosition.TakeProfit);
        }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class Sample_cBot():
    def on_start(self):
        api.ExecuteMarketOrderAsync(TradeType.Buy, api.SymbolName, 10000, "myLabel", None, 10)

    def on_tick(self):
        myPosition = Positions.Find("myLabel")

        if myPosition is None or myPosition.StopLoss is not None:
            return

        stopLoss = api.Symbol.Bid - 10 * api.Symbol.PipSize

        api.ModifyPositionAsync(myPosition, stopLoss, myPosition.TakeProfit)        

ログ出力

ポジションを非同期で閉じる

次の例は、ポジションが存在する場合に非同期でポジションを閉じる方法を示しています。

Find() メソッドを使用して、特定のラベルを持つポジションを Positions コレクション内で検索します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
[Robot()]
public class Sample_cBot : Robot
{
    protected override void OnStart()
    {
        ExecuteMarketOrderAsync(TradeType.Buy, Symbol, 10000, "myLabel", null, 10);
    }

    protected override void OnTick()
    {
        Position myPosition = Positions.Find("myLabel");
        if (myPosition != null && myPosition.GrossProfit > 10)
        {
            ClosePositionAsync(myPosition);
            Stop();
        }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class Sample_cBot():
    def on_start(self):
        api.ExecuteMarketOrderAsync(TradeType.Buy, api.SymbolName, 10000, "myLabel", None, 10)

    def on_tick(self):
        myPosition = Positions.Find("myLabel")

        if myPosition is None or myPosition.GrossProfit <= 10:
            return

        api.ClosePositionAsync(myPosition)
        api.Stop()        

ログ出力

指値注文と逆指値注文を非同期で実行

上記で述べたように、予約注文を実行することは成行注文を作成することと似ています。

ただし、これらの2つのメソッドの間には引数に若干の違いがあります。 引数リストからスリッページ許容幅が除外されています。 さらに、目標価格を指定する必要があり、注文の有効期限日を指定するオプションの引数を渡すことができます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[Robot()]
public class Sample_cBot : Robot
{
    protected override void OnStart()
    {
        var expiry = Server.Time.AddHours(12);
        PlaceLimitOrderAsync(TradeType.Buy, SymbolName, 10000, Symbol.Bid, "myLabel", null, null, expiry);
        PlaceStopOrderAsync(TradeType.Buy, SymbolName, 10000, Symbol.Ask + 10 * Symbol.PipSize, "myLabel", null, null, expiry);
    }
}
1
2
3
4
5
class Sample_cBot():
    def on_start(self):
        expiry = api.Server.Time.AddHours(12)
        api.PlaceLimitOrderAsync(TradeType.Buy, api.SymbolName, 10000, api.Symbol.Bid, "myLabel", None, None, expiry)
        api.PlaceStopOrderAsync(TradeType.Buy, api.SymbolName, 10000, api.Symbol.Ask + 10 * api.Symbol.PipSize, "myLabel", None, None, expiry)    

ログ出力

予約注文を非同期で変更

以下のcBotは、指値注文を非同期で変更します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
[Robot()]
public class Sample_cBot : Robot
{
    protected override void OnStart()
    {
        var expiry = Server.Time.AddHours(12);
        PlaceLimitOrderAsync(TradeType.Buy, SymbolName, 10000, Symbol.Bid, "myLabel", null, 10, expiry);

    }
    protected override void OnTick()
    {
        foreach (var order in PendingOrders)
        {
            if (order.Label == "myLabel" && order.StopLoss == null)
                ModifyPendingOrderAsync(order, order.TargetPrice, 10, 10, null);
        }
    }
}
1
2
3
4
5
6
7
8
9
class Sample_cBot():
    def on_start(self):
        expiry = api.Server.Time.AddHours(12)
        api.PlaceLimitOrderAsync(TradeType.Buy, api.SymbolName, 10000, api.Symbol.Bid, "myLabel", None, 10, expiry)

    def on_tick(self):
        for order in api.PendingOrders:
            if order.Label == "myLabel" and order.StopLoss is None:
                api.ModifyPendingOrderAsync(order, order.TargetPrice, 10, 10, None)

ログ出力

予約注文を非同期でキャンセル

  • すべての予約注文をキャンセル

    以下のcBotは、現在のすべての予約注文を非同期でキャンセルします。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    [Robot()]
    public class Sample_cBot : Robot
    {
        protected override void OnBar()
        {
            foreach (var pendingOrder in PendingOrders)
            {
                CancelPendingOrderAsync(pendingOrder);
            }
        }
    }
    
    1
    2
    3
    4
    class Sample_cBot():
        def on_bar(self):
            for order in api.PendingOrders:
                api.CancelPendingOrderAsync(order)
    

    ログ出力

    • cBot "cancel pending order" が EURUSD, h1 で正常に開始されました。
    • 予約注文 OID274705 をキャンセル
    • 予約注文 OID274706 をキャンセル
    • 予約注文 OID274707 をキャンセル
    • 予約注文 OID274708 をキャンセル
    • 予約注文 OID274709 をキャンセル
    • 予約注文 OID274705 をキャンセル 成功, 予約注文 OID274705
    • 予約注文 OID274706 をキャンセル 成功, 予約注文 OID274706
    • 予約注文 OID274707 をキャンセル 成功, 予約注文 OID274707
    • 予約注文 OID274708 をキャンセル 成功, 予約注文 OID274708
    • 予約注文 OID274709 をキャンセル 成功, 予約注文 OID274709
  • 特定のラベルが付いた予約注文をキャンセルする

    このcBotは特定のラベルが付いた予約注文のみをキャンセルします。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    [Robot()]
    public class Sample_cBot : Robot
    {
        protected override void OnBar()
        {
            foreach (var pendingOrder in PendingOrders)
            {
                if (pendingOrder.Label == "myLabel")
                    CancelPendingOrderAsync(pendingOrder);
            }
        }
    }
    
    1
    2
    3
    4
    5
    class Sample_cBot():
        def on_bar(self):
            for order in api.PendingOrders:
                if order.Label == "myLabel":
                    api.CancelPendingOrderAsync(order)
    

非同期メソッドのコールバック関数

結果が返された後、非同期操作を使用する場合、実行を制御する必要があることがよくあります。 これを処理するために、すべての非同期メソッドのパラメータリストの最後にコールバック関数を追加できます。

この関数は、サーバーから応答が受信されるとすぐに呼び出されます。 たとえば、ポジションが開かれた、変更された、または決済されたときに呼び出される可能性があります。

  • コールバック付き非同期成行注文

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    [Robot()]
    public class Sample_cBot : Robot
    {
        protected override void OnStart()
        {
            var operation = ExecuteMarketOrderAsync(TradeType.Buy, SymbolName, 10000, PositionOpened);
            if (operation.IsExecuting)
                Print(operation.ToString());
            else
                Print(operation.TradeResult.ToString());
    
        }
    
        private void PositionOpened(TradeResult tradeResult)
        {
            var position = tradeResult.Position;
            Print(tradeResult.ToString());
            if (tradeResult.IsSuccessful)
                Print("Position {0} opened at {1}", position.Id, position.EntryPrice);
        }
    }
    
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    from System import Action
    
    class Sample_cBot():
        def on_start(self):
            operation = api.ExecuteMarketOrderAsync(TradeType.Buy, api.SymbolName, 10000, Action[TradeResult](self.on_position_opened))
    
            if (operation.IsExecuting)
                api.Print(operation.ToString())
            else
                api.Print(operation.TradeResult.ToString())
    
        def on_position_opened(self, tradeResult):
            position = tradeResult.Position
    
            api.Print(tradeResult.ToString())
    
            if tradeResult.IsSuccessful:
                api.Print(f"Position {position.Id} opened at {position.EntryPrice}")
    

    ログ出力

    • cBot "New cBot"がEURUSD、h1で正常に開始されました。
    • 10000 EURUSDの買い成行注文を実行中
    • TradeOperation (10000 EURUSDの買い成行注文を実行中 EXECUTING)
    • 10000 EURUSDの買い成行注文が成功しました、ポジション PID14579835
    • TradeResult (成功, ポジション: PID14579835)
    • ポジション 14579835 が 1.19414 で開かれました
  • ラムダ式の使用

    名前付きコールバックメソッドを定義する代わりに、ラムダ式を使用できます。

    次の例では、注文が実行されると、結果の説明がログに出力されます。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    [Robot()]
    public class Sample_cBot : Robot
    {
        protected override void OnStart()
        {
            PlaceLimitOrderAsync(TradeType.Buy, SymbolName, 10000,
                    Symbol.Ask - 20 * Symbol.PipSize, "myLabel", result => Print(result.ToString()));
        }
    }
    
    1
    2
    3
    4
    5
    from System import Action
    
    class Samples():
        def on_start(self):
            operation = api.PlaceLimitOrderAsync(TradeType.Buy, api.SymbolName, 10000, api.Symbol.Ask - 20 * api.Symbol.PipSize, "myLabel", Action[TradeResult](lambda result: api.Print(result.ToString())))
    

    ログ出力

    • cBot "新しいcBot" がEURUSD、H1で正常に開始されました。
    • 10000 EURUSDの買い指値注文を実行中 (価格: 1.19320)
    • 10000 EURUSDの買い指値注文が成功しました、予約注文 OID25222083
    • TradeResult (成功, 予約注文: OID25222083)

Image title