This commit is contained in:
zhutoutoutousan
2026-02-13 20:06:41 +01:00
parent 98a87a69ca
commit 860978962d
15 changed files with 2671 additions and 171 deletions
+7 -4
View File
@@ -11,6 +11,7 @@
#include <Trade\Trade.mqh>
#include <Indicators\Trend.mqh>
#include <Indicators\Volumes.mqh>
#include "../_united/MagicNumberHelpers.mqh"
// Input parameters
input int BoxPeriod = 165; // Period for Darvas Box calculation
@@ -33,6 +34,9 @@ input double TrendThreshold = 4.94; // Trend strength threshold
input int VolumeMA_Period = 110; // Period for Volume MA
input double VolumeThresholdMultiplier = 1.5; // Volume spike threshold
// Magic Number
input int MagicNumber = 135790; // Magic Number for Trades
// Global variables
double boxHigh = 0;
double boxLow = 0;
@@ -42,7 +46,6 @@ string boxName = "DarvasBox_";
double minStopLevel = 0;
double point = 0;
CTrade trade;
ulong magicNumber = 135790;
// Indicator handles
int maHandle;
@@ -77,7 +80,7 @@ int OnInit()
trade.SetDeviationInPoints(10);
trade.SetTypeFilling(ORDER_FILLING_IOC);
trade.SetAsyncMode(false);
trade.SetExpertMagicNumber(magicNumber);
trade.SetExpertMagicNumber(MagicNumber);
if(EnableLogging)
{
@@ -343,7 +346,7 @@ void OnTick()
Print("Breakout Signal Detected - Price above box high");
// Buy signal
if(PositionsTotal() == 0) // No existing positions
if(!PositionExistsByMagic(_Symbol, MagicNumber)) // No existing positions with our magic number
{
double sl = currentPrice - StopLoss * _Point;
double tp = currentPrice + TakeProfit * _Point;
@@ -364,7 +367,7 @@ void OnTick()
Print("Breakdown Signal Detected - Price below box low");
// Sell signal
if(PositionsTotal() == 0) // No existing positions
if(!PositionExistsByMagic(_Symbol, MagicNumber)) // No existing positions with our magic number
{
double sl = currentPrice + StopLoss * _Point;
double tp = currentPrice - TakeProfit * _Point;
@@ -7,6 +7,7 @@
#property link "https://www.mql5.com"
#property version "1.00"
#include <Trade\Trade.mqh>
#include "../_united/MagicNumberHelpers.mqh"
//--- Eingabeparameter (Input Parameters) - Optimized Profitable Parameters
input int EMA_Periode = 46; // EMA Periode
input double PreisSchwelle = 600.0; // Preisbewegung Schwelle in Pips
@@ -127,7 +128,7 @@ void OnTick()
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("Position offen: ", PositionExistsByMagic(_Symbol, MagicNumber));
Print("Trades im aktuellen Crossover: ", trades_in_current_crossover, "/", MaxTradesPerCrossover);
Print("==================");
}
@@ -289,7 +290,7 @@ void PrüfeTrigger()
return;
}
if(bullish_signal && !PositionSelect(_Symbol))
if(bullish_signal && !PositionExistsByMagic(_Symbol, MagicNumber))
{
Print("TRACE: Versuche KAUF-Trade zu platzieren (Trade #", trades_in_current_crossover + 1, ")");
if(PlatziereTrade(ORDER_TYPE_BUY))
@@ -297,7 +298,7 @@ void PrüfeTrigger()
trades_in_current_crossover++;
}
}
else if(bearish_signal && !PositionSelect(_Symbol))
else if(bearish_signal && !PositionExistsByMagic(_Symbol, MagicNumber))
{
Print("TRACE: Versuche VERKAUF-Trade zu platzieren (Trade #", trades_in_current_crossover + 1, ")");
if(PlatziereTrade(ORDER_TYPE_SELL))
@@ -305,7 +306,7 @@ void PrüfeTrigger()
trades_in_current_crossover++;
}
}
else if(PositionSelect(_Symbol))
else if(PositionExistsByMagic(_Symbol, MagicNumber))
{
Print("TRACE: Position bereits offen - kein neuer Trade");
}
@@ -361,7 +362,7 @@ bool PlatziereTrade(ENUM_ORDER_TYPE order_type)
//+------------------------------------------------------------------+
void VerwalteTrades()
{
if(!PositionSelect(_Symbol))
if(!PositionSelectByMagic(_Symbol, MagicNumber))
return;
double position_profit = PositionGetDouble(POSITION_PROFIT);
@@ -417,7 +418,7 @@ void VerwalteTrades()
}
//--- Profit-Prüfung nach X Bars (Profit check after X bars)
if(CloseUnprofitableTrades && trade_open_time != 0 && PositionSelect(_Symbol))
if(CloseUnprofitableTrades && trade_open_time != 0 && PositionExistsByMagic(_Symbol, MagicNumber))
{
Print("TRACE: Profit-Prüfung aktiviert - CloseUnprofitableTrades: ", CloseUnprofitableTrades);
PrüfeProfitNachBars();
@@ -433,7 +434,7 @@ void VerwalteTrades()
//+------------------------------------------------------------------+
void PrüfeProfitNachBars()
{
if(!PositionSelect(_Symbol))
if(!PositionSelectByMagic(_Symbol, MagicNumber))
{
return; // Keine Position offen
}
@@ -479,7 +480,7 @@ 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));
bool success = ModifyPositionByMagic(trade, _Symbol, MagicNumber, new_stop_loss, PositionGetDouble(POSITION_TP));
if(success)
{
@@ -499,7 +500,7 @@ void SchließePosition(string reason = "Unbekannt")
{
Print("TRACE: Versuche Position zu schließen - Grund: ", reason);
bool success = trade.PositionClose(_Symbol);
bool success = ClosePositionByMagic(trade, _Symbol, MagicNumber);
if(success)
{
+82
View File
@@ -0,0 +1,82 @@
# MQL5 EA Improvements - Magic Number Isolation
## Problem
When multiple EAs run together on the same symbol, they interfere with each other because magic numbers are not properly checked in all position-related functions.
## Solution
1. Created `MagicNumberHelpers.mqh` with magic-aware helper functions
2. Updated EAs to use these helper functions
3. Created `_united/main.mq5` - a unified EA that runs multiple strategies together
## Fixed Functions
### Helper Functions (MagicNumberHelpers.mqh)
- `PositionSelectByMagic()` - Select position by symbol AND magic number
- `PositionSelectByTicketAndMagic()` - Verify ticket has correct magic number
- `PositionExistsByMagic()` - Check if position exists with magic number
- `GetPositionTicketByMagic()` - Get ticket by symbol and magic number
- `ClosePositionByMagic()` - Close position with magic number verification
- `ModifyPositionByMagic()` - Modify position with magic number verification
- `GetPositionProfitByMagic()` - Get profit with magic number check
- `GetPositionTypeByMagic()` - Get position type with magic number check
- `CountPositionsByMagic()` - Count positions with specific magic number
## Fixed EAs
### RSIScalpingXAUUSD
- ✅ Fixed `CheckExistingPosition()` to use `PositionSelectByTicketAndMagic()`
- ✅ Fixed `ClosePosition()` to verify magic number before closing
- ✅ Fixed entry signal check to use `PositionExistsByMagic()`
### MeanReversionXAUUSD
- ✅ Fixed all `PositionSelect(_Symbol)` calls to use `PositionSelectByMagic()`
- ✅ Fixed `SchließePosition()` to use `ClosePositionByMagic()`
- ✅ Fixed `ÄndereStopLoss()` to use `ModifyPositionByMagic()`
- ✅ Fixed all position existence checks to use `PositionExistsByMagic()`
## United EA
The `_united/main.mq5` EA allows running multiple strategies together:
- Each strategy has its own unique magic number
- Strategies operate independently without interference
- Can enable/disable individual strategies via input parameters
- Currently implements:
- RSI Scalping Strategy
- Mean Reversion Strategy
- Framework for additional strategies (DarvasBox, RSICrossOver, RSIMidPoint)
## Usage
### For Individual EAs
Simply include the helper file:
```mql5
#include "../_united/MagicNumberHelpers.mqh"
```
Then replace:
- `PositionSelect(_Symbol)``PositionSelectByMagic(_Symbol, MagicNumber)`
- `PositionSelectByTicket(ticket)``PositionSelectByTicketAndMagic(ticket, MagicNumber)`
- `trade.PositionClose(_Symbol)``ClosePositionByMagic(trade, _Symbol, MagicNumber)`
- `trade.PositionModify(_Symbol, ...)``ModifyPositionByMagic(trade, _Symbol, MagicNumber, ...)`
### For United EA
1. Set unique magic numbers for each strategy
2. Enable/disable strategies via input parameters
3. Configure strategy-specific parameters
4. Run on chart - all enabled strategies will operate independently
## Remaining EAs to Fix
The following EAs should be updated similarly:
- DarvasBoxXAUUSD
- RSICrossOverReversalXAUUSD
- RSIMidPointHijackXAUUSD
- EMASlopeDistanceCocktailXAUUSD
- All RSIScalping variants (APPL, BTCUSD, MSFT, NVDA, TSLA)
## Best Practices
1. **Always use magic-aware functions** when checking/modifying positions
2. **Set unique magic numbers** for each EA instance
3. **Verify magic number** before any position operation
4. **Use United EA** when running multiple strategies on same symbol
+10 -9
View File
@@ -7,6 +7,7 @@
#property copyright "Copyright 2025, MetaQuotes Ltd."
#property version "1.00"
#include <Trade\Trade.mqh>
#include "../_united/MagicNumberHelpers.mqh"
//--- Eingabeparameter (Input Parameters) - Optimized Profitable Parameters
input int EMA_Periode = 46; // EMA Periode
input double PreisSchwelle = 600.0; // Preisbewegung Schwelle in Pips
@@ -127,7 +128,7 @@ void OnTick()
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("Position offen: ", PositionExistsByMagic(_Symbol, MagicNumber));
Print("Trades im aktuellen Crossover: ", trades_in_current_crossover, "/", MaxTradesPerCrossover);
Print("==================");
}
@@ -289,7 +290,7 @@ void PrüfeTrigger()
return;
}
if(bullish_signal && !PositionSelect(_Symbol))
if(bullish_signal && !PositionExistsByMagic(_Symbol, MagicNumber))
{
Print("TRACE: Versuche KAUF-Trade zu platzieren (Trade #", trades_in_current_crossover + 1, ")");
if(PlatziereTrade(ORDER_TYPE_BUY))
@@ -297,7 +298,7 @@ void PrüfeTrigger()
trades_in_current_crossover++;
}
}
else if(bearish_signal && !PositionSelect(_Symbol))
else if(bearish_signal && !PositionExistsByMagic(_Symbol, MagicNumber))
{
Print("TRACE: Versuche VERKAUF-Trade zu platzieren (Trade #", trades_in_current_crossover + 1, ")");
if(PlatziereTrade(ORDER_TYPE_SELL))
@@ -305,7 +306,7 @@ void PrüfeTrigger()
trades_in_current_crossover++;
}
}
else if(PositionSelect(_Symbol))
else if(PositionExistsByMagic(_Symbol, MagicNumber))
{
Print("TRACE: Position bereits offen - kein neuer Trade");
}
@@ -361,7 +362,7 @@ bool PlatziereTrade(ENUM_ORDER_TYPE order_type)
//+------------------------------------------------------------------+
void VerwalteTrades()
{
if(!PositionSelect(_Symbol))
if(!PositionSelectByMagic(_Symbol, MagicNumber))
return;
double position_profit = PositionGetDouble(POSITION_PROFIT);
@@ -417,7 +418,7 @@ void VerwalteTrades()
}
//--- Profit-Prüfung nach X Bars (Profit check after X bars)
if(CloseUnprofitableTrades && trade_open_time != 0 && PositionSelect(_Symbol))
if(CloseUnprofitableTrades && trade_open_time != 0 && PositionExistsByMagic(_Symbol, MagicNumber))
{
Print("TRACE: Profit-Prüfung aktiviert - CloseUnprofitableTrades: ", CloseUnprofitableTrades);
PrüfeProfitNachBars();
@@ -433,7 +434,7 @@ void VerwalteTrades()
//+------------------------------------------------------------------+
void PrüfeProfitNachBars()
{
if(!PositionSelect(_Symbol))
if(!PositionSelectByMagic(_Symbol, MagicNumber))
{
return; // Keine Position offen
}
@@ -479,7 +480,7 @@ 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));
bool success = ModifyPositionByMagic(trade, _Symbol, MagicNumber, new_stop_loss, PositionGetDouble(POSITION_TP));
if(success)
{
@@ -499,7 +500,7 @@ void SchließePosition(string reason = "Unbekannt")
{
Print("TRACE: Versuche Position zu schließen - Grund: ", reason);
bool success = trade.PositionClose(_Symbol);
bool success = ClosePositionByMagic(trade, _Symbol, MagicNumber);
if(success)
{
@@ -1,5 +1,6 @@
// Input Parameters
#include <Trade\Trade.mqh>
#include "../_united/MagicNumberHelpers.mqh"
input group "Trade Management"
input int MagicNumber = 7;
@@ -125,7 +126,7 @@ void OnTick() {
// Ensure there is at least one position
bool hasPosition = (PositionsTotal() > 0);
bool hasPosition = PositionExistsByMagic(_Symbol, MagicNumber);
@@ -157,7 +158,7 @@ void OnTick() {
bool isBuyPosition = false;
bool isSellPosition = false;
if (hasPosition) {
if (PositionSelect(_Symbol)) {
if (PositionSelectByMagic(_Symbol, MagicNumber)) {
int positionType = PositionGetInteger(POSITION_TYPE);
if (positionType == POSITION_TYPE_BUY) {
isBuyPosition = true;
@@ -237,77 +238,56 @@ void OnDeinit(const int reason) {
void Close_Position_MN(ulong magicNumber)
{
int total = PositionsTotal();
for(int i = total - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
// Use PositionSelect by symbol instead of ticket
string symbol = PositionGetSymbol(i);
if(PositionSelect(symbol))
{
if (PositionGetInteger(POSITION_MAGIC) == magicNumber && PositionGetInteger(POSITION_TICKET) == ticket)
{
if(symbol == _Symbol) // Verify the symbol
{
Print("MN " + magicNumber);
trade.PositionClose(ticket);
}
}
}
else
{
int errorCode = GetLastError();
Print("aaaa PositionSelect failed with error code: ", errorCode);
}
}
// Use helper function to close position by magic number
ClosePositionByMagic(trade, _Symbol, (int)magicNumber);
}
void ApplyTrailingStop()
{
Print("Scanning for trailing stop");
for(int i=PositionsTotal()-1; i>=0; i--)
// Check if position exists with our magic number
if(!PositionSelectByMagic(_Symbol, MagicNumber))
{
string symbol = PositionGetSymbol(i);
ulong PositionTicket = PositionGetTicket(i);
long trade_type = PositionGetInteger(POSITION_TYPE);
return; // No position with our magic number
}
ulong PositionTicket = PositionGetInteger(POSITION_TICKET);
long trade_type = PositionGetInteger(POSITION_TYPE);
string symbol = _Symbol;
if(!PositionGetInteger(POSITION_MAGIC) == MagicNumber) {
return;
}
double POINT = SymbolInfoDouble( symbol, SYMBOL_POINT );
int DIGIT = (int) SymbolInfoInteger( symbol, SYMBOL_DIGITS );
double POINT = SymbolInfoDouble(symbol, SYMBOL_POINT);
int DIGIT = (int) SymbolInfoInteger(symbol, SYMBOL_DIGITS);
if(trade_type == 0)
{
double Bid = NormalizeDouble(SymbolInfoDouble(symbol,SYMBOL_BID),DIGIT);
if(trade_type == POSITION_TYPE_BUY)
{
double Bid = NormalizeDouble(SymbolInfoDouble(symbol, SYMBOL_BID), DIGIT);
if(Bid-PositionGetDouble(POSITION_PRICE_OPEN) > NormalizeDouble(POINT * TrailingStop,DIGIT))
{
if(PositionGetDouble(POSITION_SL) < NormalizeDouble(Bid - POINT * TrailingStop,DIGIT))
{
trade.PositionModify(PositionTicket,NormalizeDouble(Bid - POINT * TrailingStop,DIGIT),PositionGetDouble(POSITION_TP));
}
}
if(Bid - PositionGetDouble(POSITION_PRICE_OPEN) > NormalizeDouble(POINT * TrailingStop, DIGIT))
{
if(PositionGetDouble(POSITION_SL) < NormalizeDouble(Bid - POINT * TrailingStop, DIGIT))
{
ModifyPositionByMagic(trade, symbol, MagicNumber,
NormalizeDouble(Bid - POINT * TrailingStop, DIGIT),
PositionGetDouble(POSITION_TP));
}
if(trade_type == 1)
{
double Ask = NormalizeDouble(SymbolInfoDouble(symbol,SYMBOL_ASK),DIGIT);
}
}
else if(trade_type == POSITION_TYPE_SELL)
{
double Ask = NormalizeDouble(SymbolInfoDouble(symbol, SYMBOL_ASK), DIGIT);
if((PositionGetDouble(POSITION_PRICE_OPEN) - Ask) > NormalizeDouble( POINT * TrailingStop,DIGIT))
{
if((PositionGetDouble(POSITION_SL) > NormalizeDouble(Ask + POINT * TrailingStop,DIGIT)) || (PositionGetDouble(POSITION_SL)==0))
{
trade.PositionModify(PositionTicket,NormalizeDouble(Ask + POINT * TrailingStop,DIGIT),PositionGetDouble(POSITION_TP));
}
}
if((PositionGetDouble(POSITION_PRICE_OPEN) - Ask) > NormalizeDouble(POINT * TrailingStop, DIGIT))
{
if((PositionGetDouble(POSITION_SL) > NormalizeDouble(Ask + POINT * TrailingStop, DIGIT)) ||
(PositionGetDouble(POSITION_SL) == 0))
{
ModifyPositionByMagic(trade, symbol, MagicNumber,
NormalizeDouble(Ask + POINT * TrailingStop, DIGIT),
PositionGetDouble(POSITION_TP));
}
}
}
}
}
int TimeHour(datetime when=0){ if(when == 0) when = TimeCurrent();
+31 -28
View File
@@ -9,6 +9,7 @@
#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>
#include "../_united/MagicNumberHelpers.mqh"
// Input Parameters
input group "General Settings"
@@ -158,19 +159,12 @@ bool IsWithinTradingHours(int startHour, int endHour)
}
//+------------------------------------------------------------------+
//| Check if position exists for given magic number |
//| Check if position exists for given magic number AND symbol |
//+------------------------------------------------------------------+
bool HasPosition(int magic)
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
if(positionInfo.SelectByIndex(i))
{
if(positionInfo.Magic() == magic)
return true;
}
}
return false;
// Use helper function that verifies BOTH symbol AND magic number for THIS EA
return PositionExistsByMagic(_Symbol, magic);
}
//+------------------------------------------------------------------+
@@ -572,30 +566,39 @@ void CheckExitConditions()
//+------------------------------------------------------------------+
void ClosePosition(int magic)
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
// Close position using helper that verifies symbol AND magic number for THIS EA
// First check if position exists for this EA on this symbol
if(!PositionExistsByMagic(_Symbol, magic))
{
if(positionInfo.SelectByIndex(i))
return; // No position for this EA on this symbol
}
// Get the position ticket for this EA on this symbol
ulong ticket = GetPositionTicketByMagic(_Symbol, magic);
if(ticket == 0)
{
return; // No valid ticket found
}
// Check if this is RSI Reverse position and update cooldown
if(magic == InpMagicNumberRSIReverse)
{
if(PositionSelectByTicketSymbolAndMagic(ticket, _Symbol, magic))
{
if(positionInfo.Magic() == magic)
datetime time[];
if(CopyTime(_Symbol, InpTimeframe, 0, 1, time) > 0)
{
// Check if this is RSI Reverse position and update cooldown
if(magic == InpMagicNumberRSIReverse)
rsiReverseLastCloseTime = time[0];
// Only enter cooldown if it's a loss or if cooldown on loss is disabled
double profit = PositionGetDouble(POSITION_PROFIT);
if(!InpRSIReverseCooldownOnLoss || profit < 0)
{
datetime time[];
if(CopyTime(_Symbol, InpTimeframe, 0, 1, time) > 0)
{
rsiReverseLastCloseTime = time[0];
// Only enter cooldown if it's a loss or if cooldown on loss is disabled
if(!InpRSIReverseCooldownOnLoss || positionInfo.Profit() < 0)
{
rsiReverseInCooldown = true;
}
}
rsiReverseInCooldown = true;
}
trade.PositionClose(positionInfo.Ticket());
break;
}
}
}
// Close the position using helper function
ClosePositionByMagic(trade, _Symbol, magic);
}
+57 -11
View File
@@ -8,6 +8,7 @@
#property version "1.00"
#include <Trade\Trade.mqh>
#include "../_united/MagicNumberHelpers.mqh"
//--- Input parameters
input ENUM_TIMEFRAMES TimeFrame = PERIOD_M10; // Timeframe for Analysis
@@ -95,8 +96,8 @@ void OnTick()
// Check for existing position
CheckExistingPosition();
// Check for new entry signals
if(!position_open)
// Check for new entry signals - only if no position exists for THIS EA (magic number) on THIS symbol
if(!position_open && !PositionExistsByMagic(_Symbol, MagicNumber))
{
CheckEntrySignals();
}
@@ -129,8 +130,8 @@ void CheckExistingPosition()
return;
}
// Check if position still exists
if(!PositionSelectByTicket(position_ticket))
// Check if position still exists with correct magic number AND symbol for THIS EA
if(!PositionSelectByTicketSymbolAndMagic(position_ticket, _Symbol, MagicNumber))
{
position_open = false;
position_ticket = 0;
@@ -241,13 +242,31 @@ void CheckEntrySignals()
//+------------------------------------------------------------------+
void OpenBuyPosition()
{
// Verify no position exists for THIS EA (magic number) on THIS symbol before opening
if(PositionExistsByMagic(_Symbol, MagicNumber))
{
return; // Position already exists for this EA
}
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;
ulong new_ticket = trade.ResultOrder();
if(new_ticket > 0)
{
// Verify position was opened for THIS EA (magic number) on THIS symbol
if(PositionSelectByTicketSymbolAndMagic(new_ticket, _Symbol, MagicNumber))
{
position_ticket = new_ticket;
position_open = true;
current_position_type = POSITION_TYPE_BUY;
}
else
{
Print("Error: Position opened but doesn't match EA magic number or symbol");
}
}
}
}
@@ -256,13 +275,31 @@ void OpenBuyPosition()
//+------------------------------------------------------------------+
void OpenSellPosition()
{
// Verify no position exists for THIS EA (magic number) on THIS symbol before opening
if(PositionExistsByMagic(_Symbol, MagicNumber))
{
return; // Position already exists for this EA
}
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;
ulong new_ticket = trade.ResultOrder();
if(new_ticket > 0)
{
// Verify position was opened for THIS EA (magic number) on THIS symbol
if(PositionSelectByTicketSymbolAndMagic(new_ticket, _Symbol, MagicNumber))
{
position_ticket = new_ticket;
position_open = true;
current_position_type = POSITION_TYPE_SELL;
}
else
{
Print("Error: Position opened but doesn't match EA magic number or symbol");
}
}
}
}
@@ -271,11 +308,20 @@ void OpenSellPosition()
//+------------------------------------------------------------------+
void ClosePosition()
{
if(trade.PositionClose(position_ticket))
// Close position using helper that verifies symbol AND magic number for THIS EA
if(ClosePositionByMagic(trade, _Symbol, MagicNumber))
{
position_open = false;
position_ticket = 0;
rsi_against_position = false;
bars_against_count = 0;
}
else
{
// Position doesn't exist or wrong magic number - reset tracking
position_open = false;
position_ticket = 0;
rsi_against_position = false;
bars_against_count = 0;
}
}
+57 -11
View File
@@ -8,6 +8,7 @@
#property version "1.00"
#include <Trade\Trade.mqh>
#include "../_united/MagicNumberHelpers.mqh"
//--- Input parameters
input ENUM_TIMEFRAMES TimeFrame = PERIOD_H1; // Timeframe for Analysis
@@ -95,8 +96,8 @@ void OnTick()
// Check for existing position
CheckExistingPosition();
// Check for new entry signals
if(!position_open)
// Check for new entry signals - only if no position exists for THIS EA (magic number) on THIS symbol
if(!position_open && !PositionExistsByMagic(_Symbol, MagicNumber))
{
CheckEntrySignals();
}
@@ -129,8 +130,8 @@ void CheckExistingPosition()
return;
}
// Check if position still exists
if(!PositionSelectByTicket(position_ticket))
// Check if position still exists with correct magic number AND symbol for THIS EA
if(!PositionSelectByTicketSymbolAndMagic(position_ticket, _Symbol, MagicNumber))
{
position_open = false;
position_ticket = 0;
@@ -241,13 +242,31 @@ void CheckEntrySignals()
//+------------------------------------------------------------------+
void OpenBuyPosition()
{
// Verify no position exists for THIS EA (magic number) on THIS symbol before opening
if(PositionExistsByMagic(_Symbol, MagicNumber))
{
return; // Position already exists for this EA
}
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;
ulong new_ticket = trade.ResultOrder();
if(new_ticket > 0)
{
// Verify position was opened for THIS EA (magic number) on THIS symbol
if(PositionSelectByTicketSymbolAndMagic(new_ticket, _Symbol, MagicNumber))
{
position_ticket = new_ticket;
position_open = true;
current_position_type = POSITION_TYPE_BUY;
}
else
{
Print("Error: Position opened but doesn't match EA magic number or symbol");
}
}
}
}
@@ -256,13 +275,31 @@ void OpenBuyPosition()
//+------------------------------------------------------------------+
void OpenSellPosition()
{
// Verify no position exists for THIS EA (magic number) on THIS symbol before opening
if(PositionExistsByMagic(_Symbol, MagicNumber))
{
return; // Position already exists for this EA
}
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;
ulong new_ticket = trade.ResultOrder();
if(new_ticket > 0)
{
// Verify position was opened for THIS EA (magic number) on THIS symbol
if(PositionSelectByTicketSymbolAndMagic(new_ticket, _Symbol, MagicNumber))
{
position_ticket = new_ticket;
position_open = true;
current_position_type = POSITION_TYPE_SELL;
}
else
{
Print("Error: Position opened but doesn't match EA magic number or symbol");
}
}
}
}
@@ -271,11 +308,20 @@ void OpenSellPosition()
//+------------------------------------------------------------------+
void ClosePosition()
{
if(trade.PositionClose(position_ticket))
// Close position using helper that verifies symbol AND magic number for THIS EA
if(ClosePositionByMagic(trade, _Symbol, MagicNumber))
{
position_open = false;
position_ticket = 0;
rsi_against_position = false;
bars_against_count = 0;
}
else
{
// Position doesn't exist or wrong magic number - reset tracking
position_open = false;
position_ticket = 0;
rsi_against_position = false;
bars_against_count = 0;
}
}
+57 -11
View File
@@ -8,6 +8,7 @@
#property version "1.00"
#include <Trade\Trade.mqh>
#include "../_united/MagicNumberHelpers.mqh"
//--- Input parameters
input ENUM_TIMEFRAMES TimeFrame = PERIOD_H3; // Timeframe for Analysis
@@ -95,8 +96,8 @@ void OnTick()
// Check for existing position
CheckExistingPosition();
// Check for new entry signals
if(!position_open)
// Check for new entry signals - only if no position exists for THIS EA (magic number) on THIS symbol
if(!position_open && !PositionExistsByMagic(_Symbol, MagicNumber))
{
CheckEntrySignals();
}
@@ -129,8 +130,8 @@ void CheckExistingPosition()
return;
}
// Check if position still exists
if(!PositionSelectByTicket(position_ticket))
// Check if position still exists with correct magic number AND symbol for THIS EA
if(!PositionSelectByTicketSymbolAndMagic(position_ticket, _Symbol, MagicNumber))
{
position_open = false;
position_ticket = 0;
@@ -241,13 +242,31 @@ void CheckEntrySignals()
//+------------------------------------------------------------------+
void OpenBuyPosition()
{
// Verify no position exists for THIS EA (magic number) on THIS symbol before opening
if(PositionExistsByMagic(_Symbol, MagicNumber))
{
return; // Position already exists for this EA
}
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;
ulong new_ticket = trade.ResultOrder();
if(new_ticket > 0)
{
// Verify position was opened for THIS EA (magic number) on THIS symbol
if(PositionSelectByTicketSymbolAndMagic(new_ticket, _Symbol, MagicNumber))
{
position_ticket = new_ticket;
position_open = true;
current_position_type = POSITION_TYPE_BUY;
}
else
{
Print("Error: Position opened but doesn't match EA magic number or symbol");
}
}
}
}
@@ -256,13 +275,31 @@ void OpenBuyPosition()
//+------------------------------------------------------------------+
void OpenSellPosition()
{
// Verify no position exists for THIS EA (magic number) on THIS symbol before opening
if(PositionExistsByMagic(_Symbol, MagicNumber))
{
return; // Position already exists for this EA
}
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;
ulong new_ticket = trade.ResultOrder();
if(new_ticket > 0)
{
// Verify position was opened for THIS EA (magic number) on THIS symbol
if(PositionSelectByTicketSymbolAndMagic(new_ticket, _Symbol, MagicNumber))
{
position_ticket = new_ticket;
position_open = true;
current_position_type = POSITION_TYPE_SELL;
}
else
{
Print("Error: Position opened but doesn't match EA magic number or symbol");
}
}
}
}
@@ -271,11 +308,20 @@ void OpenSellPosition()
//+------------------------------------------------------------------+
void ClosePosition()
{
if(trade.PositionClose(position_ticket))
// Close position using helper that verifies symbol AND magic number for THIS EA
if(ClosePositionByMagic(trade, _Symbol, MagicNumber))
{
position_open = false;
position_ticket = 0;
rsi_against_position = false;
bars_against_count = 0;
}
else
{
// Position doesn't exist or wrong magic number - reset tracking
position_open = false;
position_ticket = 0;
rsi_against_position = false;
bars_against_count = 0;
}
}
+57 -11
View File
@@ -8,6 +8,7 @@
#property version "1.00"
#include <Trade\Trade.mqh>
#include "../_united/MagicNumberHelpers.mqh"
//--- Input parameters
input ENUM_TIMEFRAMES TimeFrame = PERIOD_M15; // Timeframe for Analysis
@@ -95,8 +96,8 @@ void OnTick()
// Check for existing position
CheckExistingPosition();
// Check for new entry signals
if(!position_open)
// Check for new entry signals - only if no position exists for THIS EA (magic number) on THIS symbol
if(!position_open && !PositionExistsByMagic(_Symbol, MagicNumber))
{
CheckEntrySignals();
}
@@ -129,8 +130,8 @@ void CheckExistingPosition()
return;
}
// Check if position still exists
if(!PositionSelectByTicket(position_ticket))
// Check if position still exists with correct magic number AND symbol for THIS EA
if(!PositionSelectByTicketSymbolAndMagic(position_ticket, _Symbol, MagicNumber))
{
position_open = false;
position_ticket = 0;
@@ -241,13 +242,31 @@ void CheckEntrySignals()
//+------------------------------------------------------------------+
void OpenBuyPosition()
{
// Verify no position exists for THIS EA (magic number) on THIS symbol before opening
if(PositionExistsByMagic(_Symbol, MagicNumber))
{
return; // Position already exists for this EA
}
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;
ulong new_ticket = trade.ResultOrder();
if(new_ticket > 0)
{
// Verify position was opened for THIS EA (magic number) on THIS symbol
if(PositionSelectByTicketSymbolAndMagic(new_ticket, _Symbol, MagicNumber))
{
position_ticket = new_ticket;
position_open = true;
current_position_type = POSITION_TYPE_BUY;
}
else
{
Print("Error: Position opened but doesn't match EA magic number or symbol");
}
}
}
}
@@ -256,13 +275,31 @@ void OpenBuyPosition()
//+------------------------------------------------------------------+
void OpenSellPosition()
{
// Verify no position exists for THIS EA (magic number) on THIS symbol before opening
if(PositionExistsByMagic(_Symbol, MagicNumber))
{
return; // Position already exists for this EA
}
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;
ulong new_ticket = trade.ResultOrder();
if(new_ticket > 0)
{
// Verify position was opened for THIS EA (magic number) on THIS symbol
if(PositionSelectByTicketSymbolAndMagic(new_ticket, _Symbol, MagicNumber))
{
position_ticket = new_ticket;
position_open = true;
current_position_type = POSITION_TYPE_SELL;
}
else
{
Print("Error: Position opened but doesn't match EA magic number or symbol");
}
}
}
}
@@ -271,11 +308,20 @@ void OpenSellPosition()
//+------------------------------------------------------------------+
void ClosePosition()
{
if(trade.PositionClose(position_ticket))
// Close position using helper that verifies symbol AND magic number for THIS EA
if(ClosePositionByMagic(trade, _Symbol, MagicNumber))
{
position_open = false;
position_ticket = 0;
rsi_against_position = false;
bars_against_count = 0;
}
else
{
// Position doesn't exist or wrong magic number - reset tracking
position_open = false;
position_ticket = 0;
rsi_against_position = false;
bars_against_count = 0;
}
}
+57 -11
View File
@@ -8,6 +8,7 @@
#property version "1.00"
#include <Trade\Trade.mqh>
#include "../_united/MagicNumberHelpers.mqh"
//--- Input parameters
input ENUM_TIMEFRAMES TimeFrame = PERIOD_H1; // Timeframe for Analysis
@@ -95,8 +96,8 @@ void OnTick()
// Check for existing position
CheckExistingPosition();
// Check for new entry signals
if(!position_open)
// Check for new entry signals - only if no position exists for THIS EA (magic number) on THIS symbol
if(!position_open && !PositionExistsByMagic(_Symbol, MagicNumber))
{
CheckEntrySignals();
}
@@ -129,8 +130,8 @@ void CheckExistingPosition()
return;
}
// Check if position still exists
if(!PositionSelectByTicket(position_ticket))
// Check if position still exists with correct magic number AND symbol for THIS EA
if(!PositionSelectByTicketSymbolAndMagic(position_ticket, _Symbol, MagicNumber))
{
position_open = false;
position_ticket = 0;
@@ -241,13 +242,31 @@ void CheckEntrySignals()
//+------------------------------------------------------------------+
void OpenBuyPosition()
{
// Verify no position exists for THIS EA (magic number) on THIS symbol before opening
if(PositionExistsByMagic(_Symbol, MagicNumber))
{
return; // Position already exists for this EA
}
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;
ulong new_ticket = trade.ResultOrder();
if(new_ticket > 0)
{
// Verify position was opened for THIS EA (magic number) on THIS symbol
if(PositionSelectByTicketSymbolAndMagic(new_ticket, _Symbol, MagicNumber))
{
position_ticket = new_ticket;
position_open = true;
current_position_type = POSITION_TYPE_BUY;
}
else
{
Print("Error: Position opened but doesn't match EA magic number or symbol");
}
}
}
}
@@ -256,13 +275,31 @@ void OpenBuyPosition()
//+------------------------------------------------------------------+
void OpenSellPosition()
{
// Verify no position exists for THIS EA (magic number) on THIS symbol before opening
if(PositionExistsByMagic(_Symbol, MagicNumber))
{
return; // Position already exists for this EA
}
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;
ulong new_ticket = trade.ResultOrder();
if(new_ticket > 0)
{
// Verify position was opened for THIS EA (magic number) on THIS symbol
if(PositionSelectByTicketSymbolAndMagic(new_ticket, _Symbol, MagicNumber))
{
position_ticket = new_ticket;
position_open = true;
current_position_type = POSITION_TYPE_SELL;
}
else
{
Print("Error: Position opened but doesn't match EA magic number or symbol");
}
}
}
}
@@ -271,11 +308,20 @@ void OpenSellPosition()
//+------------------------------------------------------------------+
void ClosePosition()
{
if(trade.PositionClose(position_ticket))
// Close position using helper that verifies symbol AND magic number for THIS EA
if(ClosePositionByMagic(trade, _Symbol, MagicNumber))
{
position_open = false;
position_ticket = 0;
rsi_against_position = false;
bars_against_count = 0;
}
else
{
// Position doesn't exist or wrong magic number - reset tracking
position_open = false;
position_ticket = 0;
rsi_against_position = false;
bars_against_count = 0;
}
}
+15 -5
View File
@@ -8,6 +8,7 @@
#property version "1.00"
#include <Trade\Trade.mqh>
#include "../_united/MagicNumberHelpers.mqh"
//--- Input parameters
input ENUM_TIMEFRAMES TimeFrame = PERIOD_H1; // Timeframe for Analysis
@@ -95,8 +96,8 @@ void OnTick()
// Check for existing position
CheckExistingPosition();
// Check for new entry signals
if(!position_open)
// Check for new entry signals (also verify no position exists with our magic number)
if(!position_open && !PositionExistsByMagic(_Symbol, MagicNumber))
{
CheckEntrySignals();
}
@@ -129,8 +130,8 @@ void CheckExistingPosition()
return;
}
// Check if position still exists
if(!PositionSelectByTicket(position_ticket))
// Check if position still exists with correct magic number
if(!PositionSelectByTicketAndMagic(position_ticket, MagicNumber))
{
position_open = false;
position_ticket = 0;
@@ -271,11 +272,20 @@ void OpenSellPosition()
//+------------------------------------------------------------------+
void ClosePosition()
{
if(trade.PositionClose(position_ticket))
// Close position using helper function that verifies symbol AND magic number
if(ClosePositionByMagic(trade, _Symbol, MagicNumber))
{
position_open = false;
position_ticket = 0;
rsi_against_position = false;
bars_against_count = 0;
}
else
{
// Position doesn't exist or wrong magic number - reset tracking anyway
position_open = false;
position_ticket = 0;
rsi_against_position = false;
bars_against_count = 0;
}
}
@@ -0,0 +1,159 @@
//+------------------------------------------------------------------+
//| MagicNumberHelpers.mqh |
//| Copyright 2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
//+------------------------------------------------------------------+
//| Select position by symbol and magic number |
//+------------------------------------------------------------------+
bool PositionSelectByMagic(string symbol, ulong magic_number)
{
// First try to find position by symbol
if(!PositionSelect(symbol))
return false;
// Check if the selected position has the correct magic number
if(PositionGetInteger(POSITION_MAGIC) != magic_number)
{
// Position exists but wrong magic number, search all positions
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
if(PositionGetTicket(i) > 0)
{
if(PositionGetString(POSITION_SYMBOL) == symbol &&
PositionGetInteger(POSITION_MAGIC) == magic_number)
{
return true;
}
}
}
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| Select position by ticket and verify magic number and symbol |
//+------------------------------------------------------------------+
bool PositionSelectByTicketAndMagic(ulong ticket, ulong magic_number)
{
if(!PositionSelectByTicket(ticket))
return false;
return (PositionGetInteger(POSITION_MAGIC) == magic_number);
}
//+------------------------------------------------------------------+
//| Select position by ticket and verify symbol, magic number |
//+------------------------------------------------------------------+
bool PositionSelectByTicketSymbolAndMagic(ulong ticket, string symbol, ulong magic_number)
{
if(!PositionSelectByTicket(ticket))
return false;
return (PositionGetString(POSITION_SYMBOL) == symbol &&
PositionGetInteger(POSITION_MAGIC) == magic_number);
}
//+------------------------------------------------------------------+
//| Check if position exists with correct magic number |
//+------------------------------------------------------------------+
bool PositionExistsByMagic(string symbol, ulong magic_number)
{
return PositionSelectByMagic(symbol, magic_number);
}
//+------------------------------------------------------------------+
//| Get position ticket by symbol and magic number |
//+------------------------------------------------------------------+
ulong GetPositionTicketByMagic(string symbol, ulong magic_number)
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket > 0)
{
if(PositionGetString(POSITION_SYMBOL) == symbol &&
PositionGetInteger(POSITION_MAGIC) == magic_number)
{
return ticket;
}
}
}
return 0;
}
//+------------------------------------------------------------------+
//| Close position by symbol and magic number |
//+------------------------------------------------------------------+
bool ClosePositionByMagic(CTrade &trade_obj, string symbol, ulong magic_number)
{
ulong ticket = GetPositionTicketByMagic(symbol, magic_number);
if(ticket == 0)
return false;
return trade_obj.PositionClose(ticket);
}
//+------------------------------------------------------------------+
//| Modify position by symbol and magic number |
//+------------------------------------------------------------------+
bool ModifyPositionByMagic(CTrade &trade_obj, string symbol, ulong magic_number,
double sl, double tp)
{
ulong ticket = GetPositionTicketByMagic(symbol, magic_number);
if(ticket == 0)
return false;
return trade_obj.PositionModify(ticket, sl, tp);
}
//+------------------------------------------------------------------+
//| Get position profit by symbol and magic number |
//+------------------------------------------------------------------+
double GetPositionProfitByMagic(string symbol, ulong magic_number)
{
if(!PositionSelectByMagic(symbol, magic_number))
return 0.0;
return PositionGetDouble(POSITION_PROFIT);
}
//+------------------------------------------------------------------+
//| Get position type by symbol and magic number |
//+------------------------------------------------------------------+
ENUM_POSITION_TYPE GetPositionTypeByMagic(string symbol, ulong magic_number)
{
if(!PositionSelectByMagic(symbol, magic_number))
return WRONG_VALUE;
return (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
}
//+------------------------------------------------------------------+
//| Count positions by symbol and magic number |
//+------------------------------------------------------------------+
int CountPositionsByMagic(string symbol, ulong magic_number)
{
int count = 0;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket > 0)
{
if(PositionGetString(POSITION_SYMBOL) == symbol &&
PositionGetInteger(POSITION_MAGIC) == magic_number)
{
count++;
}
}
}
return count;
}
//+------------------------------------------------------------------+
+962
View File
@@ -0,0 +1,962 @@
//+------------------------------------------------------------------+
//| UnitedEA.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"
#property description "United EA - Runs multiple strategies on multiple instruments with instrument-specific parameters"
#include <Trade\Trade.mqh>
#include "MagicNumberHelpers.mqh"
//--- Strategy Selection
input bool EnableRSIScalping = true; // Enable RSI Scalping Strategy
input bool EnableMeanReversion = true; // Enable Mean Reversion Strategy
input bool EnableDarvasBox = true; // Enable Darvas Box Strategy
input bool EnableRSICrossOver = true; // Enable RSI Crossover Strategy
input bool EnableRSIMidPoint = true; // Enable RSI Midpoint Strategy
//--- Instrument Selection for RSI Scalping (each with its own parameters)
input bool EnableRSI_XAUUSD = true; // Enable RSI Scalping on XAUUSD
input bool EnableRSI_APPL = true; // Enable RSI Scalping on APPL
input bool EnableRSI_BTCUSD = true; // Enable RSI Scalping on BTCUSD
input bool EnableRSI_MSFT = true; // Enable RSI Scalping on MSFT
input bool EnableRSI_NVDA = true; // Enable RSI Scalping on NVDA
input bool EnableRSI_TSLA = true; // Enable RSI Scalping on TSLA
//--- Magic Numbers for RSI Scalping (one per instrument)
input int MagicNumber_RSI_XAUUSD = 129102315; // Magic Number for RSI Scalping XAUUSD
input int MagicNumber_RSI_APPL = 123457; // Magic Number for RSI Scalping APPL
input int MagicNumber_RSI_BTCUSD = 123459123; // Magic Number for RSI Scalping BTCUSD
input int MagicNumber_RSI_MSFT = 123456; // Magic Number for RSI Scalping MSFT
input int MagicNumber_RSI_NVDA = 12345; // Magic Number for RSI Scalping NVDA
input int MagicNumber_RSI_TSLA = 125421321; // Magic Number for RSI Scalping TSLA
//--- Magic Numbers for Other Strategies
input int MagicNumber_MeanReversion = 12351; // Magic Number for Mean Reversion
input int MagicNumber_DarvasBox = 135790; // Magic Number for Darvas Box
input int MagicNumber_RSICrossOver = 123456; // Magic Number for RSI Crossover
input int MagicNumber_RSIMidPoint = 123457; // Magic Number for RSI Midpoint
//--- RSI Scalping Parameters: XAUUSD
input ENUM_TIMEFRAMES RSI_XAUUSD_TimeFrame = PERIOD_H1;
input int RSI_XAUUSD_Period = 14;
input double RSI_XAUUSD_Overbought = 71;
input double RSI_XAUUSD_Oversold = 57;
input double RSI_XAUUSD_Target_Buy = 80;
input double RSI_XAUUSD_Target_Sell = 57;
input int RSI_XAUUSD_BarsToWait = 4;
input double RSI_XAUUSD_LotSize = 0.1;
//--- RSI Scalping Parameters: APPL
input ENUM_TIMEFRAMES RSI_APPL_TimeFrame = PERIOD_M10;
input int RSI_APPL_Period = 14;
input double RSI_APPL_Overbought = 80;
input double RSI_APPL_Oversold = 78;
input double RSI_APPL_Target_Buy = 94;
input double RSI_APPL_Target_Sell = 44;
input int RSI_APPL_BarsToWait = 7;
input double RSI_APPL_LotSize = 25;
//--- RSI Scalping Parameters: BTCUSD
input ENUM_TIMEFRAMES RSI_BTCUSD_TimeFrame = PERIOD_H1;
input int RSI_BTCUSD_Period = 14;
input double RSI_BTCUSD_Overbought = 90;
input double RSI_BTCUSD_Oversold = 73;
input double RSI_BTCUSD_Target_Buy = 88;
input double RSI_BTCUSD_Target_Sell = 48;
input int RSI_BTCUSD_BarsToWait = 6;
input double RSI_BTCUSD_LotSize = 0.1;
//--- RSI Scalping Parameters: MSFT
input ENUM_TIMEFRAMES RSI_MSFT_TimeFrame = PERIOD_H3;
input int RSI_MSFT_Period = 14;
input double RSI_MSFT_Overbought = 19;
input double RSI_MSFT_Oversold = 50;
input double RSI_MSFT_Target_Buy = 71;
input double RSI_MSFT_Target_Sell = 70;
input int RSI_MSFT_BarsToWait = 1;
input double RSI_MSFT_LotSize = 50;
//--- RSI Scalping Parameters: NVDA
input ENUM_TIMEFRAMES RSI_NVDA_TimeFrame = PERIOD_M15;
input int RSI_NVDA_Period = 8;
input double RSI_NVDA_Overbought = 36;
input double RSI_NVDA_Oversold = 38;
input double RSI_NVDA_Target_Buy = 90;
input double RSI_NVDA_Target_Sell = 70;
input int RSI_NVDA_BarsToWait = 5;
input double RSI_NVDA_LotSize = 50;
//--- RSI Scalping Parameters: TSLA
input ENUM_TIMEFRAMES RSI_TSLA_TimeFrame = PERIOD_H1;
input int RSI_TSLA_Period = 14;
input double RSI_TSLA_Overbought = 54;
input double RSI_TSLA_Oversold = 73;
input double RSI_TSLA_Target_Buy = 87;
input double RSI_TSLA_Target_Sell = 33;
input int RSI_TSLA_BarsToWait = 1;
input double RSI_TSLA_LotSize = 50;
//--- Mean Reversion Parameters
input int EMA_Periode = 46;
input double PreisSchwelle = 600.0;
input double SteigungSchwelle = 80.0;
input int ÜberwachungTimeout = 800;
input double TrailingStop = 260.0;
input double MeanRev_LotSize = 0.03;
input ENUM_TIMEFRAMES MeanRev_Timeframe = PERIOD_H1;
//--- Structure for RSI Scalping Strategy Instance
struct RSIScalpingStrategy
{
string symbol;
int magic_number;
ENUM_TIMEFRAMES timeframe;
int period;
double overbought;
double oversold;
double target_buy;
double target_sell;
int bars_to_wait;
double lot_size;
int rsi_handle;
double rsi_buffer[];
ulong position_ticket;
bool position_open;
bool buy_position_open;
bool sell_position_open;
datetime last_bar_time;
bool rsi_against_position;
int bars_against_count;
ENUM_POSITION_TYPE current_position_type;
};
//--- Global variables
CTrade trade;
RSIScalpingStrategy rsi_strategies[6]; // Array for 6 instruments
int rsi_strategy_count = 0;
int ema_handle_meanrev = INVALID_HANDLE;
double ema_array[];
ulong meanrev_ticket = 0;
bool meanrev_position_open = false;
datetime last_bar_time_meanrev = 0;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Initialize trade object
trade.SetDeviationInPoints(10);
trade.SetTypeFilling(ORDER_FILLING_FOK);
// Initialize RSI Scalping strategies for each enabled instrument
if(EnableRSIScalping)
{
if(EnableRSI_XAUUSD)
{
InitializeRSIStrategy("XAUUSD", MagicNumber_RSI_XAUUSD,
RSI_XAUUSD_TimeFrame, RSI_XAUUSD_Period,
RSI_XAUUSD_Overbought, RSI_XAUUSD_Oversold,
RSI_XAUUSD_Target_Buy, RSI_XAUUSD_Target_Sell,
RSI_XAUUSD_BarsToWait, RSI_XAUUSD_LotSize);
}
if(EnableRSI_APPL)
{
// Try different symbol variations for Apple (Pepperstone typically uses AAPL without suffix)
// Try: AAPL, AAPL.US, APPL (in case of typo in broker)
string appl_symbol = GetValidSymbol("AAPL", "AAPL.US");
if(appl_symbol != "")
{
InitializeRSIStrategy(appl_symbol, MagicNumber_RSI_APPL,
RSI_APPL_TimeFrame, RSI_APPL_Period,
RSI_APPL_Overbought, RSI_APPL_Oversold,
RSI_APPL_Target_Buy, RSI_APPL_Target_Sell,
RSI_APPL_BarsToWait, RSI_APPL_LotSize);
}
else
{
Print("Skipping AAPL strategy - symbol not available");
}
}
if(EnableRSI_BTCUSD)
{
InitializeRSIStrategy("BTCUSD", MagicNumber_RSI_BTCUSD,
RSI_BTCUSD_TimeFrame, RSI_BTCUSD_Period,
RSI_BTCUSD_Overbought, RSI_BTCUSD_Oversold,
RSI_BTCUSD_Target_Buy, RSI_BTCUSD_Target_Sell,
RSI_BTCUSD_BarsToWait, RSI_BTCUSD_LotSize);
}
if(EnableRSI_MSFT)
{
// Pepperstone typically uses MSFT without suffix
string msft_symbol = GetValidSymbol("MSFT", "MSFT.US");
if(msft_symbol != "")
{
InitializeRSIStrategy(msft_symbol, MagicNumber_RSI_MSFT,
RSI_MSFT_TimeFrame, RSI_MSFT_Period,
RSI_MSFT_Overbought, RSI_MSFT_Oversold,
RSI_MSFT_Target_Buy, RSI_MSFT_Target_Sell,
RSI_MSFT_BarsToWait, RSI_MSFT_LotSize);
}
else
{
Print("Skipping MSFT strategy - symbol not available");
}
}
if(EnableRSI_NVDA)
{
// Pepperstone typically uses NVDA without suffix
string nvda_symbol = GetValidSymbol("NVDA", "NVDA.US");
if(nvda_symbol != "")
{
InitializeRSIStrategy(nvda_symbol, MagicNumber_RSI_NVDA,
RSI_NVDA_TimeFrame, RSI_NVDA_Period,
RSI_NVDA_Overbought, RSI_NVDA_Oversold,
RSI_NVDA_Target_Buy, RSI_NVDA_Target_Sell,
RSI_NVDA_BarsToWait, RSI_NVDA_LotSize);
}
else
{
Print("Skipping NVDA strategy - symbol not available");
}
}
if(EnableRSI_TSLA)
{
// Pepperstone typically uses TSLA without suffix
string tsla_symbol = GetValidSymbol("TSLA", "TSLA.US");
if(tsla_symbol != "")
{
InitializeRSIStrategy(tsla_symbol, MagicNumber_RSI_TSLA,
RSI_TSLA_TimeFrame, RSI_TSLA_Period,
RSI_TSLA_Overbought, RSI_TSLA_Oversold,
RSI_TSLA_Target_Buy, RSI_TSLA_Target_Sell,
RSI_TSLA_BarsToWait, RSI_TSLA_LotSize);
}
else
{
Print("Skipping TSLA strategy - symbol not available");
}
}
}
// Initialize Mean Reversion indicator
if(EnableMeanReversion)
{
ema_handle_meanrev = iMA(_Symbol, MeanRev_Timeframe, EMA_Periode, 0, MODE_EMA, PRICE_CLOSE);
if(ema_handle_meanrev == INVALID_HANDLE)
{
Print("Error: Failed to create EMA indicator for Mean Reversion");
return(INIT_FAILED);
}
ArraySetAsSeries(ema_array, true);
trade.SetExpertMagicNumber(MagicNumber_MeanReversion);
Print("Mean Reversion Strategy initialized with Magic: ", MagicNumber_MeanReversion);
}
Print("United EA initialized successfully");
Print("Active RSI Scalping Strategies: ", rsi_strategy_count);
for(int i = 0; i < rsi_strategy_count; i++)
{
Print(" - ", rsi_strategies[i].symbol, " (Magic: ", rsi_strategies[i].magic_number,
", TF: ", EnumToString(rsi_strategies[i].timeframe), ")");
}
if(EnableMeanReversion) Print(" - Mean Reversion (Magic: ", MagicNumber_MeanReversion, ")");
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Get valid symbol name (try variations) |
//+------------------------------------------------------------------+
string GetValidSymbol(string preferred, string fallback)
{
string symbols_to_try[];
ArrayResize(symbols_to_try, 0);
// Build list of symbols to try
ArrayResize(symbols_to_try, 1);
symbols_to_try[0] = preferred;
if(fallback != preferred)
{
ArrayResize(symbols_to_try, 2);
symbols_to_try[1] = fallback;
}
// If preferred has .US, also try without it
if(StringFind(preferred, ".US") >= 0)
{
string without_suffix = preferred;
StringReplace(without_suffix, ".US", "");
if(without_suffix != fallback)
{
int size = ArraySize(symbols_to_try);
ArrayResize(symbols_to_try, size + 1);
symbols_to_try[size] = without_suffix;
}
}
// Try each symbol variation
for(int i = 0; i < ArraySize(symbols_to_try); i++)
{
string test_symbol = symbols_to_try[i];
// Try to select the symbol
if(!SymbolSelect(test_symbol, true))
{
// Symbol might already be selected, check if it exists
if(!SymbolInfoInteger(test_symbol, SYMBOL_SELECT))
{
continue; // Symbol doesn't exist, try next
}
}
// Verify symbol is visible
if(SymbolInfoInteger(test_symbol, SYMBOL_VISIBLE))
{
// Check if we can get price data (symbol is really available)
// During initialization, prices might be 0 if symbol is still synchronizing
// So we'll be lenient and accept the symbol if it's visible
double bid = SymbolInfoDouble(test_symbol, SYMBOL_BID);
double ask = SymbolInfoDouble(test_symbol, SYMBOL_ASK);
// Accept symbol if it has valid prices OR if it's visible (might be syncing)
if((bid > 0 && ask > 0) || SymbolInfoInteger(test_symbol, SYMBOL_VISIBLE))
{
if(bid > 0 && ask > 0)
{
Print("Using symbol: ", test_symbol, " (Bid: ", bid, ", Ask: ", ask, ")");
}
else
{
Print("Using symbol: ", test_symbol, " (synchronizing, prices not yet available)");
}
return test_symbol;
}
}
}
Print("Error: Could not find valid symbol for ", preferred, " or ", fallback);
Print("Tried ", ArraySize(symbols_to_try), " symbol variations:");
for(int i = 0; i < ArraySize(symbols_to_try); i++)
{
Print(" ", (i+1), ". ", symbols_to_try[i]);
}
Print("These symbols may not be available in your broker's symbol list.");
Print("Please add the symbol to Market Watch or disable this strategy.");
return ""; // Return empty string to indicate failure
}
//+------------------------------------------------------------------+
//| Initialize RSI Scalping Strategy for an instrument |
//+------------------------------------------------------------------+
void InitializeRSIStrategy(string symbol, int magic, ENUM_TIMEFRAMES tf, int period,
double overbought, double oversold, double target_buy,
double target_sell, int bars_wait, double lot_size)
{
if(rsi_strategy_count >= 6)
{
Print("Error: Maximum 6 RSI strategies allowed");
return;
}
// Work directly with array element (no reference)
rsi_strategies[rsi_strategy_count].symbol = symbol;
rsi_strategies[rsi_strategy_count].magic_number = magic;
rsi_strategies[rsi_strategy_count].timeframe = tf;
rsi_strategies[rsi_strategy_count].period = period;
rsi_strategies[rsi_strategy_count].overbought = overbought;
rsi_strategies[rsi_strategy_count].oversold = oversold;
rsi_strategies[rsi_strategy_count].target_buy = target_buy;
rsi_strategies[rsi_strategy_count].target_sell = target_sell;
rsi_strategies[rsi_strategy_count].bars_to_wait = bars_wait;
rsi_strategies[rsi_strategy_count].lot_size = lot_size;
rsi_strategies[rsi_strategy_count].position_ticket = 0;
rsi_strategies[rsi_strategy_count].position_open = false;
rsi_strategies[rsi_strategy_count].buy_position_open = false;
rsi_strategies[rsi_strategy_count].sell_position_open = false;
rsi_strategies[rsi_strategy_count].last_bar_time = 0;
rsi_strategies[rsi_strategy_count].rsi_against_position = false;
rsi_strategies[rsi_strategy_count].bars_against_count = 0;
rsi_strategies[rsi_strategy_count].current_position_type = WRONG_VALUE;
// Ensure symbol is selected before creating indicator
if(!SymbolSelect(symbol, true))
{
// Symbol might already be selected, check if it exists
if(!SymbolInfoInteger(symbol, SYMBOL_SELECT))
{
Print("Error: Failed to select symbol ", symbol, " for RSI indicator");
Print("Please ensure the symbol exists in Market Watch or add it manually");
return;
}
}
// Verify symbol is visible (prices might be 0 during synchronization)
if(!SymbolInfoInteger(symbol, SYMBOL_VISIBLE))
{
Print("Error: Symbol ", symbol, " is not visible");
Print("Please add the symbol to Market Watch");
return;
}
// Check prices (but don't fail if they're 0 - symbol might be syncing)
double bid = SymbolInfoDouble(symbol, SYMBOL_BID);
double ask = SymbolInfoDouble(symbol, SYMBOL_ASK);
if(bid <= 0 || ask <= 0)
{
Print("Warning: Symbol ", symbol, " has no prices yet (Bid: ", bid, ", Ask: ", ask, ")");
Print("Symbol may be synchronizing. Will attempt to create indicator anyway...");
}
// Create RSI indicator for this symbol
rsi_strategies[rsi_strategy_count].rsi_handle = iRSI(symbol, tf, period, PRICE_CLOSE);
if(rsi_strategies[rsi_strategy_count].rsi_handle == INVALID_HANDLE)
{
int error = GetLastError();
Print("Error: Failed to create RSI indicator for ", symbol, " (Error: ", error, ")");
Print("Symbol: ", symbol, ", Timeframe: ", EnumToString(tf), ", Period: ", period);
Print("Please check if the symbol is available in your broker's symbol list");
return;
}
ArraySetAsSeries(rsi_strategies[rsi_strategy_count].rsi_buffer, true);
rsi_strategy_count++;
Print("RSI Scalping Strategy initialized for ", symbol,
" (Magic: ", magic, ", TF: ", EnumToString(tf), ")");
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// Release all RSI indicators
for(int i = 0; i < rsi_strategy_count; i++)
{
if(rsi_strategies[i].rsi_handle != INVALID_HANDLE)
IndicatorRelease(rsi_strategies[i].rsi_handle);
}
if(ema_handle_meanrev != INVALID_HANDLE)
IndicatorRelease(ema_handle_meanrev);
Print("United EA deinitialized");
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Run RSI Scalping Strategies for all enabled instruments
if(EnableRSIScalping)
{
for(int i = 0; i < rsi_strategy_count; i++)
{
RunRSIScalpingStrategy(i);
}
}
// Run Mean Reversion Strategy
if(EnableMeanReversion)
{
RunMeanReversionStrategy();
}
}
//+------------------------------------------------------------------+
//| RSI Scalping Strategy for a specific instrument (by index) |
//+------------------------------------------------------------------+
void RunRSIScalpingStrategy(int strategy_index)
{
// Access strategy by index (no reference needed)
// Check if we have enough bars
if(Bars(rsi_strategies[strategy_index].symbol, rsi_strategies[strategy_index].timeframe) <
rsi_strategies[strategy_index].period + 2)
return;
// Check if this is a new bar
datetime current_bar_time = iTime(rsi_strategies[strategy_index].symbol,
rsi_strategies[strategy_index].timeframe, 0);
if(current_bar_time == rsi_strategies[strategy_index].last_bar_time)
return;
rsi_strategies[strategy_index].last_bar_time = current_bar_time;
// Update RSI values
if(CopyBuffer(rsi_strategies[strategy_index].rsi_handle, 0, 0, 3,
rsi_strategies[strategy_index].rsi_buffer) < 3)
return;
double rsi_current = rsi_strategies[strategy_index].rsi_buffer[0];
double rsi_prev = rsi_strategies[strategy_index].rsi_buffer[1];
double rsi_two_bars_ago = rsi_strategies[strategy_index].rsi_buffer[2];
// Set magic number for this strategy
trade.SetExpertMagicNumber(rsi_strategies[strategy_index].magic_number);
// Check if position exists (regardless of flag state - handles EA restart)
bool position_exists = PositionExistsByMagic(rsi_strategies[strategy_index].symbol,
rsi_strategies[strategy_index].magic_number);
if(position_exists)
{
// Get actual position type and ticket
ulong ticket = GetPositionTicketByMagic(rsi_strategies[strategy_index].symbol,
rsi_strategies[strategy_index].magic_number);
ENUM_POSITION_TYPE pos_type = GetPositionTypeByMagic(rsi_strategies[strategy_index].symbol,
rsi_strategies[strategy_index].magic_number);
if(ticket == 0 || pos_type == WRONG_VALUE)
{
// Position doesn't exist or invalid
rsi_strategies[strategy_index].position_open = false;
rsi_strategies[strategy_index].buy_position_open = false;
rsi_strategies[strategy_index].sell_position_open = false;
rsi_strategies[strategy_index].position_ticket = 0;
rsi_strategies[strategy_index].rsi_against_position = false;
rsi_strategies[strategy_index].bars_against_count = 0;
return;
}
// Update position tracking with fine-grained flags
rsi_strategies[strategy_index].position_ticket = ticket;
rsi_strategies[strategy_index].position_open = true;
rsi_strategies[strategy_index].current_position_type = pos_type;
if(pos_type == POSITION_TYPE_BUY)
{
rsi_strategies[strategy_index].buy_position_open = true;
rsi_strategies[strategy_index].sell_position_open = false;
}
else if(pos_type == POSITION_TYPE_SELL)
{
rsi_strategies[strategy_index].buy_position_open = false;
rsi_strategies[strategy_index].sell_position_open = true;
}
// Verify position still exists with correct ticket, symbol, and magic number
if(!PositionSelectByTicketSymbolAndMagic(rsi_strategies[strategy_index].position_ticket,
rsi_strategies[strategy_index].symbol,
rsi_strategies[strategy_index].magic_number))
{
// Position was closed externally or doesn't match this instrument, reset tracking
rsi_strategies[strategy_index].position_open = false;
rsi_strategies[strategy_index].buy_position_open = false;
rsi_strategies[strategy_index].sell_position_open = false;
rsi_strategies[strategy_index].position_ticket = 0;
rsi_strategies[strategy_index].rsi_against_position = false;
rsi_strategies[strategy_index].bars_against_count = 0;
return;
}
// Double-check position type matches our tracking (instrument-specific verification)
ENUM_POSITION_TYPE actual_pos_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
string actual_symbol = PositionGetString(POSITION_SYMBOL);
if(actual_symbol != rsi_strategies[strategy_index].symbol)
{
Print("Warning: Position symbol mismatch for ", rsi_strategies[strategy_index].symbol,
" - Found: ", actual_symbol, ". Resetting tracking.");
rsi_strategies[strategy_index].position_open = false;
rsi_strategies[strategy_index].buy_position_open = false;
rsi_strategies[strategy_index].sell_position_open = false;
rsi_strategies[strategy_index].position_ticket = 0;
rsi_strategies[strategy_index].rsi_against_position = false;
rsi_strategies[strategy_index].bars_against_count = 0;
return;
}
// Update position type if it changed (shouldn't happen, but safety check)
if(actual_pos_type != pos_type)
{
Print("Warning: Position type changed for ", rsi_strategies[strategy_index].symbol,
" - Updating from ", EnumToString(pos_type), " to ", EnumToString(actual_pos_type));
pos_type = actual_pos_type;
rsi_strategies[strategy_index].current_position_type = pos_type;
if(pos_type == POSITION_TYPE_BUY)
{
rsi_strategies[strategy_index].buy_position_open = true;
rsi_strategies[strategy_index].sell_position_open = false;
}
else if(pos_type == POSITION_TYPE_SELL)
{
rsi_strategies[strategy_index].buy_position_open = false;
rsi_strategies[strategy_index].sell_position_open = true;
}
}
if(pos_type == POSITION_TYPE_BUY)
{
// Check if RSI is against the position (below oversold)
if(rsi_current < rsi_strategies[strategy_index].oversold)
{
if(!rsi_strategies[strategy_index].rsi_against_position)
{
rsi_strategies[strategy_index].rsi_against_position = true;
rsi_strategies[strategy_index].bars_against_count = 1;
}
else
{
rsi_strategies[strategy_index].bars_against_count++;
}
// Close position if RSI has been against for Y bars
if(rsi_strategies[strategy_index].bars_against_count >=
rsi_strategies[strategy_index].bars_to_wait)
{
if(ClosePositionByMagic(trade, rsi_strategies[strategy_index].symbol,
rsi_strategies[strategy_index].magic_number))
{
rsi_strategies[strategy_index].position_open = false;
rsi_strategies[strategy_index].buy_position_open = false;
rsi_strategies[strategy_index].sell_position_open = false;
rsi_strategies[strategy_index].position_ticket = 0;
rsi_strategies[strategy_index].rsi_against_position = false;
rsi_strategies[strategy_index].bars_against_count = 0;
Print("Closed ", rsi_strategies[strategy_index].symbol, " BUY position - RSI against for ",
rsi_strategies[strategy_index].bars_to_wait, " bars");
}
else
{
Print("Failed to close ", rsi_strategies[strategy_index].symbol, " BUY position - will retry");
}
return;
}
}
else
{
// RSI is no longer against the position, reset counter
if(rsi_strategies[strategy_index].rsi_against_position)
{
rsi_strategies[strategy_index].rsi_against_position = false;
rsi_strategies[strategy_index].bars_against_count = 0;
}
// Exit long position when RSI reaches buy target
if(rsi_current >= rsi_strategies[strategy_index].target_buy)
{
if(ClosePositionByMagic(trade, rsi_strategies[strategy_index].symbol,
rsi_strategies[strategy_index].magic_number))
{
rsi_strategies[strategy_index].position_open = false;
rsi_strategies[strategy_index].buy_position_open = false;
rsi_strategies[strategy_index].sell_position_open = false;
rsi_strategies[strategy_index].position_ticket = 0;
rsi_strategies[strategy_index].rsi_against_position = false;
rsi_strategies[strategy_index].bars_against_count = 0;
Print("Closed ", rsi_strategies[strategy_index].symbol, " BUY position - RSI reached target: ",
rsi_strategies[strategy_index].target_buy);
}
else
{
Print("Failed to close ", rsi_strategies[strategy_index].symbol, " BUY position - will retry");
}
}
}
}
else if(pos_type == POSITION_TYPE_SELL)
{
// Check if RSI is against the position (above overbought)
if(rsi_current > rsi_strategies[strategy_index].overbought)
{
if(!rsi_strategies[strategy_index].rsi_against_position)
{
rsi_strategies[strategy_index].rsi_against_position = true;
rsi_strategies[strategy_index].bars_against_count = 1;
}
else
{
rsi_strategies[strategy_index].bars_against_count++;
}
// Close position if RSI has been against for Y bars
if(rsi_strategies[strategy_index].bars_against_count >=
rsi_strategies[strategy_index].bars_to_wait)
{
if(ClosePositionByMagic(trade, rsi_strategies[strategy_index].symbol,
rsi_strategies[strategy_index].magic_number))
{
rsi_strategies[strategy_index].position_open = false;
rsi_strategies[strategy_index].buy_position_open = false;
rsi_strategies[strategy_index].sell_position_open = false;
rsi_strategies[strategy_index].position_ticket = 0;
rsi_strategies[strategy_index].rsi_against_position = false;
rsi_strategies[strategy_index].bars_against_count = 0;
Print("Closed ", rsi_strategies[strategy_index].symbol, " SELL position - RSI against for ",
rsi_strategies[strategy_index].bars_to_wait, " bars");
}
else
{
Print("Failed to close ", rsi_strategies[strategy_index].symbol, " SELL position - will retry");
}
return;
}
}
else
{
// RSI is no longer against the position, reset counter
if(rsi_strategies[strategy_index].rsi_against_position)
{
rsi_strategies[strategy_index].rsi_against_position = false;
rsi_strategies[strategy_index].bars_against_count = 0;
}
// Exit short position when RSI reaches sell target
if(rsi_current <= rsi_strategies[strategy_index].target_sell)
{
if(ClosePositionByMagic(trade, rsi_strategies[strategy_index].symbol,
rsi_strategies[strategy_index].magic_number))
{
rsi_strategies[strategy_index].position_open = false;
rsi_strategies[strategy_index].buy_position_open = false;
rsi_strategies[strategy_index].sell_position_open = false;
rsi_strategies[strategy_index].position_ticket = 0;
rsi_strategies[strategy_index].rsi_against_position = false;
rsi_strategies[strategy_index].bars_against_count = 0;
Print("Closed ", rsi_strategies[strategy_index].symbol, " SELL position - RSI reached target: ",
rsi_strategies[strategy_index].target_sell);
}
else
{
Print("Failed to close ", rsi_strategies[strategy_index].symbol, " SELL position - will retry");
}
}
}
}
}
else
{
// No position exists - reset all tracking flags
rsi_strategies[strategy_index].position_open = false;
rsi_strategies[strategy_index].buy_position_open = false;
rsi_strategies[strategy_index].sell_position_open = false;
rsi_strategies[strategy_index].position_ticket = 0;
rsi_strategies[strategy_index].rsi_against_position = false;
rsi_strategies[strategy_index].bars_against_count = 0;
// Check for new entry signals (only if no position exists)
if(!PositionExistsByMagic(rsi_strategies[strategy_index].symbol,
rsi_strategies[strategy_index].magic_number))
{
// Buy signal: RSI crosses from oversold to above oversold
// Only enter if we don't already have a buy position for THIS EA (magic number) on THIS INSTRUMENT
if(!rsi_strategies[strategy_index].buy_position_open)
{
if(rsi_two_bars_ago <= rsi_strategies[strategy_index].oversold &&
rsi_prev > rsi_strategies[strategy_index].oversold)
{
double ask = SymbolInfoDouble(rsi_strategies[strategy_index].symbol, SYMBOL_ASK);
if(trade.Buy(rsi_strategies[strategy_index].lot_size,
rsi_strategies[strategy_index].symbol, ask, 0, 0,
"RSI Scalping Buy " + rsi_strategies[strategy_index].symbol))
{
ulong new_ticket = trade.ResultOrder();
if(new_ticket > 0)
{
// Verify the position was actually opened for THIS SPECIFIC INSTRUMENT
if(PositionSelectByTicketSymbolAndMagic(new_ticket,
rsi_strategies[strategy_index].symbol,
rsi_strategies[strategy_index].magic_number))
{
rsi_strategies[strategy_index].position_ticket = new_ticket;
rsi_strategies[strategy_index].position_open = true;
rsi_strategies[strategy_index].buy_position_open = true;
rsi_strategies[strategy_index].sell_position_open = false;
rsi_strategies[strategy_index].current_position_type = POSITION_TYPE_BUY;
Print("Opened BUY position for ", rsi_strategies[strategy_index].symbol,
" (Ticket: ", rsi_strategies[strategy_index].position_ticket,
", Magic: ", rsi_strategies[strategy_index].magic_number, ")");
}
else
{
Print("Error: Position opened but doesn't match instrument ",
rsi_strategies[strategy_index].symbol, " - resetting tracking");
rsi_strategies[strategy_index].position_ticket = 0;
rsi_strategies[strategy_index].position_open = false;
rsi_strategies[strategy_index].buy_position_open = false;
}
}
}
}
}
// Sell signal: RSI crosses from overbought to below overbought
// Only enter if we don't already have a sell position for THIS EA (magic number) on THIS INSTRUMENT
if(!rsi_strategies[strategy_index].sell_position_open)
{
if(rsi_two_bars_ago >= rsi_strategies[strategy_index].overbought &&
rsi_prev < rsi_strategies[strategy_index].overbought)
{
double bid = SymbolInfoDouble(rsi_strategies[strategy_index].symbol, SYMBOL_BID);
if(trade.Sell(rsi_strategies[strategy_index].lot_size,
rsi_strategies[strategy_index].symbol, bid, 0, 0,
"RSI Scalping Sell " + rsi_strategies[strategy_index].symbol))
{
ulong new_ticket = trade.ResultOrder();
if(new_ticket > 0)
{
// Verify the position was actually opened for THIS SPECIFIC INSTRUMENT
if(PositionSelectByTicketSymbolAndMagic(new_ticket,
rsi_strategies[strategy_index].symbol,
rsi_strategies[strategy_index].magic_number))
{
rsi_strategies[strategy_index].position_ticket = new_ticket;
rsi_strategies[strategy_index].position_open = true;
rsi_strategies[strategy_index].buy_position_open = false;
rsi_strategies[strategy_index].sell_position_open = true;
rsi_strategies[strategy_index].current_position_type = POSITION_TYPE_SELL;
Print("Opened SELL position for ", rsi_strategies[strategy_index].symbol,
" (Ticket: ", rsi_strategies[strategy_index].position_ticket,
", Magic: ", rsi_strategies[strategy_index].magic_number, ")");
}
else
{
Print("Error: Position opened but doesn't match instrument ",
rsi_strategies[strategy_index].symbol, " - resetting tracking");
rsi_strategies[strategy_index].position_ticket = 0;
rsi_strategies[strategy_index].position_open = false;
rsi_strategies[strategy_index].sell_position_open = false;
}
}
}
}
}
}
}
}
//+------------------------------------------------------------------+
//| Mean Reversion Strategy |
//+------------------------------------------------------------------+
void RunMeanReversionStrategy()
{
// Check if this is a new bar
datetime current_bar_time = iTime(_Symbol, MeanRev_Timeframe, 0);
if(current_bar_time == last_bar_time_meanrev)
return;
last_bar_time_meanrev = current_bar_time;
// Update EMA values
if(CopyBuffer(ema_handle_meanrev, 0, 0, 3, ema_array) < 3)
return;
double ema_current = ema_array[0];
double ema_prev = ema_array[1];
double current_close = iClose(_Symbol, MeanRev_Timeframe, 0);
// Set magic number for this strategy
trade.SetExpertMagicNumber(MagicNumber_MeanReversion);
// Check existing position
if(PositionExistsByMagic(_Symbol, MagicNumber_MeanReversion))
{
// Manage existing position (trailing stop, exit conditions, etc.)
ManageMeanReversionPosition(ema_current, current_close);
}
else
{
// Check for new entry signals
CheckMeanReversionEntry(ema_current, ema_prev, current_close);
}
}
//+------------------------------------------------------------------+
//| Manage Mean Reversion Position |
//+------------------------------------------------------------------+
void ManageMeanReversionPosition(double ema_current, double current_close)
{
if(!PositionSelectByMagic(_Symbol, MagicNumber_MeanReversion))
return;
double position_profit = PositionGetDouble(POSITION_PROFIT);
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;
// Trailing stop
if(position_profit > 0)
{
if(position_type == POSITION_TYPE_BUY)
{
double new_stop_loss = current_price - (TrailingStop * _Point * pips_multiplier);
double current_stop_loss = PositionGetDouble(POSITION_SL);
if(new_stop_loss > current_stop_loss)
{
ModifyPositionByMagic(trade, _Symbol, MagicNumber_MeanReversion,
new_stop_loss, PositionGetDouble(POSITION_TP));
}
}
else if(position_type == POSITION_TYPE_SELL)
{
double new_stop_loss = current_price + (TrailingStop * _Point * pips_multiplier);
double current_stop_loss = PositionGetDouble(POSITION_SL);
if(new_stop_loss < current_stop_loss || current_stop_loss == 0)
{
ModifyPositionByMagic(trade, _Symbol, MagicNumber_MeanReversion,
new_stop_loss, PositionGetDouble(POSITION_TP));
}
}
}
// Exit when price crosses EMA
bool exit_bullish = (position_type == POSITION_TYPE_SELL && current_close > ema_current);
bool exit_bearish = (position_type == POSITION_TYPE_BUY && current_close < ema_current);
if(exit_bullish || exit_bearish)
{
ClosePositionByMagic(trade, _Symbol, MagicNumber_MeanReversion);
}
}
//+------------------------------------------------------------------+
//| Check Mean Reversion Entry Signals |
//+------------------------------------------------------------------+
void CheckMeanReversionEntry(double ema_current, double ema_prev, double current_close)
{
// Simplified entry logic - can be expanded
double pips_multiplier = (_Digits == 3 || _Digits == 5) ? 10.0 : 1.0;
double preis_abstand = MathAbs(current_close - ema_current) / _Point / pips_multiplier;
double steigung = (ema_current - ema_prev) / _Point / pips_multiplier;
// Entry conditions
bool bullish_signal = (current_close > ema_current && preis_abstand > PreisSchwelle &&
MathAbs(steigung) > SteigungSchwelle);
bool bearish_signal = (current_close < ema_current && preis_abstand > PreisSchwelle &&
MathAbs(steigung) > SteigungSchwelle);
if(bullish_signal)
{
if(trade.Buy(MeanRev_LotSize, _Symbol, 0, 0, 0, "Mean Reversion Buy"))
{
meanrev_ticket = trade.ResultOrder();
meanrev_position_open = true;
}
}
else if(bearish_signal)
{
if(trade.Sell(MeanRev_LotSize, _Symbol, 0, 0, 0, "Mean Reversion Sell"))
{
meanrev_ticket = trade.ResultOrder();
meanrev_position_open = true;
}
}
}
//+------------------------------------------------------------------+
File diff suppressed because it is too large Load Diff