Aller au contenu

Créer un indicateur technique dans cTrader

Cet article décrit les étapes pour créer des indicateurs techniques personnalisés, y compris des outils pour le trading algorithmique ou les actions manuelles dans cTrader.

Astuce

Apprenez à créer des indicateurs techniques en regardant une vidéo dans un guide étape par étape.

Dans l'onglet Indicateurs de l'application Algo, cliquez sur le bouton Nouveau pour ouvrir l'assistant de création d'algorithme.

Saisissez un nom pour votre indicateur, puis sélectionnez un langage de programmation entre C# et Python.

Choisissez une méthode de création parmi :

  • À partir de zéro – le nouvel indicateur ne contiendra qu'un modèle de base.

  • En utilisant un modèle – vous pourrez sélectionner un algorithme prédéfini dans une liste de modèles Python# ou C#, couvrant une large gamme de types d'indicateurs, d'outils d'analyse technique et plus encore.

Remarque

Les algorithmes prédéfinis contiennent déjà la logique pour les calculs et les paramètres personnalisables. Ces indicateurs sont prêts à être affichés sur les graphiques une fois que vous les avez enregistrés et construits.

Après avoir cliqué sur Créer, l'éditeur de code s'ouvre et vous pouvez commencer à modifier le code de l'indicateur.

Modifier le code

Selon votre méthode de création, l'exemple de code de l'indicateur doit contenir un ou plusieurs des éléments suivants :

 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
[Indicator(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class SimpleIndicator : Indicator
{
    [Parameter(DefaultValue = "Hello world!")]
    public string Message { get; set; }

    [Output("Main")]
    public IndicatorDataSeries Result { get; set; }

    protected override void Initialize()
    {
    // Called once when the indicator is launched
    // Initialise variables, nested indicators or series

        Print(Message);
    }

    public override void Calculate(int index)
    {
    // Called automatically on each historical bar
    // Also called in real-time on each tick
    // Place the indicator formula and logic here
    }

    // === Custom Methods ===
    // Add helper methods below to structure your indicator logic

}

L'attribut Indicator, ainsi que ses propriétés optionnelles telles que TimeZone et AccessRights, précède la déclaration de la classe d'indicateur (SimpleIndicator).

Ces méthodes sont incluses dans chaque indicateur par défaut :

  • La méthode Initialize() est invoquée une fois lorsque votre indicateur démarre. Elle est généralement utilisée pour configurer les variables, les indicateurs imbriqués et les séries qui doivent être prêts dès le début.
  • La méthode Calculate() est invoquée automatiquement sur chaque barre historique et en temps réel à chaque nouveau tick. C'est ici que vous implémentez la formule de l'indicateur et définissez comment les résultats sont calculés et affichés.

L'attribut [Output()] spécifie les valeurs que votre indicateur produit et comment elles apparaissent sur le graphique. Vous pouvez personnaliser le nom et le style de chaque sortie, par exemple en définissant la couleur de sa ligne.

Les méthodes Initialize() et Calculate() constituent la base de chaque indicateur personnalisé et ne doivent jamais être omises. Vous pouvez ajouter vos propres méthodes pour étendre les fonctionnalités, tout comme vous le feriez lors du codage d'un cBot. Pour en savoir plus sur les algorithmes, commencez par le guide Bases de C# et explorez les exemples de code d'indicateur.

Remarque

Références inclut toutes les classes, événements, méthodes, variables, etc. pour créer des algorithmes dans cTrader, tandis que des exemples d'algorithmes complets et des modèles sont disponibles dans un dépôt GitHub.

Appliquez vos nouvelles connaissances pour modifier le code de l'indicateur et l'adapter à vos besoins.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class SimpleIndicator:
    def initialize(self):
        # Called once when the indicator is launched
        # Initialise variables, nested indicators or series
        api.Print(api.Message)

    def calculate(self, index):
        # Called automatically on each historical bar
        # Also called in real-time on each tick
        # Place the indicator formula and logic here
        api.Result[index] = 100 # Example calculation

    # === Custom Methods ===
    # Add helper methods below to structure your indicator logic

La classe SimpleIndicator définit un indicateur personnalisé en Python.

Ces méthodes sont incluses dans chaque indicateur par défaut :

  • La méthode initialize(self) est invoquée une fois lorsque votre indicateur démarre. Elle est généralement utilisée pour initialiser les variables, les indicateurs imbriqués et les séries qui doivent être prêts dès le début.
  • La méthode calculate(self, index) est invoquée automatiquement sur chaque barre historique et en temps réel à chaque nouveau tick. C'est ici que vous implémentez la formule de l'indicateur et définissez comment les résultats sont calculés et affichés.

Les méthodes initialize(self) et calculate(self, index) constituent la base de chaque indicateur personnalisé et ne doivent jamais être omises. Vous pouvez également ajouter vos propres méthodes d'assistance à l'intérieur de la classe pour étendre les fonctionnalités, tout comme vous le feriez lors du codage d'un cBot. Pour en savoir plus sur les algorithmes, commencez par Bases de Python et explorez les exemples de code d'indicateur.

Appliquez vos nouvelles connaissances pour modifier le code de l'indicateur et l'adapter à vos besoins.

Enregistrer et compiler

Enregistrez votre code en cliquant sur le bouton Enregistrer en haut de l'éditeur de code ou utilisez le raccourci Ctrl+S.

Avant de pouvoir utiliser votre indicateur, vous devez valider son code en construisant le projet d'indicateur. Cliquez sur le bouton Compiler en haut de l'éditeur de code ou appuyez sur Ctrl+B.

Enregistrez votre code en cliquant sur l'icône Enregistrer en haut de l'éditeur de code ou utilisez le raccourci Cmd+S.

Avant de pouvoir utiliser votre indicateur, vous devez valider son code en construisant le projet d'indicateur. Cliquez sur l'icône Compiler en haut de l'éditeur de code ou appuyez sur Cmd+B.

Lorsque la compilation réussit, un message de confirmation s'affiche dans Résultat de la compilation. Si la compilation échoue, un résumé de toutes les erreurs rencontrées apparaît à la place.

Si des modifications ont été apportées au code depuis la dernière compilation, un astérisque apparaît à côté de l'icône Compiler. Dans ce cas, vous devez reconstruire l'indicateur avant d'ajouter une instance de celui-ci à un graphique.

Pour utiliser ou afficher l'indicateur sur un graphique, ajoutez une instance de celui-ci, ou vous pouvez continuer à modifier le code de l'indicateur comme expliqué dans les sections.

Utiliser l'arithmétique NaN

Les indicateurs effectuent des calculs pour produire des visuels spécifiques, et il est essentiel que votre code gère correctement les cas limites et les conditions aux limites pendant ces calculs.

Considérez l'extrait suivant d'un indicateur qui produit un oscillateur de prix sans tendance :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private MovingAverage movingAverage;

protected override void Initialize()
{
    movingAverage = Indicators.SimpleMovingAverage(Source, Periods);
}

public override void Calculate(int index)
{
    Result[index] = Source[index] - movingAverage.Result[index - Periods / 2 - 1];
}

Le code ci-dessus définit des règles de calcul générales mais omet les conditions aux limites. Par exemple, si Periods est défini sur 10 et que index se situe dans la plage 0–9, le calcul renverra NaN (Not a Number). Ce problème se produit parce que l'indicateur ne peut pas calculer les valeurs pour un graphique à barres avec un index négatif.

Pour résoudre le problème, vous pouvez ajouter une condition comme indiqué ci-dessous :

1
2
3
4
5
6
7
public override void Calculate(int index)
{
    if (index >= Periods + Periods / 2 + 1)
    {
        Result[index] = Source[index] - movingAverage.Result[index - Periods / 2 - 1];
    }
}

Le code de la moyenne mobile simple lui-même doit également vérifier que index >= Periods. Si vous utilisez un indicateur imbriqué, tel qu'un autre type de moyenne mobile, la condition sera différente pour tenir compte des calculs supplémentaires.

Bien que vous puissiez définir des conditions aux limites explicites, C# offre un moyen pratique d'éviter ces problèmes grâce à l'arithmétique NaN. Plus précisément, le type de données double prend entièrement en charge les calculs NaN. Par exemple :

1
2
3
4
5
double result = double.NaN + 1.4; 
// result will be NaN

bool isNaN = double.IsNaN(result); 
// isNaN will be true

Cependant, lorsqu'un opérande dans un calcul est NaN, le résultat sera également NaN. Comme les indicateurs cTrader personnalisés fonctionnent sur le type DataSeries, si vous tentez d'accéder à un élément DataSeries avec un index négatif, il renverra NaN, et la valeur ne sera pas tracée sur le graphique de trading. Ce comportement permet à l'indicateur de continuer à fonctionner sans générer d'exceptions. Dans la plupart des cas, vous pouvez ignorer en toute sécurité les conditions limites et vous concentrer uniquement sur la logique de calcul générale.

Ajouter des vérifications explicites

Bien que l'arithmétique NaN simplifie la gestion des conditions limites, certains cas nécessitent encore des vérifications NaN explicites. Les indicateurs récursifs en sont un exemple courant. Un indicateur récursif calcule sa valeur actuelle en fonction de la valeur précédemment calculée.

Considérez l'implémentation suivante d'une moyenne mobile exponentielle :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public override void Calculate(int index)
{
    var previousValue = Result[index - 1];

    if (double.IsNaN(previousValue))
    {
        Result[index] = Source[index];
    }
    else
    {
        Result[index] = Source[index] * _exp + previousValue * (1 - _exp);
    }
}

Lorsque l'indicateur calcule la première période, la valeur initiale doit être explicitement définie sur un type non-NaN. Sinon, tous les calculs suivants renverront NaN, rendant l'indicateur inutile.

Dans le code ci-dessus, cela est géré avec la méthode double.IsNaN(previousValue). L'opérateur == ne peut pas être utilisé pour cette vérification (previousValue == double.NaN) car toute comparaison de NaN avec une autre valeur, y compris elle-même, est toujours évaluée à false.

Lorsque vous êtes satisfait du code de l'indicateur, générez-le, puis utilisez-le en ajoutant une instance à un graphique.

Image title