Algoritmi Genetici

 

Cosa sono gli Algoritmi Genetici ?

Gli Algoritmi Genetici non sono altro che l'applicazione "informatica" della teoria evoluzionistica dei sistemi biologici, basata sul principio secondo cui le possibilità di sopravvivenza di un individuo sono legate principalmente alla sua capacità di adattamento all'ambiente (capacità definita fitness).


I mezzi che, in ciascun individuo, caratterizzano tale capacità risiedono nel suo patrimonio genetico, cioè in un insieme di informazioni ereditate anzitutto da padre e madre in un processo definito crossover, e successivamente assoggettate parzialmente a un processo di trasformazione casuale (mutazione genetica) per far sì che ognuno abbia una identità propria, distinta da quella dei genitori.


Gli individui più deboli, meno idonei a far fronte all'ambiente, muoiono, in genere, prima degli altri e, perciò, si riproducono di meno mentre quelli più forti sopravvivono generalmente più a lungo e si riproducono maggiormente.


L'effetto di questo processo è una più diffusa trasmissione delle caratteristiche migliori che, su tempi lunghi, porta automaticamente all'evoluzione della specie e all'esistenza di generazioni in possesso di capacità di adattamento all'ambiente sempre maggiori.


L'algoritmo di calcolo che permette al computer di simulare in poco tempo il processo evolutivo di molti secoli prende proprio il nome di "Algoritmo Genetico".

 


Come si possono applicare in ambito finanziario ?

In particolare, nel campo delle applicazioni finanziarie, si può immaginare che la popolazione di individui sia costituita da un insieme di operatori di Borsa, differenti l'uno dall'altro, la cui capacità di adattamento all'ambiente coincide con l'efficacia della loro strategia di trading.

 

Questa popolazione può essere sottoposta a un processo di evoluzione dando agli operatori più bravi la possibilità di generare altri operatori con le caratteristiche del padre e della madre leggermente modificate dal meccanismo della mutazione genetica.

 

La mutazione, in sé, non è necessariamente migliorativa; tuttavia, quando non c'è miglioramento, il nuovo nato è destinato a una minore proliferazione e a una morte precoce per effetto del principio della selezione naturale.
In tal modo, dopo molti cicli generazionali, la discendenza della popolazione originaria sarà costituita esclusivamente da operatori di Borsa bravissimi le cui strategie, frutto dell'evoluzione, potranno essere senz'altro imitate nell'operatività reale.

 

Tra le ampie possibilità di utilizzo degli algoritmi genetici, va segnalata la possibilità di ottimizzare i parametri di un trading system selezionandoli tra i migliori sperimentati da migliaia di operatori virtuali nel corso di diversi cicli generazionali.
Infatti i parametri degli indicatori del trading system possono essere considerati come geni trasmissibili ereditariamente.

 

In questo caso, ogni individuo che nasce eredita alcuni di questi valori e ne modifica casualmente altri. Si vengono così a configurare, di volta in volta, delle combinazioni differenti la cui efficacia (fitness) viene misurata sulla base dei risultati che scaturiscono dalla loro applicazione sulla serie storica del titolo sottostante, naturalmente tenendo conto delle commissioni e costi vari sulle operazioni eseguite.
In questo modo si convergerà molto più velocemente su quei "geni" più profittevoli senza dover effettuare innumerevoli cicli per testare ogni possibile combinazione numerica dei parametri.

 

 

Esempi applicativi

Un esempio concreto di quanto dicevamo poc'anzi, è l'utilizzo di un Algoritmo Genetico (quello implementato in Momentum v9) per l'ottimizzazione dei parametri di un trading system basato sulla combinazione degli indicatori RSI e ROC, (vedi esempio di TS Primario della pagina sui trading systems).

 

Il TS in questione ha come parametri da ottimizzare quattro variabili (due per indicatore) con un ben definito range di valori, in quanto pur con la dovuta generalizzazione, il TS è stato creato con dei criteri e regole ben precise che limitano le combinazioni numeriche possibili. Ad esempio il valore della soglia di intervento dell'RSI non dovrebbe essere meno di 40 visto che si intende realizzare un sistema che agisce in condizioni di venduto o ipervenduto, (quindi con valori compresi tra 50 e 80 o da 80 a 100).

 

Quindi i 4 parametri con i relativi range potrebbero essere:

 

Giorni Base RSI --> da 5 a 100
Soglia Intervento RSI --> da 40 a 90
Giorni Base ROC --> da 10 a 100
Giorni Base Media Mobile ROC --> da 5 a 200

 

Da notare la quantità enorme di combinazioni che si dovrebbero esplorare con un metodo tradizionale di test su tutti i valori possibili.

 

Ora si devono definire i parametri per la simulazione genetica, ovvero il numero di "operatori di Borsa" (popolazione), il numero di generazioni da effettuare l'incidenza di crossover e la probabilità di mutazione. Per cominciare possiamo utilizzare i seguenti valori di esempio:

 

Popolazione --> 100
Generazioni --> 50
Probabilità Crossover --> 0.8
Probabilità Mutazione --> 0.01

 

A questo punto mancano solo i parametri che riguardano il titolo ovvero le date che determinano la finestra sulla serie storica, il capitale iniziale e le eventuali commissioni fisse o percentuali sulle operazioni di acquisto e vendita.

 

Il risultato dell'elaborazione sarà una serie di record una per generazione, in cui verrà stampata la fitness migliore (miglior profitto), con i relativi valori degli indicatori, ma anche altre informazioni molto utili alla valutazione del processo, come la fitness media che ci indica se tutta la popolazione sta gradualmente migliorando (con maggior probabilità di generare figli ancora migliori), e la deviazione standard della fitness, utile per capire se il processo sta convergendo verso i valori ottimali.

 

Alla fine del processo verranno visualizzati i geni migliori insieme al profitto realizzato.
La fitness è il "rendimento" di un individuo qualunque della popolazione, quindi la fitness media non è altro che la media di tutta la popolazione corrente. La deviazione standard è diciamo così la forbice di differenza tra la fitness migliore e quella peggiore.

 

Il primo di questi due valori importanti ci dice se la popolazione sta globalmente migliorando (quindi con maggior probabilità che da questa nasca un nuovo individuo che ha "geni" ancora migliori), mentre il secondo ci conferma che la popolazione si sta casomai stabilizzando ed uniformando verso l'altro senza tanti picchi positivi e negativi.

 

 

 

 

 

Come impostare i parametri di generazione ?

Non ci sono delle ricette precise, ogni titolo ed ogni TS hanno situazioni diverse, comunque per la mia personale esperienza un algoritmo genetico che deve ottimizzare da 2 a 4 variabili, ottiene maggiori (e soprattutto più rapidi risultati) con una popolazione decisamente maggiore del numero di generazioni ad esempio da 2 a 5 volte. 

 

Questo perché la numerosità della popolazione influisce direttamente sulle probabilità di trovare la strada giusta tra le tante che danno risultati soddisfacenti, visto che i geni vengono assegnati inizialmente in maniera random ad ogni individuo, mentre la numerosità delle generazioni permette di affinare progressivamente i valori trovati, quindi ad esempio si può impostare la popolazione a 1000 e 200 generazioni per la prima elaborazione, poi si può fare il fine-tuning con dei range minori (nell'intorno della "zona" più profittevole) con popolazione = 300 e generazioni = 200.

 

Per quanto riguarda gli altri parametri, io utilizzo quasi sempre un crossover nell'intorno di 0.8, perché ho visto che con l'algoritmo che ho implementato si trova in cima alla "campana" dei risultati migliori (spostandolo peggioro sempre i risultati). 
Mentre la Mutazione mi da risultati ottimali con 0.01 con il rapporto popolazione/generazioni sopradescritto, ma se voglio accelerare il ritrovamento di una zona profittevole di valori aumento la Mutazione sino a 0.05 o anche 0.08. 

Naturalmente questa accelerazione ha come effetto collaterale la mancanza della progressiva diminuzione della deviazione standard tra tutte le fitness calcolate, quindi l'impossibilità di valutare la linearità dell'ottimizzazione come si può vedere da questo log di esempio:

 

Mercato: BORSA DI MILANO 
Titolo: MIB 30 
Data Inizio: 27/08/1997 
Data Fine: 27/08/2001 
Capitale Iniziale: 3000 

 

Sistema basato su: RSI/ROC 
Limiti Base RSI: 9 - 16 
Limiti Soglia RSI: 50 - 90 
Limiti Base ROC: 10 - 50 
Limiti Media Mobile ROC: 20 - 150 

 

Inizio Elaborazione [lunedì, ago 27 2001 11:57:21] 

Impostazioni Algoritmo Genetico: [27/08/2001 11:57:21] 
POPSIZE: 100 
MAXGENS: 50 
NVARS: 4 
PXOVER: 0.8 
PMUTATION: 0.08 

 

generation best average standard
number value fitness deviation 
1 5277.627 4132.848 515.623 (12 82 49 64) [11:57:32] 
2 5277.627 4126.671 458.268 (12 82 49 64) [11:57:43] 
3 5277.627 4173.068 465.282 (12 82 49 64) [11:57:53] 
4 5277.627 4164.484 484.221 (12 82 49 64) [11:58:04] 
5 5577.647 4224.957 490.146 (12 82 49 71) [11:58:20] 
6 5577.647 4280.503 522.470 (12 82 49 71) [11:58:31] 

 

Interruzione Elaborazione [lunedì, ago 27 2001 11:58:41] 

 

Simulation completed 
Best member: 
Var(0) = 11.8705125451088 [ 12] 
Var(1) = 81.6051554679871 [ 82] 
Var(2) = 49.4149565696716 [ 49] 
Var(3) = 70.5920213460922 [ 71] 

 

Best fitness = 5577.64794921875 
Success 
Fine Elaborazione [lunedì, ago 27 2001 11:58:41] 

 

Come si può vedere prima che lo interrompessi ha fatto 6 cicli su cinquanta in 1 minuto ed ha ottimizzato 4 parametri nei range sopra descritti su una base storica di 4 anni. Ci avrebbe messo meno di 10 minuti per l'intera simulazione su di un vecchio PII 400 Mhz. Naturalmente con 2 soli parametri sarebbe stato ancora più veloce.

 

 

 

 

 

Altre considerazioni.
L'algoritmo genetico è proprio simile all'evoluzione naturale della specie, e ad ogni elaborazione la popolazione di partenza e di conseguenza quella che rimane dopo l'evoluzione possono essere molto diverse.
E' un po' come giocare a battaglia navale sparando prima a caso poi appena trovo qualcosa sparo li intorno per migliorare la resa (ed affondare la nave) anziché sparare in sequenza a tutte le caselle con maggiore dispendio di elaborazioni.
Questa casualità di partenza mi porta a volte a trovare un sommergibile a volte una portaerei.

 

Se noi partiamo con un ampio range di parametri ed impostiamo una alta probabilità di mutazione, giochiamo alla "battaglia navale" per trovare una zona con dei parametri discreti e remunerativi.
Poi abbassiamo la probabilità di mutazione (= meno casualità e più selezione naturale dei migliori) riducendo i range dei parametri attorno ai valori trovati prima. Così trovo il valore migliore in assoluto di quella zona.