Come creare un sistema di trading basato su IA completamente automatizzato con Python
Progetto end-to-end: ottieni i dati, addestra il modello, effettua l’ordine, ricevi una notifica
Un paio di settimane fa ero casualmente chiacchierando con un amico, maschere, distanza sociale, la solita st u FF. Mi stava dicendo come stava cercando, e cito, di disintossicarsi dall’app del broker che stava usando. Gli ho chiesto il significato della parola disintossicazione in questo particolare contesto, preoccupandomi che potesse andare in rovina, ma no: mi ha detto che faceva costantemente trading. “Se un particolare titolo è salito da più di un’ora circa e sono già oltre la soglia di profitto dell’1%, allora vendo”, ha detto, “tra le altre regole personali che ho seguito”. Tralasciando il lieve aspetto pseudoscientifico di quelle regole, ho capito cosa intendesse per disintossicazione: seguirle implicava controllare il telefono un numero di volte astronomicamente elevato.
Quindi ho iniziato a chiedermi: sarebbe possibile automatizzare l’insieme di regole che questo ragazzo ha in mente? E in realtà – sarebbe possibile automatizzare un insieme di regole più sano, quindi lascio che il sistema faccia il trading per me? Dato che stai leggendo questo, presumo che tu sia stato catturato dal titolo, quindi probabilmente hai già indovinato che la risposta è sì. Analizziamo questo, ma prima di tutto: il tempo è oro e non voglio fare clickbait con nessuno. Questo è quello che faremo:
Ottieni dati granulari sui prezzi delle azioni in tempo reale: idealmente, a intervalli di un minuto. Più ricco è, meglio è: useremo Yahoo! Finanziamenti per questo, ulteriori dettagli da seguire.
Invece di una serie di regole personali , aggiungeremo un tocco di intelligenza artificiale al sistema. Divulgazione completa: non sono affatto un esperto nell’analisi delle serie temporali, ci sono già molti tutorial su come addestrare le reti neurali al commercio e non voglio davvero ingegnerizzare troppo in un sistema di giocattoli come questo, quindi cerchiamo mantienilo semplice: per ora va bene un modello ARIMA molto semplice.
A questo punto avremo i dati e la previsione provenienti dall’algoritmo, quindi dovremmo essere in grado di decidere se vendere, comprare o tenere; dobbiamo connetterci con il nostro broker per eseguire effettivamente l’azione. Useremo RobinHood e Alpaca.
Questo è praticamente tutto: il sistema è finito. L’ultima cosa di cui abbiamo bisogno è distribuirlo da qualche parte, nel nostro caso AWS, e monitorare l’attività. Ho scelto di inviare un messaggio di Telegram a un gruppo ogni volta che viene eseguita un’azione dal mio sistema.
E di cosa avremo bisogno?
Python 3.6 con alcune librerie.
Un account AWS con diritti di amministratore, per l’archiviazione e la distribuzione.
Node.js, solo per configurare il framework serverless per la distribuzione.
Un account Telegram, per il monitoraggio.
Tutto quello che ho codificato è disponibile qui . Va bene! Quindi, senza ulteriori indugi, passiamo alla prima parte: ottenere i dati.
Recupero dei dati
Ottenere i dati non è facile. Alcuni anni fa c’era un Yahoo! ufficiale Finanza API, così come alternative come Google Finance, purtroppo, entrambe sono state interrotte da anni ormai. Ma non preoccuparti, ci sono ancora molte alternative sul mercato. Le mie esigenze personali erano:
Gratuito: per un sistema di produzione cambierei sicuramente questo punto elenco con alternative economiche , ma per un sistema giocattolo, o proof of concept, come vuoi chiamarlo, lo voglio gratis.
Tasso di limite alto: idealmente nessun limite, ma qualsiasi valore superiore a 500 colpi al minuto è più che sufficiente.
Dati in tempo reale: alcune API forniscono dati con un leggero ritardo, diciamo 15 minuti. Voglio il vero affare, il più vicino possibile al prezzo in tempo reale delle azioni.
Facile da usare: ancora una volta, questo è solo un POC. Voglio il più semplice.
Con questo elenco in mente, ho scelto yfinance- l’alternativa non ufficiale alla vecchia API di Yahoo Finance. Tieni presente che per un sistema reale e sulla base del fantastico elenco fornito da Patrick Collins , sceglierei sicuramente l’API Alpha Vantage, ma per ora manteniamolo semplice.
La yfinancelibreria è stata sviluppata da Ran Aroussi per ottenere l’accesso a Yahoo! Dati finanziari quando l’API ufficiale è stata chiusa. Citando dal repository GitHub,
Da quando Yahoo! la finanza ha disattivato l’API dei dati storici, molti programmi che facevano affidamento su di essa per smettere di funzionare.
yfinance mira a risolvere questo problema offrendo un modo affidabile, filettato e Pythonic per scaricare i dati storici di mercato da Yahoo! finanza.
Dolce, abbastanza buono per me. Come funziona? Per prima cosa dobbiamo installarlo:
$ pip install yfinance –user
E poi possiamo accedere a tutto usando l’oggetto Ticker:
importa yfinance come yf
google = yf.Ticker (“GOOG”)
Questo metodo è abbastanza veloce, in media leggermente superiore a 0,005 secondi e restituisce MOLTE informazioni sul titolo; ad esempio, google.infocontiene 123 campi, inclusi i seguenti:
52WeekChange: 0.3531152
SandP52WeekChange: 0.17859101
address1: 1600 Amphitheatre Parkway
algoritmo: Nessuno
annualHoldingsTurnover: Nessuno
annualReportExpenseRatio: Nessuno
ask: 1815
askSize: 1100
…
twoHundredDayAverage: 1553.0764
volume: 1320946
volume24Hr: Nessuno
volumeAllCurrencies: Nessuno
website: http://www.abc.xyz
yield: Nessuno
ytdReturn: Nessuno
zip: 94043
Non v’è più informazioni disponibili attraverso diversi metodi: dividends, splits, balance_sheeto earningstra gli altri. La maggior parte di questi metodi restituisce i dati in un pandasoggetto DataFrame, quindi dovremo giocarci un po ‘per ottenere quello che vogliamo. Per ora mi servono solo le informazioni sul prezzo delle azioni nel tempo; il historymetodo è il migliore per quello scopo. Possiamo selezionare sia il periodo che le date dell’intervallo e la frequenza dei dati fino a un minuto: si noti che le informazioni intraday sono disponibili solo se il periodo è minore di 60 giorni e che sono consentiti solo 7 giorni per 1 milione di dati di granularità essere recuperati per richiesta. I dati trasposti dell’ultima voce con un intervallo di 1m sono i seguenti:
df = google.history (period = ‘1d’, interval = “1m”)
print (df.head ())
Immagine per post
Dataframe del prezzo storico delle azioni di Google – Immagine dell’autore
Possiamo vedere come è indicizzato in base al datetime e ogni voce ha sette caratteristiche: quattro punti fissi del prezzo delle azioni durante quel minuto (apertura, massimo, minimo e chiusura) più il volume, i dividendi e le suddivisioni delle azioni. Userò solo il minimo, quindi conserviamo quei dati:
df = google.history (period = ‘1d’, interval = “1m”)
df = df [[‘Low’]]
df.head ()
Immagine per post
Immagine dell’autore
Infine, poiché utilizzeremo i dati solo per l’ultimo giorno, reindicizziamo il dataframe per rimuovere i componenti di data e fuso orario e conserviamo solo l’ora:
df [‘date’] = pd.to_datetime (df.index) .time
df.set_index (‘date’, inplace = True)
df.head ()
Immagine per post
Immagine dell’autore
Stai bene! Sappiamo già come recuperare le informazioni più recenti da yfinance- in seguito forniremo il nostro algoritmo con questo. Ma per questo, abbiamo bisogno di un algoritmo da alimentare: passiamo alla parte successiva.
Aggiunta dell’IA
L’ho detto prima ma lo ripeto: non provateci a casa. Quello che ho intenzione di fare qui è adattare un modello ARIMA MOLTO semplice per prevedere il prossimo valore del prezzo delle azioni; pensalo come un modello fittizio. Se vuoi usarlo per il trading reale, ti consiglio di cercare modelli migliori e più forti, ma attenzione: se fosse facile, lo farebbero tutti.
Per prima cosa dividiamo il dataframe in train e test, così possiamo usare il set di test per convalidare i risultati del modello fittizio – manterrò l’ultimo 10% dei dati come set di test:
X = df.index.values
y = df [‘Basso’]. Valori
Il punto di divisione è il 10% dell’offset della lunghezza del frame di dati
= int (0.10 * len (df))
X_train = X [: – offset]
y_train = y [: – offset]
X_test = X [-offset:]
y_test = y [-offset:]
Se lo tracciamo, otteniamo:
plt.plot (range (0, len (y_train)), y_train, label = ‘Train’)
plt.plot (range (len (y_train), len (y)), y_test, label = ‘Test’)
plt.legend ()
plt. mostra ()
Immagine per post
Immagine dell’autore
Adattiamo ora il modello ai dati di addestramento e otteniamo la previsione. Nota che gli iperparametri del modello sono fissi mentre nel mondo reale dovresti usare la convalida incrociata per ottenere quelli ottimali: dai un’occhiata a questo fantastico tutorial su How To Grid Search ARIMA Hyperparameters With Python . Sto utilizzando una configurazione 5, 0, 1 e ottengo la previsione per il momento immediatamente dopo la fine dei dati di allenamento:
da statsmodels.tsa.arima.model importa ARIMA
model = ARIMA (y_train, order = (5,0,1)). fit ()
forecast = model.forecast (passaggi = 1) [0]
Vediamo come ha funzionato bene il nostro modello fittizio:
print (f’Real data for time 0: {y_train [len (y_train) -1]} ‘)
print (f’Real data for time 1: {y_test [0]}’)
print (f’Pred data for time 1 : {forecast} ‘)
Dati reali per tempo 0: 1776.3199462890625
Dati reali per il tempo 1: 1776.4000244140625
Dati precedenti per il tempo 1: 1776.392609828666
Non è male, possiamo lavorarci. Con queste informazioni possiamo definire una serie di regole basate su qualsiasi cosa vogliamo fare, come tenere se sta aumentando o vendere se sta andando giù. Non ho intenzione di approfondire questa parte perché non voglio che mi facciate causa dicendo che avete perso tutti i vostri soldi, quindi per favore vai avanti e definisci le tue regole 🙂 Nel frattempo, io vado per spiegare la parte successiva: connessione al broker.
Connessione al broker
Come probabilmente avrai intuito, questa parte dipende molto dal broker che stai utilizzando. Sto coprendo qui due broker, RobinHood e Alpaca; il motivo è che entrambi:
Avere a disposizione un’API pubblica (ufficiale o meno).
Non addebitare commissioni per il trading.
A seconda del tipo di account potresti avere dei limiti: ad esempio, RobinHood consente solo 3 scambi in un periodo di 5 giorni se il saldo del tuo account è inferiore a 25000 $; Alpaca consente molte più richieste ma ha ancora un limite di 200 richieste al minuto per chiave API.
Robin Hood
Esistono diverse librerie che racchiudono l’API RobinHood, ma purtroppo, per quanto ne so, nessuna di esse è ufficiale. La libreria di Sanko era la più grande, con 1,5k stelle in GitHub, ma è stata interrotta; LichAmnesia ha continuato il percorso di Sanko, ma finora ha solo 99 stelle. Ho intenzione di utilizzare robin_stocks biblioteca , che ha poco più di 670 stelle, al momento della stesura di questo. Installiamolo:
$ pip installa robin_stocks
Non tutte le azioni richiedono l’accesso, ma la maggior parte lo fa, quindi è utile accedere prima di fare qualsiasi altra cosa. RobinHood richiede MFA, quindi è necessario configurarlo: vai sul tuo account, attiva l’autenticazione a due fattori e seleziona “altro” quando ti viene chiesto dell’app che desideri utilizzare. Ti verrà presentato un codice alfanumerico, che utilizzerai nel codice seguente:
importa pyotp
importa robin_stocks come robinhood
RH_USER_EMAIL = <<< LA TUA EMAIL VA QUI >>>
RH_PASSWORD = <<< LA TUA PASSWORD VA QUI >>>
RH_MFA_CODE = <<< IL CODICE ALFANUMERICO VA QUI >>>
timed_otp = pyotp.TOTP (RH_MFA_CODE) .now ()
login = rh.login (RH_USER_EMAIL, RH_PASSWORD, mfa_code = totp)
Acquistare o vendere è piuttosto semplice:
Acquisto di 5 azioni di Google
rh.order_buy_market (“GOOG”, 5)
Vendere 5 azioni di Google
rh. order_sell_market (“GOOG”, 5)
Controlla i documenti per l’utilizzo avanzato e gli esempi.
Alpaca
Per Alpaca useremo la alpaca-trade-api libreria , che ha oltre 700 stelle in GitHub. Installare:
$ pip install alpaca-trade-api
Dopo aver effettuato l’accesso al tuo account riceverai un ID chiave API e una chiave segreta; entrambi sono necessari per il login:
importa alpaca_trade_api come alpaca
ALPACA_KEY_ID = <<< LA TUA CHIAVE ID VA QUI >>>
ALPACA_SECRET_KEY = <<< LA TUA CHIAVE SEGRETA VA QUI >>>
Cambia in https://api.alpaca.markets per
BASE_URL live = ‘https://paper-api.alpaca.markets’
api = alpaca.REST (
ALPACA_KEY_ID, ALPACA_SECRET_KEY, base_url = BASE_URL)
L’invio degli ordini è leggermente più complesso rispetto a RobinHood:
Acquisto di 5 azioni di Google
api.submit_order (
symbol = ‘GOOG’,
qty = ‘5’,
side = ‘buy’,
type = ‘market’,
time_in_force = ‘day’
)
Vendita di 5 azioni di Google
api.submit_order (
symbol = ‘GOOG’,
qty = ‘5’,
side = ‘sell’,
type = ‘market’,
time_in_force = ‘day’
)
Questo è tutto! Nota che lasciare le tue credenziali in testo normale è una cosa molto, MOLTO brutta da fare – non preoccuparti, passeremo nel passaggio successivo alle variabili di ambiente, che è molto più sicuro. Ora distribuiamo tutto nel cloud e monitoriamolo.
Distribuire e monitorare
Distribuiremo tutto in AWS Lambda. Questa non sarebbe l’opzione migliore per un sistema di produzione, ovviamente, poiché Lambda non dispone di storage e vorremmo memorizzare il modello addestrato da qualche parte, ad esempio in S3. Tuttavia, per ora andrà bene: pianificheremo l’esecuzione di Lambda quotidianamente, addestrando il modello ogni volta con i dati del giorno corrente. A scopo di monitoraggio configureremo un bot di Telegram che invierà un messaggio con l’azione da intraprendere e il suo esito. Tieni presente che AWS Lambda è gratuito fino a un certo limite, ma fai attenzione alle quote nel caso in cui desideri inviare molti messaggi.
La prima cosa da fare è creare un bot. Ho seguito le istruzioni ufficiali di Telegram:
Cerca l’utente @BotFather in Telegram.
Usa il comando \newbote scegli un nome e un nome utente per il tuo bot.
Prendi il token e conservalo in un luogo sicuro, ne avrai bisogno a breve.
Passaggio successivo: distribuzione. Esistono diversi modi per eseguire la distribuzione su Lambda. Ho intenzione di utilizzare il serverless quadro, quindi cerchiamo di installarlo e creare un modello :
$ npm install serverless –global
$ serverless create –template aws-python3 –path ai_trading_system
Che creerà un scheduled_tg_botcartella con tre file: .gitignore, serverless.yml, e handler.py. Il file serverless definisce la distribuzione: cosa, quando e come verrà eseguita. Il file del gestore conterrà il codice da eseguire:
import telegram
import sys
import os
CHAT_ID = XXXXXXXX
TOKEN = os.environ [‘TELEGRAM_TOKEN’]
Le variabili globali dovrebbero seguire la struttura:
VARIABLE = os.environ [‘VARIABLE’]
ad esempio:
RH_USER_EMAIL = os.environ [‘RH_USER_EMAIL]
def do_everything ():
# Il codice precedente per ottenere i dati, addestrare il modello
# e inviare l’ordine al broker va qui.
return ‘L’azione eseguita’
def send_message (evento, contesto):
bot = telegram.Bot (token = TOKEN)
action_performed = do_everything ()
bot.sendMessage (chat_id = CHAT_ID, text = action_performed)
È necessario modificare CHAT_IDl’ID del gruppo, del canale o della conversazione con cui si desidera che il bot interagisca. Qui puoi trovare come ottenere l’ID da un canale ed ecco come ottenere l’ID da un gruppo .
Ora definiremo come eseguire il codice. Apri serverless.ymle scrivi:
org: nome-della-organizzazione
app: nome -della-app
servizio: ai_trading_system
frameworkVersion: “> = 1.2.0 <2.0.0”
provider:
Nome: AWS
Durata: python3.6
ambiente:
TELEGRAM_TOKEN: $ {ENV: TELEGRAM_TOKEN}
# Se si utilizza RobinHood
RH_USER_EMAIL: $ {ENV: RH_USER_EMAIL}
RH_PASSWORD: $ {ENV: RH_PASSWORD}
RH_MFA_CODE: $ {ENV: RH_MFA_CODE}
# Se utilizzando Alpaca
ALPACA_KEY_ID: $ {env: ALPACA_KEY_ID}
ALPACA_SECRET_KEY: $ {env: ALPACA_SECRET_KEY}
funzioni:
cron:
handler: handler.send_message
events:
# Invoca la funzione Lambda alle 21:00 UTC ogni giorno
– schedule: cron (00 21 * *? *)
Questo codice indica ad AWS il tipo di runtime che vogliamo e propaga il token di Telegram dal nostro ambiente in modo che non sia necessario distribuirlo. Successivamente, stiamo definendo il cron per eseguire la funzione ogni giorno alle 21:00 UTC.
L’unica cosa rimasta è ottenere le credenziali AWS e impostarle, insieme al token e al resto delle variabili, come variabili di ambiente prima della distribuzione. Ottenere le credenziali è abbastanza semplice:
Dalla tua console AWS:
Vai a Le mie credenziali di sicurezza – Utenti – Aggiungi utente.
Scegli un nome utente e seleziona Accesso programmatico.
Pagina successiva: seleziona Collega direttamente i criteri esistenti – Accesso amministratore.
Copiare l’ ID della chiave di accesso e la chiave di accesso segreta e archiviarle.
Questo è tutto. Ora, esportiamo le credenziali AWS e il token di Telegram. Apri un terminale e scrivi:
$ export AWS_ACCESS_KEY_ID = [la tua chiave va qui]
$ export AWS_SECRET_ACCESS_KEY = [la tua chiave va qui]
$ export TELEGRAM_TOKEN = [il tuo token va qui]
Se usi
RobinHood $ export RH_USER_EMAIL = [la tua posta va qui]
$ export RH_PASSWORD = [la tua password va qui]
$ export RH_MFA_CODE = [il tuo codice mfa va qui]
Se usi Alpaca
$ export ALPACA_KEY_ID = [la tua chiave va qui]
$ esporta ALPACA_SECRET_KEY = [la tua chiave va qui]
Installa i pacchetti necessari in locale e, infine, distribuisci tutto su AWS:
$ pip3 install -r requisiti.txt -t. –system
$ distribuzione senza server
Sono state fatte! Il bot scambierà per noi ogni giorno alle 21:00 UTC e ci invierà un messaggio con l’azione eseguita. Non male per una prova di concetto: ora posso dire al mio amico che può smettere di controllare freneticamente il suo telefono per fare trading 🙂
Nota che tutte le risorse che abbiamo usato attraverso questo tutorial hanno la loro documentazione: incoraggio tutti voi ad andare più a fondo su ciò che pensate sia interessante – ricordate che questo è solo un sistema di giocattoli! Tuttavia, come sistema giocattolo, credo che sia un buon punto di partenza per un prodotto più ricco e complesso. Buona programmazione!
Puoi controllare il codice in GitHub .
Nota degli editori di Towards Data Science: sebbene consentiamo ad autori indipendenti di pubblicare articoli in conformità con le nostre regole e linee guida , non approviamo il contributo di ciascun autore. In questo caso, come sottolinea lo stesso autore: non tentare di fare trading senza chiedere una consulenza professionale. Consulta i nostri Termini per i lettori per i dettagli.
di Rubén Romero da towardsdatascience.com