跳转至

cBot 代码示例

本页面提供了多个 PythonC# 代码示例,用于创建交易机器人和开发算法。 请注意,以下列出的 cBot 均不保证任何财务回报。 在实盘账户上部署任何实例之前,请确保对您的 cBot 进行回测和自定义。

cBot 示例仓库

全面的 cBot 代码示例,包括各种自动化策略和交易风格的即用模板,可在 GitHub 的 PythonC# 仓库中找到。

同步操作

本节中的所有 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 (SL: 10, TP: 10) 成功,头寸 PID14576098
    • 头寸入场价格为 1.1896

修改头寸

在下面的示例中,我们仅在订单执行时添加了止盈值 (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") 的市价单。 在每个新柱上,我们的交易机器人将关闭其中一个订单的一半,但仅当其交易量等于或大于 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 创建了两个限价单和一个止损单。 然后它遍历订单并将其标签和 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 (价格: 1.19036) 成功,挂单 OID25220794
    • 下达限价单买入 20000 EURUSD (价格: 1.19017)
    • 下达限价单买入 20000 EURUSD (价格: 1.19017) 成功,挂单 OID25220795
    • 下达止损单买入 10000 EURUSD (价格: 1.19040)
    • 下达止损单买入 10000 EURUSD (价格: 1.19040) 成功,挂单 OID25220796
    • 订单已下达,标签为 myLimitOrder,id 为 25220794
    • 订单已下达,标签为 myLimitOrder,id 为 25220795
    • 订单已下达,标签为 myStopOrder,id 为 25220796
  • 使用更多参数创建挂单

    与市价单一样,您还可以指定订单标签、各种保护机制、订单到期日期并提供注释。

     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, SL: 10, ExpireTime: 12/05/2018 00:00:00)
    • 下达限价单买入 10000 EURUSD (价格: 1.19049, SL: 10, ExpireTime: 12/05/2018 00:00:00) 成功,挂单 OID25220807
    • 下达止损单买入 10000 EURUSD (价格: 1.19053, SL: 10, TP: 10)
    • 下达止损单买入 10000 EURUSD (价格: 1.19053, SL: 10, TP: 10) 成功,挂单 OID25220808
    • 限价单
    • 第一个限价单 SL: 1.18949
    • 第二个止损单 SL: 1.18953 TP: 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),其中 order 的类型为 PendingOrder

以下示例展示了取消所有带有标签 "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在同一时间段内执行多个操作。

异步执行市价单

异步方法的语法与同步方法相似。 虽然它们接受相同类型的参数,但它们的返回类型是 TradeOperation 而不是 TradeResult

  • 基本异步操作

    以下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 "新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()        

日志输出

异步下达限价单和止损单

上文所述,下达挂单与创建市价单类似。

然而,这两种方法在参数上有一些细微差别。 参数列表中缺少市价范围。 此外,您必须指定目标价格,并且可以传递一个可选参数来指定订单到期日期。

 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 "取消挂单" 已成功启动,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 执行中)
    • 执行市价单买入 10000 EURUSD 成功,头寸 PID14579835
    • TradeResult (成功,头寸: PID14579835)
    • 头寸 14579835 以 1.19414 的价格开仓
  • 使用 lambda 表达式

    您可以不使用命名的回调方法,而是使用 lambda 表达式。

    在以下示例中,当订单被下达时,结果的描述将被打印到日志中。

    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 (价格: 1.19320) 成功,挂单 OID25222083
    • TradeResult (成功,挂单: OID25222083)

Image title