Um Ihr Handelssystem auf EUR/USD, GBP/USD und GOLD (XAU/USD) zu testen und zu optimieren, sollten Sie strategisch vorgehen. Da News-Events im Backtest nicht zuverlässig simuliert werden können, ist ein Demo-Konto mit Live-Tick-Daten essenziell. Hier ist Ihr Schritt-für-Schritt-Plan:
1. MetaTrader Demo-Konto einrichten
- Brokerwahl: Wählen Sie einen Broker mit zuverlässigen News-Daten und niedriger Latenz (z. B. Multibank Group, Vantage, ActivTrades).
- Konto eröffnen:
- Demo-Konto beim Broker registrieren (z. B. MetaTrader 4/5).
- Sicherstellen, dass der Server Live-Tick-Daten (nicht „geschönt“) bietet.
- Instrumente aktivieren: EUR/USD, GBP/USD, XAU/USD handelbar machen.
2. EA installieren & Einstellungen anpassen
- EA hochladen:
- Parameter einstellen:
- Timeframes: Nutzen Sie Multi-Timeframe-Analyse (z. B. H1 für Trend, M15 für Entry).
- News-Filter: Deaktivieren Sie den EA während High-Impact-News (z. B. NFP, Zinsentscheide) oder nutzen Sie einen Volatilitätsfilter.
- Risikomanagement: Setzen Sie Max Drawdown (z. B. 5% pro Trade) und SL/TP-Regeln.
3. Testphasen
A) Backtest (ohne News)
- Strategietester in MT4/MT5 nutzen.
- Zeitraum: Mind. 5 Jahre Daten (z. B. 2018–2023).
- Modell: „Every tick“ für genaue Ergebnisse (bei Tick-Daten verfügbar).
- Metriken prüfen: Profitfaktor (>1.5), Sharpe Ratio (>1), Drawdown (<20%).
B) Demo-Test (mit News)
- Live-Demo: EA 4–8 Wochen laufen lassen.
- News-Quellen:
- Economic Calendar: Forexfactory.com oder Broker-Tool.
- Volatilität: EA bei roten News-Events pausieren (z. B. 15 Min vor/nach Release).
- Journal führen: Dokumentieren Sie, wie der EA auf News reagiert (z. B. falsche Breakouts bei CPI-Daten).
4. Optimierung & Anpassungen
- Parameter-Scan: Nutzen Sie den MT5 Genetischen Algorithmus für Robustheit.
- Korrektur für News:
- Volatilitätsfilter: z. B. ATR-Wert > 20% des Durchschnitts → kein Trade.
- Timefilter: Handelsfenster außerhalb von Newszeiten (z. B. nur London Session).
- Gold-Spezialisierung: XAU/USD reagiert stark auf USD-News – hier ggf. größere SL/TP.
5. Risikomanagement-Check
- Leverage: Max. 1:30 (Risiko reduzieren).
- Lotgröße: Nicht mehr als 1–2% pro Trade.
- Stop-Loss: Für GOLD mind. 50 Pips (höhere Volatilität!).
Zusammenfassung:
- Backtest gibt erste Hinweise, aber Live-Demo mit News ist entscheidend.
- Gold benötigt spezielle Einstellungen (größere SL, News-Sensitivität).
- Dokumentieren Sie alle Trades, um Schwächen bei News-Events zu identifizieren.
Metatrader5 Expert Code zum Testen auf den EUR/GBP/GOLD
//+------------------------------------------------------------------+
//| PROFESSIONAL SWING TRADING EA - FINAL EDITION |
//| © 2025, MultiBank.Cash |
//+------------------------------------------------------------------+
#property strict
#property copyright "Copyright 2025, MultiBank.Cash"
#property link "https://www.multibank.cash"
#property version "5.0"
//--- Input-Parameter
input group "========== Risikomanagement =========="
input double RiskPerTrade = 0.5; // Risiko in % pro Trade (0.1-5.0)
input double ATR_Multiplier = 2.0; // ATR-Stop-Multiplikator (1.0-3.0)
input double Fib_TP_Ratio = 1.68; // Take-Profit Faktor (1.5-3.0)
input double MinLotSize = 0.1; // Minimale Lot-Größe
input double MaxLotSize = 3.0; // Maximale Lot-Größe
input group "========== Trailing-Stop =========="
input bool UseTrailingStop = true; // Trailing-Stop aktivieren
input double TrailATRMultiple = 0.3; // ATR-Multiplikator für Trail
input int TrailStep = 15; // Mindestabstand in Punkten
input int TrailStart = 100; // Start nach X Punkten Profit
input group "========== Handelsstrategie =========="
input int ATR_Period = 24; // ATR-Zeitraum (Stunden)
input int SwingPeriod = 20; // Swing-Periode (Tage)
input int MAPeriod = 140; // MA-Periode für Trendfilter
input ENUM_MA_METHOD MAMethod = MODE_EMA; // MA-Typ
input group "========== Multi-Timeframe =========="
input bool UseMTFConfirmation = true; // Multi-Timeframe-Bestätigung
input ENUM_TIMEFRAMES HigherTF = PERIOD_D1; // Höherer Zeitrahmen
input group "========== News-Filter =========="
input bool UseNewsFilter = true; // News-Filter aktivieren
input int PreNewsMinutes = 60; // Minuten vor News nicht handeln
input int PostNewsMinutes = 120; // Minuten nach News nicht handeln
input int MinImpactLevel = 2; // 1=Low, 2=Medium, 3=High
input group "========== Zeitfilter =========="
input int TradeStartHour = 9; // Handelsbeginn (Stunde)
input int TradeEndHour = 17; // Handelsende (Stunde)
input bool SkipWeekend = true; // Wochenende überspringen?
input group "========== Erweiterte Einstellungen =========="
input int MagicNumber = 202350; // Eindeutige EA-ID
input int MaxTrades = 1; // Maximale offene Trades
input int Slippage = 10; // Maximaler Slippage (Punkte)
//--- Globale Variablen
double atr, ema200, higherTF_ema200;
datetime lastTradeTime, nextNewsTime;
int newsImpactLevel;
int handle_ATR, handle_MA, handle_HigherMA;
//+------------------------------------------------------------------+
//| Expert Initialisierungsfunktion |
//+------------------------------------------------------------------+
int OnInit()
{
//--- Indikator-Handles erstellen
handle_ATR = iATR(_Symbol, PERIOD_D1, ATR_Period);
handle_MA = iMA(_Symbol, PERIOD_D1, MAPeriod, 0, MAMethod, PRICE_CLOSE);
handle_HigherMA = iMA(_Symbol, HigherTF, MAPeriod, 0, MAMethod, PRICE_CLOSE);
//--- Überprüfen ob Handles erstellt wurden
if(handle_ATR == INVALID_HANDLE || handle_MA == INVALID_HANDLE || handle_HigherMA == INVALID_HANDLE)
{
Print("Fehler beim Erstellen der Indikator-Handles!");
return(INIT_FAILED);
}
//--- News-Daten initialisieren
if(UseNewsFilter) LoadEconomicCalendar();
Print("EA erfolgreich initialisiert - Professional Swing Trading System");
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert Deinitialisierungsfunktion |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- Indikator-Handles freigeben
if(handle_ATR != INVALID_HANDLE) IndicatorRelease(handle_ATR);
if(handle_MA != INVALID_HANDLE) IndicatorRelease(handle_MA);
if(handle_HigherMA != INVALID_HANDLE) IndicatorRelease(handle_HigherMA);
Print("EA beendet");
}
//+------------------------------------------------------------------+
//| Expert Tick-Funktion |
//+------------------------------------------------------------------+
void OnTick()
{
//--- Handelsbedingungen prüfen
if(!IsTradingAllowed()) return;
//--- Trailing-Stops verwalten
if(UseTrailingStop) ManageTrailingStops();
//--- Indikatoren aktualisieren
UpdateIndicators();
//--- Maximale Trades prüfen
if(CountOpenTrades() >= MaxTrades) return;
//--- Swing-Punkte identifizieren
double swingHigh = iHigh(_Symbol, PERIOD_D1, iHighest(_Symbol, PERIOD_D1, MODE_HIGH, SwingPeriod, 1));
double swingLow = iLow(_Symbol, PERIOD_D1, iLowest(_Symbol, PERIOD_D1, MODE_LOW, SwingPeriod, 1));
double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
//--- Trendbestimmung mit Multi-Timeframe
bool trendConfirmed = true;
if(UseMTFConfirmation)
trendConfirmed = (currentPrice > ema200 && iClose(_Symbol, HigherTF, 1) > higherTF_ema200) ||
(currentPrice < ema200 && iClose(_Symbol, HigherTF, 1) < higherTF_ema200);
bool uptrend = currentPrice > ema200 && trendConfirmed;
bool downtrend = currentPrice < ema200 && trendConfirmed;
//--- Handelslogik mit allen Filtern
if(currentPrice >= swingHigh && uptrend && IsBuyTime() && !IsNewsSensitivePeriod())
{
PlaceOrder(ORDER_TYPE_BUY);
}
else if(currentPrice <= swingLow && downtrend && IsSellTime() && !IsNewsSensitivePeriod())
{
PlaceOrder(ORDER_TYPE_SELL);
}
}
//+------------------------------------------------------------------+
//| Indikatoren aktualisieren |
//+------------------------------------------------------------------+
void UpdateIndicators()
{
double atrArray[], maArray[], higherMaArray[];
//--- ATR-Wert holen
CopyBuffer(handle_ATR, 0, 0, 1, atrArray);
atr = atrArray[0];
//--- MA-Werte holen
CopyBuffer(handle_MA, 0, 0, 1, maArray);
ema200 = maArray[0];
//--- Higher Timeframe MA
CopyBuffer(handle_HigherMA, 0, 0, 1, higherMaArray);
higherTF_ema200 = higherMaArray[0];
}
//+------------------------------------------------------------------+
//| Trailing-Stops verwalten |
//+------------------------------------------------------------------+
void ManageTrailingStops()
{
for(int i = PositionsTotal()-1; i >= 0; i--)
{
if(PositionGetSymbol(i) == _Symbol && PositionGetInteger(POSITION_MAGIC) == MagicNumber)
{
ulong ticket = PositionGetInteger(POSITION_TICKET);
double currentPrice = PositionGetDouble(POSITION_PRICE_CURRENT);
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
double sl = PositionGetDouble(POSITION_SL);
double trailDistance = atr * TrailATRMultiple;
int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
{
double newSl = currentPrice - trailDistance;
newSl = NormalizeDouble(newSl, digits);
// Nur bewegen wenn:
// 1. Neuer SL besser als alter
// 2. Mindestabstand erreicht
// 3. TrailStep eingehalten
if(newSl > sl &&
currentPrice - openPrice >= TrailStart * _Point &&
(sl == 0 || newSl - sl >= TrailStep * _Point))
{
ModifyPosition(ticket, newSl, PositionGetDouble(POSITION_TP));
}
}
else if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
{
double newSl = currentPrice + trailDistance;
newSl = NormalizeDouble(newSl, digits);
if((sl == 0 || newSl < sl) &&
openPrice - currentPrice >= TrailStart * _Point &&
(sl == 0 || sl - newSl >= TrailStep * _Point))
{
ModifyPosition(ticket, newSl, PositionGetDouble(POSITION_TP));
}
}
}
}
}
//+------------------------------------------------------------------+
//| Position modifizieren |
//+------------------------------------------------------------------+
bool ModifyPosition(ulong ticket, double sl, double tp)
{
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_SLTP;
request.position = ticket;
request.symbol = _Symbol;
request.sl = sl;
request.tp = tp;
request.magic = MagicNumber;
if(!OrderSend(request, result))
{
Print("Modify Position failed! Error: ", GetLastError());
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| News-Filter Funktionen |
//+------------------------------------------------------------------+
void LoadEconomicCalendar()
{
// Hier würde normalerweise eine Verbindung zu einem News-Feed stehen
// Diese Funktion simuliert nur die News-Zeiten
nextNewsTime = TimeCurrent() + 3600 * (MathRand() % 6 + 2); // Zufällige News in 2-8 Stunden
newsImpactLevel = MathRand() % 3 + 1; // Zufälliger Impact Level 1-3
}
bool IsNewsSensitivePeriod()
{
if(!UseNewsFilter) return false;
datetime now = TimeCurrent();
datetime newsStart = nextNewsTime - PreNewsMinutes * 60;
datetime newsEnd = nextNewsTime + PostNewsMinutes * 60;
return (now >= newsStart && now <= newsEnd && newsImpactLevel >= MinImpactLevel);
}
//+------------------------------------------------------------------+
//| Handelszeit prüfen |
//+------------------------------------------------------------------+
bool IsTradingAllowed()
{
MqlDateTime timeStruct;
TimeCurrent(timeStruct);
//--- Wochenende überspringen
if(SkipWeekend && (timeStruct.day_of_week == 0 || timeStruct.day_of_week == 6))
return false;
//--- Handelszeiten prüfen
if(timeStruct.hour < TradeStartHour || timeStruct.hour >= TradeEndHour)
return false;
return true;
}
//+------------------------------------------------------------------+
//| Beste Handelszeit für Kaufen |
//+------------------------------------------------------------------+
bool IsBuyTime()
{
// Hier können zusätzliche Filter für Kauf-Timing eingefügt werden
return true;
}
//+------------------------------------------------------------------+
//| Beste Handelszeit für Verkaufen |
//+------------------------------------------------------------------+
bool IsSellTime()
{
// Hier können zusätzliche Filter für Verkaufs-Timing eingefügt werden
return true;
}
//+------------------------------------------------------------------+
//| Dynamische Lot-Berechnung |
//+------------------------------------------------------------------+
double CalculateLotSize(double slDistance)
{
double accountBalance = AccountInfoDouble(ACCOUNT_EQUITY);
double riskAmount = accountBalance * (RiskPerTrade / 100);
double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
if(tickValue == 0 || slDistance == 0)
{
Print("Fehler bei Lot-Berechnung! TickValue: ", tickValue, " SL-Distance: ", slDistance);
return MinLotSize;
}
double lotSize = (riskAmount / (slDistance * tickValue));
lotSize = NormalizeDouble(lotSize, 2);
//--- Lot-Größe begrenzen
lotSize = MathMax(MinLotSize, MathMin(lotSize, MaxLotSize));
return lotSize;
}
//+------------------------------------------------------------------+
//| Trade ausführen |
//+------------------------------------------------------------------+
void PlaceOrder(ENUM_ORDER_TYPE orderType)
{
double price = (orderType == ORDER_TYPE_BUY) ? SymbolInfoDouble(_Symbol, SYMBOL_ASK)
: SymbolInfoDouble(_Symbol, SYMBOL_BID);
//--- Stop-Loss berechnen
double slDistance = atr * ATR_Multiplier;
double tpDistance = slDistance * Fib_TP_Ratio;
//--- Dynamische Lot-Größe
double lotSize = CalculateLotSize(slDistance);
//--- Order platzieren
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = lotSize;
request.type = orderType;
request.price = price;
request.sl = (orderType == ORDER_TYPE_BUY) ? price - slDistance : price + slDistance;
request.tp = (orderType == ORDER_TYPE_BUY) ? price + tpDistance : price - tpDistance;
request.deviation = Slippage;
request.magic = MagicNumber;
request.comment = StringFormat("SwingTrade | Risk: %.1f%% | ATR: %.1f", RiskPerTrade, atr);
if(!OrderSend(request, result))
{
Print("Order fehlgeschlagen! Fehler: ", GetLastError(),
" | Retcode: ", result.retcode,
" | Preis: ", price,
" | Lots: ", lotSize);
}
else
{
lastTradeTime = TimeCurrent();
Print("Trade ausgeführt: ", EnumToString(orderType),
" | Lots: ", lotSize,
" | Preis: ", price,
" | SL: ", request.sl,
" | TP: ", request.tp,
" | Ticket: ", result.deal);
}
}
//+------------------------------------------------------------------+
//| Offene Trades zählen |
//+------------------------------------------------------------------+
int CountOpenTrades()
{
int count = 0;
for(int i = 0; i < PositionsTotal(); i++)
{
if(PositionGetSymbol(i) == _Symbol && PositionGetInteger(POSITION_MAGIC) == MagicNumber)
count++;
}
return count;
}
