Esempi di codice per indicatori
Questa pagina fornisce diversi esempi di codice Python e C# per la creazione di indicatori tecnici utilizzati per il trading manuale o algoritmico.
Repository di esempi di indicatori
Esempi completi di codice per indicatori, inclusi modelli pronti all'uso per vari tipi di indicatori e strumenti di analisi tecnica, sono disponibili in repository separati per Python e C# su GitHub.
Indicatori semplici
L'indicatore high minus low calcola la differenza tra i prezzi massimo e minimo della barra corrente e la visualizza in una serie di output. La serie viene tracciata sul grafico come una linea che collega i valori risultanti in ciascuna barra.
1 2 3 4 5 6 7 8 9 10 11 | |
Nota
Gli indicatori Python utilizzano parametri personalizzabili dichiarati nei loro file .cs.
1 2 3 4 5 6 7 | |
La dichiarazione [Indicator...] include diversi parametri che sono definiti come segue:
IsOverlay- un valore booleano che definisce se la linea verrà sovrapposta al grafico o visualizzata in un pannello UI separato.TimeZone- un campo della classeTimeZonesche specifica il fuso orario dei dati dell'indicatore e l'orario del server.AccessRights- un campo della classeAccessRightsche determina i diritti di accesso assegnati al tuo indicatore.ScalePrecision- un int che imposta la precisione della scala dell'output dell'indicatore.
Come hai appreso in precedenza durante la modifica del codice dell'indicatore, l'attributo Output viene dichiarato per contrassegnare una proprietà come output dell'indicatore. Questa proprietà deve essere public in modo che possa essere referenziata da altre classi.
L'output dell'indicatore deve essere sempre del tipo di dati IndicatorDataSeries, che è un elenco di double che può essere indicizzato come un array. Pertanto, il valore a ciascun [index] nell'elenco Result può essere assegnato nel metodo Calculate come segue.
1 2 3 4 | |
1 2 | |
Indicatori con parametri
Nella maggior parte dei casi, l'output degli indicatori può variare a seconda dell'input dell'utente. Il modo in cui i parametri personalizzabili vengono configurati per gli indicatori è simile a come viene fatto per i cBot.
L'indicatore simple moving average riportato di seguito è progettato per accettare una fonte di prezzo e un periodo come parametri personalizzabili. Tali parametri (Source e Periods in questo particolare esempio) devono essere preceduti dall'attributo Parameter.
Analogamente agli attributi [Indicator()] e [Output()] discussi in precedenza, l'attributo [Parameter()] può definire determinate caratteristiche applicate all'input dell'utente.
1 | |
Nota
Gli indicatori Python utilizzano parametri personalizzabili dichiarati nei loro file .cs.
Sopra, specifichiamo le seguenti caratteristiche:
- Il nome visualizzato per indicare questo parametro nell'interfaccia utente di cTrader (
"MA Periods). - Il valore predefinito del parametro; può essere modificato dall'utente durante la personalizzazione di un'istanza (
DefaultValue = 14) - I valori minimo e massimo del parametro (
MinValue = 1, MaxValue = 20)
Nel seguente snippet, mostriamo come i parametri personalizzabili possono essere integrati nel codice dell'indicatore.
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 | |
Nota
Gli indicatori Python utilizzano parametri personalizzabili dichiarati nei loro file .cs.
1 2 3 4 5 6 7 8 | |
Indicatori nidificati
Gli indicatori nidificati sono definiti come indicatori il cui valore dipende dai risultati dei calcoli eseguiti da altri indicatori. Sono utili quando si scrivono determinati tipi di estensioni come l'indicatore DeMark 9. Considera il seguente codice di esempio:
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 | |
Nota
Gli indicatori Python utilizzano parametri personalizzabili dichiarati nei loro file .cs.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
Nell'esempio sopra, deMinMA e deMaxMA sono due variabili utilizzate per calcolare il valore del nostro indicatore DeMarker.
Gli indicatori nidificati devono essere definiti nel metodo Initialize(). Ad esempio, deMinMA è definito come la media mobile semplice della serie deMin.
1 | |
1 | |
deMin, a sua volta, è definito nel metodo Calculate() come il massimo degli ultimi due valori di prezzo minimo.
1 | |
1 | |
Per semplificare il lavoro con gli indicatori nidificati, IntelliSense popola automaticamente l'elenco di tutti gli indicatori integrati quando digiti Indicators seguito da un punto nell'editor di codice. Visualizzerà anche tutti i parametri di input correlati una volta selezionato un determinato indicatore da questo elenco.

Caricamento lazy
cTrader Algo utilizza il caricamento lazy quando utilizzi indicatori referenziati. I valori forniti dall'indicatore referenziato non vengono calcolati finché il tuo codice non inizia a utilizzarli attivamente.
Se accedi ai dati Outputs di un indicatore referenziato, cTrader inizierà a caricare i dati dell'indicatore chiamando il suo metodo Calculate() sulle barre passate e future. In qualsiasi altro caso, l'indicatore referenziato rimarrà inattivo e, pertanto, non consumerà alcuna risorsa di sistema.
Ciò significa anche che se il tuo indicatore non ha alcun Output o se provi ad accedere a una qualsiasi delle sue proprietà pubbliche, otterrai il valore predefinito della proprietà in questione. Per risolvere questo problema, chiama il metodo Calculate() del tuo indicatore personalizzato dal metodo Calculate() dell'indicatore corrente.
Oscillatori e l'attributo levels
Il termine "oscillatori" comprende tutti gli indicatori che oscillano attorno a una determinata variabile costante.
Quando si creano oscillatori, è utile tracciare prima una linea orizzontale o di "livello" a quel valore costante; l'indicatore oscillerà quindi attorno a questa linea. In molti casi, il valore costante è uguale a zero.
Nell'esempio seguente, definiamo un oscillatore momentum. Tipicamente oscilla attorno al valore di 100. Aggiungiamo una linea di livello a questo valore utilizzando l'attributo Levels che viene dichiarato prima degli attributi dell'indicatore.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
Nota
Gli indicatori Python utilizzano parametri personalizzabili dichiarati nei loro file .cs.
1 2 3 4 | |
Nota che l'attributo Levels può essere utilizzato solo se l'indicatore non è sovrapposto al grafico, il che significa che la proprietà IsOverlay non è impostata su true. Per impostazione predefinita, il valore di IsOverlay è false. Se questo attributo viene omesso dal tuo codice, Levels dovrebbe funzionare correttamente.
Se devi stabilire più linee di "livello", aggiungi un elenco di valori separati da virgole tra le parentesi come mostrato di seguito.
1 | |
1 | |
1 | |
Livelli negli indicatori Python
In Python dichiari i Levels nel file C# del tuo indicatore allo stesso modo degli indicatori C#.
La proprietà IsLastBar
In alcuni casi, potresti voler creare un indicatore che deve essere calcolato solo per l'ultima barra nel grafico di trading. Per semplificare questo, la proprietà IsLastBar può essere utilizzata per verificare se il parametro index del metodo Calculate() è quello dell'ultima barra.
L'indicatore seguente è basato sull'ora UTC; tuttavia, può visualizzare l'ultimo orario di apertura a New York e 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 | |
Combinare indicatori
cTrader permette di combinare più indicatori nello stesso pannello o all'interno dello stesso grafico.
L'indicatore seguente combina gli indicatori Aroon, RSI e Directional Movement System in uno solo.
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 | |
Nota
Gli indicatori Python utilizzano parametri personalizzabili dichiarati nei loro file .cs.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |
Più periodi di tempo
-
Utilizzare più periodi di tempo
L'esempio seguente mostra un indicatore Moving Average su diversi periodi di tempo.
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]; } }Nota
Gli indicatori Python utilizzano parametri personalizzabili dichiarati nei loro file
.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] -
Utilizzare più periodi di tempo e simboli
L'esempio seguente mostra l'indicatore Moving Average su più periodi di tempo e simboli.
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); } }Nota
Gli indicatori Python utilizzano parametri personalizzabili dichiarati nei loro file
.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)
