Ir para o conteúdo

Ciclo de vida do cBot

Neste artigo e no vídeo que o acompanha, analisamos a estrutura do código e explicamos a lógica por trás dos eventos e do ciclo de vida de um cBot do cTrader.

Como lembrete, pode aceder aos seus cBots na aplicação Algo no cTrader. Para criar um novo cBot, basta clicar no botão Novo cBot ou selecionar esta opção no menu suspenso mostrado abaixo.

Interpretar o modelo básico

Depois de criar um novo cBot, deverá ver a seguinte estrutura básica na janela do editor de código.

 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
        }
    }
}

Note que existem apenas três eventos exibidos no modelo básico; estes eventos são tratados pelos métodos OnStart(), OnTick() e OnStop(). Iremos adicionar dois métodos adicionais (OnBar() e OnException()) e explicar como funcionam mais tarde; primeiro, iremos discutir o método OnStart().

Usar o método OnStart()

O método OnStart() é acionado quando um cBot é iniciado pela primeira vez. É usado para inicializar quaisquer variáveis que planeia usar no seu cBot, incluindo indicadores, contadores, manipuladores de eventos ou temporizadores.

Nota

O modelo de código inicial já inclui uma declaração de código para imprimir uma mensagem no registo quando um cBot é iniciado. Como pode ver, o nosso cBot tem o parâmetro Message, e o método OnStart() passa o valor deste parâmetro para o método Print().

Podemos demonstrar como o método OnStart() funciona simplesmente iniciando a instância do cBot na aplicação Trade e abrindo o separador Log para ver o resultado.

Também podemos parar o cBot a qualquer momento, alterar o valor do parâmetro Message no separador Parâmetros e reiniciar a nossa instância. Ao iniciar, a nossa nova mensagem ainda será impressa no registo.

Usar o método OnTick()

O método OnTick() é acionado sempre que o preço de venda ou de compra do símbolo muda. Dentro deste método, normalmente pode programar condições de entrada e saída de posição, bem como quaisquer outras funções auxiliares que precise de executar quando chega um novo tick de dados.

Iremos adicionar o seguinte código ao método OnTick() para que imprima uma mensagem no registo.

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

Como pode ver abaixo, o nosso cBot agora imprime os preços de venda e compra no registo a cada alteração de preço.

Usar o método OnBar()

O método OnBar() não está incluído no modelo de código padrão do cBot, por isso iremos adicionar o seguinte trecho de código para adicioná-lo.

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

O método OnBar() é acionado sempre que uma nova barra ou vela é desenhada no gráfico ao qual um cBot está anexado. De forma semelhante ao método OnTick(), pode usar o método OnBar() para programar as condições de entrada e saída de posição, bem como quaisquer outras lógicas que precisem de ser executadas na formação de cada nova barra.

Como o método OnBar() é acionado

Se tiver um gráfico H1, uma nova barra é formada a cada hora, o que significa que o método OnBar() será chamado uma vez por hora. Se tiver um gráfico m1, o mesmo método será chamado uma vez por minuto.

O nosso método OnBar() imprimirá "OnBar" em cada nova barra/vela. Para demonstrar como funciona, iremos anexar o nosso cBot a um gráfico m1 e dar uma olhada no registo.

Usar o método OnStop()

O método OnStop() é chamado quando o cBot para, seja pelo utilizador ou através do código. Quando isso acontece, qualquer código dentro do método OnStop() é executado. Isto pode ser usado para realizar operações finais, como fechar posições.

Iremos adicionar o seguinte código ao nosso método OnStop() - como de costume, o nosso cBot imprimirá o valor do parâmetro Message quando for parado.

1
Print(Message);

Na captura de ecrã abaixo, lançamos e paramos uma instância do nosso cBot para demonstrar como tudo funciona.

Usar o método OnException()

O método OnException() fornece tolerância a falhas capturando exceções não tratadas, permitindo que decida como lidar com elas. Não está incluído no modelo de código padrão, por isso iremos adicioná-lo usando o seguinte trecho.

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

Para acionar o método OnException(), iremos escrever algum código para capturar uma exceção que ocorre quando tentamos aceder a informações sobre uma negociação que já não existe. Iremos adicionar o código abaixo ao método OnStart().

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

O código que escrevemos no método OnStart() irá executar uma ordem de mercado com os seguintes parâmetros configuráveis.

  • O tipo de negociação será uma ordem de compra.
  • A negociação será executada para o símbolo atual do gráfico ao qual o cBot está anexado.
  • O volume da ordem será de 1.000 unidades.
  • O rótulo único anexado à ordem será "my label".

Também iremos adicionar o seguinte código ao método OnTick().

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

O código que escrevemos no método OnTick() irá encontrar a posição que foi aberta no método OnStart() usando o nome do rótulo "my label".

Se a posição for encontrada com o mesmo rótulo, imprimirá no registo o ID da posição da negociação aberta. Também imprimirá outra mensagem chamada "Message below" como a próxima linha de código é executada.

Quando o nosso cBot é lançado e o método OnTick() é chamado e a ordem é encontrada, o cBot imprimirá o ID da ordem no registo e, após o ID da ordem, imprimirá a mensagem "Message below".

Como pode ver, não surgem exceções e o nosso cBot faz o seu trabalho perfeitamente.

Agora, no entanto, iremos fechar manualmente a posição aberta pelo cBot e fazer pequenas alterações no código para que uma exceção seja garantida. No método OnStart(), iremos alterar o rótulo da ordem para "cTrader". No método OnTick(), iremos comentar a condição que verifica se existe uma posição com o rótulo "my label".

Aqui está o código final do nosso cBot - note que este código irá sempre acionar uma exceção.

 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");            
        }
    }
}

Iremos executar o cBot novamente e ver o que acontece.

O que aconteceu é que uma nova ordem de mercado foi criada quando o cBot iniciou. O rótulo anexado a esta ordem era "cTrader". No método OnTick(), o código tentou obter uma posição com o rótulo de "my label" e como comentamos a linha de código com a condicional. Em seguida, tentou imprimir no registo o ID da posição.

Isto causou um erro de exceção que normalmente teria parado o cBot em versões anteriores do cTrader, mas com o novo método OnException(), agora podemos capturar isto e lidar com o erro. O cBot continuará a funcionar e podemos registar o erro para que possa ser corrigido.

Resumo

O ciclo de vida do cBot consiste em vários eventos-chave que pode tratar através dos métodos OnStart(), OnTick(), OnStop(), OnBar() e OnException(). Ao personalizar como o seu cBot responde aos principais eventos, pode garantir que os seus algoritmos se comportam exatamente como esperado.