Exemples de code d'indicateurs
Cette page fournit plusieurs exemples de code Python et C# pour créer des indicateurs techniques utilisés pour le trading manuel ou algorithmique.
Référentiels d'exemples d'indicateurs
Des exemples de code d'indicateurs complets, y compris des modèles prêts à exécuter pour divers types d'indicateurs et outils d'analyse technique, sont disponibles dans des référentiels Python et C# distincts dans GitHub.
Indicateurs simples
L'indicateur haut moins bas calcule la différence entre les prix haut et bas de la barre actuelle et l'affiche dans une série de résultats. La série est tracée sur le graphique sous forme de ligne reliant les valeurs résultantes dans chaque barre.
1 2 3 4 5 6 7 8 9 10 11 | |
Remarque
Les indicateurs Python utilisent des paramètres personnalisables déclarés dans leurs fichiers .cs.
1 2 3 4 5 6 7 | |
La déclaration [Indicator...] comprend plusieurs paramètres définis comme suit :
IsOverlay- un booléen qui définit si la ligne sera superposée sur le graphique ou affichée dans un panneau d'interface utilisateur séparé.TimeZone- un champ de classeTimeZonesqui spécifie le fuseau horaire des données de l'indicateur et l'heure du serveur.AccessRights- un champ de classeAccessRightsqui détermine les droits d'accès alloués à votre indicateur.ScalePrecision- un int configurant la précision de l'échelle du résultat de l'indicateur.
Comme vous l'avez appris précédemment lors de la modification du code de l'indicateur, l'attribut Output est déclaré pour marquer une propriété comme résultat d'indicateur. Cette propriété doit être public afin de pouvoir être référencée par d'autres classes.
Le résultat de l'indicateur doit toujours être du type de données IndicatorDataSeries, qui est une liste de doubles pouvant être indexée comme un tableau. Par conséquent, la valeur à chaque [index] dans la liste Result peut être attribuée dans la méthode Calculate comme suit.
1 2 3 4 | |
1 2 | |
Indicateurs avec paramètres
Dans la plupart des cas, le résultat des indicateurs peut varier en fonction de la saisie de l'utilisateur. La façon dont les paramètres personnalisables sont configurés pour les indicateurs est similaire à la façon dont cela est fait pour les cBots.
L'indicateur Simple Moving Average ci-dessous est conçu pour accepter une source de prix et une période comme paramètres personnalisables. Ces paramètres (Source et Periods dans cet exemple particulier) doivent être précédés de l'attribut Parameter.
Comme pour les attributs [Indicator()] et [Output()] abordés précédemment, l'attribut [Parameter()] peut définir certaines caractéristiques appliquées à la saisie de l'utilisateur.
1 | |
Remarque
Les indicateurs Python utilisent des paramètres personnalisables déclarés dans leurs fichiers .cs.
Ci-dessus, nous spécifions les caractéristiques suivantes :
- Le nom affiché pour désigner ce paramètre dans l'interface utilisateur de cTrader (
"MA Periods). - La valeur par défaut du paramètre ; elle peut être modifiée par l'utilisateur lors de la personnalisation d'une instance (
DefaultValue = 14) - Les valeurs minimale et maximale du paramètre (
MinValue = 1, MaxValue = 20)
Dans l'extrait suivant, nous montrons comment les paramètres personnalisables peuvent être intégrés dans le code de l'indicateur.
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 | |
Remarque
Les indicateurs Python utilisent des paramètres personnalisables déclarés dans leurs fichiers .cs.
1 2 3 4 5 6 7 8 | |
Indicateurs imbriqués
Les indicateurs imbriqués sont définis comme des indicateurs dont la valeur dépend des résultats de calculs effectués par d'autres indicateurs. Ils sont utiles lors de l'écriture de certains types d'extensions telles que l'indicateur DeMark 9. Considérez l'exemple de code suivant :
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 | |
Remarque
Les indicateurs Python utilisent des paramètres personnalisables déclarés dans leurs fichiers .cs.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
Dans l'exemple ci-dessus, deMinMA et deMaxMA sont deux variables utilisées pour calculer la valeur de notre indicateur DeMarker.
Les indicateurs imbriqués doivent être définis dans la méthode Initialize(). Par exemple, deMinMA est défini comme la Simple Moving Average de la série deMin.
1 | |
1 | |
deMin, à son tour, est défini dans la méthode Calculate() comme le maximum des deux dernières valeurs de prix bas.
1 | |
1 | |
Pour simplifier le travail avec les indicateurs imbriqués, IntelliSense remplit automatiquement la liste de tous les indicateurs intégrés lorsque vous tapez Indicators suivi d'un point dans l'éditeur de code. Il affichera également tous les paramètres d'entrée associés une fois que vous aurez sélectionné un certain indicateur dans cette liste.

Chargement différé
cTrader Algo utilise le chargement différé lorsque vous utilisez des indicateurs référencés. Les valeurs fournies par l'indicateur référencé ne sont pas calculées tant que votre code ne commence pas à les utiliser activement.
Si vous accédez aux données Outputs d'un indicateur référencé, cTrader commencera à charger les données de l'indicateur en appelant sa méthode Calculate() sur les barres passées et futures. Dans tous les autres cas, l'indicateur référencé restera inactif et, par conséquent, ne consommera aucune ressource système.
Cela signifie également que si votre indicateur n'a pas de Output ou si vous essayez d'accéder à l'une de ses propriétés publiques, vous obtiendrez la valeur par défaut de la propriété en question. Pour résoudre ce problème, appelez la méthode Calculate() de votre indicateur personnalisé à partir de la méthode Calculate() de l'indicateur actuel.
Oscillateurs et l'attribut levels
Le terme « oscillateurs » englobe tous les indicateurs qui oscillent autour d'une certaine variable constante.
Lors de la création d'oscillateurs, il est utile de tracer d'abord une ligne horizontale ou de « niveau » à cette valeur constante ; l'indicateur oscillera ensuite autour de cette ligne. Dans de nombreux cas, la valeur constante est égale à zéro.
Dans l'exemple ci-dessous, nous définissons un oscillateur de momentum. Il oscille généralement autour de la valeur de 100. Nous ajoutons une ligne de niveau à cette valeur en utilisant l'attribut Levels qui est déclaré avant les attributs de l'indicateur.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
Remarque
Les indicateurs Python utilisent des paramètres personnalisables déclarés dans leurs fichiers .cs.
1 2 3 4 | |
Notez que l'attribut Levels ne peut être utilisé que si l'indicateur n'est pas superposé sur le graphique, ce qui signifie que la propriété IsOverlay n'est pas définie sur true. Par défaut, la valeur de IsOverlay est false. Si cet attribut est omis de votre code, Levels devrait fonctionner correctement.
Si vous devez établir plusieurs lignes de « niveau », ajoutez une liste de valeurs séparées par des virgules entre les parenthèses comme indiqué ci-dessous.
1 | |
1 | |
1 | |
Niveaux dans les indicateurs Python
En Python, vous déclarez les niveaux dans votre fichier C# d'indicateur de la même manière que pour les indicateurs C#.
La propriété IsLastBar
Dans certains cas, vous souhaiterez peut-être créer un indicateur qui ne doit être calculé que pour la dernière barre du graphique de trading. Pour simplifier cela, la propriété IsLastBar peut être utilisée pour vérifier si le paramètre d'index de la méthode Calculate() est celui de la dernière barre.
L'indicateur ci-dessous est basé sur l'heure UTC ; cependant, il peut afficher la dernière heure d'ouverture à New York et Tokyo.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
Combinaison d'indicateurs
cTrader permet de combiner plusieurs indicateurs dans le même panneau ou dans le même graphique.
L'indicateur suivant combine les indicateurs Aroon, RSI et Directional Movement System en un seul.
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 | |
Remarque
Les indicateurs Python utilisent des paramètres personnalisables déclarés dans leurs fichiers .cs.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |
Périodes multiples
-
Utilisation de périodes multiples
L'exemple suivant affiche un indicateur Moving Average sur différentes périodes.
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
[Indicator(IsOverlay = true, TimeZone = TimeZones.UTC)] public class MultiTF_MA : Indicator { [Parameter(DefaultValue = 50)] public int Period { get; set; } [Output("MA", LineColor = "Yellow")] public IndicatorDataSeries MA { get; set; } [Output("MA5", LineColor = "Orange")] public IndicatorDataSeries MA5 { get; set; } [Output("MA10", LineColor = "Red")] public IndicatorDataSeries MA10 { get; set; } private Bars bars5; private Bars bars10; private MovingAverage ma; private MovingAverage ma5; private MovingAverage ma10; protected override void Initialize() { bars5 = MarketData.GetBars(TimeFrame.Minute5); bars10 = MarketData.GetBars(TimeFrame.Minute10); ma = Indicators.MovingAverage(Bars.ClosePrices, Period, MovingAverageType.Triangular); ma5 = Indicators.MovingAverage(bars5.ClosePrices, Period, MovingAverageType.Triangular); ma10 = Indicators.MovingAverage(bars10.ClosePrices, Period, MovingAverageType.Triangular); } public override void Calculate(int index) { MA[index] = ma.Result[index]; var index5 = bars5.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]); if (index5 != -1) MA5[index] = ma5.Result[index5]; var index10 = bars10.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]); if (index10 != -1) MA10[index] = ma10.Result[index10]; } }Remarque
Les indicateurs Python utilisent des paramètres personnalisables déclarés dans leurs fichiers
.cs.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
class MultiTF_MA(): def initialize(self): self.bars5 = api.MarketData.GetBars(TimeFrame.Minute5) self.bars10 = api.MarketData.GetBars(TimeFrame.Minute10) # Period is declared as a parameter in the C# file # We use indicator time frame bars for this moving average self.ma = Indicators.MovingAverage(api.Bars.ClosePrices, api.Period, MovingAverageType.Triangular) # We use other two time frame bars that we created previously # for these two moving averages self.ma5 = Indicators.MovingAverage(self.bars5.ClosePrices, api.Period, MovingAverageType.Triangular) self.ma10 = Indicators.MovingAverage(self.bars10.ClosePrices, api.Period, MovingAverageType.Triangular) def calculate(self, index): # MA, MA5, and MA10 are outputs we declared in the C# file api.MA[index] = self.ma.Result[index] index5 = self.bars5.OpenTimes.GetIndexByTime(api.Bars.OpenTimes[index]) if index5 > -1: api.MA5[index] = self.ma5.Result[index5] index10 = self.bars10.OpenTimes.GetIndexByTime(api.Bars.OpenTimes[index]) if index10 > -1: api.MA10[index] = self.ma10.Result[index10] -
Utilisation de périodes et de symboles multiples
L'exemple suivant affiche l'indicateur Moving Average sur plusieurs périodes et symboles.
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 57
[Indicator(IsOverlay = true, TimeZone = TimeZones.UTC)] public class MultiSymbolMA : Indicator { private MovingAverage ma1, ma2, ma3; private Bars bars2, bars3; private Symbol symbol2, symbol3; [Parameter(DefaultValue = "EURCHF")] public string Symbol2 { get; set; } [Parameter(DefaultValue = "EURCAD")] public string Symbol3 { get; set; } [Parameter(DefaultValue = 14)] public int Period { get; set; } [Parameter(DefaultValue = MovingAverageType.Simple)] public MovingAverageType MaType { get; set; } [Output("MA Symbol 1", LineColor = "Magenta")] public IndicatorDataSeries Result1 { get; set; } [Output("MA Symbol 2", LineColor = "Magenta")] public IndicatorDataSeries Result2 { get; set; } [Output("MA Symbol 3", LineColor = "Magenta")] public IndicatorDataSeries Result3 { get; set; } protected override void Initialize() { symbol2 = Symbols.GetSymbol(Symbol2); symbol3 = Symbols.GetSymbol(Symbol3); bars2 = MarketData.GetBars(TimeFrame, symbol2.Name); bars3 = MarketData.GetBars(TimeFrame, symbol3.Name); ma1 = Indicators.MovingAverage(Bars.ClosePrices, Period, MaType); ma2 = Indicators.MovingAverage(bars2.ClosePrices, Period, MaType); ma3 = Indicators.MovingAverage(bars3.ClosePrices, Period, MaType); } public override void Calculate(int index) { ShowOutput(Symbol, Result1, ma1, Bars, index); ShowOutput(symbol2, Result2, ma2, bars2, index); ShowOutput(symbol3, Result3, ma3, bars3, index); } private void ShowOutput(Symbol symbol, IndicatorDataSeries result, MovingAverage movingAverage, Bars bars, int index) { var index2 = bars.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]); result[index] = movingAverage.Result[index2]; string text = string.Format("{0} {1}", symbol.Name, Math.Round(result[index], symbol.Digits)); Chart.DrawStaticText(symbol.Name, text, VerticalAlignment.Top, HorizontalAlignment.Right, Color.Yellow); } }Remarque
Les indicateurs Python utilisent des paramètres personnalisables déclarés dans leurs fichiers
.cs.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
class MultiSymbolMA(): def initialize(self): # Symbol2 and Symbol3 are declared as parameters in the C# file self.symbol2 = api.Symbols.GetSymbol(api.Symbol2) self.symbol3 = api.Symbols.GetSymbol(api.Symbol3) self.bars2 = api.MarketData.GetBars(api.TimeFrame, self.symbol2.Name) self.bars3 = api.MarketData.GetBars(api.TimeFrame, self.symbol3.Name) self.ma1 = api.Indicators.MovingAverage(api.Bars.ClosePrices, api.Period, api.MaType) self.ma2 = api.Indicators.MovingAverage(self.bars2.ClosePrices, api.Period, api.MaType) self.ma3 = api.Indicators.MovingAverage(self.bars3.ClosePrices, api.Period, api.MaType) def calculate(self, index): # Result1, Result2, and Result3 are declared as outputs in the C# file self.show_output(api.Symbol, api.Result1, self.ma1, api.Bars, index) self.show_output(self.symbol2, api.Result2, self.ma2, self.bars2, index) self.show_output(self.symbol3, api.Result3, self.ma3, self.bars3, index) def show_output(self, symbol, result, movingAverage, bars, index): index2 = bars.OpenTimes.GetIndexByTime(api.Bars.OpenTimes[index]) result[index] = movingAverage.Result[index2] text = f"{symbol.Name} {round(result[index], symbol.Digits)}" api.Chart.DrawStaticText(symbol.Name, text, VerticalAlignment.Top, HorizontalAlignment.Right, Color.Yellow)
