English Русский Deutsch 日本語
preview
Trading algoritmico senza lavoro di routine: Analisi rapida dei trade in MetaTrader 5 con SQLite

Trading algoritmico senza lavoro di routine: Analisi rapida dei trade in MetaTrader 5 con SQLite

MetaTrader 5Esempi |
10 1
MetaQuotes
MetaQuotes

Il problema del feedback nel trading algoritmico

Il trading algoritmico richiede non solo lo sviluppo di strategie competitive, ma anche un monitoraggio costante dei risultati. Senza feedback, un sistema di trading può diventare incontrollabile. Finché non si osserva il comportamento di una strategia in tempo reale, non si sta gestendo un sistema, ma una serie di ipotesi.

Nei moderni mercati azionari e nel FOREX, la frequenza delle transazioni è aumentata in modo esponenziale. I dati diventano obsoleti più velocemente di quanto si possa trarre delle conclusioni. E man mano che i dati diventano obsoleti, lo diventano anche le conclusioni basate su di essi. Inoltre, le azioni manuali ripetitive e di routine creano inevitabilmente ritardi ed errori. Compaiono semplicemente perché una persona è stanca, distratta o di fretta.

È proprio in questo contesto che MetaTrader 5 si rivela particolarmente prezioso. Il supporto integrato per SQLite (un database locale) cambia radicalmente il modo di lavorare. Il database non è più solo un archivio esterno, ma parte integrante del processo di trading. Le query vengono eseguite quasi istantaneamente, le statistiche vengono aggiornate automaticamente e l'analisi delle operazioni richiede pochi secondi anziché ore. E i risultati dell'analisi sono disponibili esattamente dove servono - a fianco del processo di trading, non in un luogo esterno al terminale.

L'articolo esamina il "set minimo di strumenti necessari" ad un trader algoritmico: la struttura di un database per il registro delle operazioni, la registrazione sicura e veloce dei dati, le query SQL analitiche e la visualizzazione delle statistiche principali su una dashboard interattiva in MetaTrader 5. Questo aiuta a eliminare la maggior parte del lavoro di routine e permette al trader di concentrarsi sul lato creativo: analizzare e migliorare il sistema di trading.


Perché un trader algoritmico ha bisogno di un database locale?

Lo sviluppo e il testing di strategie di trading generano enormi quantità di dati. Risultati di ottimizzazione, storico delle transazioni, segnali degli indicatori, eventi macroeconomici - tutto ciò richiede non solo archiviazione, ma anche strutturazione e accesso rapido. Un database locale risolve questi problemi che ogni trader algoritmico serio si trova ad affrontare.

Salvataggio dei risultati dei test e dell'ottimizzazione

L'ottimizzazione di una strategia tramite l'enumerazione dei parametri genera centinaia, se non migliaia, di varianti di parametri. Ogni passaggio è un insieme di metriche, valori dei parametri e risultati. Come possiamo confrontarli tra loro? Come monitorare l'evoluzione di una strategia nel tempo? Il database consente di memorizzare una cronologia completa delle ottimizzazioni e di analizzarla in qualsiasi contesto - dalle semplici tabelle alle correlazioni complesse.

Registro di trading automatico

Anziché tenere un registro manualmente in un foglio di calcolo, eseguite un Expert Advisor (EA) nel terminale e ottienete la registrazione automatica di ogni operazione con un set completo di proprietà: simbolo, numero magico, volume, prezzo, ora, risultato e commento. I dati vengono inseriti nel database in tempo reale e sono immediatamente disponibili per l'analisi, senza alcuna azione aggiuntiva da parte del trader.

Analisi dei segnali di trading

Salvare e analizzare i segnali di trading apre opportunità non disponibili quando si lavora con i registri tradizionali. Quanto sono efficaci i segnali? Quali indicatori sono correlati tra loro? In quali condizioni i punti di ingresso e di uscita sono ottimali? Tutti i trader vogliono conoscere le risposte a queste domande. Le query SQL offrono un potente strumento di analisi senza la necessità di scrivere codice aggiuntivo.

Per iniziare a usare SQLite, ci servono solo tre funzioni:

  1. DatabaseOpen — apre il database
  2. DatabaseExecute — esegue una query al database
  3. DatabaseClose — chiude il database

Questo è sufficiente a risolvere il 90% dei problemi che un trader algoritmico si trova ad affrontare.

Esempio di apertura e chiusura di un database:

int db = DatabaseOpen("trading.sqlite", DATABASE_OPEN_READWRITE | DATABASE_OPEN_CREATE);
if(db == INVALID_HANDLE)
 {
  Print("Error opening Database: ", GetLastError());
  return;
 }
// ... working with the database ...
DatabaseClose(db);     // close the database

L’aspetto principale: SQLite è integrato nel sistema MetaTrader 5, per così dire, "di serie" e funziona direttamente con il core del terminale. Excel e altri fogli di calcolo sono programmi esterni a cui un Expert Advisor MQL5 accede tramite metodi obsoleti come l'automazione OLE o tramite un file CSV esterno. La differenza a favore di SQLite in MetaTrader 5 è enorme - in termini di velocità, praticità e affidabilità.


Struttura delle tabelle: architettura del registro di trading

La progettazione di un database inizia con la domanda: cosa esattamente deve essere memorizzato? Per un registro di trading, la risposta è ovvia: storico di trading, segnali ed eventi. Ma perché proprio tre tabelle, e non una unica "grande e universale"? La suddivisione in OPERAZIONI (DEALS), SEGNALI (SIGNALS) ed EVENTI (EVENTS) non è un capriccio, ma una necessità. Ciascuna entità viene memorizzata separatamente e collegata alle altre quando necessario durante una query. Vuoi conoscere "tutte le operazioni effettuate dopo un segnale con un livello di confidenza superiore all'80%"? SQLite gestirà tutto questo in modo semplice ed elegante, senza bisogno di uscire dal terminale di trading.

Tabella DEALS - storico di trading

La tabella contiene informazioni complete su ciascun trade: ID, ticket, simbolo, numero "magico" (ID della strategia), volume, prezzi di apertura e chiusura, orario, risultato finanziario e commento facoltativo. Questo è lo "scheletro" di un registro di trading - la base per qualsiasi analisi.

Tabella SIGNALS - cronologia dei segnali

La tabella memorizza i segnali provenienti da indicatori e sistemi di trading: simbolo, timeframe, tipo di segnale (acquisto/vendita), prezzo, ora di occorrenza e parametri aggiuntivi. Consente inoltre di analizzare la qualità dei segnali e la loro correlazione con le operazioni reali - elemento chiave per capire se la propria strategia sta funzionando.

Tabella EVENTS - contesto delle notizie

La tabella contiene informazioni su importanti eventi economici: nome, valuta, livello di importanza, previsione, valore effettivo e data di pubblicazione. Consente di individuare correlazioni tra i risultati di trading e il contesto delle notizie - dopotutto, il mercato non esiste nel vuoto.

La figura seguente mostra un diagramma ER (Entity-Relationship Diagram), ovvero una rappresentazione visiva della struttura del database e delle relazioni tra le tabelle:

Diagramma Entity-Relationship

Fig. 1: Diagramma ER delle tabelle del registro di trade

Codice per la creazione delle tabelle:

   //  Deal history table - DEALS:
   string createDeals = "CREATE TABLE IF NOT EXISTS DEALS ("
                       "id INTEGER PRIMARY KEY AUTOINCREMENT, "
                       "deal_ticket INTEGER UNIQUE, "
                       "order_ticket INTEGER, "
                       "symbol TEXT NOT NULL, "
                       "type INTEGER, "                // 0=BUY, 1=SELL
                       "direction INTEGER, "           // 0=IN, 1=OUT, 2=IN/OUT
                       "volume REAL, "
                       "price_open REAL, "
                       "price_close REAL, "
                       "profit REAL, "
                       "swap REAL, "
                       "commission REAL, "
                       "sl REAL, "
                       "tp REAL, "
                       "magic INTEGER, "
                       "comment TEXT, "
                       "time INTEGER, "                // Unix timestamp
                       "time_msc INTEGER, "
                       "reason INTEGER"
                       ");";
   
   //  Trading signals table - SIGNALS:
   string createSignals = "CREATE TABLE IF NOT EXISTS SIGNALS ("
                         "id INTEGER PRIMARY KEY AUTOINCREMENT, "
                         "symbol TEXT NOT NULL, "
                         "signal_type TEXT, "          // 'BUY', 'SELL', 'CLOSE'
                         "price REAL, "
                         "stop_loss REAL, "
                         "take_profit REAL, "
                         "strength REAL, "             // 0.0 - 1.0
                         "source TEXT, "               // Strategy name
                         "notes TEXT, "
                         "time INTEGER"
                         ");";
   
   //  Events table - EVENTS:
   string createEvents = "CREATE TABLE IF NOT EXISTS EVENTS ("
                        "id INTEGER PRIMARY KEY AUTOINCREMENT, "
                        "event_type TEXT, "            // 'NEWS', 'ERROR', 'NOTE', etc.
                        "symbol TEXT, "
                        "description TEXT, "
                        "importance INTEGER, "         // 1=Low, 2=Medium, 3=High
                        "time INTEGER,"
                        "actual REAL, "
                        "previous REAL, "
                        "forecast REAL "
                        ");";
   
   //  Indices to speed up search queries:
   string createIndexes[] = 
    {
      "CREATE INDEX IF NOT EXISTS idx_deals_symbol ON DEALS(symbol);",
      "CREATE INDEX IF NOT EXISTS idx_deals_magic ON DEALS(magic);",
      "CREATE INDEX IF NOT EXISTS idx_deals_time ON DEALS(time);",
      "CREATE INDEX IF NOT EXISTS idx_signals_symbol ON SIGNALS(symbol);",
      "CREATE INDEX IF NOT EXISTS idx_signals_time ON SIGNALS(time);"
    };
   
   //  Create tables in the database:
   if(!DatabaseExecute(database, createDeals))
    {
      Print("Error creating DEALS table: ", GetLastError());
      return(false);
    }
   
   if(!DatabaseExecute(database, createSignals))
    {
      Print("Error creating SIGNALS table: ", GetLastError());
      return(false);
    }
   
   if(!DatabaseExecute(database, createEvents))
    {
      Print("Error creating EVENTS table: ", GetLastError());
      return(false);
    }
   
   //  Create indices:
   for(int i = 0; i < ArraySize(createIndexes); i++)
    {
      DatabaseExecute(database, createIndexes[i]);
    }

Prestate attenzione agli indici: idx_deals_symbol, idx_deals_magic, idx_deals_time, idx_signals_symbol e idx_signals_time. Velocizzano le query sui campi principali: simbolo, magic, ora nella tabella DEALS e simbolo, ora in SIGNALS. Gli indici rappresentano un investimento in performance che ripaga con ogni query analitica.


Inserimento dati e transazioni: La velocità è importante

MQL5 offre due modi per inserire dati nelle tabelle: eseguendo direttamente una query SQL o utilizzando istruzioni preparate. Quale scegliere? La risposta è chiara: le istruzioni preparate sono preferibili sia dal punto di vista della sicurezza che delle prestazioni.

Inserimento diretto tramite DatabaseExecute :

string sql = StringFormat(
                         "INSERT INTO DEALS (ticket, symbol, magic, volume, price, time, profit) "
                         "VALUES (%d, '%s', %d, %.2f, %.5f, %I64d, %.2f)",
                         ticket, symbol, magic, volume, price, TimeCurrent(), profit);
DatabaseExecute(db, sql);

Query parametrizzata tramite DatabasePrepare :

//  Create a parameterized query:
int request = DatabasePrepare(db,
                             "INSERT INTO DEALS (ticket, symbol, magic, volume, price, time, profit) "
                             "VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)");

//  Set the value of the first query parameter - in the DatabaseBind function, the indexing of fields in the entry starts from zero:
DatabaseBind(request, 0, ticket);
DatabaseTransactionBegin(db);

//  Set the values of the remaining parameters before adding the entry:
DatabaseBind(request, 1, symbol);
DatabaseBind(request, 2, magic);
DatabaseBind(request, 3, volume);
DatabaseBind(request, 4, price);
DatabaseBind(request, 5, TimeCurrent());
DatabaseBind(request, 6, profit);

//  Execute a request for inserting the entry:
DatabaseRead(request);
DatabaseFinalize(request);
DatabaseTransactionCommit(db);

L'utilizzo delle transazioni non è un'opzione, ma una necessità. Per le operazioni di inserimento e aggiornamento in blocco, le transazioni velocizzano le prestazioni di centinaia o addirittura migliaia di volte. Perché? In assenza di una transazione, ogni operazione viene salvata su disco separatamente. Con una transazione, tutte le operazioni vengono raggruppate e registrate in un unico blocco.

I risultati dei nostri test sono impressionanti: Le prestazioni di SQLite in MQL5 sono paragonabili a quelle del codice C++ nativo (LLVM 9.0). Nella maggior parte dei test la differenza è inferiore al 5% e in alcuni scenari MQL5 supera persino le prestazioni di C++. Il diagramma sottostante confronta il tempo di inserimento di 1000 record senza transazioni rispetto a 25.000 record con transazioni - una differenza di oltre 3500 volte per record!

Confronto delle transazioni

Fig. 2: Confronto della velocità di inserimento: senza/con transazioni

Esempio di utilizzo di una transazione per l'inserimento in blocco:

DatabaseTransactionBegin(db);
for(int i = 0; i < ArraySize(deals); i++)
 {
  InsertDeal(db, deals[i]);  // inserting the next trade - an element of the array of deals[] structures
 }
DatabaseTransactionCommit(db);

Tutti i test possono essere studiati (e verificati!) nella sezione del forum dedicata a MQL5:  SQLite in MQL5: nuove funzionalità e test delle prestazioni.


Query SQL: Analisi senza programmazione

Uno dei principali vantaggi di SQL è la possibilità di ottenere analisi complesse con una singola query. In MetaTrader 5 questa funzionalità è direttamente accessibile. Nessun ciclo, nessuna condizione, nessuna variabile di supporto. È sufficiente una sola query. Analizziamo alcuni scenari tipici.

Statistiche sui simboli di trading

Quali strumenti generano profitto e quali, silenziosamente, "erodono" il vostro deposito? Questa domanda, e la relativa query SQL, dovrebbero essere le prime nel bagaglio di conoscenze di ogni trader. Mostra informazioni riassuntive per ogni simbolo: numero di transazioni, profitto totale e risultato medio.

string sql = "SELECT symbol, COUNT(*) as deals, "
             "SUM(profit) as total_profit, "
             "AVG(profit) as avg_profit "
             "FROM DEALS GROUP BY symbol "
             "ORDER BY total_profit DESC";
DatabasePrint(db, sql);

Analisi degli elementi della query:

Elemento di query Descrizione
SELECT symbol Seleziona la colonna con il nome del simbolo
COUNT(*) Conta il numero di trade per un simbolo
SUM(profit) Somma il profitto per tutti i trade dei simboli
GROUP BY symbol Raggruppa i risultati per simbolo
ORDER BY total_profit DESC Ordina per profitto totale in ordine decrescente

Analisi tramite strategie (magic numbers)

Il magic number (numero magico) è un ID EA univoco aggiunto a ogni trade. Se su un singolo account operano diverse strategie, questa query mostrerà quale è la più efficiente. La particolarità sta nell'utilizzo di un'espressione condizionale CASE per calcolare le operazioni profittevoli.

string sql = "SELECT magic, COUNT(*) as trades, "
             "SUM(CASE WHEN profit > 0 THEN 1 ELSE 0 END) as wins, "
             "SUM(profit) as net_profit "
             "FROM DEALS GROUP BY magic";
DatabasePrint(db, sql);

Analisi degli elementi della query:

Elemento di query Descrizione
SELECT magic Seleziona la colonna con il numero magico
COUNT(*) Numero totale di trade per la strategia selezionata
CASE WHEN profit > 0 Condizione: se il profitto è positivo
THEN 1 ELSE 0 END Restituisce 1 per le operazioni profittevoli e 0 per quelle in perdita.
SUM(wins) Somma le unità per ottenere il numero di operazioni profittevoli (vittorie)

Dividendo il numero di operazioni vincenti per il numero totale di operazioni, otteniamo la percentuale di operazioni vincenti - un parametro chiave per valutare la qualità della strategia. Hai ricevuto un'alta percentuale con un profitto totale negativo? Questo è un segnale di un problema di gestione del rischio - le operazioni in perdita sono più consistenti di quelle vincenti.

Distribuzione dei trade per orario

Quando questa strategia funziona meglio? Durante la sessione Europea? O Americana? O magari durante le "ore tranquille"? La funzione strftime estrae l'ora dall'orario di apertura del trade (formato 00-23), consentendoci di identificare gli intervalli di tempo più e meno profittevoli.

string sql = "SELECT strftime('%H', time, 'unixepoch') as hour, "
             "COUNT(*) as trades, SUM(profit) as profit "
             "FROM DEALS GROUP BY hour";
DatabasePrint(db, sql);

Importante: in MQL5 e SQLite, l'ora viene memorizzata come timestamp Unix (secondi trascorsi dal 1° gennaio 1970). Pertanto, è stato aggiunto il modificatore 'unixepoch'. Allo stesso modo, possiamo analizzare la distribuzione per giorno della settimana strftime('%w', ...), mese strftime('%m', ...) o combinazioni.

Analisi degli elementi della query:

Elemento di query Descrizione
strftime('%H', ...) Estrae l'ora dall'orario di apertura del trade (00-23)
time Colonna con l'orario di apertura del trade
GROUP BY hour Raggruppa i trade in base all’ora di apertura


Dashboard delle statistiche: Visualizzazione all'interno del terminale

I numeri, da soli, sono buoni, ma la chiarezza è meglio. Il database si integra facilmente con le dashboard grafiche all'interno del terminale, trasformando i dati in informazioni visive comprensibili. La dashboard interattiva delle statistiche funziona in tempo reale, mostrando esattamente ciò di cui il trader ha bisogno.

La dashboard sottostante mostra il risultato totale per un determinato numero di giorni (SUMMARY), il risultato suddiviso per strumento (BY SYMBOL) e le migliori ore di trading (BEST HOURS). Per leggere i dati in una struttura, utilizzare la funzione DatabaseReadBind:

Pannello Statistico

Fig. 3. Dashboard interattiva delle statistiche nel terminale

struct DealStats
 {
  string symbol;
  int count;
  double total_profit;
  double avg_profit;
 };

int request = DatabasePrepare(db,
                             "SELECT symbol, COUNT(*) as count, SUM(profit) as total_profit, "
                             "AVG(profit) as avg_profit FROM DEALS GROUP BY symbol");
DealStats stats;
while(DatabaseReadBind(request, stats))
 {
  //  Output to the table on the dashboard:
  AddRowToTable(stats);
 }
DatabaseFinalize(request);

La funzione DatabaseReadBind associa automaticamente i campi della struttura alle colonne della query in base al nome. È sufficiente dichiarare una struttura con campi corrispondenti ai nomi delle colonne nella query SQL.

Gestione della Dashboard

Il pulsante [Refresh] aggiorna le statistiche con un ricalcolo completo. Il pulsante [Export] esporta i dati calcolati dalle tabelle del database, in un file CSV: risultato complessivo del lavoro, trade, eventi e segnali. Esempio di esportazione:

(#),symbol,trades,total_profit,avg_profit,wins,losses
1,XAGUSD,196,322.25,1.64,14,181
2,AUDUSD,196,-12.0,-0.06,82,99
3,EURUSD,58,-38.5,-0.66,23,35
4,GBPUSD,57,-43.2,-0.75,17,40

Tasti di scelta rapida per un controllo immediato:

  • 'A' o 'a' — aggiorna le analisi,
  • 'E' o 'e' — invia i dati a un file CSV,
  • 'R' o 'r' — carica la cronologia di trade,
  • 'P' o 'p' — abilita/disabilita la visualizzazione della dashboard.

Impostazioni dell’EA:

  • Database file name — nome del file del database (predefinito: "TradingJournal.db"),
  • Auto-import trade history — caricamento automatico della cronologia (impostazione predefinita: true),
  • History depth in days — quantità in giorni della cronologia (predefinita: 30 giorni),
  • Export path — percorso dei file CSV (predefinito: "MQL5/Files"),
  • Export to CSV format — esporta in formato CSV (impostazione predefinita: true),
  • Show statistics dashboard on chart — visualizzazione della dashboard (impostazione predefinita: true).


MetaEditor: uno strumento per la gestione di database

MetaEditor, incluso in MetaTrader 5, dispone di uno strumento integrato per lavorare con SQLite: consente di aprire e modificare tabelle, eseguire query SQL e annullare le modifiche. Poiché il database SQLite è memorizzato in un singolo file sul computer dell'utente, è possibile accedervi in qualsiasi momento tramite il navigatore MetaEditor - per esaminare la struttura e il contenuto delle tabelle ed eseguire query di debug.

Ciò risulta particolarmente utile durante il debug di applicazioni MQL5 che interagiscono con un database. Provate a visualizzare in tempo reale i dati mostrati e adattate la logica dell'EA di conseguenza.

Vediamo come questo si possa fare facilmente utilizzando un database di esempio creato dall'EA di test TradingJournalSQLite-EA descritto in questo articolo. Apriamo il database e le relative tabelle, eseguiamo alcune query SQL e poi chiudiamolo. Potrei spiegare tutto questo a parole per molto tempo, ma è meglio vederlo una volta...

1. Iniziate dalla cosa più semplice - aprite il database e selezionate la tabella desiderata:

    Apri/Seleziona/Chiudi

    Fig. 4.  Apri/Seleziona tabella/Chiudi

    La tabella DEALS si seleziona facendo doppio clic con il pulsante sinistro del mouse sul suo nome. Questo equivale a eseguire una query SQL nel navigatore:

    SELECT * FROM 'DEALS';
    2. Imposta il formato dell'ora:

      Formato Orario

      Fig. 5. Formato orario

      3. La domanda principale: Chi guadagna e quanto? Scopriamolo in millisecondi:
        SELECT symbol, COUNT(*) as count, SUM(profit) as total_profit, AVG(profit) as avg_profit FROM DEALS GROUP BY symbol;

        Per chi non ama le lunghe righe:

        SELECT symbol,
        COUNT(*) as count,
        SUM(profit) as total_profit,
        AVG(profit) as avg_profit FROM DEALS GROUP BY symbol;
        

        PnL

        Fig. 6. Chi guadagna e quanto?

        4. Ordina per guadagni decrescenti:
          SELECT symbol, COUNT(*) as count, SUM(profit) as total_profit, AVG(profit) as avg_profit FROM DEALS GROUP BY symbol
          ORDER BY total_profit DESC;
          

          PnL ordinato

          Fig. 7. In ordine decrescente di guadagno


          5. Qual è il profitto totale? Scopriamolo:
            SELECT  SUM(CASE WHEN direction IN (1, 2, 3) THEN profit ELSE 0 END) as net_profit FROM DEALS;

            NetPnL

            Fig. 8. Totale

            Desideri eseguire il debug di una query complessa? Nessun problema:

            SELECT   COUNT(*) as total_deals, 
                            SUM(CASE WHEN direction IN (1, 2, 3) THEN 1 ELSE 0 END) as closed_trades, 
                            SUM(CASE WHEN (profit + swap + commission) > 0 AND direction IN (1, 2, 3) THEN 1 ELSE 0 END) as total_wins, 
                            SUM(CASE WHEN (profit + swap + commission) < 0 AND direction IN (1, 2, 3) THEN 1 ELSE 0 END) as total_losses, 
                            ROUND(100.0 * SUM(CASE WHEN (profit + swap + commission) > 0 AND direction IN (1, 2, 3) THEN 1 ELSE 0 END) / 
                            NULLIF(SUM(CASE WHEN direction IN (1, 2, 3) THEN 1 ELSE 0 END), 0), 2) as overall_win_rate, 
                            SUM(CASE WHEN direction IN (1, 2, 3) THEN profit ELSE 0 END) as net_profit, 
                            SUM(CASE WHEN direction IN (1, 2, 3) THEN swap ELSE 0 END) as total_swap,
                            SUM(CASE WHEN direction IN (1, 2, 3) THEN commission ELSE 0 END) as total_commission, 
                            SUM(CASE WHEN direction IN (1, 2, 3) THEN profit + swap + commission ELSE 0 END) as net_result, 
                            ROUND(AVG(CASE WHEN direction IN (1, 2, 3) THEN profit + swap + commission ELSE NULL END), 2) as avg_profit_per_trade, 
                            SUM(CASE WHEN (profit + swap + commission) > 0 AND direction IN (1, 2, 3) THEN (profit + swap + commission) ELSE 0 END) as gross_profit, 
                            SUM(CASE WHEN (profit + swap + commission) < 0 AND direction IN (1, 2, 3) THEN ABS(profit + swap + commission) ELSE 0 END) as gross_loss, 
                            CASE WHEN SUM(CASE WHEN (profit + swap + commission) < 0 AND direction IN (1, 2, 3) THEN ABS(profit + swap + commission) ELSE 0 END) > 0 
                            THEN ROUND(SUM(CASE WHEN (profit + swap + commission) > 0 AND direction IN (1, 2, 3) THEN (profit + swap + commission) ELSE 0 END) / 
                            SUM(CASE WHEN (profit + swap + commission) < 0 AND direction IN (1, 2, 3) THEN ABS(profit + swap + commission) ELSE 0 END), 2) 
                            ELSE 0 END as profit_factor, 
                            COUNT(DISTINCT symbol) as symbols_traded, 
                            COUNT(DISTINCT magic) as strategies_used 
                            FROM DEALS;
            

            Richiesta Complessa

            Fig. 9. Query SQL Complessa

            La query SQL è ripresa senza modifiche dall'EA di test TradingJournalSQLite-EA allegato all'articolo.


            Conclusioni: Un sistema di trading e analisi integrato direttamente in MetaTrader 5.

            Il registro di trading non è più un file statico che deve essere esportato, aperto in un programma di terze parti e convertito manualmente in un formato conveniente. In MetaTrader 5, è diventato parte integrante del sistema di trading e analisi - preciso, affidabile e reattivo ai cambiamenti in tempo reale. Questo avviene in modo nativo - SQLite è integrato nel terminale MetaTrader 5 a livello di core.

            Questo ci permette di utilizzare MetaTrader 5 come sistema di trading e analisi autonomo, sfruttando appieno la potenza delle query SQL e la possibilità di espandere e modificare il sistema in base a nuove esigenze. Ciò offre ai trader i seguenti vantaggi:

              • I dati vengono salvati automaticamente e sono disponibili per l'analisi immediatamente dopo la loro comparsa;
              • Le query SQL analitiche possono essere modificate in modo rapido e flessibile, senza complicare il codice dell'EA;
              • La dashboard di analisi è disponibile direttamente sul grafico nel terminale, dove si svolge l'attività di trading;
              • Il sistema può essere facilmente ampliato per includere nuove idee, metriche e prospettive analitiche senza ricorrere ad applicazioni di terze parti.

              Ecco perché il supporto SQLite integrato in MetaTrader 5 è molto più di una semplice soluzione di archiviazione dati. Rappresenta una solida base per un'infrastruttura di trading e analisi completa, in cui trading e analisi operano in un unico ambiente, utilizzando un unico linguaggio e il supporto SQL nativo.


              Risorse consigliate per uno studio approfondito di SQLite in MQL5:

              Elenco dei file allegati all'articolo:

              Nome del File Descrizione
              TradingJournalSQLite-EA.mq5 Il file contenente il codice per un Expert Advisor (EA) di prova che crea una dashboard con statistiche di trading.

              Tradotto dal russo da MetaQuotes Ltd.
              Articolo originale: https://www.mql5.com/ru/articles/22009

              File allegati |
              Ultimi commenti | Vai alla discussione (1)
              Gerard William G J B M Dinh Sy
              Gerard William G J B M Dinh Sy | 5 mag 2026 a 12:35
              Grazie
              Arriva il Nuovo MetaTrader 5 e MQL5 Arriva il Nuovo MetaTrader 5 e MQL5
              Questa è solo una panoramica di MetaTrader 5. Non posso descrivere tutte le nuove funzionalità del sistema per un periodo di tempo così breve: i test sono iniziati il 09.09.2009. Questa è una data simbolica e sono sicuro che sarà un numero fortunato. Sono passati alcuni giorni da quando ho ricevuto la versione beta del terminale MetaTrader 5 e MQL5. Non sono riuscito a provare tutte le sue funzionalità, ma sono già sorpreso.
              Ottimizzazione del portafoglio nel Forex: Integrazione tra VaR e teoria di Markowitz Ottimizzazione del portafoglio nel Forex: Integrazione tra VaR e teoria di Markowitz
              Come funziona il trading di portafoglio sul Forex? Come si possono sintetizzare la teoria del portafoglio di Markowitz per l'ottimizzazione delle proporzioni del portafoglio e il modello VaR per l'ottimizzazione del rischio di portafoglio? Creiamo un codice in base alla teoria del portafoglio, che da un lato ci consentirà di ottenere un basso rischio e, dall'altro, una redditività accettabile a lungo termine.
              Utilizza i canali MQL5.community e le chat di gruppo Utilizza i canali MQL5.community e le chat di gruppo
              Il sito web MQL5.com riunisce trader di tutto il mondo. Gli utenti pubblicano articoli, condividono codici gratuiti, vendono prodotti nel Market, offrono servizi da freelance e copiano segnali di trading. Puoi comunicare con loro sul Forum, nelle chat dei trader e nei canali MetaTrader.
              Trading algoritmico basato su pattern 3D di inversione Trading algoritmico basato su pattern 3D di inversione
              Alla scoperta di un nuovo mondo sul trading automatizzato con grafici a barre 3D. Come si presenta un robot di trading applicato a barre di prezzo multidimensionali? I cluster "gialli" delle barre 3D sono in grado di prevedere le inversioni di trend? Cosa si intende per trading multidimensionale?