Vai al contenuto

Come automatizzare una strategia di trading manuale

Il trading automatizzato o algoritmico offre diversi vantaggi rispetto al trading manuale:

  • I sistemi automatizzati eliminano le decisioni emotive ed eseguono operazioni con maggiore precisione, velocità ed efficienza.
  • Gli algoritmi implementano in modo coerente strategie di trading avanzate mentre le misure di gestione del rischio vengono applicate in modo affidabile.
  • Gli algoritmi consentono di effettuare il backtesting delle strategie utilizzando dati storici e di diversificare su più asset e mercati contemporaneamente.

L'API cTrader Algo consente ai trader di automatizzare strategie manuali complesse, permettendo loro di sfruttare i numerosi vantaggi del trading algoritmico. In questo articolo e nel video che lo accompagna, imparerai come automatizzare strategie manuali complesse e trasformare sequenze di operazioni in algoritmi.

Identifica i pattern della strategia manuale

Per sviluppare un algoritmo, supponiamo di fare trading manuale del pattern hammer per le entrate long e del pattern hanging man per le entrate short.

Un hammer si verifica durante un trend ribassista e suggerisce una potenziale inversione rialzista. Il pattern hammer viene utilizzato per identificare le entrate di acquisto.

Un hanging man appare durante un trend rialzista e indica una potenziale inversione ribassista. Il pattern hanging man viene utilizzato per identificare le entrate di vendita.

Sviluppa un cBot per fare trading con la strategia manuale

In cTrader Algo, creiamo un algoritmo che implementa la strategia descritta nella sezione precedente.

Fai clic sul pulsante Nuovo nella scheda cBot. Digita Patterns Strategy nel campo del nome e fai clic su Crea.

Nel metodo OnBarClosed(), implementiamo la logica per la nostra strategia. Le nostre entrate devono soddisfare queste due condizioni:

  • Il prezzo di chiusura corrisponde al prezzo massimo.
  • La dimensione della candela è almeno cinque volte più grande del corpo della candela.

Iniziamo definendo i parametri 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; }

Quindi scriviamo uno snippet per eseguire un'operazione di acquisto quando vengono soddisfatte le condizioni richieste.

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)

Sul lato opposto, queste sono le condizioni che devono essere soddisfatte per le nostre entrate di vendita:

  • Il prezzo di chiusura corrisponde al prezzo minimo.
  • La dimensione della candela è almeno cinque volte più grande del corpo della candela.

Allo stesso modo, scriviamo uno snippet per eseguire un'operazione di vendita quando vengono soddisfatte le condizioni richieste.

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)

Puoi copiare il codice completo qui sotto:

 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

Per compilare il cBot, premi Ctrl+B o fai clic su Compila.

Per effettuare il backtesting del cBot, aggiungiamo prima un'istanza. Seleziona l'opzione Localmente, specifica i parametri preferiti e fai clic sul pulsante Aggiungi istanza.

Quindi andiamo alla scheda Backtesting, specifichiamo un periodo per l'operazione di backtesting e avviamo il backtesting.

Una volta completato il processo di backtesting, possiamo ispezionare le operazioni. Vedrai che le condizioni di entrata sono soddisfatte appena prima che venga inserita ogni operazione.

Con la riuscita automazione della nostra strategia, possiamo utilizzare il cBot per effettuare operazioni per nostro conto.

Implementa la strategia di inversione RSI

Nel nostro secondo esempio, vogliamo implementare una strategia basata sull'inversione dell'indicatore Relative Strength Index (RSI). In questa strategia, entriamo in posizioni aspettandoci che l'RSI inverta la sua direzione e seguiamo queste regole:

  • Quando il valore dell'RSI scende al di sotto della soglia di acquisto RSI, entriamo in una posizione di acquisto.
  • Quando il valore dell'RSI sale al di sopra della soglia di vendita RSI, entriamo in una posizione di vendita.

Creiamo un nuovo cBot, inseriamo RSI Reversal Strategy come nome e facciamo clic su Crea.

Una volta visualizzato l'editor di codice, aggiungi System.Linq nella parte superiore del codice come riferimento.

1
using System.Linq;

Aggiungiamo due parametri che ci permetteranno di modificare le soglie prima di eseguire il cBot.

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

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

Dichiariamo e inizializziamo il nostro indicatore relative strength.

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)

Quindi implementiamo le condizioni che definiscono la nostra logica di trading.

 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()

Puoi copiare il codice completo qui sotto:

 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

Compiliamo la nostra strategia, aggiungiamo un'istanza ed effettuiamo il backtesting, come abbiamo fatto con la strategia precedente.

Possiamo ispezionare e rivedere alcune operazioni di nuovo per vedere le condizioni di entrata soddisfatte appena prima che venga inserita un'operazione.

Questo articolo ha dimostrato come identificare una strategia manuale e convertirla in una automatizzata, consentendo operazioni di trading algoritmico.

Image title