QuantConnect-aggiungere-timeframe

Aggiungere timeframe con QuantConnect

In questo articolo descriviamo come aggiungere timeframe con QuantConnect per personalizzare un algoritmo, dato che QuantConnect fornisce solo feed di dati Tick, Second, Minute, Hourly e Daily. Quindi, come possiamo fare trading su un timeframe settimanale, di 15 minuti, 30 minuti o di 4 ore? Vediamo come fare!

trading-quantconnect-Resolution-Image

Obiettivo

Vogliamo creare un timeframe “settimanale” personalizzato e aggiungerlo ad un algoritmo. Il timeframe settimanale è utilizzato nella strategia per confermare le entrate in posizione tramite un secondo indicatore RSI. Oltre a questo, vogliamo anche aggiungere la serie con timeframe settimanale al grafico RSI. Tuttavia, il “come e perché ” aggiungere una serie ad un grafico non sono descritti dato che tutti i dettagli sono stati condivisi nel precedente articolo. A prima vista, lo scopo di questo articolol può sembrare relativamente semplice. Tuttavia, ci sono alcuni specifici passaggi che dobbiamo compiere per creare un timeframe personalizzato e aggiungere un indicatore. Pertanto, l’articolo descrive dettagliatamente i seguenti argomenti:

  • Consolidatori: cosa sono e come si usano.
  • Uno sguardo alle differenze tra tradebar e quotebar.
  • Registrazione di un indicatore con un timeframe personalizzato.
  • Come evitare un errore di runtime “Forward Only Indicator”.

Consolidatori

I consolidatori rispondono alla domanda “come posso utilizzare il timeframe XYZ se QuantConnect non fornisce i dati per esso?”. Anche se è improbabile che “consolidator” sia la prima parola che verrebbe in mente quando si cerca documentazione su “come accedere ai feed di dati con timeframe di 30 minuti”, il nome è in realtà abbastanza appropriato. Un “consolidator” consoliderà i dati più piccoli in dati più grandi. Quindi, ad esempio, possiamo prendere dati di 1 minuto ed aggregare 30 barre di 1 minuto in un’unica barra di 30 minuti. Sebbene imparare ad usare i consolidatori possa richiedere un po’ più di tempo, utilizzarli per creare intervalli di tempo personalizzati presenta un paio di vantaggi chiave:

  • Possiamo creare qualsiasi timeframe a cui possiamo pensare! Non abbiamo bisogno di attenerci ai soliti  timeframe da 1 minuto, 5 minuti, 15 minuti ecc. Possiamo creare un data feed di 25 tick, 17 secondi o 12 minuti!
  • Significa che QuantConnect non ha bisogno di archiviare o elaborare tutti questi dati per nostro conto.

Quindi, in generale, scambiamo un po’ di complessità con una maggiore flessibilità. Ad esempio, invece di richiedere semplicemente la risoluzione che desideriamo quando aggiungiamo lo strumento (come facciamo con i dati Tick, Second, Minute e Daily), dobbiamo eseguire i seguenti passaggi (che verranno trattati nel successivo esempio):

  1. Creare una classe “consolidator”.
  2. Creare un gestore. Questo è un metodo (funzione) che viene chiamato/eseguito ogni volta che viene creata una nuova barra di dati consolidati.
  3. Aggiungere il consolidatore tramite il SubscriptionManager.

Dopo questi passaggi, dobbiamo selezionare il tipo di consolidatore corretto in base alle nostre esigenze. In realtà ci sono quattro tipi di consolidatore tra cui puoi scegliere:

  • TickConsolidator
  • TickQuoteBarConsolidator
  • TradeBarConsolidator
  • QuoteBarConsolidator

I quattro consolidatori di cui sopra rientrano in due grandi categorie, consolidatori TradeBar e QuoteBar. Quindi qual è la differenza tra loro e come sappiamo quale usare?

Barre Trade Vs barre Quote

Le barre di tipo Trade contengono i dati Open, high, low,close e volume. Questi sono i prezzi “medi”, dove il prezzo medio è la media tra i prezzi  bid e ask. I prezzi medi sono quelli che ti vengono dati quando vedi che Stock XYZ è a $ 200. Al contrario, le Quote Bars contengono effettivamente i dati bid e ask. Con le informazioni  bid e ask, possiamo effettivamente vedere lo spread (la differenza tra bid e ask) e ottenere risultati di backtesting più accurati. Per maggiori informazioni in merito ai prezzi bid e ask si può consultare il seguente link: https://www.investopedia.com/terms/b/bid-and-ask.asp

Selezione del corretto consolidatore 

Quindi, ora che conosciamo la differenza tra i due gruppi, come facciamo a sapere quale utilizzare con i nostri dati? Fortunatamente la documentazione di QuantConnect ci può aiutare:

Per ogni classe di asset e di dati che forniamo, consultare la data library. È un po’ confusa, ma ecco il riepilogo dei dati forniti da QuantConnect:

  • Azioni: solo dati Trade. Per Resolution.Tick usa TickConsolidator, per tutte le altre risoluzioni usa TradeBarConsolidator.
  • Forex e CFD: solo dati Quote. Per Resolution.Tick usa TickQuoteBarConsolidator, per tutte le altre risoluzioni usa QuoteBarConsolidators.
  • Opzioni: dati Trade e Quote, solo su Resolution.Minute. Per consolidare i dati delle opzioni usa TradeBarConsolidator o QuoteBarConsolidator (a seconda che tu stia consolidando operazioni o quotazioni).
  • Futures: dati Trade e Quote, risoluzioni al tick, al secondo e al minuto.

Fonte: https://www.quantconnect.com/docs/v2/writing-algorithms/consolidating-data/getting-started.

Quindi, se vogliamo aggiungere un asset che dispone solo di dati Trade (come le azioni), allora dobbiamo usare il TradeBarConsolidator. Allo stesso modo, per gli asset che hanno solo dati Quote (come FX) utilizziamo il formato QuoteBarConsolidator.

Aggiungere timeframe con QuantConnect

Ora che abbiamo capito i concetti alla base dei consolidators, tradebar e quotebar, vediamo il codice per aggiungere timeframe con QuantConnect.

				
					### <summary>
### Semplice strategia RSI che vuole fornire un esempio di un algoritmo
### usando un indicatore
### </summary>
#region imports
from AlgorithmImports import *
from datetime import timedelta
#endregion

class RSIAlgorithm(QCAlgorithm):

    def Initialize(self):
        '''Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.'''
        
        # Impostazione parametri strategia
        self.SetStartDate(2012,1, 1)   # Data inizio
        self.SetEndDate(2020,1,1)      # Data Fine
        self.SetCash(10000)            # Capitale iniziale
        
        RSI_Period    = 14                # periodo del RSI
        self.RSI_OB   = 60                # Livello overcomprato
        self.RSI_OS   = 40                # Livello overvenduto
        self.Allocate = 0.25              # Percentuale di capitale allocato
        
        # Altri ticker sono disponibili in https://www.quantconnect.com/datasets/
        self.AddEquity("AAPL", Resolution.Daily)
        
        # Creare i consolidatori
        W1_Con = TradeBarConsolidator(timedelta(days=5))
        
        # Registrare gli Handlers
        W1_Con.DataConsolidated += self.On_W1
        
        # Creare gli indicatori
        self.RSI_Ind = self.RSI("AAPL", RSI_Period)
        self.W1_RSI = RelativeStrengthIndex("AAPL", RSI_Period)
        
        # Registrare gli indicatori per l'asset e il consolidatore
        self.RegisterIndicator("AAPL", self.W1_RSI, W1_Con)
        
        # Aggiungere i consolidatori al manager delle sottoscrizioni
        # in modo da ricevere aggiornamente dal motore
        self.SubscriptionManager.AddConsolidator("AAPL", W1_Con)
        
        # Verifica che gli indicatori haano abbasta dati prima di iniziare il trading,
        # x5 è sufficiente per i dati settimanali
        self.SetWarmUp(RSI_Period*5)

        # Grafico il RSI
        RSIChart = Chart("RSI", ChartType.Stacked)
        RSIChart.AddSeries(Series("D1", SeriesType.Line))
        RSIChart.AddSeries(Series("W1", SeriesType.Line))
        self.AddChart(RSIChart)

        # Creazione di un grafico custom per i volumi
        VolChart = Chart("Volume", ChartType.Stacked)
        VolChart.AddSeries(Series('Buying Volume', SeriesType.Bar))
        VolChart.AddSeries(Series('Selling Volume', SeriesType.Bar))
        self.AddChart(VolChart)


    def On_W1(self,sender,bar):
        '''
        This method will be called every time a new 30 minute bar is ready. 
   
        bar = The incoming Tradebar. This is different to the data object in OnData()
        '''
        self.Plot('RSI', 'W1', self.W1_RSI.Current.Value)

        
    def OnData(self, data):
        '''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.

        Arguments:
            data: Slice object keyed by symbol containing the stock data
        '''

        self.Plot('RSI', 'D1', self.RSI_Ind.Current.Value)

        if data["AAPL"] is not None:
            if data["AAPL"].Close >= data["AAPL"].Open:
                self.Plot('Volume', 'Buying Volume', data["AAPL"].Volume)
            else:
                self.Plot('Volume', 'Selling Volume', data["AAPL"].Volume)
        
        # Assicura che non siamo in warm up
        if self.IsWarmingUp: return
        
        # Determina le condizioni di entrata e uscita
        long_cond1 = self.RSI_Ind.Current.Value < self.RSI_OS
        long_cond2 = self.W1_RSI.Current.Value < self.RSI_OS
        exit_cond1 = self.RSI_Ind.Current.Value > self.RSI_OB
        exit_cond2 = self.W1_RSI.Current.Value > self.RSI_OB  

        # Verifica se siamo a mercato
        if not self.Portfolio.Invested:
            # Se siamo flat verifichiamo l'RSI
            if all([long_cond1, long_cond2]):
                # Compriamo Apple
                self.SetHoldings("AAPL", self.Allocate)
        else:
            if all([exit_cond1, exit_cond2]):
                # Vendiamo Apple 
                self.Liquidate("AAPL")
				
			

Rispetto al precedente articolo sulla visualizzazione dei grafici, il metodo initialize() è cresciuto in modo significativo. È qui che implementiamo la maggior parte del lavoro per aggiungere il timeframe personalizzato e un secondo indicatore. Tuttavia, prima di tutto ciò, dobbiamo importare un modulo python all’inizio dello script: from datetime import timedeltaQuindi utilizziamo la funzione importata  timedelta per impostare la quantità di dati che il consolidatore deve utilizzare nel comando W1_Con = TradeBarConsolidator(timedelta(days=5)). Qui, stiamo creando il consolidatore W1_Con utilizzando la classe TradeBarConsolidator, dato che AAPL è un’equity la documentazione di QuantConnect dice che sono disponibili solo i dati Trade). Successivamente, passiamo al TradeBarConsolidator un delta temporale di 5 giorni (che è una settimana nei mercati azionari). Ad esempio, se vogliamo creare un timeframe di 30 minuti per FX, dobbiamo fare 2 cose:

  1. Importare i dati Forex MINUTE  utilizzando il metodo AddForex()
  2. Usare un consolidatore QuotebarConsolidator, con un timedelta(minutes=30).

Creazione e registrazione dei gestori

Come accennato nella sezione precedente sui consolidatori, dobbiamo creare un gestore che viene chiamato ogni volta che è pronta una nuova barra di dati. Pertanto abbiamo aggiunto:

				
					
    def On_W1(self,sender,bar):
        '''
        This method will be called every time a new 30 minute bar is ready. 
   
        bar = The incoming Tradebar. This is different to the data object in OnData()
        '''
        self.Plot('RSI', 'W1', self.W1_RSI.Current.Value)

				
			

Possiamo dare a questo gestore qualsiasi nome desideriamo. Nel nostro codice di esempio, è stato denominato  On_W1(). Da notare che nel metodo  non facciamo altro che visualizzare il grafico del valore RSI. La principale logica di ingresso/uscita è comunque eseguita nel timeframe inferiore all’interno del metodo On_Data(). Dopo aver ottenuto il gestore, possiamo registrarlo nel  metodo initialize() con il comando: W1_Con.DataConsolidated += self.On_W1Coloro che conoscono il linguaggio Python  avranno  familiarità con l’uso dell’operatore += per aggiungere un numero a una variabile corrente, ad es x += 1. Tuttavia, l’operatore += può fare altre cose. Un’ottima introduzione è l’ottima risposta presente su questo post su stack overflow: https://stackoverflow.com/questions/4841436/what-exactly-does-do-in-python. Infine, aggiungiamo  il timeframe all’algoritmo tramite il Subscription Manager con il comando : self.SubscriptionManager.AddConsolidator("AAPL", W1_Con).

Nota: questi sono tutti i passaggi necessari per aggiungere un timeframe all’algoritmo. Potremmo fermarci qui se se non desideriamo aggiungere indicatori al timeframe.

Creazione e registrazione dell’indicatore RSI

Poiché il nostro obiettivo è utilizzare un secondo timeframe superiore per la conferma dell’operazione, dobbiamo registrare un indicatore RSI nel secondo timeframe. Questo viene fatto in un modo leggermente diverso da come abbiamo aggiunto l’indicatore RSI nel primo script e se non effettuato correttamente, possiamo avere risultati completamente errati.

				
					
        # Creare gli indicatori
        self.RSI_Ind = self.RSI("AAPL", RSI_Period)
        self.W1_RSI = RelativeStrengthIndex("AAPL", RSI_Period)
        
        # Registrare gli indicatori per l'asset e il consolidatore
        self.RegisterIndicator("AAPL", self.W1_RSI, W1_Con)
        
       
				
			

Il primo indicatore self.RSI_Ind  viene creato esattamente nello stesso modo descritto nel primo script. Tuttavia, da notare la differenza tra  self.W1_RSI e self.RSI_Ind usano chiamate API diverse. Se proviamo a creare l’indicatore RSI settimanale con  l’istruzione self.RSI(), otteniamo il seguente errore.

Runtime Error: This is a forward only indicator:

Quando ho iniziato ad utilizzare la piattaforma QuantConnect, questo errore mi ha lasciato perplesso per una o due ore. Stavo creando entrambi gli indicatori usando  self.RSI(). Ovviamente, ora so che questo NON è il modo corretto per farlo per i feed di dati consolidati. Diamo un’occhiata al motivo per cui viene visualizzato l’errore. Quando usiamo self.RSI(), in realtà stiamo usando uno dei metodi “helper” di QuantConnect. È una scorciatoia che fa alcune cose dietro le quinte per risparmiare righe di codice. In questo caso, registra l’indicatore “automaticamente”, quindi se poi lo registriamo noi stessi nel timeframe settimanale, lo stesso indicatore sarà stato registrato due volte portando all’errore. Quindi riassumendo:

  • RSI("AAPL", RSI_Period): è un metodo di supporto.
  • RelativeStrengthIndex("AAPL", RSI_Period): è quello che dovremmo usare. QuantConnect si riferisce a questo come al “costruttore”.

Per approfondimenti si pò far riferimento a questo post utile:  https://www.quantconnect.com/forum/discussion/2217/consolidated-bar-indicators/p1. Pertanto, la soluzione per evitare questo errore è assicurarsi di creare solo indicatori utilizzando il costruttore. Lo stesso vale per gli altri indicatori EMA, quindi è necessario fare attenzione!

Esecuzione dello script

Dopo aver eseguito lo script, otteniamo un grafico che assomiglia a questo:

trading-quantconnect-Adding-Timeframe-Results

E se diamo un’occhiata al grafico RSI possiamo vedere che entrambi i timeframe sono tracciati.

Codice completo

In questo articolo abbiamo descritto aggiungere timeframe con QuantConnect. Per il codice completo riportato in questo articolo, si può consultare il seguente repository di github:
https://github.com/datatrading-info/QuantConnect

Gli altri articoli di questa serie

Benvenuto su DataTrading!

Sono Gianluca, ingegnere software e data scientist. Sono appassionato di coding, finanza e trading. Leggi la mia storia.

Ho creato DataTrading per aiutare le altre persone ad utilizzare nuovi approcci e nuovi strumenti, ed applicarli correttamente al mondo del trading.

DataTrading vuole essere un punto di ritrovo per scambiare esperienze, opinioni ed idee.

SCRIVIMI SU TELEGRAM

Per informazioni, suggerimenti, collaborazioni...

Torna in alto
Scroll to Top