Esplora E-book
Categorie
Esplora Audiolibri
Categorie
Esplora Riviste
Categorie
Esplora Documenti
Categorie
I mercati finanziari sono delle entità particolari che, sebbene frutto della volontà degli uomini nel
comprare o vendere, sembrano animati da una vita propria. Se analizziamo i grafici delle quotazioni
possiamo notare come certi comportamenti siano ciclici, ovvero spesso a seguito di un determinato
comportamento ne segue sempre un altro, sempre lo stesso.
Quando i prezzi salgono molto è normale aspettarsi una presa di posizione e quindi un riassestamento
verso il basso delle quotazioni. Quando poi i prezzi attraversano un momento di incertezza e i livelli
di prezzo più scambiati sono sensibilmente differenti ecco che si formano dei livelli entro i quali le
quotazioni "rimbalzano".
Un mercato laterale è uno dei tre scenari tipici nei quali ci si ritrova tutti i giorni ad operare sulle
Borse valori e mercati interbancari.
In una visione semplicistica i mercati tendono a riflettere lo stato di salute di un azienda, un comparto
o di un economia: quando lo stato di salute è buono il prezzo si rafforzerà sempre di più e
teoricamente il grafico delle sue quotazioni dovrebbe assomigliare ad una linea inclinata
positivamente. Il limite alla sua ascesa è dettato dalle aspettative e dalla lenta modificazione del
potere di acquisto e quindi dell'inflazione. Se un bene è costantemente apprezzato e l'inflazione è pari
al 5% allora è lecito aspettarsi un'analoga rivalutazione delle sue quotazioni.
Ma siccome la realtà è più complessa della teoria, i prezzi tenderanno ad aumentare e
periodicamente riassestarsi a causa delle prese di beneficio. Aspettative e rumors amplificheranno
l'importanza dei fattori che sono alla base del processo di formazione del prezzo e di conseguenza il
grafico non sarà più una linea ma una sorta di elettrocardiogramma con tendenza a spostare la linea
di base in alto o in basso. Prima e dopo questi spostamenti potremo notare che il prezzo stazionerà
per tempi più o meno lunghi in un intervallo di prezzo che prenderà il nome di "canale laterale".
Il presente testo prende in esame questi "canali laterali" e cerca di analizzarli sono molteplici aspetti,
tutti destinati a dare indicazioni operative per l'attività di trading.
Gli scenari in cui ci troviamo ad operare quotidianamente possono essere ridotti a tre fattispecie:
mercato direzionale, mercato laterale e mercato volatile.
Questo libro vuole affrontare proprio lo scenario centrale, la Lateralità, e cercare di capirne le
caratteristiche, le peculiarità, i parametri di rischio e proporre più metodi per impostare una strategia
di trading efficace.
Al lettore verrà presentata una visione classica del mercato ed una definizione di lateralità. Vedremo
i canali orizzontali ma anche i canali obliqui. L'approccio partirà da una visione classica per poi
passare ad approcci più evoluti ed in grado di dare un grado di affidabilità più elevato.
A corollario della parte teorica si spiega come costruire un trading system che implementi quanto
spiegato nel testo. Al tempo in cui si scrive la piattaforma di trading automatico più diffusa è
MetaTrader4 della russa MetaQuotes, il cui linguaggio di programmazione è MQL, un linguaggio
basato sul diffusissimo ma non troppo semplice C.
Parte prima
La lateralità
I teorici definiscono la lateralità come un intervallo di prezzi entro i quali stazionano per un certo
tempo le quotazioni degli scambi .
Gli estremi di questo intervallo di prezzo saranno rappresentati da una resistenza (livello superiore)
ed un supporto (livello inferiore).
Affinché ci sia reale lateralità occorre che le quotazioni abbiano testato più volte i suddetti livelli.
I due livelli di supporto e resistenza sono spesso coincidenti con livelli di prezzo nei quali sono
avvenuti molti scambi e quindi denota un interesse particolare la loro "inviolabilità" (stop loss, take
profit o ragioni esogene al titolo ma strumentali per il dissesto/riassesto di un economia (micro o
[1]
macro che sia) .
Il concetto di lateralità è anche legato al riconoscimento dei massimi e minimi di periodo i quali sono
delle alternative ai supporti e resistenze.
Figura 2 - Canale laterale costruito intorno ai massimi e minimi di periodo
I massimi ed i minimi di periodo evidenziano i livelli di forza del mercato, ovvero sino a che livello
la forza dei compratori è riuscita a spingersi prima di trovare una barriera insormontabile che li ha
fatti desistere.
Caratteristiche della lateralità
Uno dei passi più importanti in ogni strategia di trading consiste nel riconoscimento dello scenario di
mercato. Non è sufficiente ottenere un massimo ed un minimo di periodo per affermare di essere in un
canale laterale.
Le condizioni minime e necessarie per poter affermare di trovarsi in lateralità sono le seguenti:
· Presenza di almeno due massimi, separati da altrettanti minimi, posizionati su livelli simili di
prezzo
· Momentum calanti nelle fasi di inversione, ovvero nell'intorno dei massimi e dei minimi
· La distanza tra il livello massimo ed il livello minimo deve essere superiore ad un multiplo
della volatilità
Il primo punto è stato già spiegato mentre sul secondo occorre fare dare qualche spiegazione in più.
Quando il mercato è prossimo all'inversione le forze degli investitori tendono a riequilibrarsi per poi
invertirsi. Questo momento di "stallo" che precede l'inversione viene catturato sia dagli oscillatori
(RSI, CCI, %r di Williams e Stocastico) sia graficamente dall'inclinazione delle medie esponenziali.
Il valore degli oscillatori tenderà a "girare" mentre si trova in una delle due fasce denominate "di
ipercomprato" e "di ipervenduto".
La media tenderà a smorzare la sua inclinazione passando per una fase orizzontale che precede
l'inversione.
Figura 3 - Le medie e gli oscillatori evidenziano le inversioni del mercato all'interno di un canale laterale
Uno dei difetti degli indicatori consiste nel loro ritardo cronico nella fornitura di un segnale
operativo. In pratica il segnale da loro generato, secondo la dottrina comune, appare in ritardo e
questo produce entrate destinate a produrre profitti teorici troppo contenuti.
La descrizione che gli indicatori danno del mercato è via via più precisa come si allunga l'intervallo
di valori analizzato dall'indicatore. Tuttavia, proprio per colpa della "lunghezza" dell'indicatore il
segnale operativo avviene tardi, a volte addirittura in corrispondenza della successiva inversione
opposta al segnale generato!
Per ovviare a questo inconveniente si percorre la strada dell'osservazione del calo di momentum,
ovvero si genera un segnale quando si assiste ad un calo della progressione
nell'incremento/decremento di valore dell'oscillatore.
Naturalmente a fronte di una simile strategia emergono subito dei limiti con i quali occorre trovare
una soluzione: come si fa a sapere che il limite esterno raggiunto sia quello più estremo? In fasi di
trend la chiusura di un operazione su eccesso opposto potrebbe verificarsi troppo tardi e generare
perdite anche ingenti.
Proprio per poter leggere meglio i grafici è bene servirsi di ulteriori indicatori: le Bande di
Bollinger sono un ottimo aiuto. Questo indicatore disegna delle bande sopra e sotto la media. La
distanza tra la media e ogni banda è calcolata con una misura di volatilità, ovvero con la deviazione
standard.
Secondo il suo teorico, John Bollinger che le teorizzò nei primi anni '80, applicando, sopra e sotto la
media dei prezzi, una misura pari al doppio della sua deviazione standard si ottengono due bande al
cui interno ricadono oltre l'85% delle quotazioni, come dire che le bande riescono a descrivere
abbastanza bene una predizione di esistenza a breve termine e che ogni prezzo che ricade al di fuori
delle bande è statisticamente destinato a rientrarvi.
Sulla base di queste considerazioni è possibile rielaborare la tecnica operativa precedente abilitando
le operazioni di compravendita solo quando i prezzi ricadono al di fuori delle bande di Bollinger.
Figura 4 - Rispetto alla prima tecnica, il vincolo delle bande permette di migliorare il timing operativo
Nonostante i miglioramenti qualitativi dei segnali di ingresso dovuti all'introduzione delle bande di
Bollinger resta evidente come alcune operazioni sono negative in quanto non si è saputo interpretare
l'inizio di un trend (si veda l'operazione del 2 dicembre 2012 in figura).
Introduciamo allora un indicatore di volatilità più specifico, denominato Average True Range, ideato
da J. Welles Wilder Jr. nel 1978.
L’ATR (Average True Range) misura la media della distanza massima tra gli estremi della barra
precedente e quella successiva.
Dove TR identifica il True Range, ovvero il massimo della distanza tra il massimo degli estremi
delle ultime due barre.
I trend sono solitamente accompagnati da una notevole momentum che si traduce in una volatilità
sempre più intensa ed è quindi doveroso aspettare una sua diminuzione prima di aprire una posizione
in contrapposizione al movimento finora compiuto. Anche se i prezzi avranno superato la banda
superiore di Bollinger dovremo aspettare una calo, anche momentaneo, dell'Average True Range
prima di aprire una posizione ribassista. In figura 4 si può notare come questo accorgimento permetta
di risolvere le anomalie delle tecniche precedenti.
Figura 5 - Avendo l'accortezza di abilitare l'operatività solo in caso di ATR stabile o decrescente, la predizione migliora sensibilmente
Parte seconda
Figura 6 - I bassi volumi di scambio sul cambio EURDKK generano frequenti gap e sbalzi
Figura 7 - Osservando gli indicatori utilizzati in precedenza si può notare come appaia confusa l'operatività
L'ATRD, a differenza di altri indicatori di volatilità, nasce per evidenziare la direzione prevalente
del movimento in atto. Contrariamente ad altri indicatori qualitativi non è necessario definire livelli
soglia (si veda l'Average Directional Index o ADX) ma semplicemente osservare i valori delle due
componenti direzionali per poterne trarre informazioni operative.
Ricordando che l'ATRD è pur sempre un indicatore con una sua "lunghezza" e che quindi incapsula
geneticamente un suo ritardo informativo, occorre generare segnali operativi non all'incrocio delle
due componenti direzionali bensì al loro "punto di flesso", ovvero nel momento in cui la componente
specifica cambia inclinazione passando da crescente a piatta/decrescente o viceversa.
Figura 8 - A differenza dell'ATR, l'ATRD riesce a fornire indicazioni qualitative della volatilità in atto
Se riassumiamo la tecnica operativa sin qui elaborata possiamo enunciare quanto segue:
· Si entra in contrapposizione alle posizioni di eccesso rispetto alle bande di Bollinger
· Il segnale è valido solo se la volatilità è stabile o in diminuzione
· Utilizzando l'ATRD il segnale short è valido solo se la volatilità direzionale positiva è
stabile o in diminuzione, il segnale long è valido solo se la volatilità direzionale negativa è
stabile o in diminuzione.
Figura 9 - Con riferimento alle tecniche precedenti l'utilizzo come discriminante della sola componente di volatilità contraria la qualità dell'operatività migliora
Come per ogni scoperta, la creazione dell'ATRD nasce con il compito di risolvere i problemi
lasciati irrisolti circa l'interpretazione qualitativa della volatilità. Come abbiamo visto l'uso
dell'ATRD consente di ottenere maggiori segnali operativi e migliorarne la loro qualità e questo era
l'obiettivo che mi ero prefisso quando decisi di approfondire e migliorare le tecniche operative sui
mercati volatili tipici del 2008.
In appendice è possibile trovare il codice MQL per implementare l'indicatore ATRD.
Strategie operative in caso di volatilità "cattiva"
Quando i mercati sono particolarmente turbati è inutile adottare le tecniche classiche per cercare di
impostare una strategia di trading: risulterebbe fallimentare. Gli indicatori richiedono tempo e una
certa progressività dei movimenti di mercato per dare indicazioni attendibili e noi abbiamo definito i
mercati turbati come sequenze di rapidi ed estesi movimenti alterni intorno alla media, questo
significa che nessun indicatore tradizionale potrà essere d'aiuto. Sarebbe invece utile un indicatore di
[3]
frequenza ciclica come determinante tra le fasi di volatilità buona e quella cattiva: un'alta frequenza
farebbe risaltare una volatilità cattiva.
I mercati estremamente volatili ed instabili richiedono un'attenzione particolare per via di alcune
implicazioni non di poco conto:
· Il rischio per operazione è elevatissimo
· Lo spread operativo è generalmente molto elevato
· Lo slippage delle esecuzioni è solitamente ampio
· Le prezzi di apertura e chiusura (setup e stops) degli ordini condizionati sono spesso distanti
da quelli impostati.
Con queste premesse la gestione del rischio diviene elemento essenziale nelle strategie da adottare.
Se in scenari classici si era soliti aprire posizioni intere (es. 5 lotti), negli scenari instabili occorre
ridurre notevolmente per poter contenere perdite a più alta probabilità (es. 0,5 lotti). Per la stessa
ragione i profitti che si possono generare sono più ampi di quelli ipotizzabili in scenari più
tranquilli.
Come riconoscere i mercati instabili
In condizioni di bassi volumi è molto probabile che un grosso ordine "aggredisca" il mercato,
ovvero non viene posizionato sul book ma venga mandato a mercato per l'esecuzione "al meglio".
Questo significa che in scenari rarefatti (poche proposte di negoziazione sui livelli contigui di
prezzo) è facile assistere alla scomparsa di molteplici livelli ad opera di un unico grande ordine (in
gergo si è soliti parlare di "spazzolamento" del book). Ora, siccome l'esecuzione dell'ordine ha
provocato un vuoto (i livelli eseguiti) senza che vi sia stato alcun spostamento delle proposte di
negoziazione tra Bid e Ask, è facile immaginare che in assenza di movimento generalizzato al ribasso
o al rialzo, i vuoti vengano riempiti da piccoli volumi e che lo scambio successivo ricucia il divario
tra domanda e offerta. Graficamente vedremo una barra la cui apertura è vicina alla chiusura ma il
minimo o il massimo è molto distante da loro e l'estensione di un ombra sarà decisamente grande
rispetto alla media delle ombre precedenti. Questa figura viene denominata Spike.
Figura 10 - Lo Spike
I Gap sono invece dei salti di prezzo dovuti ad improvvise accelerazioni, in un verso o nell'altro, del
prezzo. Le motivazioni solitamente risiedono in notizie macroeconomiche in grado di turbare il
mercato e procurare allarmismo. In questo caso i volumi tendono ad essere elevati poiché le
aspettative degli investitori subiscono dei forti condizionamenti.
Figura 11 - I Gap
I Lap sono invece figure di accelerazione continuata nel tempo, dove il movimento non dura una sola
barra ma prosegue sulla successiva/e e lo si può notare dal fatto che le chiusure coincidono con i
minimi o i massimi di barra e lo sviluppo della barra successiva ha direzione in coerenza con la
precedente.
Si chiamano invece "Isole" quei pattern formati da parecchie barre che iniziano con un gap e si
concludono con un gap in direzione contraria che ritorna sui livelli di prezzo precedenti al primo gap.
La figura delle barre "Inside" (barra successiva contenuta nella precedente) e "Outside" (bassa
successiva che supera da ambo i versi la precedente) è anch'essa sinonimo di indecisione ma, a
differenza delle Doji, annuncia una più elevata capacità di breakout futura e quindi la possibilità di
escursioni molto estese.
Operatività nei mercati turbolenti
Negli scenari instabili e volatili sono possibili alcune tecniche di trading che prendono spunto dalla
prevedibilità di alcune reazioni a dei movimenti violenti. Di seguito si prenderanno in
considerazione i principali segni distintivi dei mercati instabili e si daranno delle indicazioni
operative sulle strategie da adottare.
In sintesi, in presenza di mercato volatile e instabile, non appena i prezzi iniziano a crescere/calare
rapidamente e a formare una candela molto estesa in rapporto all'ampiezza media, si apre una
posizione short/long non appena la salita/discesa rallenta (calo di momentum). L'obiettivo di profitto
deve essere posto ad un terzo della barra ed eventualmente suddividere l'uscita per parti: una metà o
più al recupero del terzo di barra e la rimanenza sottoposta a trailing stop.
Figura 15 - Analizzando il gap della figura 10 in un TF inferiore si può notare il punto di ingresso (freccia) e il punto di uscita coincidente con la ricopertura del gap down
Analogamente, quando siamo in presenza di una barra Outside, ovvero una barra che prima supera il
Minimo/Massimo della precedente e successivamente supera il Massimo/Minimo della precedente,
in corrispondenza dell'ultimo breakout si apre una posizione in direzione. Anche in questo caso
valgono le considerazioni riguardo le dimensioni superiori alla media della barra Outside.
Figura 17 - Entrata su Outside al breakout della precedente
Calcolo del rischio e gestione di portafoglio
Una tecnica abbastanza diffusa consiste nello spostare lo Stop Loss al prezzo di entrata non appena i
prezzi si discostano, di una misura maggiore della volatilità, dal setup di ingresso. In questo modo il
rischio operazione viene azzerato e si garantisce il margine per l'apertura di altre operazioni.
L'eventuale chiusura parziale della posizione diminuisce il profitto futuro sperato ma genera profitti
certi.
In scenari volatili la dimensione della volatilità a breve risulta determinante per il calcolo degli
Stops (Stop Loss e Take Profit). Considerando il timing estremamente ridotto legato alla validità dei
pattern in scenari volatili, generalmente da una a tre barre, si utilizza un multiplo della volatilità a
breve quale determinante per capire se validare il segnale e determinarne gli Stops: se l'obiettivo di
perdita è talmente prossimo al punto di ingresso da essere contenuto all'interno della volatilità, allora
il segnale di ingresso dovrebbe essere ignorato, lo stesso dicasi se l'obiettivo di profitto cade al di
fuori della volatilità.
Nel validare il segnale operativo di uno Spike, ad esempio, dovremmo verificare che l'obiettivo pari
ad un terzo della barra sia contenuto nella volatilità, in caso contrario rischieremmo di fallire.
Nel valutare la ricucitura di un Gap andrebbe verificato che questa distanza sia superiore alla
volatilità, così come l'estensione della barra Outside rispetto al punto di breakout.
Per calcolare genericamente lo stop loss di una posizione occorre tenere presente due fattori: il
timing supposto per la conclusione della strategia e un multiplo della volatilità. Il fattore di
moltiplica è pari al timing atteso: chiusura attesa in tre barre equivale ad uno stop loss calcolato
moltiplicando per un fattore 3 la volatilità.
Es.
ATR(14) = 50 pips
Timing atteso = 3 barre
Stop Loss pari a 50 x 3 = 150 pips
Una volta calcolata l'entità dello Stop Loss occorre calcolare la dimensione dell'ordine in modo che
l'eventuale perdita rimanga circoscritta ad una percentuale preordinata del proprio capitale di
rischio.
Supponiamo di non voler perdere più di 200$ ed aver calcolato tramite il multiplo della volatilità
uno stop loss di 150 pips. Per prima cosa dobbiamo correggere lo stop loss per tener conto di un
eventuale slippage (ad esempio 15 pips in scenari volatili e turbolenti) e quindi impostare
l'equazione che ci dia la dimensione corretta.
In seguito dobbiamo recuperare il valore, in moneta di conto del singolo Pip per lotto tradato.
Infine calcoliamo il volume corretto impostando l'equazione seguente:
Volume x PipValue x StopLoss = Perdita Max
Volendo calcolare il volume si reimposta l'equazione come segue:
Volume = Perdita Max / (PipValue x StopLoss)
Nell'esempio precedente avremo i seguenti dati di partenza:
PipValue = 10$
PerditaMax = 200$
StopLoss = 150 pips + 10 di Slippage = 160
Volume = 200/(10 x 160) => 200/1600 => 0,12 lotti
Il valore del Pip (esattamente come il valore del Tick per gli strumenti finanziari tradizionali,
derivati e CFD) viene fornito dall'emittente, dalla Borsa valori ove avvengono gli scambi o
dall'intermediario finanziario (broker, banca).
Il procedimento appena spiegato porta il nome di "Lotto equivalente", ovvero la dimensione che, in
base allo stop impostato, equivale ad un valore di perdita predefinita. La funzione del lotto
equivalente è stata da me definita nel corso di anni di sviluppo di trading system.
Gestione di portafoglio
Una corretta gestione patrimoniale prevede la diversificazione degli investimenti e la distribuzione
del rischio (regola della doppia D). Questi due accorgimenti permettono di stabilizzare le variazioni
più grandi che possono capitare all'interno di ogni singola strategia di trading. Come dire che in
un'orchestra il suono prodotto da tutti i musici permette di contenere le stonature di qualche elemento.
In un portafoglio ben strutturato la stessa strategia può essere utilizzata su più strumenti finanziari
attenendosi alla regola di non applicarla su strumenti correlati. Se infatti la stessa strategia fosse
applicata su strumenti correlati le operazioni in perdita si replicherebbero al posto di compensarsi.
E'invece consigliato distribuire la stessa strategia su più strumenti non correlati e applicare più
strategie in grado ognuna di approcciare i diversi scenari di mercato (trend, lateralità e volatilità).
Una corretta gestione di portafoglio, visti i limiti operativi imposti dai broker (lotto minimo e
margine richiesto) richiede un capitale di rischio di dimensioni adeguate.
Per capire quanto capitale sia necessario facciamo alcune ipotesi, abbastanza realistiche al momento
in cui si scrive, dei vincoli operativi e strategie da operare:
Caratteristiche comuni
3 strategie (trend, lateralità e volatilità)
3 Strumenti finanziari non correlati
StopLoss medio pari a 70 pips
Si consiglia di non impegnare mai più della metà del margine disponibile e comunque avere un
capitale pari al meno al doppio della presunta perdita, di modo che sia possibile replicare le
medesime operazioni per sanare eventuali perdite .
Ipotesi A
Lotto minimo: 0,10
Leva 100:1
Valore StopLoss: 70$
Lotti minimi necessari: 3 x 3 x 0,10 = 0,90
Margine richiesto: 900$
StopLoss globale: 630$
Capitale minimo richiesto: 1.800$
Ipotesi B
Lotto minimo: 0,01
Leva 500:1
Valore StopLoss: 7$
Lotti minimi necessari: 3 x 3 x 0,01 = 0,09
Margine richiesto: 18$
StopLoss globale: 63$
Capitale minimo richiesto: 36$ teorici ma 90$ reali in quanto occorre tenere presente i livelli di
Sellout dei broker.
Come si è visto nelle ipotesi sopra citate, il capitale necessario è molto ridotto se le strategie di
trading non prevedono la suddivisione per parti delle uscite. Qualora invece la prevedano è
necessario tener conto della dimensione minima dell'intero per poter ottenere una chiusura parziale
coerente con la proporzione desiderata.
Se ad esempio volessimo chiudere il 20% della posizione all'attivazione del BEP (Break Even
Point), un successivo 30% all'attivazione del trailing stop e la rimanenza (50%) sul ritracciamento
del trailing, dovremmo trovare la dimensione dell'ordine tale per cui sia possibile suddividerlo in tre
parti secondo la proporzione desiderata (20-30-50).
Appare evidente che se la dimensione minima è 0,01 lotti (un microlotto) la dimensione dell'intero
dovrà essere di un minilotto (0,10) in quanto solo così sarà possibile la suddivisione corretta.
I broker hanno infatti due vincoli nella scelta della posizione: il volume minimo e l'incremento di
volume minimo. Possono coincidere ma più frequentemente sono differenti, preservando
all'incremento la misura più piccola (es. Lotto minimo a 0,10 ed incremento minimo a 0,01).
Per trovare la dimensione dell'ordine base occorre rispettare i seguenti vincoli:
· Qualsiasi parte dell'ordine base deve essere un insieme (anche eccedente) di lotti minimi.
(VolumeBase x %EnnesimaParte)/MinLot >=1
· Il resto dell'insieme eccedente dalla divisione della parte per i lotti minimi deve essere un
multiplo intero di incrementi minimi.
Mod((VolumeBase x %EnnesimaParte)/MinStep)=0
[4]
In questa terza parte si accompagnerà il lettore nella creazione di un trading system che applicherà
le strategie descritte nella prima e seconda parte.
Per comodità verrà utilizzata la piattaforma MetaTrader 4, giunta alla versione 6.00 build 670, ed il
suo linguaggio MQL4 (C-Like).
Creazione passo-passo
Per la creazione di un nuovo trading system, in MetaTrader denominato Expert Advisor, occorre
richiamare l'editor di codice, denominato MetaEditor, tramite il comendo F4 e quindi premere il
pulsante Nuovo.
Apparirà una finestra di dialogo che ci permette di scegliere la natura del nuovo progetto.
Selezionaniamo Expert Advisor e premiamo il pulsante Avanti. Quindi scriviamo il nome del nostro
trading system: sdVolatilityBase e premiamo Avanti.
Apparirà ora l'elenco delle funzioni evento opzionali da inserire all'interno del codice (noti come
handler).
Nel nostro caso vanno più che bene gli eventi standard (sia per la prima che la seconda videata) e
quindi premiamo, alla fine, il tasto Fine.
Verrà generato automaticamente lo "scheletro" del nostro tading system, ovvero un elenco di funzioni
evento più una serie di dichiarazioni di proprietà pubbliche ed alcuni commenti utili al
programmatore per orientarsi nel codice.
//+------------------------------------------------------------------+
//| sdVolatilityBase.mq4 |
//| Copyright © 2014, SD Studio DAINESI |
//| http://www.sdStudioDainesi.com |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2014, SD Studio DAINESI"
#property link "http://www.sdStudioDainesi.com"
#property version "1.00"
#property strict
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//---
}
//+------------------------------------------------------------------+
//| Tester function |
//+------------------------------------------------------------------+
double OnTester()
{
//---
double ret=0.0;
//---
//---
return(ret);
}
//+------------------------------------------------------------------+
Rispetto alle versioni precedenti la build 600 ora la funzione principale è chiamata OnTick(), in
luogo della precedente start(). Il prefisso On sottolinea la natura di funzione evento causata dalla
generazione di un tick (OnTick), dall'inizio di un test (OnTester), ecc..
Le funzioni OnInit e OnDeinit, come suggerisce il nome sono richiamate nella fase di inizializzazione
e terminazione del trading system (inserimento sul grafico e/o sua modifica dei parametri e sua
rimozione).
Ogni trading system, al contrario di come sarebbe logico aspettarsi, deve procedere a ritroso per
poter funzionare, e quindi deve prima gestire gli ordini in essere poi aprirne di nuovi. Questo iter è
dettato dalla necessità di assicurarsi di non aprire nuovi ordini in presenza di altri. Pensate ad un
sistema che ad ogni tick verifica la generazione di un segnale di acquisto e quando riceve l'assenso
invia un ordine long. Considerando che il segnale di norma vale per tutta la durata della barra
avremo tanti ordini quanti sono i tick generati in quella candela!! E'evidentemente una pratica da
dimenticare. Occorre prima verificare la presenza di ordini preesistenti che possano invalidare
nuove aperture, gestire il portafoglio in essere e solo dopo verificare i segnali di apertura per i nuovi
ordini.
Nel nostro trading system dovremo dapprima inserire le proprietà esterne e quindi introdurre le
routine di controllo portafogli, verifica segnali e generazione ordini.
Dato che la generazione dei segnali avviene leggendo i prezzi ed alcuni indicatori, è necessario poter
indicare i parametri di questi oltre che definire la dimensione del lotto base.
//+------------------------------------------------------------------+
//| sdVolatilityBase.mq4 |
//| Copyright © 2014, SD Studio DAINESI |
//| http://www.sdStudioDainesi.com |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2014, SD Studio DAINESI"
#property link "http://www.sdStudioDainesi.com"
#property version "1.00"
#property strict
//ATR parameter
input int ATRPeriods = 14;
//ATRD parameter
input int ATRDPeriods = 14;
La parola input indica che la variabile è definita come parametro modificabile dall'utente tramite una
mascherina. Nelle precedenti versioni in luogo di input veniva utilizzato il token extern.
Questi parametri saranno utilizzati dalle funzioni di verifica segnale che per comodità chiameremo
VerifyLong() e VerifyShort(). Queste due funzioni devono verificare l'esistenza delle condizioni di
esistenza dei rispettivi segnali. Il valore di ritorno di queste funzioni sarà un valore booleano per
indicare la presenza o meno di segnale operativo.
Come accennato all'inizio, il primo controllo da eseguire è però l'analisi del portafoglio esistente.
Questo esame lo si effettua in due modi:
Il primo metodo ha una valenza accademica mentre il secondo è quello usato per creare un sistema
professionale.
La funzione OrdersTotal riporta il numero degli ordini in portafoglio senza distinzione di tipo, natura,
strumento finanziario nè origine.
Utilizzando la funzione OrderSelect è possibile analizzare in dettaglio la composizione del
portafoglio.
//Gestione portafoglio
if(iOrders>0)
{
//Money management
}
//Ordini LONG
if(VerifyLong()==true)
{
bResult = OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,0,"sdVolatility™ LONG", MagicNumber,0,Green);
return;
}
//Ordini SHORT
if(VerifyShort()==true)
{
bResult = OrderSend(Symbol(),OP_SELL,Lots,Bid,3,0,0,"sdVolatility™ SHORT", MagicNumber,0,Green);
return;
}
Si noti come il controllo per la generazione di nuovi ordini avvenga solo se non ci sono ordini in
portafoglio.
Occupiamoci ora di creare le funzioni di rilevamento del segnale e di tutte quelle correlate (ovvero
funzioni utili alla funzione radice).
//+------------------------------------------------------------------+
bool VerifyLong()
{
bool result = false;
//Si procede solo in presenza di rilevamento dell'eccesso dei prezzi rispetto alle bande di Bollinger
if(PercentB("C",1)>=1+PercentBLevel)
{
double dATR0 = iATR(Symbol(),Period(),ATRPeriods,1);
double dATR1 = iATR(Symbol(),Period(),ATRPeriods,2);
}
}
return(result);
}
La funzione è strutturata per limitare il tempo di elaborazione in mancanza delle singole condizioni
che formano il segnale. In pratica si evita di far compiere al processore elaborazioni inutili se le
precondizioni non sono soddisfatte. Evitare inutili calcoli risulterà importantissimo in fase di
ottimizzazione dove la quantità di processi elaborativi influisce pesantemente sui tempi di esecuzione
del processo di ottimizzazione.
//Calcolo del %b
double result = 0;
double BBI;
double BBS;
if(Price=="C")
{
if(Close[Offset]-BBI==0) result=0;
if(Close[Offset]-BBI!=0 && BBS-BBI !=0)
result = (Close[Offset]-BBI)/(BBS-BBI);
}
if(Price=="O")
{
if(Open[Offset]-BBI==0) result=0;
if(Open[Offset]-BBI!=0 && BBS-BBI !=0)
result = (Open[Offset]-BBI)/(BBS-BBI);
}
if(Price=="H")
{
if(High[Offset]-BBI==0) result=0;
if(High[Offset]-BBI!=0 && BBS-BBI !=0)
result = (High[Offset]-BBI)/(BBS-BBI);
}
if(Price=="L")
{
if(Low[Offset]-BBI==0) result=0;
if(Low[Offset]-BBI!=0 && BBS-BBI !=0)
result = (Low[Offset]-BBI)/(BBS-BBI);
}
return(result);
Da notare che la funzione accetta due argomenti: il prezzo e l'Offset, ovvero la candela relativa al
prezzo sul quale calcolare il %b.
In questa prima versione gestiremo le posizioni esistenti chiudendole per il verificarsi delle
condizioni di apertura opposta e quindi si applicherà una manovra altresì detta "Stop and Reverse".
Nel blocco di codice definito "Money Management" inseriremo quindi la funzione SAR() così
definita:
//+-----------------------------------------------------------+
void SAR()
{
bool iFool;
//ATR parameter
input int ATRPeriods = 14;
//ATRD parameter
input int ATRDPeriods = 14;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//--- Controllo di portafoglio
int iOrders = OrdersTotal();
//Gestione portafoglio
if(iOrders>0)
{
//Money management
SAR();
}
//Ordini LONG
if(VerifyLong()==true)
{
bResult = OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,0,"sdVolatility™ LONG", MagicNumber,0,Green);
return;
}
//Ordini SHORT
if(VerifyShort()==true)
{
bResult = OrderSend(Symbol(),OP_SELL,Lots,Bid,3,0,0,"sdVolatility™ SHORT", MagicNumber,0,Red);
return;
}
}
//+------------------------------------------------------------------+
//| Tester function |
//+------------------------------------------------------------------+
double OnTester()
{
//---
double ret=0.0;
//---
//---
return(ret);
}
//+------------------------------------------------------------------+
bool VerifyLong()
{
bool result = false;
//Si procede solo in presenza di rilevamento dell'eccesso dei prezzi rispetto alle bande di Bollinger
if(PercentB("C",1)>=1+PercentBLevel)
{
double dATR0 = iATR(Symbol(),Period(),ATRPeriods,1);
double dATR1 = iATR(Symbol(),Period(),ATRPeriods,2);
}
}
return(result);
}
//+------------------------------------------------------------------+
bool VerifyShort()
{
bool result = false;
//Si procede solo in presenza di rilevamento dell'eccesso dei prezzi rispetto alle bande di Bollinger
if(PercentB("C",1)<=0-PercentBLevel)
{
double dATR0 = iATR(Symbol(),Period(),ATRPeriods,1);
double dATR1 = iATR(Symbol(),Period(),ATRPeriods,2);
}
}
return(result);
}
//|---------------------------------------------------------------------+
double PercentB(string Price = "C", int Offset = 0)
{
//Calcolo del %b
double result = 0;
double BBI = iBands(Symbol(), Period() ,BBPeriods,BBDeviations,0,PRICE_CLOSE,MODE_LOWER,Offset);
double BBS = iBands(Symbol(), Period() ,BBPeriods,BBDeviations,0,PRICE_CLOSE,MODE_UPPER,Offset);
if(Price=="C")
{
if(Close[Offset]-BBI==0) result=0;
if(Close[Offset]-BBI!=0 && BBS-BBI !=0) result = (Close[Offset]-BBI)/(BBS-BBI);
}
if(Price=="O")
{
if(Open[Offset]-BBI==0) result=0;
if(Open[Offset]-BBI!=0 && BBS-BBI !=0) result = (Open[Offset]-BBI)/(BBS-BBI);
}
if(Price=="H")
{
if(High[Offset]-BBI==0) result=0;
if(High[Offset]-BBI!=0 && BBS-BBI !=0) result = (High[Offset]-BBI)/(BBS-BBI);
}
if(Price=="L")
{
if(Low[Offset]-BBI==0) result=0;
if(Low[Offset]-BBI!=0 && BBS-BBI !=0) result = (Low[Offset]-BBI)/(BBS-BBI);
}
return(result);
//+-----------------------------------------------------------+
void SAR()
{
bool iFool;
Utilizzando questo sistema per effettuare un backtest utilizzando come strumento finanziario la coppia
EURUSD, time frame a un'ora e periodo l'intero anno 2013, otterremo il seguente risultato:
Rispetto al primo test l'introduzione degli stop ha drasticamente diminuito il drawdown e accorciato
la durata delle operazioni.
L'eliminazione del TakeProfit aumenta la possibilità di profitti elevati elevando al contempo la
longevità delle operazioni. Il mantenimento dello stop loss mantiene calmierato il drawdown.
Figura 22 - Test con il solo Stop Loss dinamico e chiusura per SL o Stop & Reverse
La numerosità ridotta delle operazioni è da ricercare nel doppio filtro sulla volatilità (ATR e ATRD)
e nel time frame adottato (H1). Mantenendo le medesime configurazioni e riducendo il TF su un
quarto d'ora la quantità di operazioni aumenta sensibilmente mantenendo una performance similare:
Figura 23 - Test eseguito su M5 con il solo SL dinamico
Dal profilo della curva dell'equity si possono riconoscere i profitti derivanti da inversioni violente
del trend. Operazioni che vengono chiuse per Stop & Reverse. Le serie di perdite moderate
rappresentano invece le chiusure per StopLoss.
double result;
int MaxPips = iSL;
double Loss;
double PipValue;
if(Point==Poin)
PipValue=MarketInfo(Symbol(), MODE_TICKVALUE);
else
PipValue=MarketInfo(Symbol(), MODE_TICKVALUE)*10;
Loss = AccountBalance()*dMaxRisk;
return(result);
}
Per finire dovremo aggiornare l'elenco dei parametri esterni con l'aggiunta di quelli relativi
all'adozione della propensione al rischio e collegare la funzionalità nel codice operativo.
Il codice finale, con le aggiunte per il lotto equivalente, gli stop dinamici e la propensione al rischio
definita è il seguente:
//+------------------------------------------------------------------+
//| sdVolatilityBase.mq4 |
//| Copyright © 2014, SD Studio DAINESI |
//| http://www.sdStudioDainesi.com |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2014, SD Studio DAINESI"
#property link "http://www.sdStudioDainesi.com"
#property version "1.00"
#property strict
input int MagicNumber = 4082014;
input double Lots = 1.00;
//Money management
input bool EquivalentLots = true;
input double MaxRisk = 0.05;
//ATR parameter
input int ATRPeriods = 21;
//ATRD parameter
input int ATRDPeriods = 21;
double Poin;
double dLots;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
if (Point == 0.00001) Poin = 0.0001;
else if (Point == 0.001) Poin = 0.01;
else Poin = Point;
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
dLots = Lots;
SL=0;
TP=0;
SL = (dSATR*SLLevel)/Poin;
TP = (dSATR*TPLevel)/Poin;
//Gestione portafoglio
if(iOrders>0)
{
//Money management
SAR();
}
//Ordini LONG
if(VerifyLong()==true)
{
if(SLLevel!=0)bResult = OrderSend(Symbol(),OP_BUY,dLots,Ask, 3, Ask - SL*Poin, Ask + TP*Poin, "sdVolatility™ LONG", MagicNumber,0,Green);
if(SLLevel==0 && TPLevel==0)bResult = OrderSend(Symbol(),OP_BUY,dLots,Ask, 3, 0, 0, "sdVolatility™ LONG", MagicNumber,0,Green);
return;
}
//Ordini SHORT
if(VerifyShort()==true)
{
if(SLLevel!=0)bResult = OrderSend(Symbol(),OP_SELL,dLots,Bid, 3, Bid + SL*Poin, Bid - TP*Poin, "sdVolatility™ SHORT", MagicNumber,0,Red);
if(SLLevel==0)bResult = OrderSend(Symbol(),OP_SELL,dLots,Bid, 3, 0, 0, "sdVolatility™ SHORT", MagicNumber,0,Red);
return;
}
}
//+------------------------------------------------------------------+
//| Tester function |
//+------------------------------------------------------------------+
double OnTester()
{
//---
double ret=0.0;
//---
//---
return(ret);
}
//+------------------------------------------------------------------+
bool VerifyLong()
{
bool result = false;
//Si procede solo in presenza di rilevamento dell'eccesso dei prezzi rispetto alle bande di Bollinger
if(PercentB("C",1)<=0-PercentBLevel)
{
double dATR0 = iATR(Symbol(),Period(),ATRPeriods,1);
double dATR1 = iATR(Symbol(),Period(),ATRPeriods,2);
return(result);
}
//+------------------------------------------------------------------+
bool VerifyShort()
{
bool result = false;
//Si procede solo in presenza di rilevamento dell'eccesso dei prezzi rispetto alle bande di Bollinger
if(PercentB("C",1)>=1+PercentBLevel)
{
double dATR0 = iATR(Symbol(),Period(),ATRPeriods,1);
double dATR1 = iATR(Symbol(),Period(),ATRPeriods,2);
return(result);
}
//|---------------------------------------------------------------------+
double PercentB(string Price = "C", int Offset = 0)
{
//Calcolo del %b
double result = 0;
double BBI = iBands(Symbol(), Period() ,BBPeriods,BBDeviations,0,PRICE_CLOSE,MODE_LOWER,Offset);
double BBS = iBands(Symbol(), Period() ,BBPeriods,BBDeviations,0,PRICE_CLOSE,MODE_UPPER,Offset);
if(Price=="C")
{
if(Close[Offset]-BBI==0) result=0;
if(Close[Offset]-BBI!=0 && BBS-BBI !=0) result = (Close[Offset]-BBI)/(BBS-BBI);
}
if(Price=="O")
{
if(Open[Offset]-BBI==0) result=0;
if(Open[Offset]-BBI!=0 && BBS-BBI !=0) result = (Open[Offset]-BBI)/(BBS-BBI);
}
if(Price=="H")
{
if(High[Offset]-BBI==0) result=0;
if(High[Offset]-BBI!=0 && BBS-BBI !=0) result = (High[Offset]-BBI)/(BBS-BBI);
}
if(Price=="L")
{
if(Low[Offset]-BBI==0) result=0;
if(Low[Offset]-BBI!=0 && BBS-BBI !=0) result = (Low[Offset]-BBI)/(BBS-BBI);
}
return(result);
//+-----------------------------------------------------------+
void SAR()
{
bool iFool;
//|--------------------------------------------------------------------+
double EquivalentLots(int iSL, double dMaxRisk)
{
double result;
int MaxPips = iSL;
double Loss;
double PipValue;
if(Point==Poin)
PipValue=MarketInfo(Symbol(), MODE_TICKVALUE);
else
PipValue=MarketInfo(Symbol(), MODE_TICKVALUE)*10;
Loss = AccountBalance()*dMaxRisk;
return(result);
Con la funzionalità del lotto equivalente le performance vengono notevolmente incrementate, al pari
del drawdown che si sposta da livelli intorno al 5% a quasi il 50%.
Figura 24 - Stessi parametri ma ogni posizione ha un rischio pari al 5% del capitale
Figura 26 - Se il rischio viene impostato a mezzo punto percentuale (0,5% ) il DD cala sotto il 7% e la resa si mantiene su livelli interessanti (33% )
In uno scenario volatile la gestione del rischio tramite il calcolo degli stop ed il conseguente calcolo
del lotto equivalente è lo strumento essenziale per poter operare efficacemente con rischi ridotti.
Parte quarta
In questa quarta parte si accompagnerà il lettore nella creazione di un trading system che applicherà
le strategie descritte nelle prime parti, relativamente ai mercati ove le regole per la normale
volatilità non hanno fondamento. Si tratta dei mercati turbolenti, soggetti agli isterismi di mercato o
alle fasi sottili che caratterizzano gli strumenti finanziari meno liquidi.
In questa parte si insegnerà al lettore come riconoscere un pattern e conseguentemente operare
coerentemente, gestendo il rischio approssimando gli ipotetici stops.
//+------------------------------------------------------------------+
bool VerifySpike(int& Direction, int& SL, int& TP, double& Vol)
{
Direction = -1;
//Identificazione della direzione e distanza tra Open e Bid/Ask per determinarne il verso operativo
if(Ask>Open[0] && Ask-Open[0]>dExtension/2)Direction=OP_SELL;
if(Bid<Open[0] && Open[0]-Bid>dExtension/2)Direction=OP_BUY;
if(Direction<0)return(false);
return(result);
Osservando bene questa funzione si potrà notare come si è cercato di ottimizzare il codice per
incrementare la velocità di esecuzione (se le precondizioni non sono soddisfatte si esce dalla
funzione) e come risolvere incongruenze operative quali la dimensione assoluta minima degli stop in
relazione allo spread. Un pattern potrebbe trovarsi anche in presenza di volatilità oggettivamente
bassa e generare una barra spike quale multiplo della volatilità. Per limitare questi inconvenienti si è
deciso di adottare un parametro, SLSpreadMultiplier, che filtra i segnali con stop troppo ridotti.
Di seguito si mostrano i risultati ottenuti con diverse misure di questo parametro sul periodo 2013 e
strumento EURUSD M15 e spread fissato a 2 pips.
Come si può notare dall'esito dei test, il filtro sulla dimensione degli Stop permette di rendere
profittevole il sistema a scapito della frequenza operativa.
Figura 30 - Esempio di entrata su presunto Spike
In figura 29 è evidenziata un'operazione da manuale eseguita su quella che sino ad allora pareva
essere una Spike in formazione. Come si può notare, il brusco movimento rialzista si è parzialmente
riassorbito permettendo il raggiungimento del profitto pari al terzo dell'estensione di barra. Col
passare del tempo il segnale si sarebbe perso e l'identificazione della Spike impossibile.
Come si può notare all'aumentare del moltiplicatore aumenta l'attendibilità ma diminuiscono i segnali
con conseguente impoverimento dei profitti. Calando il parametro si accolgono troppi falsi segnali e
si generano troppe operazioni. Lo spike non è un pattern frequente per cui è lecito aspettarsi pochi
buoni segnali all'interno di un test.
Direction = -1;
result=true;
return(result);
Osservando il codice MQL si può notare come il riconoscimento del Gap sia particolarmente
semplice, è sufficiente constatare che il prezzo di apertura della candela in corso sia staccato
dall'intervallo di prezzi coperto dalla candela precedente e se l'apertura è sotto l'intervallo
precedente saremo in presenza di un "gap down", viceversa se l'apertura è sopra avremo un "gap
up". L'operatività suggerita sarà contraria alla direzione del gap.
if(Open[0]<Low[1])Direction=OP_BUY;
if(Open[0]>High[1])Direction=OP_SELL;
Il calcolo degli stop sarà fatto in funzione della distanza tra Open e estremo dell'intervallo
precedente per il take profit e come multiplo della volatilità per lo stop loss.
TP = dExtension/Poin;
SL = (iATR(Symbol(),Period(),RangeInspection,1)/Poin)*SLLevel;
Per evitare di prendere in considerazioni gap poco significativi viene introdotto un filtro "anti
rumore" che nega il segnale in caso il gap sia particolarmente ridotto (meno di un multiplo dello
spread attuale).
if(TP<((Ask-Bid)/Poin)*SLSpreadMultiplier)result=false;
La dimensione dell'operazione viene quindi calcolata in base alla propensione al rischio tramite
l'ormai nota funzione di calcolo del lotto equivalente.
Vol = EquivalentLots(SL, MaxRisk);
Al fine di testare la strategia basata sui soli Gap si riporta il grafico dell'equity ottenuta su un periodo
di quattro anni su EURUSD H4.
Dopo gli spike ed i gap veniamo ora ai pattern Inside quale strategia applicabile negli scenari di
instabilità dei mercati.
Per riconoscere un pattern inside occorre verificare l'intervallo di estensione di due barre
consecutive e quindi intercettare il breakout della barra in corso sul range precedente.
Direction = -1;
result=true;
return(result);
Nella prima parte del codice si ricerca solamente il breakout per determinare il tipo di operatività.
if(Bid<Low[1])Direction=OP_SELL;
if(Ask>High[1])Direction=OP_BUY;
Al fine di testare la strategia basata sui soli pattern Inside si riporta il grafico dell'equity ottenuta su
un periodo di quattro anni su EURUSD Daily.
Considerazioni finali
Ognuna delle strategie mostrate ha adottato degli stops fissi, calcolati nel momento stesso
dell'apertura degli ordini. Questo modo di operare è ovviamente limitante ma è ottimo per insegnare
al lettore le strategie operative che fungeranno da base di partenza per costruirsi una strategia
personale e professionale.
Un buon money management non si ferma ad un calcolo corretto degli stops e delle dimensioni più
convenienti per singola operazione ma prosegue con la loro gestione dinamica. Questo significa
implementare una strategia di uscita per parti ed uno spostamento dinamico, monodirezionale, degli
stops. Grazie a queste tecniche è possibile abbassare il drawdown e correggere in tempo gli obiettivi
di profitto.
Si rimanda ad un successivo testo l'approfondimento sulle tecniche di implementazione del money
management.
Appendice I
Codice per l'implementazione dell'indicatore ATRD
//+------------------------------------------------------------------+
//| SD Average True Range Directional.mq4 |
//| Copyright © 2014, sd Studio DAINESI |
//| http://www.sdStudioDainesi.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2014, sd Studio DAINESI"
#property link "http://www.sdStudioDainesi.com/"
#property indicator_separate_window
#property indicator_buffers 3
//COLORS
#property indicator_color1 DodgerBlue
#property indicator_color2 Green
#property indicator_color3 Yellow
//---- buffers
double AtrBuffer[];
double AtrDPlusBuffer[];
double AtrDMinusBuffer[];
double TempBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
string short_name;
IndicatorBuffers(3);
SetIndexBuffer(0,AtrDPlusBuffer);
SetIndexBuffer(1,AtrDMinusBuffer);
SetIndexBuffer(2,AtrBuffer);
SetIndexLabel(0,"Plus volatility");
SetIndexLabel(1,"Minus volatility");
SetIndexLabel(2,"ATR");
//----
SetIndexDrawBegin(0,ATRDPeriods);
SetIndexDrawBegin(1,ATRDPeriods);
SetIndexDrawBegin(2,ATRDPeriods);
//----
return(0);
}
//+------------------------------------------------------------------+
//| Average True Range |
//+------------------------------------------------------------------+
int start()
{
int i;
int counted_bars = IndicatorCounted();
if(Bars<=ATRDPeriods) return(0);
ATRI = 0;
RPlus = 0;
RMinus = 0;
for(int y=i;y<i+ATRDPeriods;y++)
{
ATRI = ATRI + MathMax(High[y],High[y+1])-MathMin(Low[y],Low[y+1]);
//Corpo Positivo
if(Open[y]<Close[y])
{
RPlus = RPlus + (Close[y]-Open[y]); //Il Body
RMinus = RMinus + (High[y]-Close[y]) + (Open[y]-Low[y]); //Le Shadows
RPlus = RPlus + (High[y]-Open[y]) + (Close[y]-Low[y]);
if(High[y+1]>High[y])RMinus = RMinus + (High[y+1]-High[y]);
if(Low[y+1]<Low[y]) RPlus = RPlus + (Low[y]-Low[y+1]);
}
//Corpo Negativo
if(Open[y]>Close[y])
{
RMinus = RMinus + (Open[y]-Close[y]);
RPlus = RPlus + (High[y]-Open[y]) + (Close[y]-Low[y]);
RMinus = RMinus + (High[y]-Close[y]) + (Open[y]-Low[y]);
if(High[y+1]>High[y])RMinus = RMinus + (High[y+1]-High[y]);
if(Low[y+1]<Low[y])RPlus = RPlus + (Low[y]-Low[y+1]);
}
//Doji
if(Open[y]==Close[y])
{
RPlus = RPlus + (High[y]-Low[y]);
RMinus = RMinus + (High[y]-Low[y]);
if(High[y+1]>High[y])RMinus = RMinus + (High[y+1]-High[y]);
if(Low[y+1]<Low[y])RPlus = RPlus + (Low[y]-Low[y+1]);
}
}
AtrBuffer[i]=ATRI/ATRDPeriods;
AtrDPlusBuffer[i] = RPlus/ATRDPeriods;
AtrDMinusBuffer[i] = RMinus/ATRDPeriods;
}
return(0);
}
//+------------------------------------------------------------------+
Codice per l'implementazione del trading system sdVolatilityBadBase
//+------------------------------------------------------------------+
//| sdVolatilityBadBase.mq4 |
//| Copyright © 2014, SD Studio DAINESI |
//| http://www.sdStudioDainesi.com |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2014, SD Studio DAINESI"
#property link "http://www.sdStudioDainesi.com"
#property version "1.00"
#property strict
//ATR parameter
input int ATRPeriods = 21;
double Poin;
double dLots;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
if (Point == 0.00001) Poin = 0.0001;
else if (Point == 0.001) Poin = 0.01;
else Poin = Point;
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
SL=0;
TP=0;
SL = (dSATR*SLLevel)/Poin;
TP = (dSATR*TPLevel)/Poin;
//Gestione portafoglio
if(iOrders>0)
{
//Money management
if(bResult == true)
{
if(Dir==OP_BUY) bResult = OrderSend(Symbol(),OP_BUY,dLots,Ask, 3, Ask - SL*Poin, Ask + TP*Poin, "sdVolatility™ LONG", MagicNumber,0,Green);
if(Dir==OP_SELL)bResult = OrderSend(Symbol(),OP_SELL,dLots,Bid, 3, Bid + SL*Poin, Bid - TP*Poin, "sdVolatility™ SHORT", MagicNumber,0,Red);
return;
}
if(bResult==false)
{
if(GapSignal==true)bResult = VerifyGap(Dir, SL, TP, dLots);
}
if(bResult == true)
{
if(Dir==OP_BUY) bResult = OrderSend(Symbol(),OP_BUY,dLots,Ask, 3, Ask - SL*Poin, Ask + TP*Poin, "sdVolatility™ LONG", MagicNumber,0,Green);
if(Dir==OP_SELL)bResult = OrderSend(Symbol(),OP_SELL,dLots,Bid, 3, Bid + SL*Poin, Bid - TP*Poin, "sdVolatility™ SHORT", MagicNumber,0,Red);
return;
}
if(bResult==false)
{
if(InsideSignal==true)bResult = VerifyInside(Dir, SL, TP, dLots);
}
if(bResult == true)
{
if(Dir==OP_BUY) bResult = OrderSend(Symbol(),OP_BUY,dLots,Ask, 3, Ask - SL*Poin, Ask + TP*Poin, "sdVolatility™ LONG", MagicNumber,0,Green);
if(Dir==OP_SELL)bResult = OrderSend(Symbol(),OP_SELL,dLots,Bid, 3, Bid + SL*Poin, Bid - TP*Poin, "sdVolatility™ SHORT", MagicNumber,0,Red);
return;
}
}
//+------------------------------------------------------------------+
//| Tester function |
//+------------------------------------------------------------------+
double OnTester()
{
//---
double ret=0.0;
//---
//---
return(ret);
}
//+------------------------------------------------------------------+
bool VerifySpike(int& Direction, int& iSL, int& iTP, double& Vol)
{
Direction = -1;
//Identificazione della direzione e distanza tra Open e Bid/Ask per determinarne il verso operativo
if(Ask>Open[0] && Ask-Open[0]>dExtension/2)Direction=OP_SELL;
if(Bid<Open[0] && Open[0]-Bid>dExtension/2)Direction=OP_BUY;
if(Direction<0)return(false);
//+------------------------------------------------------------------+
bool VerifyGap(int& Direction, int& iSL, int& iTP, double& Vol)
{
Direction = -1;
result=true;
return(result);
//+------------------------------------------------------------------+
bool VerifyInside(int& Direction, int& iSL, int& iTP, double& Vol)
{
Direction = -1;
result=true;
return(result);
//|--------------------------------------------------------------------+
double EquivalentLots(int iSL, double dMaxRisk)
{
double result;
int MaxPips = iSL;
double Loss;
double PipValue;
if(Point==Poin)
PipValue=MarketInfo(Symbol(), MODE_TICKVALUE);
else
PipValue=MarketInfo(Symbol(), MODE_TICKVALUE)*10;
Loss = AccountBalance()*dMaxRisk;
return(result);
[1]
In Microeconomia, ad esempio, un livello può rappresentare lo strike per delle opzioni e quindi un suo superamento muterebbe il valore del derivato. In Macroeconomia un livello potrebbe fare da discriminante per rendere o meno
competitiva l'economia di una nazione su beni fungibili di libero scambio.
[2]
Il corpo di una candela, o body , è la zona compresa tra prezzo di apertura e prezzo di chiusura. Le zone comprese tra il corpo ed il massimo e tra il corpo ed il minimo sono definite ombre, o shadows.
[3]
Si rimanda ad altro libro l'illustrazione di siffatti indicatori.
[4]
Si avverte il lettore che il trading system che verrà creato avrà una sola valenza accademica e non dovrà essere utilizzato con denaro reale o in concomitanza con altri trading system. Qualora si volesse la versione professionale si prega di
contattare lo Studio Dainesi per una valutazione commerciale (info@sdStudioDainesi.com).
Table of Contents
[1]
[2]
[3]
[4]