Strategia di trading Heads or Tails analisi del codice del robot di trading.

Strategia di trading Heads or Tails analisi del codice del robot di trading.

21 gennaio 2026, 20:05
Vladimir Pastushak
0
4

La strategia di trading "Testa o croce" fa parte della categoria delle strategie di trading ad alto rischio e a breve termine, utilizzata principalmente nei mercati azionari e nel mercato forex. Il suo nome deriva dalla casualità nella presa di decisioni, simile al lancio di una moneta ("testa" significa acquistare un attivo, "croce" significa venderlo). Questa strategia si basa esclusivamente sulle decisioni intuitive o sui segnali casuali e ignora gli analisi fondamentali del mercato.


Il codice sorgente della strategia di trading è stato aggiunto alla base dei codici:

MetaTrader 5: https://www.mql5.com/it/code/11637


#property copyright "Copyright 2025, Trading-Go." // Impostazione proprietà diritti d'autore
#property link      "https://www.mql5.com/en/channels/tradingo-go-en"  // Impostazione collegamento alla risorsa dello sviluppatore
#property version   "26.010" // Versione del programma

Questo blocco rappresenta istruzioni di compilazione per un programma scritto come consigliere esperto (Expert Advisor) o indicatore sulla piattaforma MetaTrader usando il linguaggio MQL4/MQL5.

Esamineremo ogni riga separatamente:

1. #property copyright "Copyright 2025, Trading-Go."

Questa istruzione definisce i diritti legali sul codice sorgente dell'esperto o dell'indicatore. Indica il proprietario dei diritti d'autore e aiuta a identificare la provenienza del prodotto nell'interfaccia proprietà dell'esperto/indicatore nel terminale cliente MetaTrader.

2. #property link " "

Permette di stabilire un collegamento verso una risorsa Web associata allo sviluppatore. Quando i trader utilizzano questo esperto o indicatore, questo collegamento diventa disponibile nelle sue proprietà. È utile per lo sviluppatore poiché può dirigere gli utenti verso pagine di supporto, documentazione o comunità correlate al prodotto.

3. #property version "26.010"

Qui viene definita la versione del software. Generalmente, gli sviluppatori specificano la versione sotto forma di "XX.XX", dove il primo numero indica la versione principale, il secondo la versione minore e il terzo il livello di patch. La versione aiuta gli utenti a seguire agevolmente gli aggiornamenti e mantenere la compatibilità degli strumenti.

#include 


 // Inclusione della libreria Trade.mqh
CTrade        trade; // Oggetto della classe CTrade per gestire le operazioni di trading

#include 


 // Inclusione della libreria PositionInfo.mqh
CPositionInfo posit; // Oggetto della classe CPositionInfo per elaborare le posizioni

Questa sezione include le librerie necessarie e crea oggetti che consentono di gestire le operazioni di trading e elaborare le posizioni aperte sulla piattaforma MetaTrader.

Analizziamo ogni elemento individualmente:

1. #include

Questa direttiva include il file di intestazione (Trade.mqh) contenente la definizione della classe CTrade. Il file si trova nella cartella /Trade, il che significa che fa parte della libreria standard delle operazioni di trading fornita da MetaTrader. La classe CTrade semplifica l'interazione con il trading, inclusa l'apertura di posizioni, la chiusura di transazioni, la modifica degli ordini e la ricezione di informazioni sulle operazioni in corso.

2. CTrade trade;

Viene creato un oggetto denominato "trade" della classe CTrade. Usando quest'oggetto, puoi controllare vari aspetti del trading, come aprire nuove posizioni, regolare gli stop loss e i take profit, chiudere posizioni esistenti e altro ancora.

3. #include

Un'altra direttiva include un altro file di intestazione (PositionInfo.mqh) presente nella stessa cartella (/Trade). Questo file contiene la definizione della classe CPositionInfo, che elabora le informazioni riguardanti le posizioni attualmente aperte sul conto. Attraverso questa classe è possibile estrarre dettagli precisi su ogni posizione aperta, come il volume della transazione, il prezzo di entrata, il profitto/perso ecc.

4. CPositionInfo posit;

È creato un oggetto denominato "posit" della classe CPositionInfo. Utilizzando questo oggetto, è possibile ottenere informazioni complete su tutte le posizioni attive presenti sul tuo conto di trading, cosa utile per analizzare lo stato attuale del portafoglio e prendere decisioni informative basate su queste informazioni.

Scopo generale:

Queste due librerie costituiscono la base necessaria per automatizzare il processo di trading mediante un'interfaccia di programmazione applicativa (API) di alto livello. Consentono agli sviluppatori di focalizzarsi direttamente sulla logica della strategia anziché sugli aspetti tecnici di comunicazione con il server del broker.

input double  iLots         = 0.10; // Parametro di ingresso per la dimensione del lotto (volume della transazione)
input int     iTakeProfit   = 450;  // Parametro di ingresso per il livello di fissazione del profitto (Take Profit)
input int     iStopLoss     = 390;  // Parametro di ingresso per il livello di limitazione delle perdite (Stop Loss)
input int     iMagicNumber  = 227; // Parametro di ingresso per il numero unico della transazione (Magic Number)
input int     iSlippage     = 30; // Parametro di ingresso per la massima deviazione del prezzo

string sy = ""; // Variabile per memorizzare il simbolo dello strumento finanziario
double pt = 0; // Variabile per calcolare il passo di cambiamento del punto
int    dt = 0; // Variabile per contare il numero di cifre dopo la virgola

Ogni elemento del blocco di codice sopra riportato ha uno scopo specifico per configurare l'ambiente di trading e prepararlo per l'utilizzo dell'automa Expert Advisor (EA) sulla piattaforma MetaTrader. Esamineremo ogni elemento singolarmente:


Parametri di ingresso:

1. iLots = 0.10;

Questo parametro di tipo double determina la dimensione del lotto (volume della transazione). Valore predefinito: 0.10. La dimensione del lotto regola quanti attivi verranno acquistati o venduti durante una singola transazione. Per esempio, se lo strumento è EURUSD, un lotto di 0.1 corrisponde a 10.000 unità della valuta base (come euro).

2. iTakeProfit = 450;

Parametro intero che definisce il livello di fissazione del profitto (Take Profit). Valore predefinito: 450. Il Take Profit chiude automaticamente la posizione quando il prezzo di mercato raggiunge il livello di profitto specificato rispetto al prezzo di entrata nella transazione. Il livello è espresso in punti (pips).

3. iStopLoss = 390;

Parametro intero che definisce il livello di limitazione delle perdite (Stop Loss). Valore predefinito: 390. Lo Stop Loss chiude automaticamente la posizione se il mercato si muove contro la posizione e le perdite raggiungono il livello prestabilito. Anche le perdite sono misurate in punti.

4. iMagicNumber = 227;

Parametro intero che funge da numero unico di identificazione (Magic Number) per le transazioni. Ogni evento (apertura di posizione, chiusura ecc.) riceve un numero magico unico che consente di filtrare le transazioni in base a tale criterio. Valore predefinito: 227.

5. iSlippage = 30;

Parametro intero che limita la deviazione massima consentita tra il prezzo richiesto e quello effettivo. Valore predefinito: 30. Se il prezzo effettivo differisce oltre questo valore, la transazione non sarà eseguita. Ciò protegge dall'eccessiva deviazione dei prezzi.

Variabili locali:

1. sy = "";

Variabile di tipo stringa che memorizza il simbolo dello strumento finanziario (ad esempio "EURUSD") utilizzato per il trading. Inizialmente vuota.

2. pt = 0;

Variabile di tipo doppio utilizzata per calcolare il passo di cambiamento del punto. Valore iniziale: 0.

3. dt = 0;

Variabile di tipo intero utilizzata per conteggiare il numero di cifre dopo la virgola nelle quotazioni dello strumento selezionato. Il numero di cifre decimali è importante per il calcolo corretto del profitto e dello stop loss, così come altre metriche. Valore iniziale: 0.

Questo blocco di codice fornisce i parametri iniziali e prepara l'ambiente per l'automa Expert Advisor in MetaTrader. I parametri di ingresso forniscono flessibilità per personalizzare il comportamento dell'EA prima dell'avvio del trading.

   sy = _Symbol; // Ottenimento del simbolo corrente dello strumento di trading
   pt = _Point; // Ottenimento della dimensione minima di cambiamento dell'unità
   dt = _Digits; // Ottenimento del numero di cifre dopo la virgola nel prezzo

   trade.SetExpertMagicNumber(iMagicNumber); // Impostazione del numero unico della transazione

   trade.SetDeviationInPoints(iSlippage); // Impostazione della deviazione massima dei punti di prezzo

   trade.SetTypeFillingBySymbol(sy); // Impostazione del tipo di esecuzione degli ordini in base alle impostazioni dello strumento

   trade.SetMarginMode(); // Impostazione del modo di margine


Questa sezione mostra le fasi di inizializzazione essenziali per il corretto funzionamento di un Expert Advisor (EA) sulla piattaforma MetaTrader. Analizzeremo ogni comando in dettaglio:

Impostazione delle variabili ambientali:

1. sy = _Symbol;

Assegna alla variabile globale sy il nome dello strumento finanziario attualmente utilizzato per il trading. _Symbol è una costante integrata che restituisce il nome dell'attivo selezionato nel terminale. Così abbiamo accesso al nome dello strumento necessario per ulteriori calcoli e lavoro con esso.

2. pt = _Point;

Definisce la variabile pt come la dimensione minima di cambiamento del prezzo dello strumento (_Point). Essa è l'unità di base per misurare le variazioni del prezzo, necessaria per interpretare correttamente i segnali del sistema e regolare gli ordini.

3. dt = _Digits;

Memorizza nella variabile dt il numero di cifre dopo la virgola per le quotazioni dello strumento corrente. Poiché diversi strumenti hanno numeri diversi di cifre decimali (ad esempio, USDJPY ha due cifre, EURUSD quattro), questa variabile è importante per l'arrondimento corretto dei numeri e i calcoli precisi.


Configurazione dell'oggetto di trading:

4. trade.SetExpertMagicNumber(iMagicNumber);

Imposta un numero unico (Magic Number) per tutte le transazioni avviate dallo stesso EA. Il Magic Number identifica le transazioni esemplate da un dato EA, facilitando il filtro delle posizioni in base a questo criterio. Un numero unico garantisce la chiarezza fra diverse strategie robotizzate.

5. trade.SetDeviationInPoints(iSlippage);

Limita la deviazione massima tra il prezzo dell'ordine e il prezzo effettivo. Una volta impostato, previene l'esecuzione di transazioni se il prezzo reale differisce troppo. Protegge dai grandi slittamenti di prezzo.

6. trade.SetTypeFillingBySymbol(sy);

Imposta il tipo di esecuzione degli ordini in base alle caratteristiche dello strumento stesso. Alcuni strumenti richiedono un'esecuzione immediata (« Market Execution »), mentre altri possono accettare un'esecuzione ritardata (« Instant Execution »). Questo comando seleziona automaticamente il metodo giusto in base alle specifiche dello strumento.

7. trade.SetMarginMode();

Imposta il modo di margine. La gestione della margine dipende dagli strumenti e dal tipo di trading. Una configurazione adeguata influisce sul numero di fondi liberi necessari per mantenere una posizione e riduce il rischio di chiusura forzata della posizione dovuto a carenza di capitale.

   double stepvol = SymbolInfoDouble(sy, SYMBOL_VOLUME_STEP); // Ottieni il passo di cambiamento della dimensione del lotto per il simbolo selezionato
   if(stepvol > 0.0) // Se il passo di cambiamento della dimensione del lotto è positivo, applica il calcolo della dimensione del lotto corretta
      lt = stepvol * (MathFloor(iLots / stepvol) - 1); // Arrotamento verso il basso della dimensione del lotto al valore più vicino al passo e riduzione di un passo
//---
   double minvol = SymbolInfoDouble(sy, SYMBOL_VOLUME_MIN); // Ottieni la dimensione minima consentita del lotto per il simbolo specificato
   if(lt < minvol) // Se la dimensione del lotto corretta è inferiore al valore minimo possibile, ripristinala a zero
      lt = 0.0;

   ::MathSrand(GetTickCount()); // Generazione del numero iniziale per il generatore casuale

Questo blocco di codice implementa una regolazione dinamica della dimensione delle transazioni (lotti) all'interno dei limiti stabiliti dalla borsa per uno strumento finanziario specifico (valuta, azione, contratto ecc.). Lo scopo primario è quello di regolare la dimensione del lotto in accordo con le regole della borsa, evitando errori durante l'apertura delle posizioni e garantendo la sicurezza delle transazioni.

Esamineremo ogni fase in dettaglio:

Fase 1: Determinazione del passo di cambiamento della dimensione del lotto:

double stepvol = SymbolInfoDouble(sy, SYMBOL_VOLUME_STEP);

La funzione SymbolInfoDouble() recupera il passo di cambiamento della dimensione del lotto per lo strumento selezionato (SYMBOL_VOLUME_STEP). Questo passo determina l'intervallo minimo di cambiamento della dimensione del lotto. Ad esempio, alcuni strumenti hanno un passo di 0,01, il che significa che le transazioni possono essere effettuate solo in multipli di centesimi di lotto.

Fase 2: Controllo della positività del passo:

if(stepvol > 0.0)

Controlla se il passo di cambiamento è effettivamente positivo. Se è negativo o nullo, i calcoli successivi sarebbero inutili.

Fase 3: Riduzione della dimensione del lotto di un passo:

lt = stepvol * (MathFloor(iLots / stepvol) - 1);

L'algoritmo riduce la dimensione del lotto inserita dall'utente (iLots) di un intero passo.

Internamente:

iLots / stepvol: calcola il numero completo di passi contenuti nel lotto inserito.

MathFloor(): arrotonda verso il basso il valore frazionario fino all'intero più vicino.

Sottrazione di una unità: diminuisce il numero di passi di una unità.

Prodotto per il passo: ottiene la nuova dimensione del lotto corretta.

Fase 4: Recupero della dimensione minima del lotto:

double minvol = SymbolInfoDouble(sy, SYMBOL_VOLUME_MIN);

La funzione SymbolInfoDouble() recupera la dimensione minima consentita del lotto per lo strumento selezionato (SYMBOL_VOLUME_MIN). La borsa potrebbe imporre limiti inferiori sulla dimensione del lotto, impedendo transazioni sotto quel valore.

Fase 5: Controllo della dimensione minima:

if(lt < minvol)

lt = 0.0;

Se la dimensione del lotto corretta è inferiore al valore minimo consentito dalla borsa, la dimensione del lotto viene azzerata per evitare violazioni.

Fase 6: Generazione del numero iniziale per il generatore casuale:

::MathSrand(GetTickCount());

Genera un numero iniziale per il generatore di numeri casuali utilizzando il conteggio dei ticks fornito da GetTickCount(). Questo migliora la qualità dei numeri casuali generati.

   int total = ::PositionsTotal(), b = 0, s = 0; // Numero totale di posizioni aperte e contatori di acquisto/vendita

   double Bid = ::SymbolInfoDouble(sy, SYMBOL_BID); // Prezzo di vendita attuale (prezzo BID)
   double Ask = ::SymbolInfoDouble(sy, SYMBOL_ASK); // Prezzo di acquisto attuale (prezzo ASK)

   double new_sl = 0, new_tp = 0, old_sl = 0, old_tp = 0; // Nuovi e vecchi livelli di stop-loss e take-profit

   if(Bid <= 0 || Ask <= 0) // Se i prezzi sono errati
      return; // Uscita anticipata dalla funzione

Questo blocco di codice effettua diverse operazioni preparatorie prima di procedere con la logica supplementare di trading nell'Expert Advisor (EA) sulla piattaforma MetaTrader. Ecco un'analisi dettagliata di ogni azione:

Fase 1: Conteggio delle posizioni aperte:

int total = ::PositionsTotal();

Recupera il numero totale di posizioni aperte sul conto, indipendentemente dalla direzione e dallo strumento. Queste informazioni sono importanti per una futura analisi e eventuale ottimizzazione delle posizioni.

Fase 2: Inizializzazione dei contatori di acquisto e vendita:

b = 0, s = 0;

Le variabili b e s vengono inizializzate come contatori di acquisto e vendita rispettivamente. Entrambe iniziano a zero ma aumentano durante l'analisi delle posizioni.

Fase 3: Recupero dei prezzi attuali del mercato:

Prezzo di vendita (BID):

double Bid = ::SymbolInfoDouble(sy, SYMBOL_BID);

Richiede il prezzo di vendita attuale (BID) per lo strumento corrente (sy). Il prezzo BID riflette il miglior prezzo di mercato al quale un trader può vendere immediatamente lo strumento.

Prezzo di acquisto (ASK):

double Ask = ::SymbolInfoDouble(sy, SYMBOL_ASK);

Analogamente, richiede il prezzo di acquisto attuale (ASK) per lo stesso strumento. Il prezzo ASK mostra il miglior prezzo al quale è possibile acquistare lo strumento immediatamente.

Fase 4: Decisione dei livelli di stop-loss e take-profit:

double new_sl = 0, new_tp = 0, old_sl = 0, old_tp = 0;

Prepara le variabili per i livelli di stop-loss (nuovo e precedente) e take-profit (nuovo e precedente). Zero indica l'assenza di livelli per ora.

Fase 5: Sicurezza e validità dei prezzi:

if(Bid <= 0 || Ask <= 0)

return;

Effettua una semplice verifica della validità dei prezzi. Se il prezzo BID o ASK è uguale a zero o negativo, la funzione esce precocemente per evitare operazioni errate.

 for(int i = 0; i < total; i++) // Ciclo attraverso le posizioni aperte
      if(posit.SelectByIndex(i)) // Selezione della posizione tramite indice
         if(posit.Symbol() == sy) // Verifica dello strumento della posizione
            if(posit.Magic() == iMagicNumber) // Verifica del numero unico della posizione
              {

               old_sl = ::NormalizeDouble(posit.StopLoss(),   dt); // Conversione del vecchio stop-loss alla precisione richiesta
               old_tp = ::NormalizeDouble(posit.TakeProfit(), dt); // Conversione del vecchio take-profit alla precisione richiesta

               if(posit.PositionType() == POSITION_TYPE_BUY) // Se la posizione è di acquisto (BUY)
                 {
                  new_sl = ::NormalizeDouble(Ask - iStopLoss   * pt, dt); // Nuovo stop-loss sotto il prezzo di acquisto corrente
                  new_tp = ::NormalizeDouble(Ask + iTakeProfit * pt, dt); // Nuovo take-profit sopra il prezzo di acquisto corrente
                  b++;                                                 // Incremento del contatore di acquisto
                 }

               if(posit.PositionType() == POSITION_TYPE_SELL) // Se la posizione è di vendita (SELL)
                 {
                  new_sl = ::NormalizeDouble(Bid + iStopLoss   * pt, dt); // Nuovo stop-loss sopra il prezzo di vendita corrente
                  new_tp = ::NormalizeDouble(Bid - iTakeProfit * pt, dt); // Nuovo take-profit sotto il prezzo di vendita corrente
                  s++; // Incremento del contatore di vendita
                 }

               if(old_sl == 0 || old_tp == 0) // Se i nuovi livelli differiscono dai precedenti
                  trade.PositionModify(posit.Ticket(), new_sl, new_tp);// Modifica della posizione con i nuovi livelli di SL e TP
              }

Questo blocco di codice illustra il processo di revisione delle posizioni aperte sul conto e l'aggiornamento dei livelli di stop-loss (SL) e take-profit (TP) per le posizioni interessate. Analizziamo ogni operazione in dettaglio:

Revisione delle posizioni aperte:

for(int i = 0; i < total; i++)

Esegue un ciclo attraverso tutte le posizioni aperte conservate internamente.

Selezione della posizione:

if(posit.SelectByIndex(i))

Cerca di selezionare una posizione tramite il suo indice nella lista. Solo le posizioni selezionate con successo continuano nel processo.

Conferma dello strumento e del numero magico:

if(posit.Symbol() == sy && posit.Magic() == iMagicNumber)

Verifica che la posizione selezionata corrisponda allo strumento desiderato (sy) e abbia il numero magico corretto. Se entrambi i criteri sono soddisfatti, continuiamo.

Aggiornamento dei livelli di stop-loss e take-profit:

Per le posizioni di acquisto (BUY):

if(posit.PositionType() == POSITION_TYPE_BUY)

Aggiorniamo i livelli SL e TP per le posizioni di acquisto.

Per le posizioni di vendita (SELL):

if(posit.PositionType() == POSITION_TYPE_SELL)

Aggiorniamo i livelli SL e TP per le posizioni di vendita.

Applicazione delle modifiche:

if(old_sl == 0 || old_tp == 0)

trade.PositionModify(posit.Ticket(), new_sl, new_tp);

Modifica i livelli di stop-loss e take-profit se i nuovi livelli differiscono dai precedenti.

   if((b + s) == 0) // Se nessuna posizione attiva è presente
      if(::MathRand() % 2 == 0) // Scelta casuale della direzione di apertura della posizione
        {
         if(trade.CheckVolume(sy, lt, Ask, ORDER_TYPE_BUY)) // Vérification de la disponibilité des fonds pour l'opération de trading
            if(trade.Buy(lt)) // Ouverture d'une position longue (BUY)
               return; // Fin de l'exécution de la fonction
        }
      else
         if(trade.CheckVolume(sy, lt, Bid, ORDER_TYPE_SELL)) // Vérification de la disponibilité des fonds pour l'opération de trading
            if(trade.Sell(lt)) // Ouverture d'une position courte (SELL)
               return; // Fin de l'exécution de la fonction

Questo blocco di codice descrive il processo di apertura casuale sia di una posizione lungo (BUY) sia corto (SELL) quando non ci sono posizioni attive sul conto. Analizziamo ogni fase in dettaglio:

Controllo delle posizioni attive:

if((b + s) == 0)

Verifica se non ci sono posizioni attive sul conto. Se nessuna posizione è trovata, continuiamo con l'apertura di una nuova posizione.

Scelta casuale della direzione:

if(MathRand() % 2 == 0)

Usa la funzione MathRand() modulata per 2 per scegliere casualmente tra l'apertura di una posizione lungo (BUY) o corto (SELL).

Apertura della posizione lungo (BUY):

if(trade.CheckVolume(sy, lt, Ask, ORDER_TYPE_BUY))

Verifica la disponibilità dei fondi necessari per eseguire la transazione richiesta. Se i fondi sono sufficienti, viene aperta una posizione lungo.

Apertura della posizione corto (SELL):

if(trade.CheckVolume(sy, lt, Bid, ORDER_TYPE_SELL))

Procediamo analogamente per l'apertura di una posizione corto. Dopo aver verificato la disponibilità dei fondi, la posizione corto viene aperta se possibile.

Fine dell'esecuzione: