Nozioni di base di Python per il trading algoritmico
I trader utilizzano Python per creare bot di trading, indicatori tecnici, plugin e altri strumenti per facilitare il trading algoritmico o le operazioni manuali, e questo articolo spiega le nozioni di base della programmazione in Python.
Python è un linguaggio di programmazione popolare, di alto livello e per scopi generali utilizzato per lo sviluppo web, la scienza dei dati, l'automazione e, più recentemente, il trading algoritmico in cTrader. Che tu stia creando semplici bot di trading basati su segnali o strategie complesse con più indicatori, Python rende il processo più veloce, più efficiente e più facile da gestire.
Algoritmi Python in un minuto!
- Sperimenta il supporto integrato di Python e l'accesso perfetto all'API cTrader Algo, con cTrader che è l'unica piattaforma importante a offrire un'integrazione nativa pronta all'uso. Nessun plugin, adattatore o configurazione complessa richiesta.
- Concentrati maggiormente su ciò che la tua strategia dovrebbe ottenere poiché la logica diventa più facile da assemblare. Goditi iterazioni rapide, componenti riutilizzabili e prestazioni scalabili.
- Sviluppa rapidamente, esegui il debug in modo più intelligente e collabora senza barriere. Il tuo codice sarà sempre adattabile, affidabile e manutenibile.
- Accedi e approfitta di migliaia di librerie gratuite/open-source, tutorial approfonditi, esempi di codice e un forte supporto della community in tutto il mondo.
Variabili e tipi di dati
In Python, le variabili sono tipizzate dinamicamente, il che significa che non è necessario dichiarare esplicitamente i loro tipi di dati. L'interprete determina il tipo in fase di esecuzione in base al valore assegnato.
Crei le variabili semplicemente assegnando loro un valore:
1 2 3 4 | |
Tipi di dati comuni
| Tipo | Descrizione | Esempio |
|---|---|---|
int | Numeri interi | 5, 100, api.StepPips |
float | Numeri decimali | 1.1234, 100.5, api.Symbol.Ask |
bool | Valori booleani | True, False |
str | Stringhe | "EURUSD", api.Label |
list | Raccolta di elementi | [1, 2, 3], [p for p in api.Positions] |
Negli algoritmi di cTrader, le variabili memorizzano dati importanti relativi alle informazioni di mercato, alle decisioni di trading e alla configurazione dei cBot. Queste variabili spesso rappresentano volumi di trading calcolati, valori degli indicatori, flag booleani, nomi di simboli, etichette e altro ancora.
Ecco un esempio:
1 2 3 4 | |
In questo caso, self.volumeInUnits è un float utilizzato per piazzare ordini, mentre self.enoughMoney è un bool che controlla se continuare ad aprire posizioni in una strategia grid.
Classi e oggetti
Python è un linguaggio di programmazione orientato agli oggetti (OOP), che fornisce strumenti per organizzare il codice attraverso classi e oggetti che modellano entità e comportamenti del mondo reale. Una classe definisce un modello per la creazione di oggetti, che sono istanze di quella classe con i propri dati e comportamenti unici. I concetti chiave sono delineati di seguito:
- Una classe viene definita utilizzando la parola chiave
class. - Il metodo
__init__(costruttore) viene comunemente utilizzato per inizializzare lo stato dell'oggetto. - I metodi di istanza definiscono il comportamento.
- Gli attributi contengono dati specifici per ogni oggetto.
Ad esempio, puoi creare una classe Car:
1 2 3 4 5 6 7 | |
Quindi puoi creare oggetti della classe Car e interagire con essi:
1 2 3 | |
Nel contesto di cTrader
In cTrader, i cBot, gli indicatori e i plugin sono implementati come classi che incapsulano la loro intera logica. Gli algoritmi interagiscono con la piattaforma cTrader utilizzando un oggetto speciale api che fornisce accesso a simboli, grafici, ordini, indicatori e altro ancora.
Puoi creare una classe SimplecBot in cTrader in questo modo:
1 2 3 | |
La classe SimplecBot include un singolo metodo (on_start(self)) che viene eseguito una volta all'avvio del bot di trading. La funzione api.Print scrive un messaggio nel log, dimostrando come i metodi degli oggetti incapsulano il comportamento di trading.
Ogni istanza di una classe rappresenta effettivamente un algoritmo di trading autonomo che gestisce il proprio ciclo di vita e le proprie decisioni di trading utilizzando i principi OOP. In un cBot cTrader standard, una classe potrebbe memorizzare dati di stato interni, come volume, risultati degli indicatori, ecc., e utilizzare diversi metodi per gestire la logica di trading.
Considera questo esempio di MACD crossover che inizializza l'indicatore MACD all'avvio e piazza un ordine di acquisto quando si verifica un segnale di crossover MACD:
1 2 3 4 5 6 7 | |
La parola chiave self
All'interno di una classe, self si riferisce all'istanza della classe e fornisce accesso alle sue variabili e ai suoi metodi. self viene utilizzato per:
- Memorizzare dati come i risultati degli indicatori, i volumi delle posizioni e i valori di configurazione.
- Tracciare lo stato interno attraverso diverse chiamate di metodo come
on_start(),on_tick()oon_bar_closed().
Questo esempio dimostra come viene utilizzato self:
1 2 3 4 | |
In questo caso, self.volume memorizza il volume calcolato da utilizzare per le operazioni, mentre self.macd memorizza l'oggetto indicatore MACD, consentendo l'accesso ai suoi valori durante l'intero ciclo di vita del cBot. Senza self, queste variabili sarebbero locali a on_start() e inaccessibili in on_bar_closed() dove potrebbero essere prese decisioni di trading.
Metodi e funzioni
Le funzioni sono blocchi di codice riutilizzabile utilizzati per eseguire un'attività specifica. Quando le funzioni sono definite all'interno di una classe, vengono chiamate metodi e operano sullo stato interno della classe tramite il parametro self. Nel contesto del trading algoritmico con cTrader, i metodi definiscono come si comporta il tuo algoritmo di trading in diverse condizioni, come tick di mercato, chiusure di barre o inizializzazione.
La piattaforma chiama automaticamente metodi speciali (noti come gestori di eventi) nei momenti appropriati, come:
on_start(self) – chiamato una volta quando il bot viene inizializzato.
1 2 | |
on_tick(self) – chiamato ad ogni tick di mercato in arrivo.
1 2 | |
on_bar_closed(self) – chiamato quando una nuova candela/barra si chiude (ideale per strategie basate sul tempo).
1 2 3 4 | |
Metodi personalizzati o di supporto
Per evitare di riscrivere e duplicare il codice, puoi definire i tuoi metodi. Tali metodi personalizzati dovrebbero incapsulare la logica comune che il tuo robot di trading può riutilizzare.
Il metodo seguente restituisce tutte le posizioni aperte associate all'etichetta del cBot corrente, rendendo facile tracciare o chiudere le posizioni in modo coerente.
1 2 | |
Considera un altro metodo che calcola la distanza in pip tra il prezzo attuale e l'entrata della posizione, che è fondamentale per le decisioni nelle strategie basate su griglia.
1 2 | |
Una volta definito un metodo, puoi chiamarlo dall'interno della stessa classe utilizzando la parola chiave self. Questo approccio ti consente di riutilizzare la logica ovunque nel tuo bot senza duplicare il codice.
Ad esempio, dopo aver definito get_bot_positions(), potresti chiamarlo all'interno di un altro metodo per chiudere tutte le posizioni:
1 2 3 4 | |
Qui, self.get_bot_positions() invoca il metodo di supporto, restituendo solo le posizioni legate all'etichetta del bot corrente.
Allo stesso modo, il metodo get_distance_in_pips() può essere riutilizzato per prendere decisioni di trading. Ad esempio, in una strategia a griglia, potresti voler aprire un nuovo ordine solo se il mercato si è spostato abbastanza lontano dall'ultima posizione:
1 2 3 4 5 6 7 | |
Altri concetti
Namespace e importazioni
I namespace in Python aiutano a organizzare il codice ed evitare collisioni di nomi raggruppando identificatori correlati (variabili, funzioni, classi). Le importazioni ti consentono di importare moduli, librerie o pacchetti esterni per estendere le funzionalità oltre le caratteristiche standard di Python.
In Python, puoi importare moduli standard o pacchetti personalizzati:
1 2 | |
Puoi anche importare funzioni o classi specifiche:
1 2 | |
Quando scrivi algoritmi per cTrader in Python, le importazioni funzionano in modo leggermente diverso perché cTrader si integra con l'API cTrader Algo basata su .NET. Questa configurazione coinvolge un bridge che consente al codice Python di interagire con gli assembly .NET, e questo spiega perché un tipico cBot inizia con:
1 2 3 4 5 6 7 8 9 | |
Dove:
import clrcarica il Common Language Runtime (CLR), consentendo a Python di interoperare con le librerie .NET.clr.AddReference("cAlgo.API")fa riferimento all'assembly dell'API cAlgo, che contiene tutte le classi, i metodi e gli oggetti relativi al trading.from cAlgo.API import *importa tutti i tipi dall'API (ad es.,TradeType,Color,Position).from robot_wrapper import *carica funzioni di supporto e wrapper che semplificano le operazioni di trading comuni.
Il sistema di namespace garantisce che:
- I nomi integrati di Python (come
print) evitino conflitti con i nomi di cTrader (comeapi.Print). - Tutti gli oggetti specifici del trading (
api.Symbol,api.Indicators,api.ExecuteMarketOrder) provengano dal namespace dell'API cTrader Algo, mantenendoli organizzati e distinti. - Puoi estendere le funzionalità importando i tuoi pacchetti personalizzati per lavorare insieme ai tipi integrati di cTrader.
Cicli
I cicli ti consentono di ripetere operazioni su una sequenza di valori o fino a quando non viene soddisfatta una condizione. Nel trading algoritmico, i cicli vengono spesso utilizzati per elaborare posizioni (ad es., chiudere, filtrare o aggiornarle), verificare condizioni su più asset o indicatori, implementare strategie a griglia o martingala dove è richiesto il piazzamento ripetuto di ordini e altro ancora.
In Python, l'iterazione è semplice e supporta sia i cicli for (per iterare attraverso le collezioni) che i cicli while (per ripetere fino a quando una condizione cambia).
Puoi scrivere un ciclo per chiudere le posizioni:
1 2 3 4 | |
In questo caso:
self.get_bot_positions()restituisce tutte le posizioni appartenenti al cBot corrente.- Il ciclo
forpassa attraverso ogni posizione. - Le posizioni corrispondenti vengono chiuse con
api.ClosePosition.
Considera un ciclo diverso che itera su tutte le posizioni a griglia aperte, le chiude una per una e verifica ricorsivamente se rimangono posizioni (sicurezza in caso di chiusure parziali).
1 2 3 4 5 6 | |
Istruzioni condizionali
Le istruzioni condizionali controllano il flusso di esecuzione in Python consentendo al tuo algoritmo di prendere decisioni basate su espressioni logiche. Le condizionali sono la spina dorsale della logica di strategia, determinando quando entrare, uscire o gestire le posizioni.
Python supporta tre costrutti condizionali principali:
if– esegue il codice quando la condizione è vera.elif(else if) – verifica un'altra condizione se la prima era falsa.else– fornisce un'alternativa quando nessuna condizione è soddisfatta.
Considera le condizioni di crossover MACD espresse in questo codice:
1 2 3 4 | |
Questa struttura:
- Piazza un ordine di acquisto quando la linea MACD è sopra la linea del segnale.
- Piazza un ordine di vendita quando la linea MACD è sotto la linea del segnale.
- Salta il trading se non c'è un segnale chiaro.
Liste
Python fornisce strumenti potenti e concisi per lavorare con collezioni di dati, come operazioni, prezzi o indicatori. Due dei più comuni sono le list comprehension e le funzioni di aggregazione integrate come sum().
Ad esempio, puoi scrivere un codice che itera su numbers e mantiene solo i numeri pari in questo modo:
1 2 | |
Puoi utilizzare una list comprehension per selezionare solo le posizioni per il simbolo corrente, producendo un elenco filtrato che è utile in ambienti multi-simbolo.
1 | |
Aggregare profitto o volume utilizzando sum() è un approccio standard nelle strategie di trading a griglia per determinare quando il profitto totale raggiunge l'obiettivo.
1 | |
Puoi combinare filtraggio e aggregazione in questo modo:
1 2 | |
Operazioni sincrone e asincrone
Python segue un modello di esecuzione sincrono per impostazione predefinita. I metodi del ciclo di vita del tuo algoritmo, come on_start, on_tick e on_bar_closed, vengono attivati dal ciclo di eventi della piattaforma, uno alla volta.
Ecco una rappresentazione di base di un flusso di trading sincrono:
graph TD
A(Rilevare<br>un segnale) ==> B(Eseguire un ordine)
B ==> C(La posizione<br>raggiunge TP/SL)
C ==> D(Chiudere la<br>posizione)
D ==> A Nei flussi sincroni, qualsiasi operazione di lunga durata può bloccare il thread, ritardando potenzialmente l'evento successivo. Tuttavia, nelle strategie del mondo reale, gli algoritmi tipicamente avviano azioni non bloccanti, come l'invio di un ordine o l'impostazione di stop-loss e take-profit, quindi attendono eventi futuri (come un nuovo tick o barra) per gestire i risultati. Questa configurazione risulta in un'orchestrazione simile all'asincrona, anche se i costrutti async/await di Python non vengono utilizzati.
Nota
Per la maggior parte degli algoritmi di trading, la programmazione asincrona esplicita non è necessaria.
cTrader gestisce la concorrenza serializzando i tuoi callback basati su eventi. Ogni metodo viene invocato indipendentemente e mai in parallelo, eliminando la necessità di protezioni per il multithreading. Questo design consente alle strategie di rispondere a più condizioni di trading contemporaneamente, in senso logico, senza blocchi.
Nell'esempio seguente, la strategia valuta i segnali di acquisto e vendita in modo indipendente e risponde di conseguenza, senza sovrapposizioni nel contesto di esecuzione.
graph TD
A([Rilevare<br>un segnale]) ==> B([Aprire un ordine<br>di acquisto]) & C([Aprire un<br>ordine di<br>vendita di<br>copertura]) ==> D([Un ordine<br>raggiunge<br>il take profit o<br>lo stop loss])
D ==> E([Chiudere la<br>posizione])
E ==> A Anche se le decisioni possono sembrare parallele, vengono gestite in sequenza dal sistema di accodamento interno di cTrader. L'architettura della piattaforma mira a prevenire problemi di concorrenza mantenendo i robot di trading reattivi ai cambiamenti del mercato.
