Ir para o conteúdo

Como automatizar uma estratégia de negociação manual

A negociação automatizada ou algorítmica oferece várias vantagens em relação à negociação manual:

  • Os sistemas automatizados eliminam a tomada de decisões emocional e executam negociações com maior precisão, velocidade e eficiência.
  • Os algoritmos implementam consistentemente estratégias de negociação avançadas, ao mesmo tempo que as medidas de gestão de risco são aplicadas de forma fiável.
  • Os algoritmos permitem testar estratégias usando dados históricos e diversificar em vários ativos e mercados simultaneamente.

A API do cTrader Algo permite que os traders automatizem estratégias manuais complexas, permitindo-lhes capitalizar as muitas vantagens da negociação algorítmica. Neste artigo e no vídeo que o acompanha, irá aprender a automatizar estratégias manuais complexas e transformar sequências de operações em algoritmos.

Identificar os padrões da estratégia manual

Para desenvolver um algoritmo, vamos assumir que estamos a negociar manualmente o padrão hammer para entradas longas e o padrão hanging man para entradas curtas.

Um hammer ocorre durante uma tendência de descida e sugere uma potencial reversão de alta. O padrão hammer é usado para identificar entradas de compra.

Um hanging man aparece durante uma tendência de subida e indica uma potencial reversão de baixa. O padrão hanging man é usado para identificar entradas de venda.

Desenvolver um cBot para negociar a estratégia manual

No Algo do cTrader, vamos criar um algoritmo que implementa a estratégia descrita na secção anterior.

Clique no botão Novo no separador cBot. Escreva Estratégia de padrões no campo do nome e clique em Criar.

No método OnBarClosed(), implementamos a lógica para a nossa estratégia. As nossas entradas têm de cumprir estas duas condições:

  • O preço de fecho corresponde ao preço mais alto.
  • O tamanho da vela é pelo menos cinco vezes maior do que o corpo da vela.

Começamos por definir os parâmetros Volume, StopLoss e TakeProfit.

1
2
3
4
5
6
7
8
[Parameter(DefaultValue = 1000)]
public double Volume { get; set; }

[Parameter(DefaultValue = 10)]
public double StopLoss { get; set; }

[Parameter(DefaultValue = 10)]
public double TakeProfit { get; set; }

Depois, escrevemos um excerto para executar uma negociação de compra quando as condições necessárias são cumpridas.

1
2
3
4
5
if (Bars.Last(0).Close == Bars.Last(0).High &&
            (Bars.Last(0).Close - Bars.Last(0).Open) < (Bars.Last(0).Close - Bars.Last(0).Low) * 0.2)
{
    ExecuteMarketOrder(TradeType.Buy, SymbolName, Volume, InstanceId, StopLoss, TakeProfit);
}
1
2
3
bar = api.Bars.Last(0)
if bar.Close == bar.High and (bar.Close - bar.Open) < (bar.Close - bar.Low) * 0.2:
    api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, api.Volume, api.InstanceId, api.StopLoss, api.TakeProfit)

Do lado oposto, estas são as condições que têm de ser cumpridas para as nossas entradas de venda:

  • O preço de fecho corresponde ao preço mais baixo.
  • O tamanho da vela é pelo menos cinco vezes maior do que o corpo da vela.

Da mesma forma, escrevemos um excerto para executar uma negociação de venda quando as condições necessárias são cumpridas.

1
2
3
4
5
if (Bars.Last(0).Close == Bars.Last(0).Low &&
                (Bars.Last(0).Open - Bars.Last(0).Close) < (Bars.Last(0).High - Bars.Last(0).Close) * 0.2)
{
    ExecuteMarketOrder(TradeType.Sell, SymbolName, Volume, InstanceId, StopLoss, TakeProfit);
}
1
2
if bar.Close == bar.Low and (bar.Open - bar.Close) < (bar.High - bar.Close) * 0.2:
    api.ExecuteMarketOrder(TradeType.Sell, api.SymbolName, api.Volume, api.InstanceId, api.StopLoss, api.TakeProfit)

Pode copiar o código completo abaixo:

 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
37
38
39
40
41
42
43
44
45
46
47
using System;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.None, AddIndicators = true)]
    public class PatternsStrategy : Robot
    {
        [Parameter(DefaultValue = 1000)]
        public double Volume { get; set; }

        [Parameter(DefaultValue = 10)]
        public double StopLoss { get; set; }

        [Parameter(DefaultValue = 10)]
        public double TakeProfit { get; set; }

        protected override void OnStart()
        {

        }

        protected override void OnBarClosed()
        {
            if (Bars.Last(0).Close == Bars.Last(0).High &&
            (Bars.Last(0).Close - Bars.Last(0).Open) < (Bars.Last(0).Close - Bars.Last(0).Low) * 0.2)
            {
                ExecuteMarketOrder(TradeType.Buy, SymbolName, Volume, InstanceId, StopLoss, TakeProfit);
            }

            if (Bars.Last(0).Close == Bars.Last(0).Low &&
            (Bars.Last(0).Open - Bars.Last(0).Close) < (Bars.Last(0).High - Bars.Last(0).Close) * 0.2)
            {
                ExecuteMarketOrder(TradeType.Sell, SymbolName, Volume, InstanceId, StopLoss, TakeProfit);
            }

        }

        protected override void OnStop()
        {

        }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import clr
clr.AddReference("cAlgo.API")
from cAlgo.API import *
from robot_wrapper import *

class PatternsStrategy():
    def on_start(self):
        pass

    def on_bar_closed(self):
        bar = api.Bars.Last(0)

        if bar.Close == bar.High and (bar.Close - bar.Open) < (bar.Close - bar.Low) * 0.2:
            api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, api.Volume, api.InstanceId, api.StopLoss, api.TakeProfit)

        if bar.Close == bar.Low and (bar.Open - bar.Close) < (bar.High - bar.Close) * 0.2:
            api.ExecuteMarketOrder(TradeType.Sell, api.SymbolName, api.Volume, api.InstanceId, api.StopLoss, api.TakeProfit)

    def on_stop(self):
        pass

Para compilar o cBot, prima Ctrl+B ou clique em Compilar.

Para testar o cBot, primeiro adicionamos uma instância. Selecione a opção Localmente, especifique os parâmetros pretendidos e clique no botão Adicionar instância.

Em seguida, navegamos até ao separador Testes de verificação, especificamos um período para a operação de teste de verificação e iniciamos o teste de verificação.

Assim que o processo de teste de verificação estiver concluído, podemos inspecionar as negociações. Verá que as condições de entrada são cumpridas imediatamente antes de cada negociação ser iniciada.

Com a automatização bem-sucedida da nossa estratégia, podemos empregar o cBot para fazer negociações em nosso nome.

Implementar a estratégia de reversão do RSI

No nosso segundo exemplo, queremos implementar uma estratégia baseada na reversão do indicador Relative Strength Index (RSI). Nesta estratégia, entramos em posições esperando que o RSI inverta a sua direção e seguimos estas regras:

  • Quando o valor do RSI desce abaixo do limiar de compra do RSI, entramos numa posição de compra.
  • Quando o valor do RSI sobe acima do limiar de venda do RSI, entramos numa posição de venda.

Vamos criar um novo cBot, inserir RSI Reversal Strategy como nome e clicar em Criar.

Quando o editor de código aparecer, adicione System.Linq no topo do código como referência.

1
using System.Linq;

Vamos adicionar dois parâmetros que nos permitirão modificar os limiares antes de executarmos o cBot.

1
2
3
4
5
[Parameter(DefaultValue = 30)]
public int BuyLevel { get; set; }

[Parameter(DefaultValue = 70)]
public int SellLevel { get; set; }

Declaramos e inicializamos o nosso indicador de força relativa.

1
2
3
4
5
6
private RelativeStrengthIndex _rsi;

protected override void OnStart()
{
    _rsi = Indicators.RelativeStrengthIndex(Bars.ClosePrices, 14);
}
1
2
3
class RSIReversalStrategy():
    def on_start(self):
        self._rsi = api.Indicators.RelativeStrengthIndex(api.Bars.ClosePrices, 14)

Em seguida, implementamos as condições que definem a nossa lógica de negociaçã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
protected override void OnBarClosed()
{

    if (_rsi.Result.LastValue < BuyLevel)
    {
        if (Positions.Count == 0)
            ExecuteMarketOrder(TradeType.Buy, SymbolName, 1000);
        foreach (var position in Positions.Where(p => p.TradeType == TradeType.Sell))
        {
            position.Close();
        }

    }
    else if (_rsi.Result.LastValue > SellLevel)
    {
        if (Positions.Count == 0)
            ExecuteMarketOrder(TradeType.Sell, SymbolName, 1000);
        foreach (var position in Positions.Where(p => p.TradeType == TradeType.Buy))
        {
            position.Close();
        }
    }

}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
def on_bar_closed(self):
    rsi_value = self._rsi.Result.LastValue

    if rsi_value < api.BuyLevel:
        if api.Positions.Count == 0:
            api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, 1000)
        for position in api.Positions:
            if position.TradeType == TradeType.Sell:
                position.Close()

    elif rsi_value > api.SellLevel:
        if api.Positions.Count == 0:
            api.ExecuteMarketOrder(TradeType.Sell, api.SymbolName, 1000)
        for position in api.Positions:
            if position.TradeType == TradeType.Buy:
                position.Close()

Pode copiar o código completo abaixo:

 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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.None, AddIndicators = true)]
    public class RSIReversalStrategy : Robot
    {
        [Parameter(DefaultValue = 30)]
        public int BuyLevel { get; set; }

        [Parameter(DefaultValue = 70)]
        public int SellLevel { get; set; }

        private RelativeStrengthIndex _rsi;

        protected override void OnStart()
        {
            _rsi = Indicators.RelativeStrengthIndex(Bars.ClosePrices, 14);
        }

        protected override void OnBarClosed()
        {

            if (_rsi.Result.LastValue < BuyLevel)
            {
                if (Positions.Count == 0)
                    ExecuteMarketOrder(TradeType.Buy, SymbolName, 1000);
                foreach (var position in Positions.Where(p => p.TradeType == TradeType.Sell))
                {
                    position.Close();
                }

            }
            else if (_rsi.Result.LastValue > SellLevel)
            {
                if (Positions.Count == 0)
                    ExecuteMarketOrder(TradeType.Sell, SymbolName, 1000);
                foreach (var position in Positions.Where(p => p.TradeType == TradeType.Buy))
                {
                    position.Close();
                }
            }

        }

        protected override void OnStop()
        {

        }
    }
}
 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
import clr
clr.AddReference("cAlgo.API")
from cAlgo.API import *
from robot_wrapper import *

class RSIReversalStrategy():
    def on_start(self):
        self._rsi = api.Indicators.RelativeStrengthIndex(api.Bars.ClosePrices, 14)

    def on_bar_closed(self):
        rsi_value = self._rsi.Result.LastValue

        if rsi_value < api.BuyLevel:
            if api.Positions.Count == 0:
                api.ExecuteMarketOrder(TradeType.Buy, api.SymbolName, 1000)
            for position in api.Positions:
                if position.TradeType == TradeType.Sell:
                    position.Close()

        elif rsi_value > api.SellLevel:
            if api.Positions.Count == 0:
                api.ExecuteMarketOrder(TradeType.Sell, api.SymbolName, 1000)
            for position in api.Positions:
                if position.TradeType == TradeType.Buy:
                    position.Close()

    def on_stop(self):
        pass

Vamos construir a nossa estratégia, adicionar uma instância e testá-la, como fizemos com a estratégia anterior.

Podemos inspecionar e rever algumas transações novamente para ver as condições de entrada a serem cumpridas logo antes de uma transação ser iniciada.

Este artigo demonstrou como identificar uma estratégia manual e convertê-la numa estratégia automatizada, permitindo operações de negociação algorítmica.

Image title