Ciao! In questa maxi guida ti spiegherò come funziona il calcolo del prezzo medio di carico (o Average Price in inglese) e come scrivere una bella funzione per il calcolo del PMC basilare ed utilizzarlo nei tuoi sistemi.
Cosa è il Prezzo Medio di Carico
Il prezzo medio di carico (da ora in avanti lo chiamerò PMC così siamo più veloci) è un dato fondamentale mutuato dai trader stocks. Infatti viene considerato (anche ai fini fiscali) per il calcolo dei profitti nel caso in cui tu abbia acquistato lo stesso strumento a più riprese.
Immagina di comprare 100 AZIONI della XYZ SpA, al prezzo di 3€ l’una, il 5 di maggio (Ei fu. Siccome immobile / dato il mortal sospiro).
Successivamente, diciamo il 24 maggio ( quando “Il Piave mormorava calmo e placido al passaggio dei primi fanti), acquisti altre 100 azioni della XYZ SpA, al prezzo di 4,50 €.
Il calcolo del PMC ti permette di capire quale sia la soglia di prezzo che separa il territorio del profitto da quello della perdita.
Quanto varrà questo prezzo? 4 €? 3,5€? Meglio calcolarlo matematicamente.
Formula del Prezzo Medio di Carico
La formula per calcolare il PMC è la seguente:
dati
Q1 = Quantità acquisto n°1
P1 = Prezzo acquisto n°1
Q2 = Quantità acquisto n°2
P2 = Prezzo acquisto n°2
Qn = Quantità acquisto ennesimo
Pn = Prezzo acquisto ennesimo
T = (Q1 + Q2 + … + Qn) = somma di tutte le quantità acquistate
PMC = (Q1*P1+Q2*P2+ … + Qn*Pn) / T
Nel caso specifico degli acquisti di azioni di XYZ SpA, avremo:
PMC = (100*3+ 100 * 4,5 ) / 200 = (300 + 450 )/ 200 = 750/200 = 3,75 €
Il prezzo medio di carico della nostra operazione globale sullo stock XYZ SpA è di 3,75.
Se l’azione batterà il prezzo di 3,90€, nonostante siamo in perdita con la seconda “posizione” saremo globalmente in profitto.
Il Prezzo Medio di Carico nei CFD
Ok, abbiamo visto come funziona sulle azioni, ma nei CFD? E in operazioni intraday? Come si fa?
Cambiamo le quantità con i lotti e usiamo gli open price, e vedrai che il calcolo del PMC sarà facile come bere un bicchiere di nafta.
La funzione del Prezzo Medio di Carico in Mql4
Apri l’editor e comincia a scrivere l’inizio della nostra funzione:
double PMC(string _s, int _dir, int _mn=-1){ }
La funzione ritornerà un valore double (è un prezzo quindi un numero a virgola mobile) e prende 3 argomenti: il Simbolo, il Magic Number e la direzione.
Questo perché possiamo calcolare il PMC solo sullo stesso asset, non su asset diversi. Il Magic ci serve per isolare solo i trade del nostro EA, oppure, se impostato a -1, di prendere tutti i trades.
La direzione, infine, ci serve per trovare il PMC per i Long e per gli Short separatamente. Nella mia personale versione, mi calcolo il PMC a prescindere dalla direzione, ma lascio a te il compito di implementare questa complicazione.
Iniziamo salvando i dati importanti del simbolo e inizializzando le variabili che ci serviranno:
double PMC(string _s, int _dir, int _mn=-1) { int _dgt= (int) MarketInfo(_s,MODE_DIGITS); double _sommaVolumi=0.0; double _sommaPrezzi=0.0; }
E avviamo successivamente il nostro classico ciclo di analisi degli ordini, ah, prepariamo già il return corretto, nel quale normalizziamo al decimale salvato in _dgt il valore della formula: _sommaPrezzi / _sommaVolumi:
double PMC(string _s, int _dir, int _mn=-1) { int _dgt= (int) MarketInfo(_s,MODE_DIGITS); double _sommaVolumi=0.0; double _sommaPrezzi=0.0; //--- for(int i=OrdersTotal()-1; i>=0; i--) { if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) { Alert("Non ho selezionato l'ordine!"); } else { // -- Logica di analisi } } return NormalizeDouble(_sommaPrezzi/_sommaVolumi,_dgt); }
Inseriamo le logiche di analisi nel ciclo
Noi useremo questa funzione in un’ottica mono-side: per la richiameremo indicando la direzione che vogliamo, nell’argomento _dir.
Per convenzione utilizzo il valore 1 per la long side e -1 per la short side.
Quindi, innanzi tutto verifichiamo che il trade selezionato da OrderSelect() sia di questo simbolo e di questo magic number (oppure che sia inserito a mano):
double PMC(string _s, int _dir, int _mn=-1) { int _dgt= (int) MarketInfo(_s,MODE_DIGITS); double _sommaVolumi=0.0; double _sommaPrezzi=0.0; //--- for(int i=OrdersTotal()-1; i>=0; i--) { if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) { Alert("Non ho selezionato l'ordine!"); } else { if(OrderSymbol()==_s && (OrderMagicNumber()==_mn || _mn==-1)) { // -- calcoli dai dati del trade. } } } return NormalizeDouble(_sommaPrezzi/_sommaVolumi,_dgt); }
E poi “setacciamo” i buy o i sell in base alla side che abbiamo deciso di analizzare.
double PMC(string _s, int _dir, int _mn=-1) { int _dgt= (int) MarketInfo(_s,MODE_DIGITS); double _sommaVolumi=0.0; double _sommaPrezzi=0.0; //--- for(int i=OrdersTotal()-1; i>=0; i--) { if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) { Alert("Non ho selezionato l'ordine!"); } else { if(OrderSymbol()==_s && (OrderMagicNumber()==_mn || _mn==-1)) { if(_dir==1) // direzione scelta= long side, per cui analizziamo solo i buy { if(OrderType()==OP_BUY) { // -- calcoli buy } } if(_dir==-1) // direzione scelta = short side, per cui analizziamo solo i sell { if(OrderType()==OP_SELL) { // -- calcoli sell } } } } } return NormalizeDouble(_sommaPrezzi/_sommaVolumi,_dgt); }
Per i calcoli, ci rifacciamo alla teoria esposta prima:
salviamo in una variabile la somma delle quantità, e nell’altra variabile la somma dei prezzi*quantità:
_sommaVolumi += OrderLots(); _sommaPrezzi += OrderOpenPrice()*OrderLots();
La funzione ultimata
Funzione del Prezzo Medio di Carico ultimata
Molto semplicemente siamo arrivati alla fine, vedi che non era tutto sto casino da fare.
È possibile renderla più accurata? Tipo considerando contemporaneamente tutte e due le side oppure fattorizzando anche commissioni e swap? Certamente! Ma lascio a te il compito di approfondire la cosa.
Puoi addirittura usare il PMC come base per il Trailing Stop a basket, basta unirlo con questa funzione
Naturalmente, sono a disposizione per darti una mano! 😉
Eccoti la funzione completa, enjoy!
double PMC(string _s, int _dir, int _mn=-1) { int _dgt= (int) MarketInfo(_s,MODE_DIGITS); double _sommaVolumi=0.0; double _sommaPrezzi=0.0; //--- for(int i=OrdersTotal()-1; i>=0; i--) { if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)) { Alert("Non ho selezionato l'ordine!"); } else { if(OrderSymbol()==_s && (OrderMagicNumber()==_mn || _mn==-1)) { if(_dir==1) { if(OrderType()==OP_BUY) { _sommaVolumi += OrderLots(); _sommaPrezzi += OrderOpenPrice()*OrderLots(); } } if(_dir==-1) { if(OrderType()==OP_SELL) { _sommaVolumi+=OrderLots(); _sommaPrezzi+=OrderOpenPrice()*OrderLots(); } } } } } return NormalizeDouble(_sommaPrezzi/_sommaVolumi,_dgt); }