@@ -0,0 +1,515 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| EMACrossOver.mq5 |
|
||||
//| Copyright 2025, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2025, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
#include <Trade\Trade.mqh>
|
||||
//--- Eingabeparameter (Input Parameters)
|
||||
input int EMA_Periode = 26; // EMA Periode
|
||||
input double PreisSchwelle = 2050.0; // Preisbewegung Schwelle in Pips
|
||||
input double SteigungSchwelle = 100.0; // EMA Steigung Schwelle in Pips
|
||||
input int ÜberwachungTimeout = 750; // Überwachungszeit in Sekunden
|
||||
input double TrailingStop = 400.0; // Gleitender Stop in Pips
|
||||
input double LotGröße = 0.1; // Handelsvolumen
|
||||
input int MagicNumber = 12350; // Magic Number für Trades
|
||||
input bool UseSpreadAdjustment = true; // Spread-Anpassung verwenden
|
||||
input ENUM_TIMEFRAMES Timeframe = PERIOD_H1; // Zeitraum für Analyse
|
||||
input bool UseBarData = true; // Bar-Daten statt Tick-Daten verwenden
|
||||
input int MaxTradesPerCrossover = 4; // Maximale Trades pro Crossover-Ereignis
|
||||
input int ProfitCheckBars = 26; // Bars bis zur Profit-Prüfung
|
||||
input bool CloseUnprofitableTrades = true; // Unprofitable Trades nach X Bars schließen
|
||||
|
||||
//--- Globale Variablen (Global Variables)
|
||||
int ema_handle; // EMA Indicator Handle
|
||||
double ema_array[]; // Array für EMA
|
||||
datetime letzte_überwachung_zeit; // Zeit der letzten Überwachung
|
||||
bool überwachung_aktiv = false; // Überwachungsstatus
|
||||
bool preis_trigger_aktiv = false; // Preis-Trigger Status
|
||||
bool steigung_trigger_aktiv = false; // Steigungs-Trigger Status
|
||||
int ticket = 0; // Trade Ticket
|
||||
CTrade trade; // CTrade Objekt
|
||||
int trades_in_current_crossover = 0; // Anzahl Trades im aktuellen Crossover
|
||||
bool crossover_detected = false; // Crossover erkannt
|
||||
datetime trade_open_time = 0; // Zeitpunkt des Trade-Öffnens
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
//--- CTrade konfigurieren (Configure CTrade)
|
||||
trade.SetExpertMagicNumber(MagicNumber);
|
||||
trade.SetDeviationInPoints(10);
|
||||
trade.SetTypeFilling(ORDER_FILLING_IOC);
|
||||
|
||||
//--- EMA Indicator Handle erstellen (Create EMA indicator handle)
|
||||
ema_handle = iMA(_Symbol, Timeframe, EMA_Periode, 0, MODE_EMA, PRICE_CLOSE);
|
||||
|
||||
if(ema_handle == INVALID_HANDLE)
|
||||
{
|
||||
Print("Fehler beim Erstellen des EMA Indicators");
|
||||
return(INIT_FAILED);
|
||||
}
|
||||
|
||||
//--- Arrays initialisieren (Initialize arrays)
|
||||
ArraySetAsSeries(ema_array, true);
|
||||
|
||||
//--- Arrays mit aktuellen Werten füllen (Fill arrays with current values)
|
||||
BerechneEMA();
|
||||
|
||||
Print("EMA EA initialisiert - Periode: ", EMA_Periode, " Timeframe: ", EnumToString(Timeframe), " Handle: ", ema_handle);
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//--- Indicator Handle freigeben (Release indicator handle)
|
||||
if(ema_handle != INVALID_HANDLE)
|
||||
{
|
||||
IndicatorRelease(ema_handle);
|
||||
}
|
||||
|
||||
Print("EA beendet - Grund: ", reason);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
//--- Bar-Daten oder Tick-Daten verwenden (Use bar data or tick data)
|
||||
if(UseBarData)
|
||||
{
|
||||
//--- Nur bei neuen Bars ausführen (Only execute on new bars)
|
||||
static datetime last_bar_time = 0;
|
||||
datetime current_bar_time = iTime(_Symbol, Timeframe, 0);
|
||||
|
||||
if(current_bar_time == last_bar_time)
|
||||
{
|
||||
return; // Kein neuer Bar, nichts tun
|
||||
}
|
||||
|
||||
last_bar_time = current_bar_time;
|
||||
}
|
||||
|
||||
//--- EMA Werte berechnen (Calculate EMA values)
|
||||
BerechneEMA();
|
||||
|
||||
//--- Debug: Aktuelle Werte ausgeben (Debug: Output current values)
|
||||
if(ArraySize(ema_array) > 0)
|
||||
{
|
||||
double aktueller_close = iClose(_Symbol, Timeframe, 0);
|
||||
double ema_aktuell = ema_array[0];
|
||||
double ema_vorher = ema_array[1];
|
||||
double preis_abstand = MathAbs(aktueller_close - ema_aktuell) / _Point;
|
||||
double steigung = (ema_aktuell - ema_vorher) / _Point;
|
||||
|
||||
if(UseBarData)
|
||||
{
|
||||
Print("=== DEBUG INFO (Neuer Bar) ===");
|
||||
Print("Bar Zeit: ", TimeToString(iTime(_Symbol, Timeframe, 0)));
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("=== DEBUG INFO (Tick) ===");
|
||||
}
|
||||
|
||||
Print("Aktueller Close: ", aktueller_close);
|
||||
Print("EMA: ", ema_aktuell);
|
||||
Print("Preis-Abstand: ", preis_abstand, " Pips");
|
||||
Print("EMA Steigung: ", steigung, " Pips");
|
||||
Print("Differenz Close-EMA: ", aktueller_close - ema_aktuell);
|
||||
Print("Preis-Trigger: ", preis_trigger_aktiv, " Steigungs-Trigger: ", steigung_trigger_aktiv);
|
||||
Print("Überwachung aktiv: ", überwachung_aktiv);
|
||||
Print("Position offen: ", PositionSelect(_Symbol));
|
||||
Print("Trades im aktuellen Crossover: ", trades_in_current_crossover, "/", MaxTradesPerCrossover);
|
||||
Print("==================");
|
||||
}
|
||||
|
||||
//--- Überwachung prüfen (Check monitoring)
|
||||
if(überwachung_aktiv)
|
||||
{
|
||||
if(UseBarData)
|
||||
{
|
||||
// Bar-basierte Überwachungszeit
|
||||
int bars_since_monitoring = iBarShift(_Symbol, Timeframe, letzte_überwachung_zeit);
|
||||
int timeout_bars = (int)(ÜberwachungTimeout / PeriodSeconds(Timeframe));
|
||||
|
||||
if(bars_since_monitoring > timeout_bars)
|
||||
{
|
||||
überwachung_aktiv = false;
|
||||
preis_trigger_aktiv = false;
|
||||
steigung_trigger_aktiv = false;
|
||||
Print("Überwachung beendet - Bar-basierte Zeitüberschreitung (", bars_since_monitoring, " Bars)");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Tick-basierte Überwachungszeit
|
||||
if(TimeCurrent() - letzte_überwachung_zeit > ÜberwachungTimeout)
|
||||
{
|
||||
überwachung_aktiv = false;
|
||||
preis_trigger_aktiv = false;
|
||||
steigung_trigger_aktiv = false;
|
||||
Print("Überwachung beendet - Tick-basierte Zeitüberschreitung");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- Trigger-Bedingungen prüfen (Check trigger conditions)
|
||||
PrüfeTrigger();
|
||||
|
||||
//--- Trade Management (Trade management)
|
||||
VerwalteTrades();
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| EMA Berechnung (EMA Calculation) |
|
||||
//+------------------------------------------------------------------+
|
||||
void BerechneEMA()
|
||||
{
|
||||
//--- EMA Werte vom Indicator kopieren (Copy EMA values from indicator)
|
||||
int copied = CopyBuffer(ema_handle, 0, 0, 3, ema_array);
|
||||
|
||||
if(copied <= 0)
|
||||
{
|
||||
Print("TRACE: Fehler beim Kopieren der EMA Werte - Copied: ", copied);
|
||||
return;
|
||||
}
|
||||
|
||||
Print("TRACE: EMA Werte kopiert: ", copied, " Bars");
|
||||
Print("TRACE: EMA [0]: ", ema_array[0], " [1]: ", ema_array[1], " [2]: ", ema_array[2]);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Trigger-Bedingungen prüfen (Check trigger conditions) |
|
||||
//+------------------------------------------------------------------+
|
||||
void PrüfeTrigger()
|
||||
{
|
||||
if(ArraySize(ema_array) < 2)
|
||||
{
|
||||
Print("TRACE: Array zu klein - Größe: ", ArraySize(ema_array));
|
||||
return;
|
||||
}
|
||||
|
||||
//--- Aktuelle Werte (Current values)
|
||||
double aktueller_preis = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
double aktueller_ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
||||
double aktueller_close = iClose(_Symbol, Timeframe, 0);
|
||||
double pips_multiplier = (_Digits == 3 || _Digits == 5) ? 10.0 : 1.0;
|
||||
|
||||
//--- EMA Werte in Variablen (EMA values in variables)
|
||||
double ema_aktuell = ema_array[0];
|
||||
double ema_vorher = ema_array[1];
|
||||
|
||||
//--- EMA Crossover Erkennung (EMA Crossover Detection)
|
||||
// Prüfe ob Preis die EMA kreuzt (Check if price crosses EMA)
|
||||
static double last_close = 0;
|
||||
static double last_ema = 0;
|
||||
|
||||
if(last_close != 0 && last_ema != 0)
|
||||
{
|
||||
bool crossover_bullish = (last_close <= last_ema) && (aktueller_close > ema_aktuell);
|
||||
bool crossover_bearish = (last_close >= last_ema) && (aktueller_close < ema_aktuell);
|
||||
|
||||
//--- Neues Crossover-Ereignis erkannt (New crossover event detected)
|
||||
if(crossover_bullish || crossover_bearish)
|
||||
{
|
||||
trades_in_current_crossover = 0; // Reset trade counter
|
||||
Print("TRACE: EMA Crossover erkannt - ", (crossover_bullish ? "BULLISH" : "BEARISH"), " - Trade-Counter zurückgesetzt");
|
||||
Print("TRACE: Vorher: Close=", last_close, " EMA=", last_ema, " Jetzt: Close=", aktueller_close, " EMA=", ema_aktuell);
|
||||
}
|
||||
}
|
||||
|
||||
//--- Aktuelle Werte für nächsten Vergleich speichern (Save current values for next comparison)
|
||||
last_close = aktueller_close;
|
||||
last_ema = ema_aktuell;
|
||||
|
||||
//--- Preisbewegung zur EMA prüfen (Check price action to EMA)
|
||||
double preis_abstand = MathAbs(aktueller_close - ema_aktuell) / _Point / pips_multiplier;
|
||||
|
||||
Print("TRACE: Preis-Abstand: ", preis_abstand, " Pips (Schwelle: ", PreisSchwelle, ")");
|
||||
Print("TRACE: Close: ", aktueller_close, " EMA: ", ema_aktuell);
|
||||
Print("TRACE: Trades im aktuellen Crossover: ", trades_in_current_crossover, "/", MaxTradesPerCrossover);
|
||||
|
||||
if(preis_abstand > PreisSchwelle && !preis_trigger_aktiv)
|
||||
{
|
||||
preis_trigger_aktiv = true;
|
||||
Print("TRACE: Preis-Trigger aktiviert: ", preis_abstand, " Pips");
|
||||
}
|
||||
|
||||
//--- EMA Steigung prüfen (Check EMA slope)
|
||||
double steigung = (ema_aktuell - ema_vorher) / _Point / pips_multiplier;
|
||||
|
||||
Print("TRACE: EMA Steigung: ", steigung, " Pips (Schwelle: ", SteigungSchwelle, ")");
|
||||
|
||||
if(MathAbs(steigung) > SteigungSchwelle && !steigung_trigger_aktiv)
|
||||
{
|
||||
steigung_trigger_aktiv = true;
|
||||
Print("TRACE: Steigungs-Trigger aktiviert: ", steigung, " Pips");
|
||||
}
|
||||
|
||||
//--- Überwachung starten wenn beide Trigger aktiv sind (Start monitoring when both triggers are active)
|
||||
if(preis_trigger_aktiv && steigung_trigger_aktiv && !überwachung_aktiv)
|
||||
{
|
||||
überwachung_aktiv = true;
|
||||
|
||||
if(UseBarData)
|
||||
{
|
||||
letzte_überwachung_zeit = iTime(_Symbol, Timeframe, 0); // Aktuelle Bar-Zeit
|
||||
Print("TRACE: Überwachung gestartet - Beide Trigger aktiv (Bar: ", TimeToString(letzte_überwachung_zeit), ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
letzte_überwachung_zeit = TimeCurrent(); // Aktuelle Tick-Zeit
|
||||
Print("TRACE: Überwachung gestartet - Beide Trigger aktiv (Tick)");
|
||||
}
|
||||
}
|
||||
|
||||
//--- Trade platzieren wenn Überwachung aktiv und Preis über/unter EMA (Place trade when monitoring active and price above/below EMA)
|
||||
if(überwachung_aktiv)
|
||||
{
|
||||
bool bullish_signal = aktueller_close > ema_aktuell;
|
||||
bool bearish_signal = aktueller_close < ema_aktuell;
|
||||
|
||||
Print("TRACE: Signal Check - Bullish: ", bullish_signal, " Bearish: ", bearish_signal);
|
||||
Print("TRACE: Close: ", aktueller_close, " EMA: ", ema_aktuell);
|
||||
Print("TRACE: Differenz: ", aktueller_close - ema_aktuell);
|
||||
|
||||
//--- Trade-Limit prüfen (Check trade limit)
|
||||
if(trades_in_current_crossover >= MaxTradesPerCrossover)
|
||||
{
|
||||
Print("TRACE: Trade-Limit erreicht (", MaxTradesPerCrossover, ") - Kein neuer Trade");
|
||||
return;
|
||||
}
|
||||
|
||||
if(bullish_signal && !PositionSelect(_Symbol))
|
||||
{
|
||||
Print("TRACE: Versuche KAUF-Trade zu platzieren (Trade #", trades_in_current_crossover + 1, ")");
|
||||
if(PlatziereTrade(ORDER_TYPE_BUY))
|
||||
{
|
||||
trades_in_current_crossover++;
|
||||
}
|
||||
}
|
||||
else if(bearish_signal && !PositionSelect(_Symbol))
|
||||
{
|
||||
Print("TRACE: Versuche VERKAUF-Trade zu platzieren (Trade #", trades_in_current_crossover + 1, ")");
|
||||
if(PlatziereTrade(ORDER_TYPE_SELL))
|
||||
{
|
||||
trades_in_current_crossover++;
|
||||
}
|
||||
}
|
||||
else if(PositionSelect(_Symbol))
|
||||
{
|
||||
Print("TRACE: Position bereits offen - kein neuer Trade");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Trade platzieren (Place trade) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PlatziereTrade(ENUM_ORDER_TYPE order_type)
|
||||
{
|
||||
Print("TRACE: Versuche Trade zu platzieren - Typ: ", (order_type == ORDER_TYPE_BUY) ? "KAUF" : "VERKAUF");
|
||||
Print("TRACE: Lot: ", LotGröße);
|
||||
|
||||
bool success = false;
|
||||
|
||||
if(order_type == ORDER_TYPE_BUY)
|
||||
{
|
||||
success = trade.Buy(LotGröße, _Symbol, 0, 0, 0, "EMA Crossover Trade");
|
||||
}
|
||||
else
|
||||
{
|
||||
success = trade.Sell(LotGröße, _Symbol, 0, 0, 0, "EMA Crossover Trade");
|
||||
}
|
||||
|
||||
if(success)
|
||||
{
|
||||
ticket = (int)trade.ResultOrder();
|
||||
Print("TRACE: Trade erfolgreich platziert: ", (order_type == ORDER_TYPE_BUY) ? "KAUF" : "VERKAUF", " Ticket: ", ticket);
|
||||
|
||||
//--- Trade-Öffnungszeit speichern (Save trade opening time)
|
||||
trade_open_time = iTime(_Symbol, Timeframe, 0);
|
||||
Print("TRACE: Trade-Öffnungszeit: ", TimeToString(trade_open_time));
|
||||
|
||||
//--- Überwachung zurücksetzen (Reset monitoring)
|
||||
überwachung_aktiv = false;
|
||||
preis_trigger_aktiv = false;
|
||||
steigung_trigger_aktiv = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("TRACE: Fehler beim Platzieren des Trades - Retcode: ", trade.ResultRetcode());
|
||||
Print("TRACE: Fehlerbeschreibung: ", trade.ResultRetcodeDescription());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Trades verwalten (Manage trades) |
|
||||
//+------------------------------------------------------------------+
|
||||
void VerwalteTrades()
|
||||
{
|
||||
if(!PositionSelect(_Symbol))
|
||||
return;
|
||||
|
||||
double position_profit = PositionGetDouble(POSITION_PROFIT);
|
||||
double position_open_price = PositionGetDouble(POSITION_PRICE_OPEN);
|
||||
double current_price = PositionGetDouble(POSITION_PRICE_CURRENT);
|
||||
ENUM_POSITION_TYPE position_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
|
||||
double pips_multiplier = (_Digits == 3 || _Digits == 5) ? 10.0 : 1.0;
|
||||
double trailing_stop_pips = TrailingStop;
|
||||
|
||||
//--- Gleitender Stop (Trailing Stop) - nur wenn Position im Profit ist
|
||||
if(position_profit > 0) // Only apply trailing stop when in profit
|
||||
{
|
||||
if(position_type == POSITION_TYPE_BUY)
|
||||
{
|
||||
double new_stop_loss = current_price - (trailing_stop_pips * _Point * pips_multiplier);
|
||||
double current_stop_loss = PositionGetDouble(POSITION_SL);
|
||||
|
||||
// Only move stop loss if new stop is higher than current stop
|
||||
if(new_stop_loss > current_stop_loss)
|
||||
{
|
||||
ÄndereStopLoss(new_stop_loss);
|
||||
}
|
||||
}
|
||||
else if(position_type == POSITION_TYPE_SELL)
|
||||
{
|
||||
double new_stop_loss = current_price + (trailing_stop_pips * _Point * pips_multiplier);
|
||||
double current_stop_loss = PositionGetDouble(POSITION_SL);
|
||||
|
||||
// Only move stop loss if new stop is lower than current stop
|
||||
if(new_stop_loss < current_stop_loss || current_stop_loss == 0)
|
||||
{
|
||||
ÄndereStopLoss(new_stop_loss);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- Ausstieg bei Preis unter/über EMA (Exit when price below/above EMA)
|
||||
if(ArraySize(ema_array) >= 1)
|
||||
{
|
||||
double aktueller_close = iClose(_Symbol, Timeframe, 0);
|
||||
double ema_aktuell = ema_array[0];
|
||||
bool exit_bullish = (position_type == POSITION_TYPE_SELL && aktueller_close > ema_aktuell);
|
||||
bool exit_bearish = (position_type == POSITION_TYPE_BUY && aktueller_close < ema_aktuell);
|
||||
|
||||
if(exit_bullish || exit_bearish)
|
||||
{
|
||||
Print("TRACE: Ausstiegssignal - Close: ", aktueller_close, " EMA: ", ema_aktuell);
|
||||
SchließePosition("EMA Crossover Exit");
|
||||
|
||||
Print("TRACE: Position geschlossen - Trade-Counter bleibt bei ", trades_in_current_crossover);
|
||||
}
|
||||
}
|
||||
|
||||
//--- Profit-Prüfung nach X Bars (Profit check after X bars)
|
||||
if(CloseUnprofitableTrades && trade_open_time != 0 && PositionSelect(_Symbol))
|
||||
{
|
||||
Print("TRACE: Profit-Prüfung aktiviert - CloseUnprofitableTrades: ", CloseUnprofitableTrades);
|
||||
PrüfeProfitNachBars();
|
||||
}
|
||||
else if(!CloseUnprofitableTrades)
|
||||
{
|
||||
Print("TRACE: Profit-Prüfung deaktiviert - CloseUnprofitableTrades: ", CloseUnprofitableTrades);
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Profit-Prüfung nach X Bars (Profit check after X bars) |
|
||||
//+------------------------------------------------------------------+
|
||||
void PrüfeProfitNachBars()
|
||||
{
|
||||
if(!PositionSelect(_Symbol))
|
||||
{
|
||||
return; // Keine Position offen
|
||||
}
|
||||
|
||||
datetime current_bar_time = iTime(_Symbol, Timeframe, 0);
|
||||
int bars_since_trade_open = iBarShift(_Symbol, Timeframe, trade_open_time);
|
||||
|
||||
Print("TRACE: Bars seit Trade-Öffnung: ", bars_since_trade_open, "/", ProfitCheckBars);
|
||||
|
||||
//--- Prüfe ob genügend Bars vergangen sind (Check if enough bars have passed)
|
||||
if(bars_since_trade_open >= ProfitCheckBars)
|
||||
{
|
||||
double position_profit = PositionGetDouble(POSITION_PROFIT);
|
||||
double position_volume = PositionGetDouble(POSITION_VOLUME);
|
||||
ENUM_POSITION_TYPE position_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
|
||||
Print("TRACE: Profit-Prüfung nach ", ProfitCheckBars, " Bars");
|
||||
Print("TRACE: Position Profit: ", position_profit, " USD");
|
||||
|
||||
//--- Schließe Position wenn nicht im Profit (Close position if not in profit)
|
||||
if(position_profit <= 0)
|
||||
{
|
||||
Print("TRACE: Position nicht im Profit - Schließe Position");
|
||||
SchließePosition("Profit Check - Unprofitable");
|
||||
|
||||
//--- Trade-Öffnungszeit zurücksetzen (Reset trade opening time)
|
||||
trade_open_time = 0;
|
||||
Print("TRACE: Trade-Öffnungszeit zurückgesetzt");
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("TRACE: Position im Profit - Behalte Position");
|
||||
//--- Trade-Öffnungszeit zurücksetzen um weitere Prüfungen zu vermeiden (Reset to avoid further checks)
|
||||
trade_open_time = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Stop Loss ändern (Modify Stop Loss) |
|
||||
//+------------------------------------------------------------------+
|
||||
void ÄndereStopLoss(double new_stop_loss)
|
||||
{
|
||||
Print("TRACE: Versuche Stop Loss zu ändern auf: ", new_stop_loss);
|
||||
|
||||
bool success = trade.PositionModify(_Symbol, new_stop_loss, PositionGetDouble(POSITION_TP));
|
||||
|
||||
if(success)
|
||||
{
|
||||
Print("TRACE: Stop Loss erfolgreich geändert auf: ", new_stop_loss);
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("TRACE: Fehler beim Ändern des Stop Loss - Retcode: ", trade.ResultRetcode());
|
||||
Print("TRACE: Fehlerbeschreibung: ", trade.ResultRetcodeDescription());
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Position schließen (Close position) |
|
||||
//+------------------------------------------------------------------+
|
||||
void SchließePosition(string reason = "Unbekannt")
|
||||
{
|
||||
Print("TRACE: Versuche Position zu schließen - Grund: ", reason);
|
||||
|
||||
bool success = trade.PositionClose(_Symbol);
|
||||
|
||||
if(success)
|
||||
{
|
||||
Print("TRACE: Position erfolgreich geschlossen - Grund: ", reason);
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("TRACE: Fehler beim Schließen der Position - Retcode: ", trade.ResultRetcode());
|
||||
Print("TRACE: Fehlerbeschreibung: ", trade.ResultRetcodeDescription());
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 270 KiB After Width: | Height: | Size: 250 KiB |
@@ -0,0 +1,281 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| RSIScalping.mq5 |
|
||||
//| Copyright 2025, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2025, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
|
||||
//--- Input parameters
|
||||
input ENUM_TIMEFRAMES TimeFrame = PERIOD_H4; // Timeframe for Analysis
|
||||
input int RSI_Period = 14; // RSI Period
|
||||
input ENUM_APPLIED_PRICE RSI_Applied_Price = PRICE_CLOSE; // RSI Applied Price
|
||||
input double RSI_Overbought = 82; // RSI Overbought Level
|
||||
input double RSI_Oversold = 55; // RSI Oversold Level
|
||||
input double RSI_Target_Buy = 39; // RSI Target for Buy Exit
|
||||
input double RSI_Target_Sell = 35; // RSI Target for Sell Exit
|
||||
input int BarsToWait = 2; // Bars to wait when RSI goes against position
|
||||
input double LotSize = 50; // Lot Size
|
||||
input int MagicNumber = 12345; // Magic Number
|
||||
input int Slippage = 3; // Slippage in points
|
||||
|
||||
//--- Global variables
|
||||
CTrade trade;
|
||||
int rsi_handle;
|
||||
double rsi_buffer[];
|
||||
double rsi_prev, rsi_current, rsi_two_bars_ago;
|
||||
bool position_open = false;
|
||||
int position_ticket = 0;
|
||||
ENUM_POSITION_TYPE current_position_type = POSITION_TYPE_BUY;
|
||||
datetime last_bar_time = 0;
|
||||
bool rsi_against_position = false;
|
||||
int bars_against_count = 0;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
// Initialize RSI indicator
|
||||
rsi_handle = iRSI(_Symbol, TimeFrame, RSI_Period, RSI_Applied_Price);
|
||||
if(rsi_handle == INVALID_HANDLE)
|
||||
{
|
||||
return(INIT_FAILED);
|
||||
}
|
||||
|
||||
// Initialize trade object
|
||||
trade.SetExpertMagicNumber(MagicNumber);
|
||||
trade.SetDeviationInPoints(Slippage);
|
||||
trade.SetTypeFilling(ORDER_FILLING_FOK);
|
||||
|
||||
// Allocate arrays
|
||||
ArraySetAsSeries(rsi_buffer, true);
|
||||
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
if(rsi_handle != INVALID_HANDLE)
|
||||
IndicatorRelease(rsi_handle);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
// Check if we have enough bars
|
||||
if(Bars(_Symbol, TimeFrame) < RSI_Period + 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if this is a new bar
|
||||
datetime current_bar_time = iTime(_Symbol, TimeFrame, 0);
|
||||
if(current_bar_time == last_bar_time)
|
||||
{
|
||||
return; // Still the same bar, don't process
|
||||
}
|
||||
|
||||
last_bar_time = current_bar_time;
|
||||
|
||||
// Update RSI values
|
||||
if(!UpdateRSI())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for existing position
|
||||
CheckExistingPosition();
|
||||
|
||||
// Check for new entry signals
|
||||
if(!position_open)
|
||||
{
|
||||
CheckEntrySignals();
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Update RSI values |
|
||||
//+------------------------------------------------------------------+
|
||||
bool UpdateRSI()
|
||||
{
|
||||
if(CopyBuffer(rsi_handle, 0, 0, 3, rsi_buffer) < 3)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
rsi_current = rsi_buffer[0]; // Current bar
|
||||
rsi_prev = rsi_buffer[1]; // Previous bar
|
||||
rsi_two_bars_ago = rsi_buffer[2]; // Two bars ago
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check existing position for exit conditions |
|
||||
//+------------------------------------------------------------------+
|
||||
void CheckExistingPosition()
|
||||
{
|
||||
if(!position_open)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if position still exists
|
||||
if(!PositionSelectByTicket(position_ticket))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Exit conditions based on RSI target
|
||||
if(current_position_type == POSITION_TYPE_BUY)
|
||||
{
|
||||
// Check if RSI is against the position (below oversold)
|
||||
if(rsi_current < RSI_Oversold)
|
||||
{
|
||||
if(!rsi_against_position)
|
||||
{
|
||||
rsi_against_position = true;
|
||||
bars_against_count = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bars_against_count++;
|
||||
}
|
||||
|
||||
// Close position if RSI has been against for Y bars
|
||||
if(bars_against_count >= BarsToWait)
|
||||
{
|
||||
ClosePosition();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// RSI is no longer against the position, reset counter
|
||||
if(rsi_against_position)
|
||||
{
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
|
||||
// Exit long position when RSI reaches buy target
|
||||
if(rsi_current >= RSI_Target_Buy)
|
||||
{
|
||||
ClosePosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(current_position_type == POSITION_TYPE_SELL)
|
||||
{
|
||||
// Check if RSI is against the position (above overbought)
|
||||
if(rsi_current > RSI_Overbought)
|
||||
{
|
||||
if(!rsi_against_position)
|
||||
{
|
||||
rsi_against_position = true;
|
||||
bars_against_count = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bars_against_count++;
|
||||
}
|
||||
|
||||
// Close position if RSI has been against for Y bars
|
||||
if(bars_against_count >= BarsToWait)
|
||||
{
|
||||
ClosePosition();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// RSI is no longer against the position, reset counter
|
||||
if(rsi_against_position)
|
||||
{
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
|
||||
// Exit short position when RSI reaches sell target
|
||||
if(rsi_current <= RSI_Target_Sell)
|
||||
{
|
||||
ClosePosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check for entry signals |
|
||||
//+------------------------------------------------------------------+
|
||||
void CheckEntrySignals()
|
||||
{
|
||||
// Buy signal: RSI crosses from oversold to above oversold (checking the actual crossover)
|
||||
if(rsi_two_bars_ago <= RSI_Oversold && rsi_prev > RSI_Oversold)
|
||||
{
|
||||
OpenBuyPosition();
|
||||
}
|
||||
|
||||
// Sell signal: RSI crosses from overbought to below overbought (checking the actual crossover)
|
||||
if(rsi_two_bars_ago >= RSI_Overbought && rsi_prev < RSI_Overbought)
|
||||
{
|
||||
OpenSellPosition();
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Open buy position |
|
||||
//+------------------------------------------------------------------+
|
||||
void OpenBuyPosition()
|
||||
{
|
||||
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
||||
|
||||
if(trade.Buy(LotSize, _Symbol, ask, 0, 0, "RSI Scalping Buy"))
|
||||
{
|
||||
position_ticket = trade.ResultOrder();
|
||||
position_open = true;
|
||||
current_position_type = POSITION_TYPE_BUY;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Open sell position |
|
||||
//+------------------------------------------------------------------+
|
||||
void OpenSellPosition()
|
||||
{
|
||||
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
|
||||
if(trade.Sell(LotSize, _Symbol, bid, 0, 0, "RSI Scalping Sell"))
|
||||
{
|
||||
position_ticket = trade.ResultOrder();
|
||||
position_open = true;
|
||||
current_position_type = POSITION_TYPE_SELL;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Close current position |
|
||||
//+------------------------------------------------------------------+
|
||||
void ClosePosition()
|
||||
{
|
||||
if(trade.PositionClose(position_ticket))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,281 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| RSIScalping.mq5 |
|
||||
//| Copyright 2025, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2025, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
|
||||
//--- Input parameters
|
||||
input ENUM_TIMEFRAMES TimeFrame = PERIOD_H3; // Timeframe for Analysis
|
||||
input int RSI_Period = 14; // RSI Period
|
||||
input ENUM_APPLIED_PRICE RSI_Applied_Price = PRICE_CLOSE; // RSI Applied Price
|
||||
input double RSI_Overbought = 19; // RSI Overbought Level
|
||||
input double RSI_Oversold = 50; // RSI Oversold Level
|
||||
input double RSI_Target_Buy = 71; // RSI Target for Buy Exit
|
||||
input double RSI_Target_Sell = 70; // RSI Target for Sell Exit
|
||||
input int BarsToWait = 1; // Bars to wait when RSI goes against position
|
||||
input double LotSize = 50; // Lot Size
|
||||
input int MagicNumber = 12345; // Magic Number
|
||||
input int Slippage = 3; // Slippage in points
|
||||
|
||||
//--- Global variables
|
||||
CTrade trade;
|
||||
int rsi_handle;
|
||||
double rsi_buffer[];
|
||||
double rsi_prev, rsi_current, rsi_two_bars_ago;
|
||||
bool position_open = false;
|
||||
int position_ticket = 0;
|
||||
ENUM_POSITION_TYPE current_position_type = POSITION_TYPE_BUY;
|
||||
datetime last_bar_time = 0;
|
||||
bool rsi_against_position = false;
|
||||
int bars_against_count = 0;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
// Initialize RSI indicator
|
||||
rsi_handle = iRSI(_Symbol, TimeFrame, RSI_Period, RSI_Applied_Price);
|
||||
if(rsi_handle == INVALID_HANDLE)
|
||||
{
|
||||
return(INIT_FAILED);
|
||||
}
|
||||
|
||||
// Initialize trade object
|
||||
trade.SetExpertMagicNumber(MagicNumber);
|
||||
trade.SetDeviationInPoints(Slippage);
|
||||
trade.SetTypeFilling(ORDER_FILLING_FOK);
|
||||
|
||||
// Allocate arrays
|
||||
ArraySetAsSeries(rsi_buffer, true);
|
||||
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
if(rsi_handle != INVALID_HANDLE)
|
||||
IndicatorRelease(rsi_handle);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
// Check if we have enough bars
|
||||
if(Bars(_Symbol, TimeFrame) < RSI_Period + 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if this is a new bar
|
||||
datetime current_bar_time = iTime(_Symbol, TimeFrame, 0);
|
||||
if(current_bar_time == last_bar_time)
|
||||
{
|
||||
return; // Still the same bar, don't process
|
||||
}
|
||||
|
||||
last_bar_time = current_bar_time;
|
||||
|
||||
// Update RSI values
|
||||
if(!UpdateRSI())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for existing position
|
||||
CheckExistingPosition();
|
||||
|
||||
// Check for new entry signals
|
||||
if(!position_open)
|
||||
{
|
||||
CheckEntrySignals();
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Update RSI values |
|
||||
//+------------------------------------------------------------------+
|
||||
bool UpdateRSI()
|
||||
{
|
||||
if(CopyBuffer(rsi_handle, 0, 0, 3, rsi_buffer) < 3)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
rsi_current = rsi_buffer[0]; // Current bar
|
||||
rsi_prev = rsi_buffer[1]; // Previous bar
|
||||
rsi_two_bars_ago = rsi_buffer[2]; // Two bars ago
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check existing position for exit conditions |
|
||||
//+------------------------------------------------------------------+
|
||||
void CheckExistingPosition()
|
||||
{
|
||||
if(!position_open)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if position still exists
|
||||
if(!PositionSelectByTicket(position_ticket))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Exit conditions based on RSI target
|
||||
if(current_position_type == POSITION_TYPE_BUY)
|
||||
{
|
||||
// Check if RSI is against the position (below oversold)
|
||||
if(rsi_current < RSI_Oversold)
|
||||
{
|
||||
if(!rsi_against_position)
|
||||
{
|
||||
rsi_against_position = true;
|
||||
bars_against_count = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bars_against_count++;
|
||||
}
|
||||
|
||||
// Close position if RSI has been against for Y bars
|
||||
if(bars_against_count >= BarsToWait)
|
||||
{
|
||||
ClosePosition();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// RSI is no longer against the position, reset counter
|
||||
if(rsi_against_position)
|
||||
{
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
|
||||
// Exit long position when RSI reaches buy target
|
||||
if(rsi_current >= RSI_Target_Buy)
|
||||
{
|
||||
ClosePosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(current_position_type == POSITION_TYPE_SELL)
|
||||
{
|
||||
// Check if RSI is against the position (above overbought)
|
||||
if(rsi_current > RSI_Overbought)
|
||||
{
|
||||
if(!rsi_against_position)
|
||||
{
|
||||
rsi_against_position = true;
|
||||
bars_against_count = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bars_against_count++;
|
||||
}
|
||||
|
||||
// Close position if RSI has been against for Y bars
|
||||
if(bars_against_count >= BarsToWait)
|
||||
{
|
||||
ClosePosition();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// RSI is no longer against the position, reset counter
|
||||
if(rsi_against_position)
|
||||
{
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
|
||||
// Exit short position when RSI reaches sell target
|
||||
if(rsi_current <= RSI_Target_Sell)
|
||||
{
|
||||
ClosePosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check for entry signals |
|
||||
//+------------------------------------------------------------------+
|
||||
void CheckEntrySignals()
|
||||
{
|
||||
// Buy signal: RSI crosses from oversold to above oversold (checking the actual crossover)
|
||||
if(rsi_two_bars_ago <= RSI_Oversold && rsi_prev > RSI_Oversold)
|
||||
{
|
||||
OpenBuyPosition();
|
||||
}
|
||||
|
||||
// Sell signal: RSI crosses from overbought to below overbought (checking the actual crossover)
|
||||
if(rsi_two_bars_ago >= RSI_Overbought && rsi_prev < RSI_Overbought)
|
||||
{
|
||||
OpenSellPosition();
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Open buy position |
|
||||
//+------------------------------------------------------------------+
|
||||
void OpenBuyPosition()
|
||||
{
|
||||
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
||||
|
||||
if(trade.Buy(LotSize, _Symbol, ask, 0, 0, "RSI Scalping Buy"))
|
||||
{
|
||||
position_ticket = trade.ResultOrder();
|
||||
position_open = true;
|
||||
current_position_type = POSITION_TYPE_BUY;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Open sell position |
|
||||
//+------------------------------------------------------------------+
|
||||
void OpenSellPosition()
|
||||
{
|
||||
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
|
||||
if(trade.Sell(LotSize, _Symbol, bid, 0, 0, "RSI Scalping Sell"))
|
||||
{
|
||||
position_ticket = trade.ResultOrder();
|
||||
position_open = true;
|
||||
current_position_type = POSITION_TYPE_SELL;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Close current position |
|
||||
//+------------------------------------------------------------------+
|
||||
void ClosePosition()
|
||||
{
|
||||
if(trade.PositionClose(position_ticket))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 234 KiB |
@@ -0,0 +1,281 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| RSIScalping.mq5 |
|
||||
//| Copyright 2025, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2025, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
|
||||
//--- Input parameters
|
||||
input ENUM_TIMEFRAMES TimeFrame = PERIOD_H1; // Timeframe for Analysis
|
||||
input int RSI_Period = 14; // RSI Period
|
||||
input ENUM_APPLIED_PRICE RSI_Applied_Price = PRICE_CLOSE; // RSI Applied Price
|
||||
input double RSI_Overbought = 54; // RSI Overbought Level
|
||||
input double RSI_Oversold = 73; // RSI Oversold Level
|
||||
input double RSI_Target_Buy = 87; // RSI Target for Buy Exit
|
||||
input double RSI_Target_Sell = 33; // RSI Target for Sell Exit
|
||||
input int BarsToWait = 1; // Bars to wait when RSI goes against position
|
||||
input double LotSize = 50; // Lot Size
|
||||
input int MagicNumber = 12345; // Magic Number
|
||||
input int Slippage = 3; // Slippage in points
|
||||
|
||||
//--- Global variables
|
||||
CTrade trade;
|
||||
int rsi_handle;
|
||||
double rsi_buffer[];
|
||||
double rsi_prev, rsi_current, rsi_two_bars_ago;
|
||||
bool position_open = false;
|
||||
int position_ticket = 0;
|
||||
ENUM_POSITION_TYPE current_position_type = POSITION_TYPE_BUY;
|
||||
datetime last_bar_time = 0;
|
||||
bool rsi_against_position = false;
|
||||
int bars_against_count = 0;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
// Initialize RSI indicator
|
||||
rsi_handle = iRSI(_Symbol, TimeFrame, RSI_Period, RSI_Applied_Price);
|
||||
if(rsi_handle == INVALID_HANDLE)
|
||||
{
|
||||
return(INIT_FAILED);
|
||||
}
|
||||
|
||||
// Initialize trade object
|
||||
trade.SetExpertMagicNumber(MagicNumber);
|
||||
trade.SetDeviationInPoints(Slippage);
|
||||
trade.SetTypeFilling(ORDER_FILLING_FOK);
|
||||
|
||||
// Allocate arrays
|
||||
ArraySetAsSeries(rsi_buffer, true);
|
||||
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
if(rsi_handle != INVALID_HANDLE)
|
||||
IndicatorRelease(rsi_handle);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
// Check if we have enough bars
|
||||
if(Bars(_Symbol, TimeFrame) < RSI_Period + 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if this is a new bar
|
||||
datetime current_bar_time = iTime(_Symbol, TimeFrame, 0);
|
||||
if(current_bar_time == last_bar_time)
|
||||
{
|
||||
return; // Still the same bar, don't process
|
||||
}
|
||||
|
||||
last_bar_time = current_bar_time;
|
||||
|
||||
// Update RSI values
|
||||
if(!UpdateRSI())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for existing position
|
||||
CheckExistingPosition();
|
||||
|
||||
// Check for new entry signals
|
||||
if(!position_open)
|
||||
{
|
||||
CheckEntrySignals();
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Update RSI values |
|
||||
//+------------------------------------------------------------------+
|
||||
bool UpdateRSI()
|
||||
{
|
||||
if(CopyBuffer(rsi_handle, 0, 0, 3, rsi_buffer) < 3)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
rsi_current = rsi_buffer[0]; // Current bar
|
||||
rsi_prev = rsi_buffer[1]; // Previous bar
|
||||
rsi_two_bars_ago = rsi_buffer[2]; // Two bars ago
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check existing position for exit conditions |
|
||||
//+------------------------------------------------------------------+
|
||||
void CheckExistingPosition()
|
||||
{
|
||||
if(!position_open)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if position still exists
|
||||
if(!PositionSelectByTicket(position_ticket))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Exit conditions based on RSI target
|
||||
if(current_position_type == POSITION_TYPE_BUY)
|
||||
{
|
||||
// Check if RSI is against the position (below oversold)
|
||||
if(rsi_current < RSI_Oversold)
|
||||
{
|
||||
if(!rsi_against_position)
|
||||
{
|
||||
rsi_against_position = true;
|
||||
bars_against_count = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bars_against_count++;
|
||||
}
|
||||
|
||||
// Close position if RSI has been against for Y bars
|
||||
if(bars_against_count >= BarsToWait)
|
||||
{
|
||||
ClosePosition();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// RSI is no longer against the position, reset counter
|
||||
if(rsi_against_position)
|
||||
{
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
|
||||
// Exit long position when RSI reaches buy target
|
||||
if(rsi_current >= RSI_Target_Buy)
|
||||
{
|
||||
ClosePosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(current_position_type == POSITION_TYPE_SELL)
|
||||
{
|
||||
// Check if RSI is against the position (above overbought)
|
||||
if(rsi_current > RSI_Overbought)
|
||||
{
|
||||
if(!rsi_against_position)
|
||||
{
|
||||
rsi_against_position = true;
|
||||
bars_against_count = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bars_against_count++;
|
||||
}
|
||||
|
||||
// Close position if RSI has been against for Y bars
|
||||
if(bars_against_count >= BarsToWait)
|
||||
{
|
||||
ClosePosition();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// RSI is no longer against the position, reset counter
|
||||
if(rsi_against_position)
|
||||
{
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
|
||||
// Exit short position when RSI reaches sell target
|
||||
if(rsi_current <= RSI_Target_Sell)
|
||||
{
|
||||
ClosePosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check for entry signals |
|
||||
//+------------------------------------------------------------------+
|
||||
void CheckEntrySignals()
|
||||
{
|
||||
// Buy signal: RSI crosses from oversold to above oversold (checking the actual crossover)
|
||||
if(rsi_two_bars_ago <= RSI_Oversold && rsi_prev > RSI_Oversold)
|
||||
{
|
||||
OpenBuyPosition();
|
||||
}
|
||||
|
||||
// Sell signal: RSI crosses from overbought to below overbought (checking the actual crossover)
|
||||
if(rsi_two_bars_ago >= RSI_Overbought && rsi_prev < RSI_Overbought)
|
||||
{
|
||||
OpenSellPosition();
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Open buy position |
|
||||
//+------------------------------------------------------------------+
|
||||
void OpenBuyPosition()
|
||||
{
|
||||
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
||||
|
||||
if(trade.Buy(LotSize, _Symbol, ask, 0, 0, "RSI Scalping Buy"))
|
||||
{
|
||||
position_ticket = trade.ResultOrder();
|
||||
position_open = true;
|
||||
current_position_type = POSITION_TYPE_BUY;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Open sell position |
|
||||
//+------------------------------------------------------------------+
|
||||
void OpenSellPosition()
|
||||
{
|
||||
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
|
||||
if(trade.Sell(LotSize, _Symbol, bid, 0, 0, "RSI Scalping Sell"))
|
||||
{
|
||||
position_ticket = trade.ResultOrder();
|
||||
position_open = true;
|
||||
current_position_type = POSITION_TYPE_SELL;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Close current position |
|
||||
//+------------------------------------------------------------------+
|
||||
void ClosePosition()
|
||||
{
|
||||
if(trade.PositionClose(position_ticket))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 201 KiB |
Reference in New Issue
Block a user