Algorithmischer Handel ohne Routine: Schnelle Handelsanalyse im MetaTrader 5 mit SQLite
Das Feedback-Problem im algorithmischen Handel
Algorithmischer Handel erfordert nicht nur die Entwicklung wettbewerbsfähiger Strategien, sondern auch die ständige Überwachung der Ergebnisse. Ohne Feedback kann ein Handelssystem unkontrollierbar werden. Solange Sie nicht sehen, wie sich eine Strategie in Echtzeit verhält, verwalten Sie kein System, sondern nur eine Reihe von Vermutungen.
Auf den modernen Aktien- und Devisenmärkten hat die Zahl der Trades exponentiell zugenommen. Daten sind schneller veraltet, als man Schlussfolgerungen ziehen kann. Und wenn die Daten veraltet sind, werden auch die darauf basierenden Schlussfolgerungen veraltet. Hinzu kommt, dass sich wiederholende manuelle Routinetätigkeiten unweigerlich zu Verzögerungen und Fehlern führen. Sie treten einfach auf, weil eine Person müde, abgelenkt oder in Eile ist.
Hier zeigt MetaTrader 5 seine besondere Stärke. Die integrierte Unterstützung für SQLite (eine lokale Datenbank) ist ein entscheidender Vorteil. Die Datenbank ist nicht länger nur ein externer Speicher, sondern ein integraler Bestandteil des Handelsprozesses. Die Abfragen werden fast sofort ausgeführt, die Statistiken werden automatisch aktualisiert, und die Handelsanalyse dauert nur Sekunden statt Stunden. Und die Analyseergebnisse stehen genau dort zur Verfügung, wo sie gebraucht werden – parallel zum Handelsprozess und nicht irgendwo außerhalb des Terminals.
Der Artikel untersucht das „Mindestmaß an Arbeitsmitteln“ eines algorithmischen Händlers: die Struktur einer Datenbank für das Handelsjournal, eine sichere und schnelle Datenaufzeichnung, analytische SQL-Abfragen und die Anzeige der wichtigsten Statistiken auf einem interaktiven Dashboard in MetaTrader 5. Dadurch entfällt ein Großteil der Routinearbeit und der Händler kann sich auf die kreative Seite konzentrieren: die Analyse und Verbesserung des Handelssystems.
Warum braucht ein algorithmischer Händler eine lokale Datenbank?
Bei der Entwicklung und Erprobung von Handelsstrategien fallen riesige Datenmengen an. Optimierungsergebnisse, Handelsverläufe, Indikatorsignale, makroökonomische Ereignisse – all das muss nicht nur gespeichert, sondern auch strukturiert und schnell zugänglich gemacht werden. Eine lokale Datenbank löst diese Probleme, mit denen jeder ernsthafte algorithmische Händler konfrontiert ist.
Speichern von Test- und OptimierungsergebnissenDie Optimierung einer Strategie durch Aufzählung von Parametern erzeugt Hunderte, wenn nicht Tausende von Parametervariationen. Jeder Durchgang besteht aus einer Reihe von Metriken, Parameterwerten und Ergebnissen. Wie können wir sie miteinander vergleichen? Wie lässt sich die Entwicklung einer Strategie im Laufe der Zeit verfolgen? Die Datenbank ermöglicht es, eine vollständige Historie der Optimierungen zu speichern und in jedem Kontext zu analysieren – von einfachen Tabellen bis hin zu komplexen Korrelationen.
Automatisches HandelsjournalAnstatt routinemäßig ein Protokoll in einer Tabellenkalkulation zu führen, führen Sie einen EA im Terminal aus und erhalten eine automatische Protokollierung jedes Handels mit einem vollständigen Satz von Attributen: Symbol, Magic Number, Volumen, Preis, Zeit, Ergebnis und Kommentar. Die Daten werden in Echtzeit in die Datenbank erfasst und stehen sofort für die Analyse zur Verfügung – ohne zusätzliche Maßnahmen seitens des Händlers.
Analyse der HandelssignaleDas Speichern und Analysieren von Handelssignalen eröffnet Möglichkeiten, die bei der Arbeit mit normalen Protokollen nicht verfügbar sind. Wie wirksam sind die Signale? Welche Indikatoren korrelieren miteinander? Unter welchen Bedingungen sind Ein- und Ausstiege optimal? Alle Händler wollen die Antworten auf diese Fragen wissen. SQL-Abfragen bieten ein leistungsstarkes Analysewerkzeug, ohne dass zusätzlicher Code geschrieben werden muss.
Für die ersten Schritte mit SQLite benötigen wir nur drei Funktionen:
- DatabaseOpen – öffnet die Datenbank
- DatabaseExecute – Führt eine Abfrage an die Datenbank aus
- DatabaseClose – schließt die Datenbank
Dies reicht aus, um 90 % der Probleme eines algorithmischen Händlers zu lösen.
Beispiel für das Öffnen und Schließen einer Datenbank:
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
Entscheidend ist: SQLite ist sozusagen „out of the box“ in das System des MetaTrader 5 integriert und arbeitet direkt mit dem Terminal-Kern. Excel und andere Tabellenkalkulationen sind externe Programme, auf die ein MQL5 EA entweder über veraltete Methoden wie OLE-Automatisierung oder über eine externe CSV-Datei zugreift. Der Unterschied zu Gunsten von SQLite im MetaTrader 5 ist kolossal – in Bezug auf Geschwindigkeit, Komfort und Zuverlässigkeit.
Layout der Tabelle: Architektur des Handelsjournals
Das Datenbankdesign beginnt mit der Frage: Was genau soll gespeichert werden? Für ein Handelsjournal liegt die Antwort auf der Hand: Handelshistorie, Signale und Ereignisse. Aber warum genau drei Tabellen und nicht eine einzige „große und universelle“? Die Unterteilung in DEALS, SIGNALS und EVENTS ist keine Laune, sondern eine Notwendigkeit. Jede Entität wird separat gespeichert und mit den anderen verknüpft, wenn sie in einer Abfrage benötigt wird. Möchten Sie „alle Trades, die nach einem Signal mit einem Konfidenzniveau von über 80% getätigt wurden“ sehen? SQLite erledigt dies einfach und elegant, ohne dass Sie das Handelsterminal verlassen müssen.
Die Tabelle DEALS – HandelshistorieDie Tabelle enthält vollständige Informationen zu jedem Trade: ID, Tickets, Symbol, „magische“ Zahl (Strategie-ID), Volumen, Eröffnungs- und Schlusskurs, Uhrzeit, Finanzergebnis und optionaler Kommentar. Dies ist das „Skelett“ eines Handelsjournals – die Grundlage für jede Analyse.
Die Tabelle SIGNALS – SignalverlaufDie Tabelle speichert Signale von Indikatoren und Handelssystemen: Symbol, Zeitrahmen, Signaltyp (Kauf/Verkauf), Preis, Zeitpunkt des Auftretens und zusätzliche Parameter. Es ermöglicht auch die Analyse der Qualität der Signale und ihrer Korrelation mit realen Trades – der Schlüssel zum Verständnis, ob Ihre Strategie funktioniert.
Die Tabelle EVENTS – NachrichtenkontextDie Tabelle enthält Informationen zu wichtigen wirtschaftlichen Ereignissen: Name, Währung, Wichtigkeitsgrad, Prognose, tatsächlicher Wert und Veröffentlichungszeitpunkt. Sie ermöglicht es, Zusammenhänge zwischen den Handelsergebnissen und dem Nachrichtenhintergrund herzustellen – schließlich existiert der Markt nicht in einem Vakuum.
Die folgende Abbildung zeigt ein ER-Diagramm (Entity-Relationship Diagram) – eine visuelle Darstellung der Datenbankstruktur und der Beziehungen zwischen den Tabellen:

Abb. 1: ER-Diagramm der Trades aus dem Handelsjournal
Code für die Tabellenerstellung:
// 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]); }
Achten Sie auf die Indizes: idx_deals_symbol, idx_deals_magic, idx_deals_time, idx_signals_symbol und idx_signals_time. Sie beschleunigen die Abfrage von Schlüsselfeldern: Symbol, Magic, Zeit in der Tabelle DEALS und Symbol, Zeit in SIGNALS. Indizes sind eine Investition in Leistung, die sich bei jeder analytischen Abfrage auszahlt.
Dateneingabe und Transaktionen: Geschwindigkeit ist entscheidend
MQL5 bietet zwei Möglichkeiten, Daten in Tabellen einzufügen: die direkte Ausführung einer SQL-Abfrage und die Verwendung vorbereiteter Anweisungen. Welches soll man wählen? Die Antwort liegt auf der Hand: Vorbereitete Anweisungen sind sowohl aus Sicherheits- als auch aus Leistungssicht vorzuziehen.
Direktes Einfügen über 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);
Parametrisierte Abfrage über 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);
Die Verwendung von Transaktionen ist keine Option, sondern eine Notwendigkeit. Bei umfangreichen Einfüge- und Aktualisierungsvorgängen beschleunigen Transaktionen die Leistung um das Hundert- oder sogar Tausendfache. Warum? Ohne eine Transaktion wird jeder Vorgang einzeln auf die Festplatte übertragen. Bei einer Transaktion werden alle Vorgänge in einem Block zusammengefasst und aufgezeichnet.
Unsere Testergebnisse sind beeindruckend: Die Leistung von SQLite in MQL5 ist vergleichbar mit nativem C++-Code (LLVM 9.0). In den meisten Tests beträgt der Unterschied weniger als 5 %, und in einigen Szenarien übertrifft MQL5 sogar C++. Das folgende Diagramm vergleicht die Einfügezeit von 1000 Datensätzen ohne Transaktionen mit der von 25.000 Datensätzen mit Transaktionen – ein Unterschied von über 3500 Mal pro Datensatz!

Abb. 2: Vergleich der Einfügegeschwindigkeit: ohne/mit Transaktionen
Beispiel für die Verwendung einer Transaktion für die Masseneinfügung:
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);
Alle Tests können im Bereich des MQL5-Forums studiert (und ausprobiert!) werden: SQLite in MQL5: neue Funktionen und Leistungstests.
SQL-Abfragen: Analytik ohne Programmierung
Einer der Hauptvorteile von SQL ist die Möglichkeit, mit einer einzigen Abfrage komplexe Analysen zu erstellen. Im MetaTrader 5 ist diese Funktion direkt zugänglich. Keine Zyklen, keine Bedingungen, keine Zeitvariablen. Eine Abfrage ist ausreichend. Schauen wir uns einige typische Szenarien an.
Statistiken über HandelssymboleWelche Instrumente sind gewinnbringend und welche „fressen“ Ihr Kapital leise auf? Diese Frage und die dazugehörige SQL-Abfrage sollten bei jedem Händler an erster Stelle stehen. Für jedes Symbol werden zusammenfassende Informationen angezeigt: Anzahl der Trades, Gesamtgewinn und durchschnittliches Ergebnis.
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);
Parsen der Abfrageelemente:
| Abfrageelement | Beschreibung |
|---|---|
| SELECT symbol | Wählt die Spalte mit einem Symbolnamen aus |
| COUNT(*) | Zählen Sie die Anzahl der Trades eines Symbols |
| SUM(profit) | Summieren des Gewinns für alle Trades des Symbols |
| GROUP BY symbol | Ergebnisse nach Symbol gruppieren |
| ORDER BY total_profit DESC | Sortieren nach dem Gesamtgewinn, absteigend |
Analyse nach Strategien (Magic Number)
Die Magic Number ist eine eindeutige EA-ID, die zu jedem Trade hinzugefügt wird. Wenn mehrere Strategien auf ein Konto angewendet werden, zeigt diese Abfrage, welche davon effizienter ist. Die Besonderheit ist die Verwendung eines bedingten CASE-Ausdrucks zur Berechnung der Gewinn-Trades.
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);
Parsen der Abfrageelemente:
| Abfrageelement | Beschreibung |
|---|---|
| SELECT magic | Wählen Sie die Spalte mit der Magic Number |
| COUNT(*) | Gesamtzahl der Trades für die ausgewählte Strategie |
| CASE WHEN profit > 0 | Bedingung: wenn der Gewinn positiv ist |
| THEN 1 ELSE 0 END | 1 für Trades mit Gewinn und 0 für die mit Verlust |
| SUM(wins) | Addieren Sie die Einheiten, um die Anzahl der gewinnbringenden Trades (wins) zu erhalten. |
Wenn man die Anzahl der Trades mit Gewinn (wins) durch die Gesamtzahl der Trades teilt, erhält man den Prozentsatz der gewinnbringenden Trades – eine wichtige Kennzahl für die Bewertung der Qualität der Strategie. Haben Sie einen hohen Prozentsatz mit einem negativen Gesamtgewinn erhalten? Dies ist ein Anzeichen für ein Risikomanagementproblem – die Trades mit Verlust sind größer als die mit Gewinn.
Verteilung des Handels nach Stunden
Wann ist die Strategie am besten geeignet? Während europäischen Handelszeiten? Oder der Amerikanischen? Oder vielleicht während der „ruhigen Stunden“? Die Funktion strftime extrahiert die Stunde aus der Eröffnungszeit des Trades (Format 00--23) und ermöglicht es uns, die profitabelsten und die am wenigsten profitablen Zeitintervalle zu ermitteln.
string sql = "SELECT strftime('%H', time, 'unixepoch') as hour, " "COUNT(*) as trades, SUM(profit) as profit " "FROM DEALS GROUP BY hour"; DatabasePrint(db, sql);
Wichtig: In MQL5 und SQLite wird die Zeit als Unix-Zeitstempel (Sekunden seit 1970-01-01) gespeichert. Daher wurde der Modifikator „unixepoch“ hinzugefügt. In ähnlicher Weise können wir die Verteilung nach Wochentag strftime('%w', ...), Monat strftime('%m', ...) oder Kombinationen analysieren.
Parsen der Abfrageelemente:
| Abfrageelement | Beschreibung |
|---|---|
| strftime('%H', ...) | Extrahiert die Stunde aus der Öffnungszeit des Handels (00-23) |
| time | Spalte mit der Öffnungszeit der Trades. |
| GROUP BY hour | Gruppierung nach Stunde der Eröffnung |
Statistik-Dashboard: Visualisierung innerhalb des Terminals
Trockene Zahlen sind gut, aber Klarheit ist besser. Die Datenbank lässt sich problemlos in grafische Dashboards innerhalb des Terminals integrieren, die Daten in verständliche visuelle Informationen umwandeln. Das interaktive Statistik-Dashboard arbeitet in Echtzeit und zeigt genau das, was der Händler braucht.
Das nachstehende Dashboard zeigt das Gesamtergebnis für eine bestimmte Anzahl von Tagen (SUMMARY), das nach Instrumenten aufgeschlüsselte Ergebnis (BY SYMBOL) und die besten Handelsstunden (BEST HOURS). Um Daten in eine Struktur zu lesen, verwenden Sie die Funktion DatabaseReadBind:

Abb. 3. Interaktives Statistik-Dashboard im Terminal
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);
Die Funktion DatabaseReadBind ordnet Strukturfelder automatisch den Abfragespalten nach Namen zu. Es reicht aus, eine Struktur mit Feldern zu deklarieren, die den Spaltennamen in der SQL-Abfrage entsprechen.
Verwaltung des DashboardsMit der Schaltfläche [Aktualisieren] wird die Statistik durch eine vollständige Neuberechnung aktualisiert. Die Schaltfläche [Exportieren] gibt die berechneten Daten aus den Datenbanktabellen in CSV-Dateien aus: das gesamte Arbeitsergebnis, die Trades, die Ereignisse und die Signale. Export-Beispiel
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
„Hot-Keys“ für schnelle Steuerung:
- „A“ oder „a“ – Analyse aktualisieren,
- „E“ oder „e“ – Ausgabe der Daten in eine CSV-Datei,
- „R“ oder „r“ – Laden der Handelshistorie,
- „P“ oder „p“ – Anzeige des Dashboards aktivieren/deaktivieren.
Einstellungen des EAs
- Database file name – Name der Datenbankdatei (Standard: „TradingJournal.db“),
- Auto-import trade history – automatisches Laden der Historie (Standard: true),
- History depth in days – Tiefe der Historie (Standard: 30 Tage),
- Export path – Pfad zu den CSV-Dateien (Standard: „MQL5/Files“),
- Export to CSV format – Export im CSV-Format (Standard: true),
- Show statistics dashboard on chart – Dashboard-Anzeige (Standard: true).
MetaEditor: ein Datenbankwerkzeug
Der MetaEditor, der in MetaTrader 5 enthalten ist, verfügt über ein integriertes Tool für die Arbeit mit SQLite: Öffnen und Bearbeiten von Tabellen, Ausführen von SQL-Abfragen und Zurücknehmen von Änderungen. Da die SQLite-Datenbank in einer einzigen Datei auf dem Computer des Nutzers gespeichert ist, kann jederzeit über den MetaEditor-Navigator auf sie zugegriffen werden, um die Struktur und den Inhalt der Tabellen zu überprüfen und Debug-Abfragen durchzuführen.
Dies ist besonders praktisch beim Debuggen von MQL5-Anwendungen, die mit einer Datenbank arbeiten. So lässt sich in Echtzeit überprüfen, welche Daten angezeigt werden, und die Logik des EAs entsprechend anpassen.
Schauen wir uns an, wie einfach das geht, indem wir eine Beispieldatenbank verwenden, die von TradingJournalSQLite-EA-Test-EA aus diesem Artikel erstellt wurde. Wir öffnen die Datenbank und die darin enthaltenen Tabellen, führen mehrere SQL-Abfragen aus und schließen sie. Ich kann das alles lange in Worten erklären, aber es ist besser, es einmal zu sehen...
1. Beginnen wir mit dem Einfachsten – wir öffnen die Datenbank und wählen die gewünschte Tabelle aus: 
Abb. 4. Tabelle öffnen/auswählen/schließen
Die Tabelle DEALS wird durch einen Doppelklick mit der linken Maustaste auf ihren Namen ausgewählt. Dies ist gleichbedeutend mit der Ausführung einer SQL-Abfrage im Navigator:
SELECT * FROM 'DEALS';2. Einstellen des Zeitformats:

Abb. 5. Zeitformat
3. Die wichtigste Frage: Wer verdient wie viel? Ermitteln wir die Antwort in Millisekunden:SELECT symbol, COUNT(*) as count, SUM(profit) as total_profit, AVG(profit) as avg_profit FROM DEALS GROUP BY symbol;
Für diejenigen, die keine langen Zeilen mögen:
SELECT symbol, COUNT(*) as count, SUM(profit) as total_profit, AVG(profit) as avg_profit FROM DEALS GROUP BY symbol;

Abb. 6. Wer verdient wie viel?
4. Sortierung nach absteigendem Gewinn: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;

Abb. 7. In absteigender Reihenfolge der Einnahmen
SELECT SUM(CASE WHEN direction IN (1, 2, 3) THEN profit ELSE 0 END) as net_profit FROM DEALS;

Abb. 8. Insgesamt
Möchten Sie eine komplexe Abfrage debuggen? Kein Problem:
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;

Abb. 9. Komplexe SQL-Abfrage
Die SQL-Abfrage wurde ohne Änderungen aus dem TradingJournalSQLite-EA-Test-EA übernommen, der dem Artikel beigefügt ist.
Schlussfolgerung: Ein Handels- und Analysesystem direkt in MetaTrader 5
Das Handelsjournal ist nicht länger eine statische Datei, die exportiert, in einem Drittprogramm geöffnet und manuell in ein geeignetes Format gebracht werden muss. Im MetaTrader 5 ist es Teil des Handels- und Analysesystems geworden – genau, zuverlässig und in Echtzeit auf Veränderungen reagierend. Dies geschieht nativ – SQLite ist in das MetaTrader 5-Terminal auf der Kernebene integriert.
So können wir MetaTrader 5 als eigenständiges Handels- und Analysesystem nutzen und die volle Leistungsfähigkeit von SQL-Abfragen mit der Möglichkeit der Erweiterung und Anpassung an neue Ideen ausschöpfen. Dies bietet den Händlern die folgenden Vorteile:
- Die Daten werden automatisch gespeichert und stehen sofort nach ihrem Erscheinen für die Analyse zur Verfügung;
- Analytische SQL-Abfragen können schnell und flexibel geändert werden, ohne den EA-Code zu verkomplizieren;
- Das Analyse-Dashboard ist direkt im Chart des Terminals verfügbar, in dem der Handel stattfindet;
- Das System kann leicht erweitert werden, um neue Ideen, Metriken und analytische Ansichten aufzunehmen, ohne auf Anwendungen von Drittanbietern zurückgreifen zu müssen.
Deshalb ist die integrierte SQLite-Unterstützung in MetaTrader 5 mehr als nur eine bequeme Datenspeicherlösung. Sie ist eine solide Grundlage für eine vollwertige Handels- und Analyse-Infrastruktur, in der Handel und Analyse in einer einzigen Umgebung mit einer einzigen Sprache und nativer SQL-Unterstützung betrieben werden.
Empfohlene Ressourcen für ein vertieftes Studium von SQLite in MQL5:
- Arbeiten mit Datenbanken
- SQLite in MQL5: Neue Funktionen und Leistungstests
- SQLite: Native Handhabung von SQL-Datenbanken in MQL5
- MQL5 Kochbuch — Datenbank für makroökonomische Ereignisse
- SQLite-Fähigkeiten in MQL5: Beispiel für ein Dashboard mit Handelsstatistiken nach Symbolen und Magic Numbers
Liste der dem Artikel beigefügten Dateien:
| Dateiname | Beschreibung |
|---|---|
| HandelsJournalSQLite-EA.mq5 | Die Datei, die den Code für einen Test-EA enthält, der ein Dashboard mit Handelsstatistiken erstellt |
Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/22009
Warnung: Alle Rechte sind von MetaQuotes Ltd. vorbehalten. Kopieren oder Vervielfältigen untersagt.
Forex-Arbitragehandel: Panel zur Bewertung von Wechselkursbeziehungen
Fraktal-basierter Algorithmus (FBA)
Eine alternative Log-datei mit der Verwendung der HTML und CSS
Winkelanalyse von Preisbewegungen: Ein hybrides Modell zur Prognose von Finanzmärkten
- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.