Aller au contenu

Comment automatiser une stratégie de trading manuel

Le trading automatisé ou algorithmique offre plusieurs avantages par rapport au trading manuel :

  • Les systèmes automatisés éliminent la prise de décision émotionnelle et exécutent les trades avec une précision, une rapidité et une efficacité accrues.
  • Les algorithmes mettent en œuvre de manière cohérente des stratégies de trading avancées tandis que les mesures de gestion des risques sont appliquées de manière fiable.
  • Les algorithmes permettent de backtester les stratégies à l'aide de données historiques et de diversifier simultanément sur plusieurs actifs et marchés.

L'API cTrader Algo permet aux traders d'automatiser des stratégies manuelles complexes, leur permettant de capitaliser sur les nombreux avantages du trading algorithmique. Dans cet article et la vidéo qui l'accompagne, vous apprendrez à automatiser des stratégies manuelles complexes et à transformer des séquences d'opérations en algorithmes.

Identifier les modèles de stratégie manuelle

Pour développer un algorithme, supposons que nous tradons manuellement le modèle hammer pour les entrées longues et le modèle hanging man pour les entrées courtes.

Un hammer se produit pendant une tendance baissière et suggère un potentiel retournement haussier. Le modèle hammer est utilisé pour identifier les entrées d'achat.

Un hanging man apparaît pendant une tendance haussière et indique un potentiel retournement baissier. Le modèle hanging man est utilisé pour identifier les entrées de vente.

Développer un cBot pour trader la stratégie manuelle

Dans cTrader Algo, créons un algorithme qui met en œuvre la stratégie décrite dans la section précédente.

Cliquez sur le bouton Nouveau sous l'onglet cBot. Saisissez Patterns Strategy dans le champ du nom et cliquez sur Créer.

Dans la méthode OnBarClosed(), nous implémentons la logique de notre stratégie. Nos entrées doivent remplir ces deux conditions :

  • Le cours de clôture correspond au cours le plus haut.
  • La taille de la bougie est au moins cinq fois plus grande que le corps de la bougie.

Nous commençons par définir les paramètres Volume, StopLoss et 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; }

Ensuite, nous écrivons un extrait pour exécuter un trade d'achat lorsque les conditions requises sont remplies.

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)

Du côté opposé, voici les conditions qui doivent être remplies pour nos entrées de vente :

  • Le cours de clôture correspond au cours le plus bas.
  • La taille de la bougie est au moins cinq fois plus grande que le corps de la bougie.

De même, nous écrivons un extrait pour exécuter un trade de vente lorsque les conditions requises sont remplies.

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)

Vous pouvez copier le code complet ci-dessous :

 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

Pour créer le cBot, appuyez sur Ctrl+B ou cliquez sur Build.

Pour backtester le cBot, nous ajoutons d'abord une instance. Sélectionnez l'option Localement, spécifiez vos paramètres préférés et cliquez sur le bouton Ajouter une instance.

Nous naviguons ensuite vers l'onglet Backtesting, spécifions une période pour l'opération de backtesting et démarrons le backtesting.

Une fois le processus de backtesting terminé, nous pouvons inspecter les trades. Vous verrez que les conditions d'entrée sont remplies juste avant chaque entrée de trade.

Avec l'automatisation réussie de notre stratégie, nous pouvons utiliser le cBot pour effectuer des trades en notre nom.

Mettre en œuvre la stratégie de retournement RSI

Dans notre deuxième exemple, nous voulons mettre en œuvre une stratégie basée sur le retournement de l'indicateur Relative Strength Index (RSI). Dans cette stratégie, nous entrons en position en nous attendant à ce que le RSI inverse sa direction et suivons ces règles :

  • Lorsque la valeur du RSI passe en dessous du seuil d'achat RSI, nous entrons en position d'achat.
  • Lorsque la valeur du RSI passe au-dessus du seuil de vente RSI, nous entrons en position de vente.

Créons un nouveau cBot, saisissez RSI Reversal Strategy comme nom et cliquez sur Créer.

Une fois que l'éditeur de code apparaît, ajoutez System.Linq en haut du code comme référence.

1
using System.Linq;

Ajoutons deux paramètres qui nous permettront de modifier les seuils avant d'exécuter le cBot.

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

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

Nous déclarons et initialisons notre indicateur de force relative.

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)

Nous mettons ensuite en œuvre les conditions qui définissent notre logique de 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()

Vous pouvez copier le code complet ci-dessous :

 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

Construisons notre stratégie, ajoutons une instance et effectuons un backtest, comme nous l'avons fait avec la stratégie précédente.

Nous pouvons inspecter et examiner à nouveau certains trades pour voir les conditions d'entrée remplies juste avant l'entrée d'un trade.

Cet article a démontré comment identifier une stratégie manuelle et la convertir en une stratégie automatisée, permettant des opérations de trading algorithmique.

Image title