Crossover delle Medie Mobili con Python

Backtest del Crossover delle Medie Mobili con Python

Sommario

In questo articolo descriviamo come implementare con Python il backtest di strategia di trading algoritmico basata sul crossover delle medie mobili sull’S&P500.

Una semplice strategia di crossover delle media mobili è forse uno degli esempi più semplici, se non il più semplice, di una strategia di trading algoritmico basata su regole di indicatori tecnici. Può essere un buon esempio per coloro che imparano Python ed è già stata oggetto di esempi su datatrading.info. Cerchiamo di mantenerlo il più semplice possibile e integrarlo con futuri sviluppi.

Preparare i dati

Come sempre quando usiamo Python per i test relativi ai dati finanziari, dobbiamo importare i moduli necessari:

				
					import pandas as pd
import numpy as np
import yfinance as yf
				
			

Per prima cosa usiamo le funzionalità di yfinance per scaricare da Yahoo Finance i dati dei prezzi dell’S&P500 dal primo giorno di negoziazione del 2000 fino ad oggi.

				
					sp500 = yf.download('^GSPC', start='2000-01-01', end='2020-01-01')
				
			

Facciamo un rapido controllo per verificare in quale formato sono stati scaricati i dati.

				
					print(sp500.head())
				
			
Crossover delle Medie Mobili con Python

Creiamo quindi un grafico dei prezzi di chiusura per verificare il comportamento dell’S&P nel periodo considerato.

Crossover delle Medie Mobili con Python

La strategia trend following che vogliamo implementare si basa sull’incrocio di due medie mobili semplici; la medie mobile a 2 mesi (42 giorni di negoziazione) e la media mobile a 1 anno (252 giorni di negoziazione).

Per prima cosa calcoliamo i valori delle medie mobili e  li aggiungiamo in nuove colonne del dataframe  dell’S&P500.

				
					sp500['42d'] = np.round(sp500['Close'].rolling(window=42).mean(),2)
sp500['252d'] = np.round(sp500['Close'].rolling(window=252).mean(),2)
				
			

Nel codice precedente creiamo le serie e le aggiungiamo  automaticamente al nostro DataFrame. 

Andiamo avanti e visualizziamo sullo stesso grafico sia i prezzi di chiusura che le medie mobili.

				
					sp500[['Close','42d','252d']].plot(grid=True,figsize=(8,5))
				
			
Backtest-Crossover-SMA-grafico-medie-mobili

I segnali della strategia

Abbiamo completato il dataset di partenza. Ora dobbiamo ideare una regola per generare i segnali di trading.

  1. Buy Signal (andare long) – la media mobile a 42 giorni è per la prima volta di X punti sopra la media a 252 giorni.
  2. Parcheggio in liquidità – nessuna posizione.
  3. Sell Signal (andare short) – la media mobile a 42 giorni è per la prima volta di X punti al di sotto della media a 252 giorni.

Per creare questi segnali dobbiamo prima di tutto aggiungere una nuova colonna al DataFrame che contiene la differenza tra le due medie mobili:

				
					sp500['42-252'] = sp500['42d'] - sp500['252d']
				
			

Il passo successivo è formalizzare i segnali aggiungendo un’ulteriore colonna chiamata Stance. Impostiamo anche la soglia di segnale “X” su 50 (questo è valore arbitrario e può essere  oggetto di ottimizzazione)

				
					X = 50
sp500['Stance'] = np.where(sp500['42-252'] > X, 1, 0)
sp500['Stance'] = np.where(sp500['42-252'] < -X, -1, sp500['Stance'])
sp500['Stance'].value_counts()
				
			

L’ultima riga di codice precedente produce il seguente risultato:

				
					 1    2608
 0    1422
-1    1001
				
			

Vediamo che durante il periodo di tempo scelto per eseguire il backtest, abbiamo 1001 giornate di mercato aperto dove la media mobile a 42 giorni si trova per più di 50 punti al di sotto della media mobile a 252 giorni, e 2608 giornate dove la media mobile a 42 giorni si trova per più di 50 punti sopra alla media mobile a 252 giorni.

Produciamo quindi un grafico che mostra una rappresentazione visiva di questa ‘Posizione’. Abbiamo impostato ‘ylim’ (che sono i limiti dell’asse y) appena sopra 1 e appena sotto -1 in modo che possiamo effettivamente vedere le parti orizzontali della linea.

				
					sp500['Stance'].plot(lw=1.5,ylim=[-1.1,1.1])
				
			
Backtest-Crossover-SMA-grafico-posizioni

Possiamo ora testare la strategia di investimento basata sui segnali che abbiamo generato. In questo caso assumiamo per semplicità che possiamo acquistare o vendere direttamente l’indice S&P500 e che abbiamo costi di transazione. In realtà dobbiamo ottenere un’esposizione all’indice tramite ETF, fondi indicizzati o futures sull’indice… e ovviamente ci sarebbero costi di transazione da pagare! Questa omissione non ha però un effetto significativo perchè non prevediamo di entrare e uscire dalle  posizione “troppo spesso”.

I risultati

In questo modello, possiamo essere long sul mercato, short sul mercato o flat: questo ci consente di lavorare con i rendimenti del mercato e semplicemente moltiplicare il rendimento giornaliero del mercato per -1 se è short, 1 se è long e 0 se è flat.

Aggiungiamo un’altra colonna al DataFrame per  raccogliere i rendimenti logaritmici giornalieri dell’indice e quindi moltiplichiamo quella colonna per la colonna “Stance” per ottenere i rendimenti della strategia:

				
					sp500['Market Returns'] = np.log(sp500['Close'] / sp500['Close'].shift(1))
sp500['Strategy'] = sp500['Market Returns'] * sp500['Stance'].shift(1)
				
			
Da notare che abbiamo spostato verso il basso la serie sp['Close'] in modo da utilizzare la ‘Stance’ alla chiusura del giorno precedente per calcolare il rendimento del giorno successivo Ora possiamo tracciare i rendimenti dell’S&P500 rispetto ai rendimenti della strategia crossover a media mobile sullo stesso grafico per un confronto:
				
					sp500[['Market Returns','Strategy']].cumsum().plot(grid=True,figsize=(8,5))
				
			
Backtest-Crossover-SMA-grafico-rendimenti

Possiamo vedere che la strategia sembra funzionare piuttosto bene durante le flessioni del mercato, ma non funziona altrettanto bene durante i rally del mercato o quando il mercato è solamente in rialzo.

Durante il periodo di prova, supera a malapena una semplice strategia di Buy&Hold, appena sufficiente per definirla come una strategia “di successo”.

Una semplice strategia cross over con media mobile testata in Python dall’inizio alla fine in poche righe di codice!!

Codice completo

In questo articolo abbiamo descritto come implementare con Python il backtest di strategia di trading algoritmico basata sul crossover delle medie mobili sull’S&P500. Per il codice completo riportato in questo articolo, si può consultare il seguente repository di github:
https://github.com/datatrading-info/Backtest_Strategie

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