Machine Learning (Random Forest)

I metodi di Machine Learning sono dei metodi che si sono sviluppati negli ultimi anni nella statistica e hanno come obiettivo quello di creare dei modelli previsivi automatici dove il ruolo cruciale viene intrapreso dalla macchina.
La macchina infatti apprende man man che si inseriscono data-set il comportamento di un certo tipo di popolazione e si allena su questo (training set).
Dopodiché apprese le caratteristiche fondamentali vengono effettuate delle previsioni sul test-set mettendo in primo piano una determinata variabile obiettivo (target).

I metodi più diffusi sono quelli basati sugli alberi decisionali che si pongono come obiettivo quello di effettuare una classificazione (variabile target qualitativa) o regressione (variabile target quantitativa) dei dati.

I più conosciuti sono i metodi Bagging, Random Forest e Gradient Boosting. Non basati sugli alberi decisionali ci sono invece le reti neurali e le support Vector machine (SVM).

Le Random Forest appartengono, così come il Bagging, alla classe di metodi Ensamble di tipo Average: l’idea base è di costruire diversi stimatori in modo indipendente e di fare una media delle previsioni sapendo che lo stimatore combinato è spesso migliori di qualsiasi singolo stimatore poiché avrà una varianza ridotta.

Con l’uso del Random Forest il risultato che si ottiene non è un singolo albero ma una foresta di alberi; in una seconda fase gli alberi vengono aggregati così da ottenere un unico classificatore.

La differenza cruciale tra BaggingRandom Forest è che in queste, nella costruzione di un singolo albero, non si usa tutto l’insieme delle variabili, ma un suo sottoinsieme.

Se infatti considerassimo tutte le variabili, i primi “split” nei vari alberi sarebbero fatti sempre nel medesimo modo e otterremmo dei risultati molto simili.

Scegliendo casualmente un sottoinsieme delle variabili per ogni (albero) campione Bootstrap si possono fare diverse prove per vedere di volta in volta quale variabile in quel nodo porta allo “split ottimo”.

Il Random Forest considera all’interno del singolo albero solo un sottoinsieme delle variabili su campioni bootstrap di unità, e la selezione delle variabili è casuale ad ogni split. Ovviamente si devono determinare a priori alcuni parametri come numero di variabili da scegliere casualmente ad ogni split, numero di alberi da creare, numerosità massima all’interno di una foglia e così via.

Strangle, Straddle e Butterfly

Le strategie di trading chiamate Strangle e Straddle vengono effettuate entrambe attraverso l’acquisto di opzioni.
Sono due strategie molto simili ma differiscono di un particolare, andiamo a vedere più nel dettaglio il loro funzionamento.

Straddle

La strategia Straddle (gabbia) prevede l’acquisto di due opzioni: una put (opzione vendita) e una call (opzione di acquisto) che hanno la stessa data di scadenza e lo stesso prezzo di esercizio (strike).
Quindi chi acquista uno Straddle (posizione long) ritiene di poter ottenere profitti grazie ad un elevata volatilità del titolo sottostante, sapendo comunque che a scadenza a seconda della direzione del prezzo (rialzo o ribasso del prezzo) eserciterà solo una delle due opzioni (o la put o la call).
Chi invece vende uno Straddle (posizione short) prevede che il prezzo del titolo resti all’interno di un certo range.

Strangle

La strategia Strangle (strangolare) invece prevede sempre l’acquisto di opzioni: una put e una call che hanno la stessa data di scadenza ma strikes diversi.
Il principio prevede che lo strike della call sia più alto dello strike della put.

Ad esempio, ipotizziamo lo strike della call a 5 e quello della put a 4.
A scadenza ci potremmo trovare in tre casi diversi:
a) prezzo del sottostante > 5: si esercita solo la call e si perde il premio della put
b) prezzo compreso tra 4 e 5: non si esercita né la call né la put
c) prezzo < 4: si esercita solamente la put e si perde il premio della call

Quindi per chi acquista uno Strangle, se a scadenza il valore del titolo è compreso tra i due strike la strategia prevede una perdita certa (i due premi pagati), mentre nei casi a) e c) vi sarebbe la perdita di uno dei due premi e un profitto pari alla differenza tra lo strike e il prezzo corrente (guadagno potenzialmente infinito)

Tale strategia è quindi acquistata da chi prevede o un forte rialzo o un forte ribasso del sottostante, mentre, è venduta per chi prevede oscillazioni del prezzo minime all’interno di un certo range.

Butterfly

La strategia Butterfly si determina con l’acquisto e la vendita di opzioni (call o put) a tre diversi livelli di strike (X1, X2=X1+a,X3=X2+a).
Anche nella strategia Butterfly si può avere una posizione short (vendita) o una posizione long (acquisto).
La Buttefly long è per chi prevede una scarsa volatilità e si ottiene con l’acquisto di una call con strike X1, la vendita di due call con strike X2 e l’acquisto di una call con strike X3 (oppure put al posto di call).
In questo caso il massimo profitto si ottiene quando il prezzo del sottostante ha valore pari a X2 mentre quando è minore di X1 e maggiore di X3 la Butterfly perde l’intero capitale investito.
La Butterfly short ha le stesse caratteristiche e mira ad un guadagno con l’aumento della volatilità e si costruisce in questa maniera: si vende una call con strike X1, si acquistano due call con strike X2 e si vende una call con strike X3 (oppure put al posto di call).




Contango e Backwardation

Il Contango e il Backwardation riguardano soprattutto la variazione dei prezzi delle materie prime e i futures sempre sulle materie prime, il mercato principale è quindi il cosiddetto Commodity, il quale ha come piazza di riferimento Chicago.

Nella normalità i Futures con scadenze diverse hanno prezzi diversi.
Specialmente nelle Commodities i prezzi delle scadenze più lontane sono più alti perché includono anche i costi di conservazione e mantenimento del bene con il passare del tempo.
Nei prodotti finanziari classici, invece, avviene solitamente il contrario.
Questa normalità viene chiamata Contango che graficamente viene rappresentata come una curva di andamento crescente.

Diversamente, se ci sono dei fattori geopolitici o climatici che cambiano il quadro della situazione, quella normalità vista prima viene meno, anzi: le scadenze più vicine sono più care di quelle lontane e questo fenomeno è denominato Backardation.
La curva di riferimento è opposta con andamento decrescente.

In generale, se andiamo a rappresentare graficamente una serie storica dei prezzi di un prodotto poco scambiato sul mercato, questo può registrare oscillazioni improvvise del proprio valore così da effettuare improvvisamente un salto netto verso l’alto o verso il basso passando per esempio da un mese all’altro.
Questo scalino che si va a creare viene denominato Contango se verso l’alto, e Backardation se verso il basso. (spread improvviso relativo al cambiamento di valore di prezzo).

Comparatori

I comparatori, anche detti operatori di confronto, hanno la funzione di indicare il criterio di ordinamento degli oggetti presi in esame in una determinata lista.
Se si tratta di una lista di numeri il comando sort(lista) li posiziona in ordine crescente, mentre se si tratta di una lista di stringhe le mette in ordine alfabetico.

Il comparatore deve essere definito in una classe e successivamente inserito come input all’interno del comando sort.

Esistono due particolari interfacce nel programma Visual Basic, che ci aiutano nel processo di ordinamento:  IComparer e Icomparable.


Queste due interfacce hanno obiettivi leggermente diversi ma possono anche essere utilizzate insieme.

IComparer:

L’interfaccia Icomparer viene utilizzata nel metodo sort di una lista in quanto consente di cambiare di volta in volta i criteri di ordinamento in maniera versatile, semplicemente fornendo come argomento dei “comparer” differenti, a seconda dell’obiettivo da perseguire.
È possibile con questa interfaccia ad esempio, ordinare la classe su diversi campi o proprietà, nell’ordine crescente o decrescente in base allo stesso campo o entrambi.

IComparable:

L’interfaccia IComparable fornisce un metodo per confrontare due oggetti di un determinato tipo, si utilizza questa interfaccia se si ha intenzione di ordinare gli oggetti.
Se si dispone di una matrice di oggetti di un certo tipo e si utilizza il metodo di ordinamento su tale matrice, è possibile utilizzare l’interfaccia IComparable per confrontare gli oggetti durante l’ordinamento. 
Quando si implementa l’interfaccia IComparable , è necessario implementare anche il metodo CompareTo.


Running Mean e Running Variance

RUNNING MEAN

In generale la media di una certa variabile è un indice in grado di sintetizzarne e di descriverne le caratteristiche. Solitamente viene espressa come la somma delle osservazioni relative alla variabile in questione, divisa poi per il numero delle osservazioni stesse. In probabilità invece la media prende il nome di valore atteso e, se si tratta di variabile assolutamente continua, viene espressa nel seguente modo:

\mathbb{E}(X):= \int_{\Omega} X(\omega) d \mathbb{P}(\omega)

Tuttavia dal punto di vista della programmazione esistono diversi algoritmi per calcolare le medie o i valori attesi.


In particolare, l’algoritmo “Running Mean” ha come obiettivo quello di tenere sempre aggiornato il valore della media man mano che affluiscono nuovi dati all’interno della lista.
Più precisamente, la formula in “forma chiusa”:

la media espressa in questo modo permette di aggiornare l’informazione ricavata fino al passo (n-1) con quella fornita dall’n-esimo dato immesso.
L’algoritmo per il calcolo della media, definito appunto Running Mean, è:

def naive_mean(data):
n=0
sum=0

for x in data:
n=n+1
sum=sum+x
mean=sum/n
return mean

RUNNING VARIANCE

Per la varianza, che è un indice in grado di sintetizzare la variabilità relativa ad una certa variabile, il discorso risulta molto simile.
In generale, la varianza è espressa come la somma degli scarti dalla media, elevati al quadrato, e il tutto viene diviso per la numerosità campionaria. In probabilità parliamo più semplicemente di varianza esprimendola come la differenza tra il momento secondo e il momento primo (valore atteso) elevato al quadrato:

\sigma^2_X=\mathbb{E}[X^2]-\mathbb{E}[X]^2\

Così come per la media, dal punto di vista informatico esiste un’espressione della varianza che consente di aggiornare l’informazione ottenuta fino al passo (n-1) con quella fornita dall’n-esimo passo. In formule:

L’uso della Running Mean e della Running Variance è molto usato in borsa per osservare l’andamento dei prezzi dei vari Titoli tenendo sempre gli indicatori aggiornati visto che il flusso di dati in entrata è continuo, così da attuare successivamente una certa strategia in base alle oscillazioni registrate.

Ereditarietà

Uno dei concetti fondamentali della programmazione tramite gli oggetti è quello dell’EREDITARIETA’, ovvero il sussistere di una relazione tra due classi grazie alle impostazioni del programmatore.

E’ opportuno dunque introdurre il concetto di classe: una classe non è altro che un modello per creare diversi oggetti, i quali insieme formano la classe stessa.
L’ereditarietà permette di estendere classi già esistenti aggiungendo di volta in volta oggetti, metodi e componenti.

Esempio: Supponiamo quindi di creare 3 classi (A,B,C), viene creata inizialmente la classe A, successivamente la classe B e infine la C; in questo caso si dice che la classe C eredita dalla classe B che eredita a sua volta dalla classe A. Le classi B e C sono in questo caso dette sottoclassi di A.

Nella programmazione l’ereditarietà è un concetto fondamentale soprattutto per lo sviluppo incrementale dei programmi; tale meccanismo ci permette di estendere e potenziare delle classi già esistenti.

Come nell’esempio fatto una classe può avere anche più sottoclassi, e quindi essere definita classe madre o super classe (classe A nell’esempio).
L’uso prolungato di questo meccanismo può portare alla creazione di una lunga gerarchia, di cui il modello più comune è quello detto albero.

Più si scende verso il basso nell’albero e più le classi saranno “specializzate”, all’inizio le classi risultano più “generali”.

Si parla quindi di:
superclasse, ovvero la classe più generale
sottoclasse: la nuova classe più specializzata composta da oggetti più ricchi
– si dice che la sottoclasse eredita dalla superclasse i membri preesistenti
– la sottoclasse invece estende la nuova classe con i nuovi membri

Leggere dati da file di testo

Visual Studio è un programma dalle tante applicazioni, è possibile caricare file di dati al fine di compiere analisi avanzate.
Un esempio tipico può essere la lettura di un file contenente le informazioni riguardanti le serie storiche dei prezzi di uno o più titoli, con l’obiettivo di creare successivamente una strategia di trading da applicare.

Per leggere un file di testo in Visual Studio viene spesso usato l’oggetto StreamReader.
Un altro metodo più comunemente utilizzato viene denominato Parsing dei dati, ovvero un processo che analizza un flusso continuo di dati in input. Un programma che esegue tali istruzioni è detto Parser (solitamente non sono scritti a mano ma realizzati attraverso generatori di parser).

Passiamo adesso alla pratica per il caricamento e la lettura di dati da VB.Net:
bisogna inizialmente utilizzare l’istruzione “Imports” per gli spazi dei “System”, “System.IO” e “System.Collections” in modo che non sia necessario richiamare in un secondo tempo nel codice le relative dichiarazioni. 

Per aprire un file per la lettura, bisogna creare un oggetto StreamReader e passare il percorso del file al costruttore come segue: 

Dim objReader As New StreamReader ("c:\Desktop\text.txt")

La classe StreamReader viene utilizzata per aprire, leggere e chiudere automaticamente il file di testo.

A questo punto, esistono vari modi per leggere all’interno del file, ad esempio è possibile utilizzare il metodo ReadLine per inserire il file una riga alla volta.
Una volta raggiunta la fine del file, il metodo restituisce “Nothing”, il che costituisce un modo per porre termine al loop. 

Do
sLine=obj.Reader.RedLine()
If Not sLine Is Nothing Then
arrText.Add(sLine)
End If
Loop Until sLine Is Nothing
objReader.Close()

Per concludere solitamente viene utilizzato un loop “For Each” per scrivere nella console il contenuto dell’ArrayList in cui sono appena stati inseriti i dati, in tal modo:

For Each sLine in arrText Console.WriteLine(sLine)NextConsole.ReadLine(sLine)

La mia strategia di trading

Si ipotizzi di voler investire un capitale di 100 euro sul mercato azionario e dopo aver studiato andamenti, rating e potenzialità si sono individuate 4 società sulle quali investire: A, B, C, D.

Essendo il mercato azionario particolarmente volatile e soggetto a rischi sistemici al fine di abbassare il livello di rischio dell’intero investimento si sceglie di frazionare il capitale per approfittare dei prezzi derivanti dagli eventuali ribassi che si potranno registrare.

Inizialmente si investono solamente 5 euro per ogni società. Il restante ammontare (80 euro all’inizio) si potrà appoggiare su un fondo no risk, anche con rendimento minimo.

Successivamente tenendo come riferimento i prezzi di acquisto dei 4 titoli ogni qual volta uno di questi scende del 5% in automatico il sistema acquisterà ulteriori 5 euro del titolo mediando così il prezzo.
Invece, quando si registreranno rialzi superiori al 5% il sistema venderà la plusvalenza ottenuta che si accumulerà sul fondo no risk.

E’ evidente che in corso d’opera de si riterrà opportuno sarà possibile introdurre nuovo titolo E gestito alla stessa maniera; così come sarà possibile vendere totalmente titoli quando non sarà interessante per gli obiettivi del nostro portafoglio.

Questa strategia ha come obiettivo principale quello di ridurre i rischi anche se può risultare meno redditizia rispetto ad altre strategie aggressive dove si investe l’intero capitale.

Principali strutture iterative e loop

Per non ripetere un’istruzione tante volte, per evitare di appesantire il codice e rallentare il sistema operativo è consigliato ricorrere alla strutture iterative o ai loop.

Le strutture iterative sono quindi un continuo ripetersi di un determinato processo volto magari al miglioramento dell’algoritmo.
Tanti modelli usano iterazioni perché magari ogni volta che effettuano il loro aggiornamento migliorano la loro efficacia (per esempio il Gradient Boosting basato sull’utilizzo di alberi decisionali minimizza sempre di più errore di classificazione). Solitamente i risultati di un’iterazione sono dati in input dell’iterazione successiva che a sua volta tira fuori un ulteriore output, e così via.

Elenchiamo i metodi principali per avviare una struttura iterativa:

——- FOR EACH: crea un ciclo per ogni oggetto presente nella lista, viene specificato il numero di istruzioni da eseguire e spesso coincide al numero di oggetti in lista.

For each "Nome Oggetto" in "Nome Lista"
"Istruzioni da eseguire"
Next

——- DO WHILE: Il ciclo Do While crea un’iterazione condizionata ad un evento con controllo posticipato

DO{
"Istruzioni da eseguire"
}
WHILE (espressione di controllo)

 ——– DO LOOP: Il ciclo Do Loop è simile al precedente: 

DO
Exit or Continue
Loop

——- CICLO FOR: Un ciclo For consiste nella ripetizione di un gruppo di istruzioni per un numero di volte specificato.

For counter [As datatype]= start To end [step step]
[statements]
[Continue For]
[statements]
[Exit For]
[statements]
Next [counter]

Liste per oggetti

La lista è una struttura dei dati creata al fine di memorizzare e gestire tante informazioni contemporaneamente. Il vantaggio principale è che la gestione e particolarmente semplice.

La lista (variabile strutturata) risulta utile per raggruppare un insieme di informazioni riguardanti uno stesso ambito, così che i dati vengono memorizzati ed è impossibile perderli.
Se la lista non risulta soddisfacente si possono utilizzare le categorie, una pagina di servizio o una pagina di prodotti specifici (liste di voci ancora da scrivere).

I tempi computazionali degli algoritmi usati per gestire le liste sono direttamente proporzionali al numero di informazioni da gestire. Il numero di elementi che compongono la lista va a definire la lunghezza stessa della lista.
Le liste,a differenza delle strutture, sono utili per creare e gestire gruppi di oggetti correlati.

Le liste sono caratterizzate da strutture e puntatori, che non la rendono un oggetto nuovo ma con il loro utilizzo si arriva a un risultato di più operazioni adottate su tali funzioni.

Esistono anche le cosiddette liste concatenate formate da una struttura di dati dinamica caratterizzata da una sequenza di nodi, dove ogni nodo contiene delle informazioni aggiuntive (dati arbitrari) e allo stesso tempo riferimenti al nodo successivo e a quello precedente (da qui il nome concatenazione) .

Array

Le più semplici variabili strutturate presenti non solo in Visual Basic.Net o C#, ma anche in molti altri linguaggi procedurali sono gli Array.
Un Array monodimensionale è una variabile strutturata ad un solo indice intero positivo. Attraverso questo indice si possono immettere, modificare o cancellare elementi dalla variabile (per esempio vettore, matrice…), con l’unico vincolo che tutti gli elementi siano dati dello stesso tipo.

List

Una variabile di tipo List è una variante più complessa e funzionale dell’Array in quanto consente di memorizzare una collezione di oggetti e può dunque contenere elementi di tipo qualunque (per esempio una lista di stringhe).

Struttura

La struttura in Visual Basic, permette di creare nuovi tipi di dati che possano adattarsi al meglio alla logica dell’applicazione che si sta scrivendo.

Le strutture sono utili quando si desidera che una singola variabile possa contenere oggetti correlati di varie informazioni.
È possibile combinare gli elementi di dati di tipi diversi per creare una struttura. 
Ad esempio, è possibile mantenere insieme nome utente, numero di telefono, residenza, stato civile e stipendio annuo.