This commit is contained in:
zhutoutoutousan
2026-04-24 14:14:09 +02:00
parent de5263de32
commit 65ace55a39
130 changed files with 10016 additions and 4439 deletions
@@ -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;
}
//+------------------------------------------------------------------+
@@ -0,0 +1,607 @@
//+------------------------------------------------------------------+
//| PerformanceEvaluator.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"
//+------------------------------------------------------------------+
//| Performance Metrics Structure |
//+------------------------------------------------------------------+
struct StrategyPerformance {
string strategyName;
string symbol; // Store symbol to determine if it's a stock
int magicNumber;
double initialLotSize;
double currentLotSize;
double quarterProfit;
double quarterTrades;
double quarterWins;
double quarterLosses;
double maxDrawdown;
double winRate;
datetime quarterStart;
datetime quarterEnd;
bool isActive;
bool inPenaltyMode; // True if strategy is in penalty (worst performer)
double lotSizeBeforePenalty; // Store lot size before penalty
datetime penaltyStartTime; // When penalty started
};
//+------------------------------------------------------------------+
//| Global Performance Tracking |
//+------------------------------------------------------------------+
StrategyPerformance strategyPerformances[];
int totalStrategies = 0;
datetime lastMonthCheck = 0;
datetime currentMonthStart = 0;
datetime currentMonthEnd = 0;
//+------------------------------------------------------------------+
//| Performance Adjustment Parameters |
//+------------------------------------------------------------------+
input group "=== Performance Evaluation Settings ==="
input bool PE_EnableAutoAdjustment = true; // Enable automatic lot size adjustment
input double PE_LotSizeIncreasePercent = 10.0; // % increase for top-ranked strategies
input double PE_LotSizeDecreasePercent = 10.0; // % decrease for bottom-ranked strategies
input double PE_MinLotSize = 0.01; // Minimum lot size for forex/crypto
input double PE_MinLotSizeStocks = 5.0; // Minimum lot size for stocks (5-10 range)
input double PE_MaxLotSize = 100.0; // Maximum lot size after adjustment
input int PE_TopPerformersCount = 3; // Number of top strategies to increase lot size
input int PE_BottomPerformersCount = 3; // Number of bottom strategies to decrease lot size
input bool PE_UseWinRateWeight = true; // Consider win rate in ranking (50% profit, 50% win rate)
input bool PE_EnableBlitzPlay = true; // Enable blitz play: worst performer gets minimum lot size penalty
input bool PE_EnableLogging = true; // Enable performance logging
//+------------------------------------------------------------------+
//| Initialize Performance Tracking |
//+------------------------------------------------------------------+
void InitPerformanceTracking()
{
// Calculate current month dates
MqlDateTime dt;
TimeToStruct(TimeCurrent(), dt);
// Determine month start (first day of current month)
dt.day = 1;
dt.hour = 0;
dt.min = 0;
dt.sec = 0;
currentMonthStart = StructToTime(dt);
// Calculate month end (first day of next month - 1 second)
dt.mon += 1;
if(dt.mon > 12)
{
dt.mon = 1;
dt.year++;
}
currentMonthEnd = StructToTime(dt) - 1; // End of last day of month
lastMonthCheck = TimeCurrent();
if(PE_EnableLogging)
{
Print("Performance Evaluator: Initialized");
Print("Current Month Start: ", TimeToString(currentMonthStart));
Print("Current Month End: ", TimeToString(currentMonthEnd));
}
}
//+------------------------------------------------------------------+
//| Check if Symbol is a Stock |
//+------------------------------------------------------------------+
bool IsStockSymbol(string symbol)
{
// Check if symbol contains common stock indicators
if(StringFind(symbol, ".US") >= 0) return true;
if(StringFind(symbol, "NASDAQ:") >= 0) return true;
if(StringFind(symbol, "NYSE:") >= 0) return true;
// Note: Symbol category check removed to avoid enum conversion issues
// String-based checks (.US, NASDAQ:, NYSE:, common tickers) are sufficient
// Common stock tickers (without .US suffix)
string commonStocks[] = {"AAPL", "MSFT", "NVDA", "TSLA", "GOOGL", "AMZN", "META", "NFLX"};
for(int i = 0; i < ArraySize(commonStocks); i++)
{
if(StringFind(symbol, commonStocks[i]) == 0) return true;
}
return false;
}
//+------------------------------------------------------------------+
//| Get Minimum Lot Size for Symbol |
//+------------------------------------------------------------------+
double GetMinLotSizeForSymbol(string symbol)
{
if(IsStockSymbol(symbol))
return PE_MinLotSizeStocks;
else
return PE_MinLotSize;
}
//+------------------------------------------------------------------+
//| Register Strategy for Performance Tracking |
//+------------------------------------------------------------------+
void RegisterStrategy(string strategyName, int magicNumber, double initialLotSize, string symbol = "")
{
// Check if strategy already registered
for(int i = 0; i < ArraySize(strategyPerformances); i++)
{
if(strategyPerformances[i].strategyName == strategyName &&
strategyPerformances[i].magicNumber == magicNumber)
{
if(PE_EnableLogging)
Print("Performance Evaluator: Strategy '", strategyName, "' already registered");
return;
}
}
// Add new strategy
int newSize = ArraySize(strategyPerformances) + 1;
ArrayResize(strategyPerformances, newSize);
strategyPerformances[newSize - 1].strategyName = strategyName;
strategyPerformances[newSize - 1].symbol = symbol;
strategyPerformances[newSize - 1].magicNumber = magicNumber;
strategyPerformances[newSize - 1].initialLotSize = initialLotSize;
// Start with minimum lot size for safety (symbol-specific minimum)
double minLot = GetMinLotSizeForSymbol(symbol);
strategyPerformances[newSize - 1].currentLotSize = minLot;
strategyPerformances[newSize - 1].quarterProfit = 0.0;
strategyPerformances[newSize - 1].quarterTrades = 0;
strategyPerformances[newSize - 1].quarterWins = 0;
strategyPerformances[newSize - 1].quarterLosses = 0;
strategyPerformances[newSize - 1].maxDrawdown = 0.0;
strategyPerformances[newSize - 1].winRate = 0.0;
strategyPerformances[newSize - 1].quarterStart = currentMonthStart;
strategyPerformances[newSize - 1].quarterEnd = currentMonthEnd;
strategyPerformances[newSize - 1].isActive = true;
strategyPerformances[newSize - 1].inPenaltyMode = false;
strategyPerformances[newSize - 1].lotSizeBeforePenalty = initialLotSize;
strategyPerformances[newSize - 1].penaltyStartTime = 0;
totalStrategies = newSize;
if(PE_EnableLogging)
Print("Performance Evaluator: Registered strategy '", strategyName,
"' (Magic: ", magicNumber, ", Initial Lot: ", initialLotSize, ")");
}
//+------------------------------------------------------------------+
//| Update Strategy Performance Metrics |
//+------------------------------------------------------------------+
void UpdateStrategyPerformance(string strategyName, int magicNumber)
{
for(int i = 0; i < ArraySize(strategyPerformances); i++)
{
if(strategyPerformances[i].strategyName == strategyName &&
strategyPerformances[i].magicNumber == magicNumber &&
strategyPerformances[i].isActive)
{
// Calculate performance for current quarter
double totalProfit = 0.0;
int totalTrades = 0;
int wins = 0;
int losses = 0;
double maxDD = 0.0;
double peakBalance = 0.0;
// Scan all closed deals in current quarter
datetime quarterStart = strategyPerformances[i].quarterStart;
datetime quarterEnd = strategyPerformances[i].quarterEnd;
// Select history for the quarter
if(HistorySelect(quarterStart, quarterEnd))
{
int totalDeals = HistoryDealsTotal();
for(int j = 0; j < totalDeals; j++)
{
ulong ticket = HistoryDealGetTicket(j);
if(ticket > 0)
{
long dealMagic = HistoryDealGetInteger(ticket, DEAL_MAGIC);
if(dealMagic == magicNumber)
{
double profit = HistoryDealGetDouble(ticket, DEAL_PROFIT);
double swap = HistoryDealGetDouble(ticket, DEAL_SWAP);
double commission = HistoryDealGetDouble(ticket, DEAL_COMMISSION);
double totalDealProfit = profit + swap + commission;
totalProfit += totalDealProfit;
totalTrades++;
if(totalDealProfit > 0)
wins++;
else if(totalDealProfit < 0)
losses++;
}
}
}
}
// Calculate win rate
double winRate = 0.0;
if(totalTrades > 0)
winRate = (double)wins / (double)totalTrades * 100.0;
// Update metrics
strategyPerformances[i].quarterProfit = totalProfit;
strategyPerformances[i].quarterTrades = totalTrades;
strategyPerformances[i].quarterWins = wins;
strategyPerformances[i].quarterLosses = losses;
strategyPerformances[i].winRate = winRate;
break;
}
}
}
//+------------------------------------------------------------------+
//| Strategy Ranking Structure |
//+------------------------------------------------------------------+
struct StrategyRank {
int index;
double score;
};
//+------------------------------------------------------------------+
//| Calculate Strategy Score for Ranking |
//+------------------------------------------------------------------+
double CalculateStrategyScore(int strategyIndex)
{
double profit = strategyPerformances[strategyIndex].quarterProfit;
double winRate = strategyPerformances[strategyIndex].winRate;
double trades = strategyPerformances[strategyIndex].quarterTrades;
// Normalize profit (scale to 0-100 range, assuming max profit of $1000)
double normalizedProfit = MathMin(profit / 10.0, 100.0);
if(profit < 0) normalizedProfit = profit / 5.0; // Penalize losses more
// Calculate score
double score = 0.0;
if(PE_UseWinRateWeight)
{
// 50% profit, 50% win rate (if enough trades)
if(trades >= 5)
score = (normalizedProfit * 0.5) + (winRate * 0.5);
else
score = normalizedProfit; // Not enough trades, use profit only
}
else
{
// Profit only
score = normalizedProfit;
}
return score;
}
//+------------------------------------------------------------------+
//| Check if Month Ended and Evaluate Performance |
//+------------------------------------------------------------------+
void CheckMonthEnd()
{
datetime now = TimeCurrent();
// Check if we've entered a new month
if(now >= currentMonthEnd)
{
if(PE_EnableLogging)
Print("Performance Evaluator: Month ended. Evaluating and ranking strategies...");
// Update performance metrics for all strategies
for(int i = 0; i < ArraySize(strategyPerformances); i++)
{
if(strategyPerformances[i].isActive)
{
UpdateStrategyPerformance(strategyPerformances[i].strategyName,
strategyPerformances[i].magicNumber);
}
}
// Rank strategies
int activeCount = 0;
for(int i = 0; i < ArraySize(strategyPerformances); i++)
{
if(strategyPerformances[i].isActive)
activeCount++;
}
if(activeCount > 0)
{
// Create ranking array
StrategyRank ranks[];
ArrayResize(ranks, activeCount);
int rankIndex = 0;
for(int i = 0; i < ArraySize(strategyPerformances); i++)
{
if(strategyPerformances[i].isActive)
{
ranks[rankIndex].index = i;
ranks[rankIndex].score = CalculateStrategyScore(i);
rankIndex++;
}
}
// Sort by score (descending - highest score first)
for(int i = 0; i < activeCount - 1; i++)
{
for(int j = i + 1; j < activeCount; j++)
{
if(ranks[j].score > ranks[i].score)
{
StrategyRank temp = ranks[i];
ranks[i] = ranks[j];
ranks[j] = temp;
}
}
}
// Adjust lot sizes based on ranking
if(PE_EnableAutoAdjustment)
{
// Increase top performers (skip if in penalty mode)
int topCount = MathMin(PE_TopPerformersCount, activeCount);
for(int i = 0; i < topCount; i++)
{
int strategyIdx = ranks[i].index;
// Skip if strategy is in penalty mode
if(strategyPerformances[strategyIdx].inPenaltyMode)
continue;
double oldLotSize = strategyPerformances[strategyIdx].currentLotSize;
double newLotSize = oldLotSize * (1.0 + PE_LotSizeIncreasePercent / 100.0);
if(newLotSize > PE_MaxLotSize)
newLotSize = PE_MaxLotSize;
strategyPerformances[strategyIdx].currentLotSize = newLotSize;
if(PE_EnableLogging)
Print("Performance Evaluator: Rank #", (i+1), " - Increasing '",
strategyPerformances[strategyIdx].strategyName,
"' lot size from ", oldLotSize, " to ", newLotSize,
" (Score: ", DoubleToString(ranks[i].score, 2),
", Profit: $", DoubleToString(strategyPerformances[strategyIdx].quarterProfit, 2),
", Win Rate: ", DoubleToString(strategyPerformances[strategyIdx].winRate, 2), "%)");
}
// Decrease bottom performers (skip worst one if blitz play is enabled)
int bottomCount = MathMin(PE_BottomPerformersCount, activeCount);
int startIdx = activeCount - bottomCount;
// If blitz play is enabled, skip the worst performer (it will get minimum penalty)
if(PE_EnableBlitzPlay && activeCount > 0)
startIdx = activeCount - bottomCount + 1;
for(int i = startIdx; i < activeCount; i++)
{
int strategyIdx = ranks[i].index;
// Skip if strategy is in penalty mode
if(strategyPerformances[strategyIdx].inPenaltyMode)
continue;
double oldLotSize = strategyPerformances[strategyIdx].currentLotSize;
double newLotSize = oldLotSize * (1.0 - PE_LotSizeDecreasePercent / 100.0);
// Use symbol-specific minimum lot size
double minLot = GetMinLotSizeForSymbol(strategyPerformances[strategyIdx].symbol);
if(newLotSize < minLot)
newLotSize = minLot;
strategyPerformances[strategyIdx].currentLotSize = newLotSize;
if(PE_EnableLogging)
Print("Performance Evaluator: Rank #", (i+1), " - Decreasing '",
strategyPerformances[strategyIdx].strategyName,
"' lot size from ", oldLotSize, " to ", newLotSize,
" (Score: ", DoubleToString(ranks[i].score, 2),
", Profit: $", DoubleToString(strategyPerformances[strategyIdx].quarterProfit, 2),
", Win Rate: ", DoubleToString(strategyPerformances[strategyIdx].winRate, 2), "%)");
}
}
// Blitz Play: Apply penalty to worst performer
if(PE_EnableBlitzPlay && activeCount > 0)
{
// Find worst performer (last in ranking)
int worstIdx = ranks[activeCount - 1].index;
// Remove penalty from previous worst performer (if any)
for(int i = 0; i < ArraySize(strategyPerformances); i++)
{
if(strategyPerformances[i].isActive && strategyPerformances[i].inPenaltyMode)
{
// Check if penalty period has passed (one month)
if(now - strategyPerformances[i].penaltyStartTime >= 2592000) // ~30 days
{
// Restore lot size to before penalty
strategyPerformances[i].currentLotSize = strategyPerformances[i].lotSizeBeforePenalty;
strategyPerformances[i].inPenaltyMode = false;
strategyPerformances[i].penaltyStartTime = 0;
if(PE_EnableLogging)
Print("Blitz Play: Penalty removed from '", strategyPerformances[i].strategyName,
"'. Lot size restored to ", strategyPerformances[i].currentLotSize);
}
}
}
// Apply penalty to new worst performer
if(!strategyPerformances[worstIdx].inPenaltyMode)
{
strategyPerformances[worstIdx].lotSizeBeforePenalty = strategyPerformances[worstIdx].currentLotSize;
// Use symbol-specific minimum lot size
double minLot = GetMinLotSizeForSymbol(strategyPerformances[worstIdx].symbol);
strategyPerformances[worstIdx].currentLotSize = minLot;
strategyPerformances[worstIdx].inPenaltyMode = true;
strategyPerformances[worstIdx].penaltyStartTime = now;
if(PE_EnableLogging)
Print("Blitz Play: WORST PERFORMER - '", strategyPerformances[worstIdx].strategyName,
"' penalized! Lot size reduced from ", strategyPerformances[worstIdx].lotSizeBeforePenalty,
" to minimum ", minLot, " (Score: ", DoubleToString(ranks[activeCount - 1].score, 2),
", Profit: $", DoubleToString(strategyPerformances[worstIdx].quarterProfit, 2), ")");
}
}
// Log performance report
if(PE_EnableLogging)
{
Print("=== Monthly Performance Ranking ===");
for(int i = 0; i < activeCount; i++)
{
int strategyIdx = ranks[i].index;
Print("Rank #", (i+1), ": ", strategyPerformances[strategyIdx].strategyName,
" - Score: ", DoubleToString(ranks[i].score, 2),
", Profit: $", DoubleToString(strategyPerformances[strategyIdx].quarterProfit, 2),
", Win Rate: ", DoubleToString(strategyPerformances[strategyIdx].winRate, 2), "%",
", Trades: ", (int)strategyPerformances[strategyIdx].quarterTrades,
", Lot Size: ", DoubleToString(strategyPerformances[strategyIdx].currentLotSize, 2));
}
Print("===================================");
}
}
// Reset month metrics for all strategies
for(int i = 0; i < ArraySize(strategyPerformances); i++)
{
if(strategyPerformances[i].isActive)
{
strategyPerformances[i].quarterProfit = 0.0;
strategyPerformances[i].quarterTrades = 0;
strategyPerformances[i].quarterWins = 0;
strategyPerformances[i].quarterLosses = 0;
strategyPerformances[i].maxDrawdown = 0.0;
strategyPerformances[i].winRate = 0.0;
}
}
// Update month dates
MqlDateTime dt;
TimeToStruct(now, dt);
// First day of current month
dt.day = 1;
dt.hour = 0;
dt.min = 0;
dt.sec = 0;
currentMonthStart = StructToTime(dt);
// First day of next month - 1 second
dt.mon += 1;
if(dt.mon > 12)
{
dt.mon = 1;
dt.year++;
}
currentMonthEnd = StructToTime(dt) - 1;
// Update month dates for all strategies
for(int i = 0; i < ArraySize(strategyPerformances); i++)
{
strategyPerformances[i].quarterStart = currentMonthStart;
strategyPerformances[i].quarterEnd = currentMonthEnd;
}
lastMonthCheck = now;
}
}
//+------------------------------------------------------------------+
//| Get Current Lot Size for Strategy |
//+------------------------------------------------------------------+
double GetStrategyLotSize(string strategyName, int magicNumber)
{
for(int i = 0; i < ArraySize(strategyPerformances); i++)
{
if(strategyPerformances[i].strategyName == strategyName &&
strategyPerformances[i].magicNumber == magicNumber &&
strategyPerformances[i].isActive)
{
return strategyPerformances[i].currentLotSize;
}
}
return 0.0;
}
//+------------------------------------------------------------------+
//| Process Performance Evaluation (call from OnTick) |
//+------------------------------------------------------------------+
void ProcessPerformanceEvaluation()
{
// Check if month ended
CheckMonthEnd();
// Check for penalty expiration (blitz play)
if(PE_EnableBlitzPlay)
{
datetime now = TimeCurrent();
for(int i = 0; i < ArraySize(strategyPerformances); i++)
{
if(strategyPerformances[i].isActive && strategyPerformances[i].inPenaltyMode)
{
// Check if penalty period has passed (one month = ~30 days)
if(now - strategyPerformances[i].penaltyStartTime >= 2592000)
{
// Restore lot size to before penalty
strategyPerformances[i].currentLotSize = strategyPerformances[i].lotSizeBeforePenalty;
strategyPerformances[i].inPenaltyMode = false;
strategyPerformances[i].penaltyStartTime = 0;
if(PE_EnableLogging)
Print("Blitz Play: Penalty expired for '", strategyPerformances[i].strategyName,
"'. Lot size restored to ", strategyPerformances[i].currentLotSize);
}
}
}
}
// Update performance metrics periodically (every hour)
static datetime lastUpdate = 0;
if(TimeCurrent() - lastUpdate >= 3600)
{
for(int i = 0; i < ArraySize(strategyPerformances); i++)
{
if(strategyPerformances[i].isActive)
{
UpdateStrategyPerformance(strategyPerformances[i].strategyName,
strategyPerformances[i].magicNumber);
}
}
lastUpdate = TimeCurrent();
}
}
//+------------------------------------------------------------------+
//| Get Performance Summary |
//+------------------------------------------------------------------+
string GetPerformanceSummary()
{
string summary = "\n=== Performance Summary ===\n";
summary += "Current Month: " + TimeToString(currentMonthStart) + " to " + TimeToString(currentMonthEnd) + "\n\n";
for(int i = 0; i < ArraySize(strategyPerformances); i++)
{
if(strategyPerformances[i].isActive)
{
summary += strategyPerformances[i].strategyName + ":\n";
summary += " Profit: $" + DoubleToString(strategyPerformances[i].quarterProfit, 2) + "\n";
summary += " Trades: " + IntegerToString((int)strategyPerformances[i].quarterTrades) + "\n";
summary += " Win Rate: " + DoubleToString(strategyPerformances[i].winRate, 2) + "%\n";
summary += " Lot Size: " + DoubleToString(strategyPerformances[i].currentLotSize, 2) + "\n\n";
}
}
return summary;
}
//+------------------------------------------------------------------+
@@ -0,0 +1,76 @@
# United EA Strategy Configuration Summary
## Strategy Symbols and Magic Numbers
### Strategy 1: DarvasBox
- **Symbol**: XAUUSD (Gold/USD)
- **Magic Number**: 135790
### Strategy 2: EMASlopeDistance
- **Symbol**: XAUUSD (Gold/USD)
- **Magic Number**: 12350
### Strategy 3: RSICrossOverReversal
- **Symbol**: XAUUSD (Gold/USD)
- **Magic Number**: 7
### Strategy 4: RSIMidPointHijack
- **Symbol**: XAUUSD (Gold/USD)
- **Magic Numbers**:
- RSIFollow: 1001
- RSIReverse: 1002
- EMACross: 1003
### Strategy 5: RSI Scalping APPL (Apple)
- **Symbol**: AAPL (Apple stock)
- **Magic Number**: 20001
- **Note**: Changed from "APPL" to "AAPL" (correct ticker symbol)
### Strategy 6: RSI Scalping BTCUSD
- **Symbol**: BTCUSD (Bitcoin/USD)
- **Magic Number**: 123459123
### Strategy 7: RSI Scalping MSFT
- **Symbol**: MSFT (Microsoft stock)
- **Magic Number**: 20002
### Strategy 8: RSI Scalping NVDA
- **Symbol**: NVDA (NVIDIA stock)
- **Magic Number**: 20003
### Strategy 9: RSI Scalping TSLA
- **Symbol**: TSLA (Tesla stock)
- **Magic Number**: 125421321
### Strategy 10: RSI Scalping XAUUSD
- **Symbol**: XAUUSD (Gold/USD)
- **Magic Number**: 129102315
## Important Notes
1. **Stock Symbols**: Stock symbols (AAPL, MSFT, NVDA, TSLA) must be:
- Added to Market Watch in MetaTrader 5
- Available from your broker
- Use the correct ticker symbol (e.g., "AAPL" not "APPL")
2. **Magic Numbers**: All strategies have unique magic numbers to prevent interference:
- Each strategy can be identified by its magic number
- RSIMidPointHijack uses 3 magic numbers (one for each sub-strategy)
3. **Symbol Configuration**: Each strategy trades on its own symbol:
- You can change symbols in the input parameters
- The EA will log warnings if a symbol is not available
- Strategies with unavailable symbols will be skipped (EA continues running)
4. **RSI Scalping Strategies**:
- Each RSI Scalping variant trades on a different symbol
- They all use the same strategy logic but with different parameters
- Buy and sell signals are generated based on RSI levels for each symbol
## Troubleshooting
If stock symbols are not working:
1. Check if the symbol exists in your broker's symbol list
2. Add the symbol to Market Watch in MetaTrader 5
3. Verify the symbol name matches your broker's naming convention
4. Some brokers use prefixes/suffixes (e.g., "NASDAQ:AAPL" or "AAPL.US")
@@ -0,0 +1,300 @@
//+------------------------------------------------------------------+
//| DarvasBoxStrategy.mqh |
//+------------------------------------------------------------------+
bool InitDarvasBox(string symbol)
{
dbData.symbol = symbol;
dbData.boxHigh = 0;
dbData.boxLow = 0;
dbData.boxFormed = false;
dbData.lastBoxTime = 0;
dbData.boxName = "DarvasBox_" + IntegerToString(DB_MagicNumber) + "_";
// Check if symbol exists
if(!SymbolSelect(symbol, true))
{
Print("DarvasBox: Symbol '", symbol, "' not available in Market Watch. Please add it to Market Watch or check symbol name.");
return false;
}
Sleep(100); // Wait for symbol to be ready
dbData.point = SymbolInfoDouble(symbol, SYMBOL_POINT);
dbData.minStopLevel = SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL) * dbData.point;
dbData.maHandle = iMA(symbol, DB_TrendTimeframe, DB_MA_Period, 0, DB_MA_Method, DB_MA_Price);
dbData.volumeHandle = iVolumes(symbol, PERIOD_CURRENT, VOLUME_TICK);
if(dbData.maHandle == INVALID_HANDLE || dbData.volumeHandle == INVALID_HANDLE)
{
Print("DarvasBox: Error creating indicators for '", symbol, "'");
return false;
}
dbData.trade.SetDeviationInPoints(10);
dbData.trade.SetTypeFilling(ORDER_FILLING_IOC);
dbData.trade.SetAsyncMode(false);
dbData.trade.SetExpertMagicNumber(DB_MagicNumber);
ObjectsDeleteAll(0, dbData.boxName);
dbData.isInitialized = true;
Print("DarvasBox: Successfully initialized for symbol '", symbol, "'");
return true;
}
void DeinitDarvasBox()
{
if(dbData.maHandle != INVALID_HANDLE) IndicatorRelease(dbData.maHandle);
if(dbData.volumeHandle != INVALID_HANDLE) IndicatorRelease(dbData.volumeHandle);
ObjectsDeleteAll(0, dbData.boxName);
}
void DrawDarvasBox()
{
if(!dbData.boxFormed) return;
datetime time1 = iTime(dbData.symbol, PERIOD_H1, DB_BoxPeriod);
datetime time2 = iTime(dbData.symbol, PERIOD_H1, 0);
ObjectsDeleteAll(0, dbData.boxName);
ObjectCreate(0, dbData.boxName + "Top", OBJ_TREND, 0, time1, dbData.boxHigh, time2, dbData.boxHigh);
ObjectCreate(0, dbData.boxName + "Bottom", OBJ_TREND, 0, time1, dbData.boxLow, time2, dbData.boxLow);
ObjectSetInteger(0, dbData.boxName + "Top", OBJPROP_COLOR, DB_BoxColor);
ObjectSetInteger(0, dbData.boxName + "Bottom", OBJPROP_COLOR, DB_BoxColor);
ObjectSetInteger(0, dbData.boxName + "Top", OBJPROP_WIDTH, DB_BoxWidth);
ObjectSetInteger(0, dbData.boxName + "Bottom", OBJPROP_WIDTH, DB_BoxWidth);
ObjectSetInteger(0, dbData.boxName + "Top", OBJPROP_RAY_RIGHT, true);
ObjectSetInteger(0, dbData.boxName + "Bottom", OBJPROP_RAY_RIGHT, true);
}
void CalculateDarvasBox()
{
double high = 0;
double low = DBL_MAX;
// Find highest high and lowest low in the period - EXACTLY like original
for(int i = 0; i < DB_BoxPeriod; i++)
{
high = MathMax(high, iHigh(dbData.symbol, PERIOD_H1, i));
low = MathMin(low, iLow(dbData.symbol, PERIOD_H1, i));
}
double range = high - low;
double allowedRange = DB_BoxDeviation * dbData.point; // Use dbData.point instead of _Point
if(DB_EnableLogging)
{
Print("DarvasBox: Box Calculation - High: ", high, " Low: ", low, " Range: ", range, " Allowed Range: ", allowedRange);
}
// Check if box is formed - EXACTLY like original
if(range <= allowedRange)
{
dbData.boxHigh = high;
dbData.boxLow = low;
dbData.boxFormed = true;
dbData.lastBoxTime = iTime(dbData.symbol, PERIOD_CURRENT, 0);
// Draw the box
DrawDarvasBox();
if(DB_EnableLogging)
Print("DarvasBox: Box Formed - High: ", dbData.boxHigh, " Low: ", dbData.boxLow, " Time: ", dbData.lastBoxTime);
}
else
{
dbData.boxFormed = false;
// Delete box if it exists
ObjectsDeleteAll(0, dbData.boxName);
}
}
bool ValidateStopLevels(double price, double &sl, double &tp, ENUM_ORDER_TYPE orderType)
{
double minSlDistance = MathMax(dbData.minStopLevel, DB_StopLoss * dbData.point);
double minTpDistance = MathMax(dbData.minStopLevel, DB_TakeProfit * dbData.point);
if(orderType == ORDER_TYPE_BUY)
{
sl = price - minSlDistance;
tp = price + minTpDistance;
}
else
{
sl = price + minSlDistance;
tp = price - minTpDistance;
}
return true;
}
bool IsTrendFavorable(ENUM_ORDER_TYPE orderType)
{
double ma[];
ArraySetAsSeries(ma, true);
if(CopyBuffer(dbData.maHandle, 0, 0, 2, ma) <= 0)
return false;
double currentPrice = SymbolInfoDouble(dbData.symbol, SYMBOL_ASK);
double trendStrength = MathAbs(currentPrice - ma[0]) / dbData.point;
if(orderType == ORDER_TYPE_BUY)
return (currentPrice > ma[0] && trendStrength > DB_TrendThreshold);
else
return (currentPrice < ma[0] && trendStrength > DB_TrendThreshold);
}
bool CheckVolumeConditions()
{
double volumes[];
ArraySetAsSeries(volumes, true);
if(CopyBuffer(dbData.volumeHandle, 0, 0, DB_VolumeMA_Period + 1, volumes) <= 0)
return false;
double volumeMA = 0;
for(int i = 1; i <= DB_VolumeMA_Period; i++)
volumeMA += volumes[i];
volumeMA /= DB_VolumeMA_Period;
double currentVolume = volumes[0];
double volumeRatio = currentVolume / volumeMA;
return (volumeRatio > DB_VolumeThresholdMultiplier);
}
bool PlaceOrder(ENUM_ORDER_TYPE orderType, double price, double sl, double tp)
{
if(!ValidateStopLevels(price, sl, tp, orderType))
{
if(DB_EnableLogging)
Print("DarvasBox: Order rejected - Stop levels validation failed");
return false;
}
if(!IsTrendFavorable(orderType))
{
if(DB_EnableLogging)
Print("DarvasBox: Order rejected - Trend not favorable for ", EnumToString(orderType));
return false;
}
if(!CheckVolumeConditions())
{
if(DB_EnableLogging)
Print("DarvasBox: Order rejected - Volume conditions not met");
return false;
}
bool result = false;
// Use market price (0) instead of explicit price - this ensures market order execution
// In backtesting, explicit price might fail if price has moved
if(orderType == ORDER_TYPE_BUY)
result = dbData.trade.Buy(0.01, dbData.symbol, 0, sl, tp, "Darvas Box Breakout");
else
result = dbData.trade.Sell(0.01, dbData.symbol, 0, sl, tp, "Darvas Box Breakdown");
// Always log errors, success only if logging enabled
if(result)
{
if(DB_EnableLogging)
Print("DarvasBox: ", (orderType == ORDER_TYPE_BUY ? "Buy" : "Sell"), " Order Placed Successfully");
}
else
{
// Always log failures with detailed info
uint retcode_uint = dbData.trade.ResultRetcode();
int retcode = (int)retcode_uint;
string desc = dbData.trade.ResultRetcodeDescription();
ulong deal = dbData.trade.ResultDeal();
ulong order = dbData.trade.ResultOrder();
Print("DarvasBox: ", (orderType == ORDER_TYPE_BUY ? "Buy" : "Sell"),
" Order Failed - Retcode: ", retcode,
", Description: ", desc,
", Deal: ", deal,
", Order: ", order,
", Symbol: ", dbData.symbol,
", Requested Price: ", price,
", SL: ", sl,
", TP: ", tp);
}
return result;
}
void ProcessDarvasBox(string symbol)
{
// Skip if not initialized (symbol not available)
if(!dbData.isInitialized)
return;
dbData.symbol = symbol; // Update symbol in case it changed
// Calculate new box levels - EXACTLY like original (called every tick)
CalculateDarvasBox();
// Check for trading signals - EXACTLY like original (checked every tick)
if(dbData.boxFormed)
{
double currentPrice = SymbolInfoDouble(dbData.symbol, SYMBOL_ASK);
long currentVolume_long = iVolume(dbData.symbol, PERIOD_CURRENT, 0);
double currentVolume = (double)currentVolume_long;
if(DB_EnableLogging)
{
Print("DarvasBox: Current Price: ", currentPrice, " Box High: ", dbData.boxHigh, " Box Low: ", dbData.boxLow);
Print("DarvasBox: Current Volume: ", currentVolume, " Volume Threshold: ", DB_VolumeThreshold);
}
// Check for breakout above box - EXACTLY like original
if(currentPrice > dbData.boxHigh && currentVolume > DB_VolumeThreshold)
{
if(DB_EnableLogging)
Print("DarvasBox: Breakout Signal Detected - Price above box high");
// Buy signal
if(!PositionExistsByMagic(dbData.symbol, (ulong)DB_MagicNumber)) // No existing positions with our magic number
{
double sl = currentPrice - DB_StopLoss * dbData.point;
double tp = currentPrice + DB_TakeProfit * dbData.point;
if(DB_EnableLogging)
Print("DarvasBox: Preparing Buy Order - Price: ", currentPrice, " SL: ", sl, " TP: ", tp);
PlaceOrder(ORDER_TYPE_BUY, currentPrice, sl, tp);
}
else if(DB_EnableLogging)
Print("DarvasBox: Skipping Buy Signal - Position already exists");
}
// Check for breakdown below box - EXACTLY like original
if(currentPrice < dbData.boxLow && currentVolume > DB_VolumeThreshold)
{
if(DB_EnableLogging)
Print("DarvasBox: Breakdown Signal Detected - Price below box low");
// Sell signal
if(!PositionExistsByMagic(dbData.symbol, (ulong)DB_MagicNumber)) // No existing positions with our magic number
{
double sl = currentPrice + DB_StopLoss * dbData.point;
double tp = currentPrice - DB_TakeProfit * dbData.point;
if(DB_EnableLogging)
Print("DarvasBox: Preparing Sell Order - Price: ", currentPrice, " SL: ", sl, " TP: ", tp);
PlaceOrder(ORDER_TYPE_SELL, currentPrice, sl, tp);
}
else if(DB_EnableLogging)
Print("DarvasBox: Skipping Sell Signal - Position already exists");
}
}
else if(DB_EnableLogging)
Print("DarvasBox: No Box Formed - Waiting for consolidation");
}
//+------------------------------------------------------------------+
@@ -0,0 +1,496 @@
//+------------------------------------------------------------------+
//| EMASlopeDistanceStrategy.mqh |
//+------------------------------------------------------------------+
bool InitEMASlopeDistance(string symbol)
{
esData.symbol = symbol;
esData.letzte_überwachung_zeit = 0;
esData.überwachung_aktiv = false;
esData.preis_trigger_aktiv = false;
esData.steigung_trigger_aktiv = false;
esData.ticket = 0;
esData.trades_in_current_crossover = 0;
esData.crossover_detected = false;
esData.trade_open_time = 0;
esData.last_bar_time = 0;
// Check if symbol exists
if(!SymbolSelect(symbol, true))
{
Print("EMASlopeDistance: Symbol '", symbol, "' not available in Market Watch. Please add it to Market Watch or check symbol name.");
return false;
}
Sleep(100); // Wait for symbol to be ready
esData.trade.SetExpertMagicNumber(ES_MagicNumber);
esData.trade.SetDeviationInPoints(10);
esData.trade.SetTypeFilling(ORDER_FILLING_IOC);
esData.ema_handle = iMA(symbol, ES_Timeframe, ES_EMA_Periode, 0, MODE_EMA, PRICE_CLOSE);
if(esData.ema_handle == INVALID_HANDLE)
{
Print("EMASlopeDistance: Error creating EMA indicator for '", symbol, "'");
return false;
}
ArraySetAsSeries(esData.ema_array, true);
esData.isInitialized = true;
Print("EMASlopeDistance: Successfully initialized for symbol '", symbol, "'");
return true;
}
void DeinitEMASlopeDistance()
{
if(esData.ema_handle != INVALID_HANDLE)
IndicatorRelease(esData.ema_handle);
}
//+------------------------------------------------------------------+
//| EMA Berechnung (EMA Calculation) |
//+------------------------------------------------------------------+
void BerechneEMA()
{
//--- EMA Werte vom Indicator kopieren (Copy EMA values from indicator)
int copied = CopyBuffer(esData.ema_handle, 0, 0, 3, esData.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]: ", esData.ema_array[0], " [1]: ", esData.ema_array[1], " [2]: ", esData.ema_array[2]);
}
//+------------------------------------------------------------------+
//| Trigger-Bedingungen prüfen (Check trigger conditions) |
//+------------------------------------------------------------------+
void PrüfeTrigger()
{
if(ArraySize(esData.ema_array) < 2)
{
Print("TRACE: Array zu klein - Größe: ", ArraySize(esData.ema_array));
return;
}
//--- Aktuelle Werte (Current values)
double aktueller_preis = SymbolInfoDouble(esData.symbol, SYMBOL_BID);
double aktueller_ask = SymbolInfoDouble(esData.symbol, SYMBOL_ASK);
double aktueller_close = iClose(esData.symbol, ES_Timeframe, 0);
int digits = (int)SymbolInfoInteger(esData.symbol, SYMBOL_DIGITS);
double point = SymbolInfoDouble(esData.symbol, SYMBOL_POINT);
double pips_multiplier = (digits == 3 || digits == 5) ? 10.0 : 1.0;
//--- EMA Werte in Variablen (EMA values in variables)
double ema_aktuell = esData.ema_array[0];
double ema_vorher = esData.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)
{
esData.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: ", ES_PreisSchwelle, ")");
Print("TRACE: Close: ", aktueller_close, " EMA: ", ema_aktuell);
Print("TRACE: Trades im aktuellen Crossover: ", esData.trades_in_current_crossover, "/", ES_MaxTradesPerCrossover);
if(preis_abstand > ES_PreisSchwelle && !esData.preis_trigger_aktiv)
{
esData.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: ", ES_SteigungSchwelle, ")");
if(MathAbs(steigung) > ES_SteigungSchwelle && !esData.steigung_trigger_aktiv)
{
esData.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(esData.preis_trigger_aktiv && esData.steigung_trigger_aktiv && !esData.überwachung_aktiv)
{
esData.überwachung_aktiv = true;
if(ES_UseBarData)
{
esData.letzte_überwachung_zeit = iTime(esData.symbol, ES_Timeframe, 0); // Aktuelle Bar-Zeit
Print("TRACE: Überwachung gestartet - Beide Trigger aktiv (Bar: ", TimeToString(esData.letzte_überwachung_zeit), ")");
}
else
{
esData.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(esData.ü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(esData.trades_in_current_crossover >= ES_MaxTradesPerCrossover)
{
Print("TRACE: Trade-Limit erreicht (", ES_MaxTradesPerCrossover, ") - Kein neuer Trade");
return;
}
if(bullish_signal && !PositionExistsByMagic(esData.symbol, (ulong)ES_MagicNumber))
{
Print("TRACE: Versuche KAUF-Trade zu platzieren (Trade #", esData.trades_in_current_crossover + 1, ")");
if(PlatziereTrade(ORDER_TYPE_BUY))
{
esData.trades_in_current_crossover++;
}
}
else if(bearish_signal && !PositionExistsByMagic(esData.symbol, (ulong)ES_MagicNumber))
{
Print("TRACE: Versuche VERKAUF-Trade zu platzieren (Trade #", esData.trades_in_current_crossover + 1, ")");
if(PlatziereTrade(ORDER_TYPE_SELL))
{
esData.trades_in_current_crossover++;
}
}
else if(PositionExistsByMagic(esData.symbol, (ulong)ES_MagicNumber))
{
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: ", g_ES_LotSize);
bool success = false;
if(order_type == ORDER_TYPE_BUY)
{
success = esData.trade.Buy(g_ES_LotSize, esData.symbol, 0, 0, 0, "EMA Crossover Trade");
}
else
{
success = esData.trade.Sell(g_ES_LotSize, esData.symbol, 0, 0, 0, "EMA Crossover Trade");
}
if(success)
{
esData.ticket = (int)esData.trade.ResultOrder();
Print("TRACE: Trade erfolgreich platziert: ", (order_type == ORDER_TYPE_BUY) ? "KAUF" : "VERKAUF", " Ticket: ", esData.ticket);
//--- Trade-Öffnungszeit speichern (Save trade opening time)
esData.trade_open_time = iTime(esData.symbol, ES_Timeframe, 0);
Print("TRACE: Trade-Öffnungszeit: ", TimeToString(esData.trade_open_time));
//--- Überwachung zurücksetzen (Reset monitoring)
esData.überwachung_aktiv = false;
esData.preis_trigger_aktiv = false;
esData.steigung_trigger_aktiv = false;
return true;
}
else
{
Print("TRACE: Fehler beim Platzieren des Trades - Retcode: ", esData.trade.ResultRetcode());
Print("TRACE: Fehlerbeschreibung: ", esData.trade.ResultRetcodeDescription());
return false;
}
}
//+------------------------------------------------------------------+
//| Trades verwalten (Manage trades) |
//+------------------------------------------------------------------+
void VerwalteTrades()
{
if(!PositionSelectByMagic(esData.symbol, (ulong)ES_MagicNumber))
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);
int digits = (int)SymbolInfoInteger(esData.symbol, SYMBOL_DIGITS);
double point = SymbolInfoDouble(esData.symbol, SYMBOL_POINT);
double pips_multiplier = (digits == 3 || digits == 5) ? 10.0 : 1.0;
double trailing_stop_pips = ES_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(esData.ema_array) >= 1)
{
double aktueller_close = iClose(esData.symbol, ES_Timeframe, 0);
double ema_aktuell = esData.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 ", esData.trades_in_current_crossover);
}
}
//--- Profit-Prüfung nach X Bars (Profit check after X bars)
if(ES_CloseUnprofitableTrades && esData.trade_open_time != 0 && PositionExistsByMagic(esData.symbol, (ulong)ES_MagicNumber))
{
Print("TRACE: Profit-Prüfung aktiviert - CloseUnprofitableTrades: ", ES_CloseUnprofitableTrades);
PrüfeProfitNachBars();
}
else if(!ES_CloseUnprofitableTrades)
{
Print("TRACE: Profit-Prüfung deaktiviert - CloseUnprofitableTrades: ", ES_CloseUnprofitableTrades);
}
}
//+------------------------------------------------------------------+
//| Profit-Prüfung nach X Bars (Profit check after X bars) |
//+------------------------------------------------------------------+
void PrüfeProfitNachBars()
{
if(!PositionSelectByMagic(esData.symbol, (ulong)ES_MagicNumber))
{
return; // Keine Position offen
}
datetime current_bar_time = iTime(esData.symbol, ES_Timeframe, 0);
int bars_since_trade_open = iBarShift(esData.symbol, ES_Timeframe, esData.trade_open_time);
Print("TRACE: Bars seit Trade-Öffnung: ", bars_since_trade_open, "/", ES_ProfitCheckBars);
//--- Prüfe ob genügend Bars vergangen sind (Check if enough bars have passed)
if(bars_since_trade_open >= ES_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 ", ES_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)
esData.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)
esData.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 = ModifyPositionByMagic(esData.trade, esData.symbol, (ulong)ES_MagicNumber, 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: ", esData.trade.ResultRetcode());
Print("TRACE: Fehlerbeschreibung: ", esData.trade.ResultRetcodeDescription());
}
}
//+------------------------------------------------------------------+
//| Position schließen (Close position) |
//+------------------------------------------------------------------+
void SchließePosition(string reason = "Unbekannt")
{
Print("TRACE: Versuche Position zu schließen - Grund: ", reason);
bool success = ClosePositionByMagic(esData.trade, esData.symbol, (ulong)ES_MagicNumber);
if(success)
{
Print("TRACE: Position erfolgreich geschlossen - Grund: ", reason);
}
else
{
Print("TRACE: Fehler beim Schließen der Position - Retcode: ", esData.trade.ResultRetcode());
Print("TRACE: Fehlerbeschreibung: ", esData.trade.ResultRetcodeDescription());
}
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void ProcessEMASlopeDistance(string symbol)
{
// Skip if not initialized (symbol not available)
if(!esData.isInitialized)
return;
esData.symbol = symbol; // Update symbol in case it changed
//--- Bar-Daten oder Tick-Daten verwenden (Use bar data or tick data)
if(ES_UseBarData)
{
//--- Nur bei neuen Bars ausführen (Only execute on new bars)
datetime current_bar_time = iTime(esData.symbol, ES_Timeframe, 0);
if(current_bar_time == esData.last_bar_time)
{
return; // Kein neuer Bar, nichts tun
}
esData.last_bar_time = current_bar_time;
}
//--- EMA Werte berechnen (Calculate EMA values)
BerechneEMA();
//--- Debug: Aktuelle Werte ausgeben (Debug: Output current values)
if(ArraySize(esData.ema_array) > 0)
{
double aktueller_close = iClose(esData.symbol, ES_Timeframe, 0);
double ema_aktuell = esData.ema_array[0];
double ema_vorher = esData.ema_array[1];
int digits = (int)SymbolInfoInteger(esData.symbol, SYMBOL_DIGITS);
double point = SymbolInfoDouble(esData.symbol, SYMBOL_POINT);
double preis_abstand = MathAbs(aktueller_close - ema_aktuell) / point;
double steigung = (ema_aktuell - ema_vorher) / point;
if(ES_UseBarData)
{
Print("=== DEBUG INFO (Neuer Bar) ===");
Print("Bar Zeit: ", TimeToString(iTime(esData.symbol, ES_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: ", esData.preis_trigger_aktiv, " Steigungs-Trigger: ", esData.steigung_trigger_aktiv);
Print("Überwachung aktiv: ", esData.überwachung_aktiv);
Print("Position offen: ", PositionExistsByMagic(esData.symbol, (ulong)ES_MagicNumber));
Print("Trades im aktuellen Crossover: ", esData.trades_in_current_crossover, "/", ES_MaxTradesPerCrossover);
Print("==================");
}
//--- Überwachung prüfen (Check monitoring)
if(esData.überwachung_aktiv)
{
if(ES_UseBarData)
{
// Bar-basierte Überwachungszeit
int bars_since_monitoring = iBarShift(esData.symbol, ES_Timeframe, esData.letzte_überwachung_zeit);
int timeout_bars = (int)(ES_ÜberwachungTimeout / PeriodSeconds(ES_Timeframe));
if(bars_since_monitoring > timeout_bars)
{
esData.überwachung_aktiv = false;
esData.preis_trigger_aktiv = false;
esData.steigung_trigger_aktiv = false;
Print("Überwachung beendet - Bar-basierte Zeitüberschreitung (", bars_since_monitoring, " Bars)");
}
}
else
{
// Tick-basierte Überwachungszeit
if(TimeCurrent() - esData.letzte_überwachung_zeit > ES_ÜberwachungTimeout)
{
esData.überwachung_aktiv = false;
esData.preis_trigger_aktiv = false;
esData.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();
}
//+------------------------------------------------------------------+
@@ -0,0 +1,257 @@
//+------------------------------------------------------------------+
//| RSICrossOverReversalStrategy.mqh |
//+------------------------------------------------------------------+
void WeekDays_Init()
{
rcData.WeekDays[0] = RC_Sunday;
rcData.WeekDays[1] = RC_Monday;
rcData.WeekDays[2] = RC_Tuesday;
rcData.WeekDays[3] = RC_Wednesday;
rcData.WeekDays[4] = RC_Thursday;
rcData.WeekDays[5] = RC_Friday;
rcData.WeekDays[6] = RC_Saturday;
}
bool WeekDays_Check(datetime aTime)
{
MqlDateTime stm;
TimeToStruct(aTime, stm);
return(rcData.WeekDays[stm.day_of_week]);
}
bool RC_HourInWindow(const int h, const int beginRaw, const int endRaw)
{
const int b = beginRaw % 24;
const int e = endRaw % 24;
if(b == e)
return false;
if(b < e)
return (h >= b && h < e);
return (h >= b || h < e);
}
bool RC_TradingHoursAllow(const int currentHour)
{
return RC_HourInWindow(currentHour, RC_tradingHourOneBegin, RC_tradingHourOneEnd)
|| RC_HourInWindow(currentHour, RC_tradingHourTwoBegin, RC_tradingHourTwoEnd);
}
int TimeHour(datetime when = 0)
{
if(when == 0) when = TimeCurrent();
MqlDateTime dt;
TimeToStruct(when, dt);
return dt.hour;
}
bool InitRSICrossOverReversal(string symbol)
{
WeekDays_Init();
rcData.symbol = symbol;
rcData.previousRSIDef = 0;
rcData.lastTradeTime = 0;
rcData.bartime = 0;
rcData.lastBarTime = 0;
// Check if symbol exists
if(!SymbolSelect(symbol, true))
{
Print("RSICrossOverReversal: Symbol '", symbol, "' not available in Market Watch. Please add it to Market Watch or check symbol name.");
return false;
}
Sleep(100); // Wait for symbol to be ready
rcData.rsiHandle = iRSI(symbol, RC_TimeFrame1, RC_rsiPeriod, PRICE_CLOSE);
if(rcData.rsiHandle == INVALID_HANDLE)
{
Print("RSICrossOverReversal: Error creating RSI handle for '", symbol, "'");
return false;
}
rcData.emaHandle = iMA(symbol, RC_TimeFrame2, RC_emaPeriod, 0, MODE_EMA, PRICE_CLOSE);
if(rcData.emaHandle == INVALID_HANDLE)
{
Print("RSICrossOverReversal: Error creating EMA handle for '", symbol, "'");
return false;
}
rcData.trade.SetExpertMagicNumber(RC_MagicNumber);
rcData.isInitialized = true;
Print("RSICrossOverReversal: Successfully initialized for symbol '", symbol, "'");
return true;
}
void DeinitRSICrossOverReversal()
{
if(rcData.rsiHandle != INVALID_HANDLE)
IndicatorRelease(rcData.rsiHandle);
if(rcData.emaHandle != INVALID_HANDLE)
IndicatorRelease(rcData.emaHandle);
}
void Close_Position_MN(ulong magicNumber)
{
ClosePositionByMagic(rcData.trade, rcData.symbol, (int)magicNumber);
}
void ApplyTrailingStop()
{
if(!PositionSelectByMagic(rcData.symbol, RC_MagicNumber))
return;
ulong PositionTicket = PositionGetInteger(POSITION_TICKET);
ENUM_POSITION_TYPE trade_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
string symbol = rcData.symbol;
double POINT = SymbolInfoDouble(symbol, SYMBOL_POINT);
int DIGIT = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
if(trade_type == POSITION_TYPE_BUY)
{
double Bid = NormalizeDouble(SymbolInfoDouble(symbol, SYMBOL_BID), DIGIT);
if(Bid - PositionGetDouble(POSITION_PRICE_OPEN) > NormalizeDouble(POINT * RC_TrailingStop, DIGIT))
{
if(PositionGetDouble(POSITION_SL) < NormalizeDouble(Bid - POINT * RC_TrailingStop, DIGIT))
{
ModifyPositionByMagic(rcData.trade, symbol, RC_MagicNumber,
NormalizeDouble(Bid - POINT * RC_TrailingStop, DIGIT),
PositionGetDouble(POSITION_TP));
}
}
}
else if(trade_type == POSITION_TYPE_SELL)
{
double Ask = NormalizeDouble(SymbolInfoDouble(symbol, SYMBOL_ASK), DIGIT);
if((PositionGetDouble(POSITION_PRICE_OPEN) - Ask) > NormalizeDouble(POINT * RC_TrailingStop, DIGIT))
{
if((PositionGetDouble(POSITION_SL) > NormalizeDouble(Ask + POINT * RC_TrailingStop, DIGIT)) ||
(PositionGetDouble(POSITION_SL) == 0))
{
ModifyPositionByMagic(rcData.trade, symbol, RC_MagicNumber,
NormalizeDouble(Ask + POINT * RC_TrailingStop, DIGIT),
PositionGetDouble(POSITION_TP));
}
}
}
}
void ProcessRSICrossOverReversal(string symbol)
{
// Skip if not initialized (symbol not available)
if(!rcData.isInitialized)
return;
rcData.symbol = symbol; // Update symbol in case it changed
if(rcData.bartime == iTime(rcData.symbol, RC_BarTimeFrame, 0))
return;
rcData.bartime = iTime(rcData.symbol, RC_BarTimeFrame, 0);
double rsi[];
if(CopyBuffer(rcData.rsiHandle, 0, 0, 2, rsi) <= 0)
return;
double ema[];
if(CopyBuffer(rcData.emaHandle, 0, 0, 2, ema) <= 0)
return;
datetime currentTime = TimeCurrent();
int currentHour = TimeHour(TimeCurrent());
if(!WeekDays_Check(TimeTradeServer()))
{
Close_Position_MN(RC_MagicNumber);
return;
}
if(!RC_TradingHoursAllow(currentHour))
{
Close_Position_MN(RC_MagicNumber);
return;
}
bool hasPosition = PositionExistsByMagic(rcData.symbol, RC_MagicNumber);
double currentRSI = rsi[0];
double previousRSI = rsi[1];
if(rcData.previousRSIDef == 0)
{
rcData.previousRSIDef = currentRSI;
return;
}
double currentEMA = ema[0];
double previousEMA = ema[1];
double emaSlope = (currentEMA - previousEMA) * 100;
const double closeCurr = iClose(rcData.symbol, RC_TimeFrame1, 0);
double priceToEmaDistance = (closeCurr - currentEMA) * 10;
bool isBuyPosition = false;
bool isSellPosition = false;
if(hasPosition)
{
if(PositionSelectByMagic(rcData.symbol, RC_MagicNumber))
{
ENUM_POSITION_TYPE positionType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
if(positionType == POSITION_TYPE_BUY)
isBuyPosition = true;
else if(positionType == POSITION_TYPE_SELL)
isSellPosition = true;
}
}
ApplyTrailingStop();
bool cooldownPassed = (currentTime - rcData.lastTradeTime) >= RC_cooldownSeconds;
bool isTrendStrong = MathAbs(emaSlope) > RC_emaSlopeThreshold || MathAbs(priceToEmaDistance) > RC_emaDistanceThreshold;
if(isBuyPosition && currentRSI > RC_exitBuyRSI)
{
Close_Position_MN(RC_MagicNumber);
rcData.lastTradeTime = currentTime;
}
if(isSellPosition && currentRSI < RC_exitSellRSI)
{
Close_Position_MN(RC_MagicNumber);
rcData.lastTradeTime = currentTime;
}
if(isTrendStrong)
{
Close_Position_MN(RC_MagicNumber);
rcData.lastTradeTime = currentTime;
}
if(!isTrendStrong &&
currentRSI < RC_overboughtLevel - RC_entryRSISellSpread && rcData.previousRSIDef >= RC_overboughtLevel &&
!isSellPosition && !hasPosition && cooldownPassed)
{
rcData.trade.SetExpertMagicNumber(RC_MagicNumber);
if(rcData.trade.Sell(g_RC_LotSize, rcData.symbol, 0.0, 0.0, 0.0, "Sell Order"))
{
rcData.lastTradeTime = currentTime;
}
}
if(!isTrendStrong &&
currentRSI > RC_oversoldLevel + RC_entryRSIBuySpread && rcData.previousRSIDef <= RC_oversoldLevel &&
!isBuyPosition && !hasPosition && cooldownPassed)
{
rcData.trade.SetExpertMagicNumber(RC_MagicNumber);
if(rcData.trade.Buy(g_RC_LotSize, rcData.symbol, 0.0, 0.0, 0.0, "Buy Order"))
{
rcData.lastTradeTime = currentTime;
}
}
rcData.previousRSIDef = currentRSI;
}
//+------------------------------------------------------------------+
@@ -0,0 +1,471 @@
//+------------------------------------------------------------------+
//| RSIMidPointHijackStrategy.mqh |
//+------------------------------------------------------------------+
bool IsNewBar(string symbol)
{
datetime time[];
if(CopyTime(symbol, RM_InpTimeframe, 0, 1, time) > 0)
{
if(time[0] != rmData.lastBarTime)
{
rmData.lastBarTime = time[0];
return true;
}
}
return false;
}
bool IsWithinTradingHours(int startHour, int endHour)
{
MqlDateTime currentTime;
TimeToStruct(TimeCurrent(), currentTime);
if(startHour <= endHour)
return (currentTime.hour >= startHour && currentTime.hour < endHour);
else
return (currentTime.hour >= startHour || currentTime.hour < endHour);
}
bool HasPosition(string symbol, int magic)
{
return PositionExistsByMagic(symbol, magic);
}
bool HasProfitablePosition(int excludeMagic)
{
bool hasProfitable = false;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
if(rmData.positionInfo.SelectByIndex(i))
{
if(rmData.positionInfo.Magic() != excludeMagic)
{
double profit = rmData.positionInfo.Profit();
if(profit > RM_InpLockProfitThreshold * _Point)
{
hasProfitable = true;
if(RM_InpCloseOppositeTrades)
{
if((excludeMagic == RM_InpMagicNumberRSIFollow && rmData.positionInfo.Magic() == RM_InpMagicNumberRSIReverse) ||
(excludeMagic == RM_InpMagicNumberRSIReverse && rmData.positionInfo.Magic() == RM_InpMagicNumberRSIFollow) ||
(excludeMagic == RM_InpMagicNumberEMACross && (rmData.positionInfo.Magic() == RM_InpMagicNumberRSIReverse || rmData.positionInfo.Magic() == RM_InpMagicNumberRSIFollow)) ||
((excludeMagic == RM_InpMagicNumberRSIFollow || excludeMagic == RM_InpMagicNumberRSIReverse) && rmData.positionInfo.Magic() == RM_InpMagicNumberEMACross))
{
ClosePosition(rmData.symbol, (int)rmData.positionInfo.Magic());
}
}
}
}
}
}
return hasProfitable;
}
bool IsRSIReverseInCooldown(string symbol)
{
if(RM_InpRSIReverseCooldownBars <= 0)
return false;
if(!rmData.rsiReverseInCooldown)
return false;
datetime time[];
if(CopyTime(symbol, RM_InpTimeframe, 0, 1, time) > 0)
{
datetime currentBarTime = time[0];
datetime cooldownEndTime = rmData.rsiReverseLastCloseTime + RM_InpRSIReverseCooldownBars * PeriodSeconds(RM_InpTimeframe);
if(currentBarTime >= cooldownEndTime)
{
rmData.rsiReverseInCooldown = false;
return false;
}
}
return true;
}
void CheckRSIFollowStrategy(string symbol)
{
if(!IsWithinTradingHours(RM_InpRSIFollowStartHour, RM_InpRSIFollowEndHour))
{
if(RM_InpRSIFollowCloseOutsideHours)
{
if(HasPosition(symbol, RM_InpMagicNumberRSIFollow))
ClosePosition(symbol, RM_InpMagicNumberRSIFollow);
}
return;
}
if(RM_InpEnableStrategyLock && HasProfitablePosition(RM_InpMagicNumberRSIFollow))
return;
if(rmData.lastBarRSI > RM_InpRSIOverbought)
rmData.rsiOverbought = true;
else if(rmData.lastBarRSI < RM_InpRSIOversold)
rmData.rsiOversold = true;
if(rmData.rsiOverbought && rmData.lastBarRSI < RM_InpRSIExitLevel)
{
if(!HasPosition(symbol, RM_InpMagicNumberRSIFollow))
{
rmData.trade.SetExpertMagicNumber(RM_InpMagicNumberRSIFollow);
rmData.trade.Sell(g_RM_LotSize, symbol, 0, 0, 0, "RSI Follow");
}
rmData.rsiOverbought = false;
}
else if(rmData.rsiOversold && rmData.lastBarRSI > RM_InpRSIExitLevel)
{
if(!HasPosition(symbol, RM_InpMagicNumberRSIFollow))
{
rmData.trade.SetExpertMagicNumber(RM_InpMagicNumberRSIFollow);
rmData.trade.Buy(g_RM_LotSize, symbol, 0, 0, 0, "RSI Follow");
}
rmData.rsiOversold = false;
}
}
void CheckRSIReverseStrategy(string symbol)
{
if(!IsWithinTradingHours(RM_InpRSIReverseStartHour, RM_InpRSIReverseEndHour))
{
if(RM_InpRSIReverseCloseOutsideHours)
{
if(HasPosition(symbol, RM_InpMagicNumberRSIReverse))
ClosePosition(symbol, RM_InpMagicNumberRSIReverse);
}
return;
}
if(RM_InpEnableStrategyLock && HasProfitablePosition(RM_InpMagicNumberRSIReverse))
return;
if(IsRSIReverseInCooldown(symbol))
return;
if(rmData.lastBarRSIReverse > RM_InpRSIReverseOverbought)
rmData.rsiReverseOverbought = true;
else if(rmData.lastBarRSIReverse < RM_InpRSIReverseOversold)
rmData.rsiReverseOversold = true;
if(rmData.rsiReverseOverbought && rmData.lastBarRSIReverse < RM_InpRSIReverseCrossLevel)
{
if(!HasPosition(symbol, RM_InpMagicNumberRSIReverse))
{
rmData.trade.SetExpertMagicNumber(RM_InpMagicNumberRSIReverse);
rmData.trade.Sell(g_RM_LotSize, symbol, 0, 0, 0, "RSI Reverse");
}
rmData.rsiReverseOverbought = false;
}
else if(rmData.rsiReverseOversold && rmData.lastBarRSIReverse > RM_InpRSIReverseCrossLevel)
{
if(!HasPosition(symbol, RM_InpMagicNumberRSIReverse))
{
rmData.trade.SetExpertMagicNumber(RM_InpMagicNumberRSIReverse);
rmData.trade.Buy(g_RM_LotSize, symbol, 0, 0, 0, "RSI Reverse");
}
rmData.rsiReverseOversold = false;
}
}
void CheckEMACrossStrategy(string symbol)
{
if(!IsWithinTradingHours(RM_InpEMACrossStartHour, RM_InpEMACrossEndHour))
{
if(RM_InpEMACrossCloseOutsideHours)
{
if(HasPosition(symbol, RM_InpMagicNumberEMACross))
ClosePosition(symbol, RM_InpMagicNumberEMACross);
}
return;
}
if(RM_InpEnableStrategyLock && HasProfitablePosition(RM_InpMagicNumberEMACross))
return;
if(rmData.lastBarEMAPrev < rmData.lastBarClosePrev && rmData.lastBarEMA > rmData.lastBarClose)
{
rmData.emaCrossBuySignal = true;
rmData.emaCrossSellSignal = false;
rmData.emaCrossSignalBar = 0;
}
else if(rmData.lastBarEMAPrev > rmData.lastBarClosePrev && rmData.lastBarEMA < rmData.lastBarClose)
{
rmData.emaCrossSellSignal = true;
rmData.emaCrossBuySignal = false;
rmData.emaCrossSignalBar = 0;
}
if(RM_InpUseEMADistanceEntry)
{
if(rmData.emaCrossBuySignal)
{
bool distanceConditionMet = true;
double emaHistory[], closeHistory[];
ArraySetAsSeries(emaHistory, true);
ArraySetAsSeries(closeHistory, true);
if(CopyBuffer(rmData.emaHandle, 0, 0, RM_InpEMADistancePeriod, emaHistory) > 0 &&
CopyClose(symbol, RM_InpTimeframe, 0, RM_InpEMADistancePeriod, closeHistory) > 0)
{
double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
for(int i = 0; i < RM_InpEMADistancePeriod; i++)
{
double distance = (closeHistory[i] - emaHistory[i]) / point;
if(distance < RM_InpEMADistancePips)
{
distanceConditionMet = false;
break;
}
}
if(distanceConditionMet && !HasPosition(symbol, RM_InpMagicNumberEMACross))
{
rmData.trade.SetExpertMagicNumber(RM_InpMagicNumberEMACross);
rmData.trade.Buy(g_RM_LotSize, symbol, 0, 0, 0, "EMA Cross Distance");
rmData.emaCrossBuySignal = false;
}
}
}
else if(rmData.emaCrossSellSignal)
{
bool distanceConditionMet = true;
double emaHistory[], closeHistory[];
ArraySetAsSeries(emaHistory, true);
ArraySetAsSeries(closeHistory, true);
if(CopyBuffer(rmData.emaHandle, 0, 0, RM_InpEMADistancePeriod, emaHistory) > 0 &&
CopyClose(symbol, RM_InpTimeframe, 0, RM_InpEMADistancePeriod, closeHistory) > 0)
{
double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
for(int i = 0; i < RM_InpEMADistancePeriod; i++)
{
double distance = (emaHistory[i] - closeHistory[i]) / point;
if(distance < RM_InpEMADistancePips)
{
distanceConditionMet = false;
break;
}
}
if(distanceConditionMet && !HasPosition(symbol, RM_InpMagicNumberEMACross))
{
rmData.trade.SetExpertMagicNumber(RM_InpMagicNumberEMACross);
rmData.trade.Sell(g_RM_LotSize, symbol, 0, 0, 0, "EMA Cross Distance");
rmData.emaCrossSellSignal = false;
}
}
}
}
else
{
if(rmData.lastBarEMAPrev < rmData.lastBarClosePrev && rmData.lastBarEMA > rmData.lastBarClose)
{
if(!HasPosition(symbol, RM_InpMagicNumberEMACross))
{
rmData.trade.SetExpertMagicNumber(RM_InpMagicNumberEMACross);
rmData.trade.Buy(g_RM_LotSize, symbol, 0, 0, 0, "EMA Cross");
}
}
else if(rmData.lastBarEMAPrev > rmData.lastBarClosePrev && rmData.lastBarEMA < rmData.lastBarClose)
{
if(!HasPosition(symbol, RM_InpMagicNumberEMACross))
{
rmData.trade.SetExpertMagicNumber(RM_InpMagicNumberEMACross);
rmData.trade.Sell(g_RM_LotSize, symbol, 0, 0, 0, "EMA Cross");
}
}
}
if(rmData.emaCrossBuySignal || rmData.emaCrossSellSignal)
{
rmData.emaCrossSignalBar++;
if(rmData.emaCrossSignalBar > RM_InpEMADistancePeriod * 2)
{
rmData.emaCrossBuySignal = false;
rmData.emaCrossSellSignal = false;
}
}
}
void CheckExitConditions(string symbol)
{
if(RM_InpEnableRSIFollow)
{
if(HasPosition(symbol, RM_InpMagicNumberRSIFollow))
{
if(PositionSelectByMagic(symbol, RM_InpMagicNumberRSIFollow))
{
ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
if((posType == POSITION_TYPE_BUY && rmData.lastBarRSI < RM_InpRSIExitLevel) ||
(posType == POSITION_TYPE_SELL && rmData.lastBarRSI > RM_InpRSIExitLevel))
{
ClosePosition(symbol, RM_InpMagicNumberRSIFollow);
}
}
}
}
if(RM_InpEnableRSIReverse)
{
if(HasPosition(symbol, RM_InpMagicNumberRSIReverse))
{
if(PositionSelectByMagic(symbol, RM_InpMagicNumberRSIReverse))
{
ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
if((posType == POSITION_TYPE_BUY && rmData.lastBarRSIReverse < RM_InpRSIReverseExitLevel) ||
(posType == POSITION_TYPE_SELL && rmData.lastBarRSIReverse > RM_InpRSIReverseExitLevel))
{
ClosePosition(symbol, RM_InpMagicNumberRSIReverse);
}
}
}
}
if(RM_InpEnableEMACross)
{
if(HasPosition(symbol, RM_InpMagicNumberEMACross))
{
if(PositionSelectByMagic(symbol, RM_InpMagicNumberEMACross))
{
ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
if((posType == POSITION_TYPE_BUY && rmData.lastBarEMA > rmData.lastBarClose) ||
(posType == POSITION_TYPE_SELL && rmData.lastBarEMA < rmData.lastBarClose))
{
ClosePosition(symbol, RM_InpMagicNumberEMACross);
}
}
}
}
}
void ClosePosition(string symbol, int magic)
{
if(!PositionExistsByMagic(symbol, magic))
return;
ulong ticket = GetPositionTicketByMagic(symbol, magic);
if(ticket == 0)
return;
if(magic == RM_InpMagicNumberRSIReverse)
{
if(PositionSelectByTicketSymbolAndMagic(ticket, symbol, magic))
{
datetime time[];
if(CopyTime(symbol, RM_InpTimeframe, 0, 1, time) > 0)
{
rmData.rsiReverseLastCloseTime = time[0];
double profit = PositionGetDouble(POSITION_PROFIT);
if(!RM_InpRSIReverseCooldownOnLoss || profit < 0)
{
rmData.rsiReverseInCooldown = true;
}
}
}
}
ClosePositionByMagic(rmData.trade, symbol, magic);
}
bool InitRSIMidPointHijack(string symbol)
{
rmData.symbol = symbol;
rmData.rsiOverbought = false;
rmData.rsiOversold = false;
rmData.rsiReverseOverbought = false;
rmData.rsiReverseOversold = false;
rmData.emaCrossBuySignal = false;
rmData.emaCrossSellSignal = false;
rmData.emaCrossSignalBar = 0;
rmData.rsiReverseInCooldown = false;
rmData.lastBarRSI = 0;
rmData.lastBarRSIReverse = 0;
rmData.lastBarEMA = 0;
rmData.lastBarClose = 0;
rmData.lastBarEMAPrev = 0;
rmData.lastBarClosePrev = 0;
// Check if symbol exists
if(!SymbolSelect(symbol, true))
{
Print("RSIMidPointHijack: Symbol '", symbol, "' not available in Market Watch. Please add it to Market Watch or check symbol name.");
return false;
}
Sleep(100); // Wait for symbol to be ready
rmData.rsiHandle = iRSI(symbol, RM_InpTimeframe, RM_InpRSIPeriod, PRICE_CLOSE);
rmData.rsiReverseHandle = iRSI(symbol, RM_InpTimeframe, RM_InpRSIReversePeriod, PRICE_CLOSE);
rmData.emaHandle = iMA(symbol, RM_InpTimeframe, RM_InpEMAPeriod, 0, MODE_EMA, PRICE_CLOSE);
if(rmData.rsiHandle == INVALID_HANDLE || rmData.rsiReverseHandle == INVALID_HANDLE || rmData.emaHandle == INVALID_HANDLE)
{
Print("RSIMidPointHijack: Error creating indicators for '", symbol, "'");
return false;
}
rmData.trade.SetExpertMagicNumber(RM_InpMagicNumberRSIFollow);
rmData.trade.SetMarginMode();
rmData.trade.SetTypeFillingBySymbol(symbol);
rmData.trade.SetDeviationInPoints(10);
datetime time[];
if(CopyTime(symbol, RM_InpTimeframe, 0, 1, time) > 0)
rmData.lastBarTime = time[0];
rmData.isInitialized = true;
Print("RSIMidPointHijack: Successfully initialized for symbol '", symbol, "'");
return true;
}
void DeinitRSIMidPointHijack()
{
if(rmData.rsiHandle != INVALID_HANDLE) IndicatorRelease(rmData.rsiHandle);
if(rmData.rsiReverseHandle != INVALID_HANDLE) IndicatorRelease(rmData.rsiReverseHandle);
if(rmData.emaHandle != INVALID_HANDLE) IndicatorRelease(rmData.emaHandle);
}
void ProcessRSIMidPointHijack(string symbol)
{
// Skip if not initialized (symbol not available)
if(!rmData.isInitialized)
return;
rmData.symbol = symbol; // Update symbol in case it changed
if(!IsNewBar(rmData.symbol))
return;
double rsi[], rsiReverse[], ema[], close[];
ArraySetAsSeries(rsi, true);
ArraySetAsSeries(rsiReverse, true);
ArraySetAsSeries(ema, true);
ArraySetAsSeries(close, true);
rmData.lastBarEMAPrev = rmData.lastBarEMA;
rmData.lastBarClosePrev = rmData.lastBarClose;
if(CopyBuffer(rmData.rsiHandle, 0, 0, 1, rsi) > 0)
rmData.lastBarRSI = rsi[0];
if(CopyBuffer(rmData.rsiReverseHandle, 0, 0, 1, rsiReverse) > 0)
rmData.lastBarRSIReverse = rsiReverse[0];
if(CopyBuffer(rmData.emaHandle, 0, 0, 1, ema) > 0)
rmData.lastBarEMA = ema[0];
if(CopyClose(rmData.symbol, RM_InpTimeframe, 0, 1, close) > 0)
rmData.lastBarClose = close[0];
if(RM_InpEnableRSIFollow)
CheckRSIFollowStrategy(rmData.symbol);
if(RM_InpEnableRSIReverse)
CheckRSIReverseStrategy(rmData.symbol);
if(RM_InpEnableEMACross)
CheckEMACrossStrategy(rmData.symbol);
CheckExitConditions(rmData.symbol);
}
//+------------------------------------------------------------------+
@@ -0,0 +1,493 @@
//+------------------------------------------------------------------+
//| RSIReversalAsianStrategy.mqh |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| RSI Reversal Asian Strategy Data Structure |
//+------------------------------------------------------------------+
struct RSIReversalAsianData {
string symbol;
bool isInitialized;
int rsiHandle;
CTrade trade;
bool isPositionOpen;
double positionOpenPrice;
datetime positionOpenTime;
ENUM_POSITION_TYPE lastPositionType;
bool sessionCloseAttempted;
// RSI crossover variables
double rsiCurrent;
double rsiPrevious;
double rsiPrevious2;
bool rsiCrossedOverbought;
bool rsiCrossedOversold;
bool rsiCrossedExitLevel;
// Strategy parameters
int RSIPeriod;
double OverboughtLevel;
double OversoldLevel;
int TakeProfitPips;
int StopLossPips;
double MaxLotSize;
int MaxSpread;
int MaxDuration;
bool UseStopLoss;
bool UseTakeProfit;
bool UseRSIExit;
double RSIExitLevel;
bool CloseOutsideSession;
ENUM_TIMEFRAMES TimeFrame;
int MagicNumber;
int Slippage;
double point;
};
// Session times (UTC)
const int AsianSessionStart = 0; // 00:00 UTC
const int AsianSessionEnd = 8; // 08:00 UTC
//+------------------------------------------------------------------+
//| Check if current time is in Asian session |
//+------------------------------------------------------------------+
bool IsAsianSession()
{
datetime currentTime = TimeCurrent();
MqlDateTime timeStruct;
TimeToStruct(currentTime, timeStruct);
return (timeStruct.hour >= AsianSessionStart && timeStruct.hour < AsianSessionEnd);
}
//+------------------------------------------------------------------+
//| Check if trading is allowed for symbol |
//+------------------------------------------------------------------+
bool IsTradingAllowed(RSIReversalAsianData& data)
{
// Check if market is open
long tradeMode = SymbolInfoInteger(data.symbol, SYMBOL_TRADE_MODE);
if(tradeMode != SYMBOL_TRADE_MODE_FULL)
{
return false;
}
// Check if we have enough money
if(AccountInfoDouble(ACCOUNT_MARGIN_FREE) <= 0)
{
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| Check RSI crossover conditions |
//+------------------------------------------------------------------+
void CheckRSICrossover(RSIReversalAsianData& data)
{
// Reset crossover flags
data.rsiCrossedOverbought = false;
data.rsiCrossedOversold = false;
data.rsiCrossedExitLevel = false;
// Check for overbought crossover (RSI crosses above overbought level)
if(data.rsiPrevious < data.OverboughtLevel && data.rsiCurrent >= data.OverboughtLevel)
{
data.rsiCrossedOverbought = true;
}
// Check for oversold crossover (RSI crosses below oversold level)
if(data.rsiPrevious > data.OversoldLevel && data.rsiCurrent <= data.OversoldLevel)
{
data.rsiCrossedOversold = true;
}
// Check for exit level crossover
if(data.rsiPrevious < data.RSIExitLevel && data.rsiCurrent >= data.RSIExitLevel)
{
data.rsiCrossedExitLevel = true;
}
else if(data.rsiPrevious > data.RSIExitLevel && data.rsiCurrent <= data.RSIExitLevel)
{
data.rsiCrossedExitLevel = true;
}
}
//+------------------------------------------------------------------+
//| Close all trades for the symbol |
//+------------------------------------------------------------------+
bool CloseAllTrades(RSIReversalAsianData& data, string reason = "")
{
bool allClosed = true;
int totalPositions = PositionsTotal();
if(totalPositions == 0)
return true;
for(int i = totalPositions - 1; i >= 0; i--)
{
if(PositionGetSymbol(i) == data.symbol)
{
ulong ticket = PositionGetTicket(i);
if(ticket > 0 && PositionSelectByTicket(ticket))
{
if(PositionGetInteger(POSITION_MAGIC) == (ulong)data.MagicNumber)
{
// Try to close position with retry logic
int retryCount = 0;
bool positionClosed = false;
while(retryCount < 3 && !positionClosed)
{
if(data.trade.PositionClose(ticket))
{
data.isPositionOpen = false;
positionClosed = true;
}
else
{
int error = GetLastError();
// If error is 4756 (Trade disabled), wait longer before retry
if(error == 4756)
{
Sleep(5000); // Wait 5 seconds before retry
retryCount++;
}
else
{
// For other errors, break the loop
break;
}
}
}
if(!positionClosed)
{
allClosed = false;
}
}
}
}
}
return allClosed;
}
//+------------------------------------------------------------------+
//| Initialize RSI Reversal Asian Strategy |
//+------------------------------------------------------------------+
bool InitRSIReversalAsian(RSIReversalAsianData& data, string symbol,
int RSIPeriod, double OverboughtLevel, double OversoldLevel,
int TakeProfitPips, int StopLossPips, double MaxLotSize,
int MaxSpread, int MaxDuration, bool UseStopLoss,
bool UseTakeProfit, bool UseRSIExit, double RSIExitLevel,
bool CloseOutsideSession, ENUM_TIMEFRAMES TimeFrame,
int MagicNumber, int Slippage)
{
data.symbol = symbol;
data.isInitialized = false;
// Check if symbol exists
if(!SymbolSelect(symbol, true))
{
Print("RSIReversalAsian: Symbol '", symbol, "' not available in Market Watch. Please add it to Market Watch or check symbol name.");
return false;
}
// Wait a bit for symbol to be ready
Sleep(100);
// Get symbol point
data.point = SymbolInfoDouble(symbol, SYMBOL_POINT);
// Store parameters
data.RSIPeriod = RSIPeriod;
data.OverboughtLevel = OverboughtLevel;
data.OversoldLevel = OversoldLevel;
data.TakeProfitPips = TakeProfitPips;
data.StopLossPips = StopLossPips;
data.MaxLotSize = MaxLotSize;
data.MaxSpread = MaxSpread;
data.MaxDuration = MaxDuration;
data.UseStopLoss = UseStopLoss;
data.UseTakeProfit = UseTakeProfit;
data.UseRSIExit = UseRSIExit;
data.RSIExitLevel = RSIExitLevel;
data.CloseOutsideSession = CloseOutsideSession;
data.TimeFrame = TimeFrame;
data.MagicNumber = MagicNumber;
data.Slippage = Slippage;
// Initialize RSI indicator with retry logic (for insufficient history in backtesting)
data.rsiHandle = INVALID_HANDLE;
int retryCount = 0;
int maxRetries = 5;
while(retryCount < maxRetries && data.rsiHandle == INVALID_HANDLE)
{
data.rsiHandle = iRSI(symbol, TimeFrame, RSIPeriod, PRICE_CLOSE);
if(data.rsiHandle == INVALID_HANDLE)
{
int error = GetLastError();
// Error 4805 = insufficient history - wait longer and retry
if(error == 4805 && retryCount < maxRetries - 1)
{
Sleep(1000); // Wait 1 second for history to load
retryCount++;
continue;
}
Print("RSIReversalAsian: Error creating RSI indicator for '", symbol, "' - Error: ", error, " (", error == 4805 ? "Insufficient history data" : "Unknown", ")");
return false;
}
}
if(data.rsiHandle == INVALID_HANDLE)
{
Print("RSIReversalAsian: Failed to create RSI indicator for '", symbol, "' after ", maxRetries, " retries");
return false;
}
// Wait a bit for the indicator to be ready
Sleep(100);
// Initialize RSI values with retry logic
double rsi[];
ArraySetAsSeries(rsi, true);
retryCount = 0;
bool rsiInitialized = false;
while(retryCount < 10 && !rsiInitialized)
{
int copied = CopyBuffer(data.rsiHandle, 0, 0, 3, rsi);
if(copied >= 3)
{
data.rsiCurrent = rsi[0];
data.rsiPrevious = rsi[1];
data.rsiPrevious2 = rsi[2];
rsiInitialized = true;
}
else
{
retryCount++;
Sleep(100);
}
}
if(!rsiInitialized)
{
// Don't fail initialization, just set default values
data.rsiCurrent = 50.0;
data.rsiPrevious = 50.0;
data.rsiPrevious2 = 50.0;
}
// Set trade parameters
data.trade.SetExpertMagicNumber(MagicNumber);
data.trade.SetDeviationInPoints(Slippage);
data.trade.SetTypeFilling(ORDER_FILLING_IOC);
// Initialize state
data.isPositionOpen = false;
data.positionOpenPrice = 0;
data.positionOpenTime = 0;
data.lastPositionType = POSITION_TYPE_BUY;
data.sessionCloseAttempted = false;
data.rsiCrossedOverbought = false;
data.rsiCrossedOversold = false;
data.rsiCrossedExitLevel = false;
data.isInitialized = true;
Print("RSIReversalAsian: Successfully initialized for symbol '", symbol, "'");
return true;
}
//+------------------------------------------------------------------+
//| Deinitialize RSI Reversal Asian Strategy |
//+------------------------------------------------------------------+
void DeinitRSIReversalAsian(RSIReversalAsianData& data)
{
if(data.rsiHandle != INVALID_HANDLE)
IndicatorRelease(data.rsiHandle);
}
//+------------------------------------------------------------------+
//| Process RSI Reversal Asian Strategy |
//+------------------------------------------------------------------+
void ProcessRSIReversalAsian(RSIReversalAsianData& data, double lotSize)
{
if(!data.isInitialized)
return;
// Check if trading is allowed
if(!IsTradingAllowed(data))
{
return;
}
// Check if we're in Asian session
if(!IsAsianSession())
{
// Close all positions if outside Asian session and CloseOutsideSession is true
if(data.CloseOutsideSession && !data.sessionCloseAttempted)
{
CloseAllTrades(data, "Outside Asian session");
data.sessionCloseAttempted = true;
}
return;
}
else
{
// Reset the session close attempt flag when we enter Asian session
data.sessionCloseAttempted = false;
}
// Get current spread
double spread = SymbolInfoDouble(data.symbol, SYMBOL_ASK) - SymbolInfoDouble(data.symbol, SYMBOL_BID);
int spreadInPips = (int)(spread / data.point);
// Check if spread is too high
if(spreadInPips > data.MaxSpread)
{
return;
}
// Get RSI values from bar data
double rsi[];
ArraySetAsSeries(rsi, true);
int copied = CopyBuffer(data.rsiHandle, 0, 0, 3, rsi);
if(copied < 3)
{
return;
}
// Update RSI values
data.rsiPrevious2 = data.rsiPrevious;
data.rsiPrevious = data.rsiCurrent;
data.rsiCurrent = rsi[0];
// Validate RSI values
if(data.rsiCurrent == 0 || data.rsiPrevious == 0)
{
return;
}
// Check for RSI crossovers
CheckRSICrossover(data);
// Get current prices
double currentBid = SymbolInfoDouble(data.symbol, SYMBOL_BID);
double currentAsk = SymbolInfoDouble(data.symbol, SYMBOL_ASK);
// Check for open position
bool hasOpenPosition = PositionExistsByMagic(data.symbol, (ulong)data.MagicNumber);
if(hasOpenPosition)
{
// Get position details
ulong ticket = GetPositionTicketByMagic(data.symbol, (ulong)data.MagicNumber);
if(ticket > 0 && PositionSelectByTicket(ticket))
{
ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
datetime openTime = (datetime)PositionGetInteger(POSITION_TIME);
// Check for RSI exit if enabled
if(data.UseRSIExit && data.rsiCrossedExitLevel)
{
bool shouldExit = false;
// For long positions, exit when RSI crosses above exit level
if(posType == POSITION_TYPE_BUY && data.rsiCurrent >= data.RSIExitLevel && data.rsiPrevious < data.RSIExitLevel)
{
shouldExit = true;
}
// For short positions, exit when RSI crosses below exit level
else if(posType == POSITION_TYPE_SELL && data.rsiCurrent <= data.RSIExitLevel && data.rsiPrevious > data.RSIExitLevel)
{
shouldExit = true;
}
if(shouldExit)
{
CloseAllTrades(data, "RSI Exit Crossover");
return;
}
}
// Check for timeout
if(TimeCurrent() - openTime > data.MaxDuration * 3600)
{
CloseAllTrades(data, "Timeout");
return;
}
}
}
// If no position is open, look for entry signals based on RSI crossover
if(!hasOpenPosition)
{
// Place buy order if RSI crosses below oversold level (oversold crossover)
if(data.rsiCrossedOversold)
{
double sl = data.UseStopLoss ? currentBid - data.StopLossPips * data.point : 0;
double tp = data.UseTakeProfit ? currentBid + data.TakeProfitPips * data.point : 0;
if(data.UseStopLoss && sl >= currentBid)
return;
if(data.UseTakeProfit && tp <= currentBid)
return;
// Set trade parameters
data.trade.SetDeviationInPoints(data.Slippage);
data.trade.SetTypeFilling(ORDER_FILLING_IOC);
data.trade.SetExpertMagicNumber(data.MagicNumber);
// Use dynamic lot size
double tradeLotSize = lotSize > 0 ? lotSize : data.MaxLotSize;
// Place buy order using CTrade
if(data.trade.Buy(tradeLotSize, data.symbol, currentAsk, sl, tp, "RSI Oversold Crossover Buy"))
{
data.isPositionOpen = true;
data.positionOpenPrice = currentAsk;
data.positionOpenTime = TimeCurrent();
data.lastPositionType = POSITION_TYPE_BUY;
}
}
// Place sell order if RSI crosses above overbought level (overbought crossover)
else if(data.rsiCrossedOverbought)
{
double sl = data.UseStopLoss ? currentAsk + data.StopLossPips * data.point : 0;
double tp = data.UseTakeProfit ? currentAsk - data.TakeProfitPips * data.point : 0;
if(data.UseStopLoss && sl <= currentAsk)
return;
if(data.UseTakeProfit && tp >= currentAsk)
return;
// Set trade parameters
data.trade.SetDeviationInPoints(data.Slippage);
data.trade.SetTypeFilling(ORDER_FILLING_IOC);
data.trade.SetExpertMagicNumber(data.MagicNumber);
// Use dynamic lot size
double tradeLotSize = lotSize > 0 ? lotSize : data.MaxLotSize;
// Place sell order using CTrade
if(data.trade.Sell(tradeLotSize, data.symbol, currentBid, sl, tp, "RSI Overbought Crossover Sell"))
{
data.isPositionOpen = true;
data.positionOpenPrice = currentBid;
data.positionOpenTime = TimeCurrent();
data.lastPositionType = POSITION_TYPE_SELL;
}
}
}
}
@@ -0,0 +1,451 @@
//+------------------------------------------------------------------+
//| RSIScalpingStrategy.mqh |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| RSI Scalping Strategy Data Structure |
//+------------------------------------------------------------------+
struct RSIScalpingData {
string symbol;
bool isInitialized;
CTrade trade;
int rsi_handle;
double rsi_buffer[];
double rsi_prev;
double rsi_current;
double rsi_two_bars_ago;
bool position_open;
ulong position_ticket;
ENUM_POSITION_TYPE current_position_type;
datetime last_bar_time;
bool rsi_against_position;
int bars_against_count;
};
string ErrorDescription(int errorCode)
{
switch(errorCode)
{
case 4801: return "Symbol not found";
case 4802: return "Symbol not selected";
case 4803: return "Symbol not visible";
case 4804: return "Symbol not available";
case 4805: return "Cannot load indicator - insufficient history data";
default: return "Unknown error " + IntegerToString(errorCode);
}
}
bool InitRSIScalping(RSIScalpingData& data, string symbol, ENUM_TIMEFRAMES TimeFrame, int RSI_Period,
ENUM_APPLIED_PRICE RSI_Applied_Price, int MagicNumber, int Slippage)
{
data.symbol = symbol;
data.isInitialized = false;
// Check if symbol exists
if(!SymbolSelect(symbol, true))
{
Print("RSIScalping: Symbol '", symbol, "' not available in Market Watch. Please add it to Market Watch or check symbol name.");
return false; // Return false but don't fail entire EA
}
// Wait a bit for symbol to be ready
Sleep(100);
// Try to create RSI indicator with retry logic (for insufficient history in backtesting)
data.rsi_handle = INVALID_HANDLE;
int retryCount = 0;
int maxRetries = 5;
while(retryCount < maxRetries && data.rsi_handle == INVALID_HANDLE)
{
data.rsi_handle = iRSI(symbol, TimeFrame, RSI_Period, RSI_Applied_Price);
if(data.rsi_handle == INVALID_HANDLE)
{
int error = GetLastError();
// Error 4805 = insufficient history - wait longer and retry
if(error == 4805 && retryCount < maxRetries - 1)
{
Sleep(1000); // Wait 1 second for history to load
retryCount++;
continue;
}
Print("RSIScalping: Error creating RSI indicator for '", symbol, "' - Error: ", error, " (", ErrorDescription(error), ")");
return false; // Return false but don't fail entire EA
}
}
if(data.rsi_handle == INVALID_HANDLE)
{
Print("RSIScalping: Failed to create RSI indicator for '", symbol, "' after ", maxRetries, " retries");
return false;
}
data.trade.SetExpertMagicNumber(MagicNumber);
data.trade.SetDeviationInPoints(Slippage);
data.trade.SetTypeFilling(ORDER_FILLING_FOK);
ArraySetAsSeries(data.rsi_buffer, true);
data.position_open = false;
data.position_ticket = 0;
data.rsi_against_position = false;
data.bars_against_count = 0;
data.isInitialized = true;
Print("RSIScalping: Successfully initialized for symbol '", symbol, "'");
return true;
}
void DeinitRSIScalping(RSIScalpingData& data)
{
if(data.rsi_handle != INVALID_HANDLE)
IndicatorRelease(data.rsi_handle);
}
bool UpdateRSI(RSIScalpingData& data)
{
if(CopyBuffer(data.rsi_handle, 0, 0, 3, data.rsi_buffer) < 3)
return false;
data.rsi_current = data.rsi_buffer[0];
data.rsi_prev = data.rsi_buffer[1];
data.rsi_two_bars_ago = data.rsi_buffer[2];
return true;
}
void CheckExistingPosition(RSIScalpingData& data, ENUM_TIMEFRAMES TimeFrame, int MagicNumber,
double RSI_Oversold, double RSI_Overbought, double RSI_Target_Buy,
double RSI_Target_Sell, int BarsToWait)
{
// Always check if position exists, even if tracking says it doesn't
bool positionExists = PositionExistsByMagic(data.symbol, MagicNumber);
if(!positionExists && data.position_open)
{
// Position was closed externally, reset tracking
data.position_open = false;
data.position_ticket = 0;
data.rsi_against_position = false;
data.bars_against_count = 0;
return;
}
if(!positionExists)
return;
// Update tracking if we have a position but tracking was lost
if(!data.position_open && positionExists)
{
ulong ticket = GetPositionTicketByMagic(data.symbol, MagicNumber);
if(ticket > 0 && PositionSelectByTicketSymbolAndMagic(ticket, data.symbol, MagicNumber))
{
data.position_ticket = ticket;
data.position_open = true;
data.current_position_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
}
}
// Verify our tracked position still exists
if(data.position_open && data.position_ticket > 0)
{
if(!PositionSelectByTicketSymbolAndMagic(data.position_ticket, data.symbol, MagicNumber))
{
// Try to find the position again
ulong ticket = GetPositionTicketByMagic(data.symbol, MagicNumber);
if(ticket > 0 && PositionSelectByTicketSymbolAndMagic(ticket, data.symbol, MagicNumber))
{
data.position_ticket = ticket;
data.current_position_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
}
else
{
// Position doesn't exist, reset tracking
data.position_open = false;
data.position_ticket = 0;
data.rsi_against_position = false;
data.bars_against_count = 0;
return;
}
}
else
{
// Update position type in case it changed (shouldn't happen, but be safe)
data.current_position_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
}
}
if(data.current_position_type == POSITION_TYPE_BUY)
{
if(data.rsi_current < RSI_Oversold)
{
if(!data.rsi_against_position)
{
data.rsi_against_position = true;
data.bars_against_count = 1;
}
else
{
data.bars_against_count++;
}
if(data.bars_against_count >= BarsToWait)
{
ClosePosition(data, MagicNumber);
return;
}
}
else
{
if(data.rsi_against_position)
{
data.rsi_against_position = false;
data.bars_against_count = 0;
}
if(data.rsi_current >= RSI_Target_Buy)
{
ClosePosition(data, MagicNumber);
}
}
}
else if(data.current_position_type == POSITION_TYPE_SELL)
{
if(data.rsi_current > RSI_Overbought)
{
if(!data.rsi_against_position)
{
data.rsi_against_position = true;
data.bars_against_count = 1;
}
else
{
data.bars_against_count++;
}
if(data.bars_against_count >= BarsToWait)
{
ClosePosition(data, MagicNumber);
return;
}
}
else
{
if(data.rsi_against_position)
{
data.rsi_against_position = false;
data.bars_against_count = 0;
}
if(data.rsi_current <= RSI_Target_Sell)
{
ClosePosition(data, MagicNumber);
}
}
}
}
void CheckEntrySignals(RSIScalpingData& data, ENUM_TIMEFRAMES TimeFrame, int MagicNumber,
double RSI_Oversold, double RSI_Overbought, double LotSize)
{
if(data.rsi_two_bars_ago <= RSI_Oversold && data.rsi_prev > RSI_Oversold)
{
OpenBuyPosition(data, MagicNumber, LotSize);
}
if(data.rsi_two_bars_ago >= RSI_Overbought && data.rsi_prev < RSI_Overbought)
{
OpenSellPosition(data, MagicNumber, LotSize);
}
}
//+------------------------------------------------------------------+
//| Normalize Lot Size According to Symbol Properties |
//+------------------------------------------------------------------+
double NormalizeLotSize(string symbol, double lotSize)
{
double minLot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
double maxLot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);
double lotStep = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
// Round to lot step
if(lotStep > 0)
lotSize = MathFloor(lotSize / lotStep) * lotStep;
// Apply min/max constraints
if(lotSize < minLot)
lotSize = minLot;
if(lotSize > maxLot)
lotSize = maxLot;
return lotSize;
}
void OpenBuyPosition(RSIScalpingData& data, int MagicNumber, double LotSize)
{
if(PositionExistsByMagic(data.symbol, MagicNumber))
return;
// Normalize lot size according to symbol properties
double normalizedLot = NormalizeLotSize(data.symbol, LotSize);
double ask = SymbolInfoDouble(data.symbol, SYMBOL_ASK);
if(data.trade.Buy(normalizedLot, data.symbol, ask, 0, 0, "RSI Scalping Buy"))
{
ulong new_ticket = data.trade.ResultOrder();
if(new_ticket > 0)
{
if(PositionSelectByTicketSymbolAndMagic(new_ticket, data.symbol, MagicNumber))
{
data.position_ticket = new_ticket;
data.position_open = true;
data.current_position_type = POSITION_TYPE_BUY;
}
}
}
}
void OpenSellPosition(RSIScalpingData& data, int MagicNumber, double LotSize)
{
if(PositionExistsByMagic(data.symbol, MagicNumber))
return;
// Normalize lot size according to symbol properties
double normalizedLot = NormalizeLotSize(data.symbol, LotSize);
double bid = SymbolInfoDouble(data.symbol, SYMBOL_BID);
if(data.trade.Sell(normalizedLot, data.symbol, bid, 0, 0, "RSI Scalping Sell"))
{
ulong new_ticket = data.trade.ResultOrder();
if(new_ticket > 0)
{
if(PositionSelectByTicketSymbolAndMagic(new_ticket, data.symbol, MagicNumber))
{
data.position_ticket = new_ticket;
data.position_open = true;
data.current_position_type = POSITION_TYPE_SELL;
}
}
}
}
void ClosePosition(RSIScalpingData& data, int MagicNumber)
{
// First verify position still exists
if(!PositionExistsByMagic(data.symbol, MagicNumber))
{
// Position doesn't exist, reset tracking
data.position_open = false;
data.position_ticket = 0;
data.rsi_against_position = false;
data.bars_against_count = 0;
return;
}
// Try to close by ticket first (more reliable)
bool closed = false;
if(data.position_ticket > 0)
{
if(PositionSelectByTicket(data.position_ticket))
{
// Verify it's our position
if(PositionGetString(POSITION_SYMBOL) == data.symbol &&
PositionGetInteger(POSITION_MAGIC) == MagicNumber)
{
closed = data.trade.PositionClose(data.position_ticket);
if(!closed)
{
Print("RSIScalping: Failed to close position by ticket ", data.position_ticket,
" - Error: ", data.trade.ResultRetcode(), " (", data.trade.ResultRetcodeDescription(), ")");
}
}
}
}
// If ticket method failed, try magic number method
if(!closed)
{
closed = ClosePositionByMagic(data.trade, data.symbol, MagicNumber);
if(!closed)
{
Print("RSIScalping: Failed to close position by magic number for '", data.symbol,
"' - Error: ", data.trade.ResultRetcode(), " (", data.trade.ResultRetcodeDescription(), ")");
}
}
// Verify position is actually closed
if(closed)
{
// Wait a moment and verify
Sleep(50);
if(!PositionExistsByMagic(data.symbol, MagicNumber))
{
data.position_open = false;
data.position_ticket = 0;
data.rsi_against_position = false;
data.bars_against_count = 0;
Print("RSIScalping: Position successfully closed for '", data.symbol, "'");
}
else
{
Print("RSIScalping: Warning - Close returned success but position still exists for '", data.symbol, "'");
// Try one more time
Sleep(100);
if(PositionExistsByMagic(data.symbol, MagicNumber))
{
ClosePositionByMagic(data.trade, data.symbol, MagicNumber);
}
// Reset tracking anyway to prevent getting stuck
data.position_open = false;
data.position_ticket = 0;
data.rsi_against_position = false;
data.bars_against_count = 0;
}
}
else
{
// Close failed, but reset tracking to prevent getting stuck
// The position might have been closed externally
data.position_open = false;
data.position_ticket = 0;
data.rsi_against_position = false;
data.bars_against_count = 0;
}
}
void ProcessRSIScalping(RSIScalpingData& data, string symbol, ENUM_TIMEFRAMES TimeFrame, int RSI_Period,
ENUM_APPLIED_PRICE RSI_Applied_Price, double RSI_Overbought,
double RSI_Oversold, double RSI_Target_Buy, double RSI_Target_Sell,
int BarsToWait, double LotSize, int MagicNumber)
{
// Skip if not initialized (symbol not available)
if(!data.isInitialized)
return;
data.symbol = symbol; // Update symbol in case it changed
if(Bars(data.symbol, TimeFrame) < RSI_Period + 2)
return;
datetime current_bar_time = iTime(data.symbol, TimeFrame, 0);
if(current_bar_time == data.last_bar_time)
return;
data.last_bar_time = current_bar_time;
if(!UpdateRSI(data))
return;
CheckExistingPosition(data, TimeFrame, MagicNumber, RSI_Oversold, RSI_Overbought,
RSI_Target_Buy, RSI_Target_Sell, BarsToWait);
if(!data.position_open && !PositionExistsByMagic(data.symbol, MagicNumber))
{
CheckEntrySignals(data, TimeFrame, MagicNumber, RSI_Oversold, RSI_Overbought, LotSize);
}
}
//+------------------------------------------------------------------+
+598
View File
@@ -0,0 +1,598 @@
//+------------------------------------------------------------------+
//| 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 strict
#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>
#include <Indicators\Trend.mqh>
#include <Indicators\Volumes.mqh>
#include "MagicNumberHelpers.mqh"
// Include strategy implementations early so structs are available
#include "Strategies/DarvasBoxStrategy.mqh"
#include "Strategies/EMASlopeDistanceStrategy.mqh"
#include "Strategies/RSICrossOverReversalStrategy.mqh"
#include "Strategies/RSIMidPointHijackStrategy.mqh"
#include "Strategies/RSIScalpingStrategy.mqh"
#include "Strategies/RSIReversalAsianStrategy.mqh"
//+------------------------------------------------------------------+
//| Global Lot Size Variables (for dynamic lot sizing) |
//+------------------------------------------------------------------+
double g_ES_LotSize; // EMA Slope Distance lot size
double g_RC_LotSize; // RSI CrossOver Reversal lot size
double g_RM_LotSize; // RSI MidPoint Hijack lot size
//+------------------------------------------------------------------+
//| Strategy Enable/Disable Switches |
//+------------------------------------------------------------------+
input group "=== Strategy Enable/Disable ==="
input bool EnableDarvasBox = true;
input bool EnableEMASlopeDistance = true;
input bool EnableRSICrossOverReversal = true;
input bool EnableRSIMidPointHijack = true;
input bool EnableRSIScalpingAPPL = true;
input bool EnableRSIScalpingBTCUSD = true;
input bool EnableRSIScalpingMSFT = true;
input bool EnableRSIScalpingNVDA = true;
input bool EnableRSIScalpingTSLA = true;
input bool EnableRSIScalpingXAUUSD = true;
input bool EnableRSIReversalAsianEURUSD = true;
input bool EnableRSIReversalAsianAUDUSD = true;
//+------------------------------------------------------------------+
//| Strategy 1: DarvasBoxXAUUSD |
//+------------------------------------------------------------------+
input group "=== DarvasBox Strategy ==="
input string DB_Symbol = "XAUUSD";
input int DB_BoxPeriod = 165;
input double DB_BoxDeviation = 30000; // Increased to allow larger ranges (was 25140)
input int DB_VolumeThreshold = 0; // Set to 0 to disable volume threshold check. Volume data from indicator used instead.
input double DB_StopLoss = 1665;
input double DB_TakeProfit = 3685;
input bool DB_EnableLogging = false;
input color DB_BoxColor = clrBlue;
input int DB_BoxWidth = 1;
input ENUM_TIMEFRAMES DB_TrendTimeframe = PERIOD_H2;
input int DB_MA_Period = 125;
input ENUM_MA_METHOD DB_MA_Method = MODE_EMA;
input ENUM_APPLIED_PRICE DB_MA_Price = PRICE_WEIGHTED;
input double DB_TrendThreshold = 4.94;
input int DB_VolumeMA_Period = 110;
input double DB_VolumeThresholdMultiplier = 1.5;
input int DB_MagicNumber = 135790;
//+------------------------------------------------------------------+
//| Strategy 2: EMASlopeDistanceCocktailXAUUSD |
//| PEPPERSTONE US: Gold symbol is typically "XAUUSD" or "GOLD" |
//+------------------------------------------------------------------+
input group "=== EMA Slope Distance Strategy ==="
input string ES_Symbol = "XAUUSD";
input int ES_EMA_Periode = 46;
input double ES_PreisSchwelle = 600.0;
input double ES_SteigungSchwelle = 80.0;
input int ES_ÜberwachungTimeout = 800;
input double ES_TrailingStop = 250.0;
input double ES_LotGröße = 0.03;
input int ES_MagicNumber = 12350;
input bool ES_UseSpreadAdjustment = true;
input ENUM_TIMEFRAMES ES_Timeframe = PERIOD_H1;
input bool ES_UseBarData = true;
input int ES_MaxTradesPerCrossover = 9;
input int ES_ProfitCheckBars = 18;
input bool ES_CloseUnprofitableTrades = true;
//+------------------------------------------------------------------+
//| Strategy 3: RSICrossOverReversalXAUUSD |
//| PEPPERSTONE US: Gold symbol is typically "XAUUSD" or "GOLD" |
//+------------------------------------------------------------------+
input group "=== RSI CrossOver Reversal Strategy ==="
input string RC_Symbol = "XAUUSD";
input int RC_MagicNumber = 7;
input int RC_rsiPeriod = 19;
input int RC_overboughtLevel = 93;
input int RC_oversoldLevel = 22;
input double RC_entryRSIBuySpread = 0;
input double RC_entryRSISellSpread = 0;
input double RC_lotSize = 0.01;
input int RC_slippage = 3;
input int RC_cooldownSeconds = 209;
input ENUM_TIMEFRAMES RC_TimeFrame1 = PERIOD_M1;
input ENUM_TIMEFRAMES RC_TimeFrame2 = PERIOD_M1;
input ENUM_TIMEFRAMES RC_BarTimeFrame = PERIOD_M12;
input int RC_emaPeriod = 140;
input double RC_emaSlopeThreshold = 105;
input double RC_exitBuyRSI = 86;
input double RC_exitSellRSI = 10;
input double RC_TrailingStop = 295;
input double RC_emaDistanceThreshold = 165;
input int RC_tradingHourOneBegin = 24;
input int RC_tradingHourOneEnd = 22;
input int RC_tradingHourTwoBegin = 6;
input int RC_tradingHourTwoEnd = 19;
input bool RC_Sunday = false;
input bool RC_Monday = false;
input bool RC_Tuesday = true;
input bool RC_Wednesday = true;
input bool RC_Thursday = true;
input bool RC_Friday = false;
input bool RC_Saturday = false;
//+------------------------------------------------------------------+
//| Strategy 4: RSIMidPointHijackXAUUSD |
//| PEPPERSTONE US: Gold symbol is typically "XAUUSD" or "GOLD" |
//+------------------------------------------------------------------+
input group "=== RSI MidPoint Hijack Strategy ==="
input string RM_Symbol = "XAUUSD";
input ENUM_TIMEFRAMES RM_InpTimeframe = PERIOD_H1;
input double RM_InpLotSize = 0.02;
input int RM_InpMagicNumberRSIFollow = 1001;
input int RM_InpMagicNumberRSIReverse = 1002;
input int RM_InpMagicNumberEMACross = 1003;
input bool RM_InpEnableRSIFollow = true;
input bool RM_InpEnableRSIReverse = true;
input bool RM_InpEnableEMACross = true;
input bool RM_InpEnableStrategyLock = false;
input double RM_InpLockProfitThreshold = 0.0;
input bool RM_InpCloseOppositeTrades = false;
input int RM_InpRSIPeriod = 32;
input int RM_InpRSIOverbought = 78;
input int RM_InpRSIOversold = 46;
input int RM_InpRSIExitLevel = 44;
input int RM_InpRSIFollowStartHour = 23;
input int RM_InpRSIFollowEndHour = 8;
input bool RM_InpRSIFollowCloseOutsideHours = false;
input int RM_InpRSIReversePeriod = 59;
input int RM_InpRSIReverseOverbought = 51;
input int RM_InpRSIReverseOversold = 49;
input int RM_InpRSIReverseCrossLevel = 53;
input int RM_InpRSIReverseExitLevel = 48;
input int RM_InpRSIReverseStartHour = 7;
input int RM_InpRSIReverseEndHour = 13;
input bool RM_InpRSIReverseCloseOutsideHours = false;
input int RM_InpRSIReverseCooldownBars = 15;
input bool RM_InpRSIReverseCooldownOnLoss = true;
input int RM_InpEMAPeriod = 120;
input int RM_InpEMACrossStartHour = 8;
input int RM_InpEMACrossEndHour = 14;
input bool RM_InpEMACrossCloseOutsideHours = true;
input bool RM_InpUseEMADistanceEntry = true;
input double RM_InpEMADistancePips = 160.0;
input int RM_InpEMADistancePeriod = 26;
//+------------------------------------------------------------------+
//| Strategy 5-10: RSI Scalping Strategies |
//| Each RSI Scalping strategy trades on its own symbol: |
//| - APPL: Apple stock (AAPL) |
//| - BTCUSD: Bitcoin/USD |
//| - MSFT: Microsoft stock |
//| - NVDA: NVIDIA stock |
//| - TSLA: Tesla stock |
//| - XAUUSD: Gold/USD |
//| |
//| PEPPERSTONE US SYMBOL FORMATS: |
//| - Stocks may use: "AAPL.US", "NASDAQ:AAPL", or just "AAPL" |
//| - To find correct symbols: |
//| 1. Open Market Watch (Ctrl+M) |
//| 2. Right-click > Show All |
//| 3. Search for the stock name |
//| 4. Use the exact symbol name shown |
//+------------------------------------------------------------------+
input group "=== RSI Scalping APPL (AAPL) - Pepperstone US ==="
input string RS_APPL_Symbol = "AAPL.US"; // Try: "AAPL.US", "NASDAQ:AAPL", or "AAPL"
input ENUM_TIMEFRAMES RS_APPL_TimeFrame = PERIOD_M10;
input int RS_APPL_RSI_Period = 14;
input ENUM_APPLIED_PRICE RS_APPL_RSI_Applied_Price = PRICE_CLOSE;
input double RS_APPL_RSI_Overbought = 80;
input double RS_APPL_RSI_Oversold = 78;
input double RS_APPL_RSI_Target_Buy = 94;
input double RS_APPL_RSI_Target_Sell = 44;
input int RS_APPL_BarsToWait = 7;
input double RS_APPL_LotSize = 25;
input int RS_APPL_MagicNumber = 20001;
input int RS_APPL_Slippage = 3;
input group "=== RSI Scalping BTCUSD ==="
input string RS_BTCUSD_Symbol = "BTCUSD"; // Pepperstone may use: "BTCUSD", "BTC/USD", or "BTCUSD.c"
input ENUM_TIMEFRAMES RS_BTCUSD_TimeFrame = PERIOD_H1;
input int RS_BTCUSD_RSI_Period = 14;
input ENUM_APPLIED_PRICE RS_BTCUSD_RSI_Applied_Price = PRICE_CLOSE;
input double RS_BTCUSD_RSI_Overbought = 90;
input double RS_BTCUSD_RSI_Oversold = 73;
input double RS_BTCUSD_RSI_Target_Buy = 88;
input double RS_BTCUSD_RSI_Target_Sell = 48;
input int RS_BTCUSD_BarsToWait = 6;
input double RS_BTCUSD_LotSize = 0.1;
input int RS_BTCUSD_MagicNumber = 123459123;
input int RS_BTCUSD_Slippage = 3;
input group "=== RSI Scalping MSFT - Pepperstone US ==="
input string RS_MSFT_Symbol = "MSFT.US"; // Try: "MSFT.US", "NASDAQ:MSFT", or "MSFT"
input ENUM_TIMEFRAMES RS_MSFT_TimeFrame = PERIOD_H3;
input int RS_MSFT_RSI_Period = 14;
input ENUM_APPLIED_PRICE RS_MSFT_RSI_Applied_Price = PRICE_CLOSE;
input double RS_MSFT_RSI_Overbought = 19;
input double RS_MSFT_RSI_Oversold = 50;
input double RS_MSFT_RSI_Target_Buy = 71;
input double RS_MSFT_RSI_Target_Sell = 70;
input int RS_MSFT_BarsToWait = 1;
input double RS_MSFT_LotSize = 50;
input int RS_MSFT_MagicNumber = 20002;
input int RS_MSFT_Slippage = 3;
input group "=== RSI Scalping NVDA - Pepperstone US ==="
input string RS_NVDA_Symbol = "NVDA.US"; // Try: "NVDA.US", "NASDAQ:NVDA", or "NVDA"
input ENUM_TIMEFRAMES RS_NVDA_TimeFrame = PERIOD_M15;
input int RS_NVDA_RSI_Period = 8;
input ENUM_APPLIED_PRICE RS_NVDA_RSI_Applied_Price = PRICE_CLOSE;
input double RS_NVDA_RSI_Overbought = 36;
input double RS_NVDA_RSI_Oversold = 38;
input double RS_NVDA_RSI_Target_Buy = 90;
input double RS_NVDA_RSI_Target_Sell = 70;
input int RS_NVDA_BarsToWait = 5;
input double RS_NVDA_LotSize = 50;
input int RS_NVDA_MagicNumber = 20003;
input int RS_NVDA_Slippage = 3;
input group "=== RSI Scalping TSLA - Pepperstone US ==="
input string RS_TSLA_Symbol = "TSLA.US"; // Try: "TSLA.US", "NASDAQ:TSLA", or "TSLA"
input ENUM_TIMEFRAMES RS_TSLA_TimeFrame = PERIOD_H1;
input int RS_TSLA_RSI_Period = 14;
input ENUM_APPLIED_PRICE RS_TSLA_RSI_Applied_Price = PRICE_CLOSE;
input double RS_TSLA_RSI_Overbought = 54;
input double RS_TSLA_RSI_Oversold = 73;
input double RS_TSLA_RSI_Target_Buy = 87;
input double RS_TSLA_RSI_Target_Sell = 33;
input int RS_TSLA_BarsToWait = 1;
input double RS_TSLA_LotSize = 50;
input int RS_TSLA_MagicNumber = 125421321;
input int RS_TSLA_Slippage = 3;
input group "=== RSI Scalping XAUUSD ==="
input string RS_XAUUSD_Symbol = "XAUUSD";
input ENUM_TIMEFRAMES RS_XAUUSD_TimeFrame = PERIOD_H1;
input int RS_XAUUSD_RSI_Period = 14;
input ENUM_APPLIED_PRICE RS_XAUUSD_RSI_Applied_Price = PRICE_CLOSE;
input double RS_XAUUSD_RSI_Overbought = 71;
input double RS_XAUUSD_RSI_Oversold = 57;
input double RS_XAUUSD_RSI_Target_Buy = 80;
input double RS_XAUUSD_RSI_Target_Sell = 57;
input int RS_XAUUSD_BarsToWait = 4;
input double RS_XAUUSD_LotSize = 0.1;
input int RS_XAUUSD_MagicNumber = 129102315;
input int RS_XAUUSD_Slippage = 3;
//+------------------------------------------------------------------+
//| Strategy 11-12: RSI Reversal Asian Strategies |
//| Each RSI Reversal Asian strategy trades on its own symbol: |
//| - EURUSD: Euro/USD |
//| - AUDUSD: Australian Dollar/USD |
//+------------------------------------------------------------------+
input group "=== RSI Reversal Asian EURUSD ==="
input string RRA_EURUSD_Symbol = "EURUSD";
input int RRA_EURUSD_RSIPeriod = 28;
input double RRA_EURUSD_OverboughtLevel = 60;
input double RRA_EURUSD_OversoldLevel = 8;
input int RRA_EURUSD_TakeProfitPips = 175;
input int RRA_EURUSD_StopLossPips = 5;
input double RRA_EURUSD_MaxLotSize = 0.1;
input int RRA_EURUSD_MaxSpread = 1000;
input int RRA_EURUSD_MaxDuration = 270;
input bool RRA_EURUSD_UseStopLoss = false;
input bool RRA_EURUSD_UseTakeProfit = false;
input bool RRA_EURUSD_UseRSIExit = true;
input double RRA_EURUSD_RSIExitLevel = 55;
input bool RRA_EURUSD_CloseOutsideSession = false;
input ENUM_TIMEFRAMES RRA_EURUSD_TimeFrame = PERIOD_M15;
input int RRA_EURUSD_MagicNumber = 30001;
input int RRA_EURUSD_Slippage = 3;
input group "=== RSI Reversal Asian AUDUSD ==="
input string RRA_AUDUSD_Symbol = "AUDUSD";
input int RRA_AUDUSD_RSIPeriod = 28;
input double RRA_AUDUSD_OverboughtLevel = 68;
input double RRA_AUDUSD_OversoldLevel = 30;
input int RRA_AUDUSD_TakeProfitPips = 175;
input int RRA_AUDUSD_StopLossPips = 5;
input double RRA_AUDUSD_MaxLotSize = 0.2;
input int RRA_AUDUSD_MaxSpread = 1000;
input int RRA_AUDUSD_MaxDuration = 340;
input bool RRA_AUDUSD_UseStopLoss = false;
input bool RRA_AUDUSD_UseTakeProfit = false;
input bool RRA_AUDUSD_UseRSIExit = true;
input double RRA_AUDUSD_RSIExitLevel = 48;
input bool RRA_AUDUSD_CloseOutsideSession = true;
input ENUM_TIMEFRAMES RRA_AUDUSD_TimeFrame = PERIOD_M15;
input int RRA_AUDUSD_MagicNumber = 30002;
input int RRA_AUDUSD_Slippage = 3;
//+------------------------------------------------------------------+
//| Global Variables - DarvasBox |
//+------------------------------------------------------------------+
struct DarvasBoxData {
string symbol;
bool isInitialized;
double boxHigh;
double boxLow;
bool boxFormed;
datetime lastBoxTime;
string boxName;
double minStopLevel;
double point;
CTrade trade;
int maHandle;
int volumeHandle;
datetime lastBarTime;
};
//+------------------------------------------------------------------+
//| Global Variables - EMA Slope Distance |
//+------------------------------------------------------------------+
struct EMASlopeData {
string symbol;
bool isInitialized;
int ema_handle;
double ema_array[];
datetime letzte_überwachung_zeit;
bool überwachung_aktiv;
bool preis_trigger_aktiv;
bool steigung_trigger_aktiv;
int ticket;
CTrade trade;
int trades_in_current_crossover;
bool crossover_detected;
datetime trade_open_time;
datetime last_bar_time;
};
//+------------------------------------------------------------------+
//| Global Variables - RSI CrossOver Reversal |
//+------------------------------------------------------------------+
struct RSICrossOverData {
string symbol;
bool isInitialized;
int rsiHandle;
int emaHandle;
double previousRSIDef;
CTrade trade;
datetime lastTradeTime;
datetime bartime;
bool WeekDays[7];
datetime lastBarTime;
};
//+------------------------------------------------------------------+
//| Global Variables - RSI MidPoint Hijack |
//+------------------------------------------------------------------+
struct RSIMidPointData {
string symbol;
bool isInitialized;
int rsiHandle;
int rsiReverseHandle;
int emaHandle;
bool rsiOverbought;
bool rsiOversold;
bool rsiReverseOverbought;
bool rsiReverseOversold;
CTrade trade;
CPositionInfo positionInfo;
bool emaCrossBuySignal;
bool emaCrossSellSignal;
int emaCrossSignalBar;
datetime lastBarTime;
datetime rsiReverseLastCloseTime;
bool rsiReverseInCooldown;
double lastBarRSI;
double lastBarRSIReverse;
double lastBarEMA;
double lastBarClose;
double lastBarEMAPrev;
double lastBarClosePrev;
};
//+------------------------------------------------------------------+
//| Global Strategy Instances |
//+------------------------------------------------------------------+
DarvasBoxData dbData;
EMASlopeData esData;
RSICrossOverData rcData;
RSIMidPointData rmData;
RSIScalpingData rsAPPLData;
RSIScalpingData rsBTCUSDData;
RSIScalpingData rsMSFTData;
RSIScalpingData rsNVDAData;
RSIScalpingData rsTSLAData;
RSIScalpingData rsXAUUSDData;
//+------------------------------------------------------------------+
//| Global Variables - RSI Reversal Asian |
//+------------------------------------------------------------------+
RSIReversalAsianData rraEURUSDData;
RSIReversalAsianData rraAUDUSDData;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
int initResult = INIT_SUCCEEDED;
// Initialize global lot size variables
g_ES_LotSize = 0.03;
g_RC_LotSize = 0.01;
g_RM_LotSize = 0.02;
// Initialize strategies - log warnings but don't fail entire EA if symbol unavailable
if(EnableDarvasBox)
if(!InitDarvasBox(DB_Symbol))
Print("Warning: DarvasBox strategy failed to initialize for symbol '", DB_Symbol, "'");
if(EnableEMASlopeDistance)
if(!InitEMASlopeDistance(ES_Symbol))
Print("Warning: EMASlopeDistance strategy failed to initialize for symbol '", ES_Symbol, "'");
if(EnableRSICrossOverReversal)
if(!InitRSICrossOverReversal(RC_Symbol))
Print("Warning: RSICrossOverReversal strategy failed to initialize for symbol '", RC_Symbol, "'");
if(EnableRSIMidPointHijack)
if(!InitRSIMidPointHijack(RM_Symbol))
Print("Warning: RSIMidPointHijack strategy failed to initialize for symbol '", RM_Symbol, "'");
// Initialize RSI Scalping strategies - don't fail entire EA if symbol unavailable
if(EnableRSIScalpingAPPL)
InitRSIScalping(rsAPPLData, RS_APPL_Symbol, RS_APPL_TimeFrame, RS_APPL_RSI_Period, RS_APPL_RSI_Applied_Price, RS_APPL_MagicNumber, RS_APPL_Slippage);
if(EnableRSIScalpingBTCUSD)
InitRSIScalping(rsBTCUSDData, RS_BTCUSD_Symbol, RS_BTCUSD_TimeFrame, RS_BTCUSD_RSI_Period, RS_BTCUSD_RSI_Applied_Price, RS_BTCUSD_MagicNumber, RS_BTCUSD_Slippage);
if(EnableRSIScalpingMSFT)
InitRSIScalping(rsMSFTData, RS_MSFT_Symbol, RS_MSFT_TimeFrame, RS_MSFT_RSI_Period, RS_MSFT_RSI_Applied_Price, RS_MSFT_MagicNumber, RS_MSFT_Slippage);
if(EnableRSIScalpingNVDA)
InitRSIScalping(rsNVDAData, RS_NVDA_Symbol, RS_NVDA_TimeFrame, RS_NVDA_RSI_Period, RS_NVDA_RSI_Applied_Price, RS_NVDA_MagicNumber, RS_NVDA_Slippage);
if(EnableRSIScalpingTSLA)
InitRSIScalping(rsTSLAData, RS_TSLA_Symbol, RS_TSLA_TimeFrame, RS_TSLA_RSI_Period, RS_TSLA_RSI_Applied_Price, RS_TSLA_MagicNumber, RS_TSLA_Slippage);
if(EnableRSIScalpingXAUUSD)
InitRSIScalping(rsXAUUSDData, RS_XAUUSD_Symbol, RS_XAUUSD_TimeFrame, RS_XAUUSD_RSI_Period, RS_XAUUSD_RSI_Applied_Price, RS_XAUUSD_MagicNumber, RS_XAUUSD_Slippage);
// Initialize RSI Reversal Asian strategies
if(EnableRSIReversalAsianEURUSD)
if(!InitRSIReversalAsian(rraEURUSDData, RRA_EURUSD_Symbol, RRA_EURUSD_RSIPeriod, RRA_EURUSD_OverboughtLevel, RRA_EURUSD_OversoldLevel,
RRA_EURUSD_TakeProfitPips, RRA_EURUSD_StopLossPips, RRA_EURUSD_MaxLotSize,
RRA_EURUSD_MaxSpread, RRA_EURUSD_MaxDuration, RRA_EURUSD_UseStopLoss,
RRA_EURUSD_UseTakeProfit, RRA_EURUSD_UseRSIExit, RRA_EURUSD_RSIExitLevel,
RRA_EURUSD_CloseOutsideSession, RRA_EURUSD_TimeFrame, RRA_EURUSD_MagicNumber, RRA_EURUSD_Slippage))
Print("Warning: RSIReversalAsianEURUSD strategy failed to initialize for symbol '", RRA_EURUSD_Symbol, "'");
if(EnableRSIReversalAsianAUDUSD)
if(!InitRSIReversalAsian(rraAUDUSDData, RRA_AUDUSD_Symbol, RRA_AUDUSD_RSIPeriod, RRA_AUDUSD_OverboughtLevel, RRA_AUDUSD_OversoldLevel,
RRA_AUDUSD_TakeProfitPips, RRA_AUDUSD_StopLossPips, RRA_AUDUSD_MaxLotSize,
RRA_AUDUSD_MaxSpread, RRA_AUDUSD_MaxDuration, RRA_AUDUSD_UseStopLoss,
RRA_AUDUSD_UseTakeProfit, RRA_AUDUSD_UseRSIExit, RRA_AUDUSD_RSIExitLevel,
RRA_AUDUSD_CloseOutsideSession, RRA_AUDUSD_TimeFrame, RRA_AUDUSD_MagicNumber, RRA_AUDUSD_Slippage))
Print("Warning: RSIReversalAsianAUDUSD strategy failed to initialize for symbol '", RRA_AUDUSD_Symbol, "'");
Print("United EA initialized. Active strategies: ",
(EnableDarvasBox ? "DarvasBox " : ""),
(EnableEMASlopeDistance ? "EMASlope " : ""),
(EnableRSICrossOverReversal ? "RSICrossOver " : ""),
(EnableRSIMidPointHijack ? "RSIMidPoint " : ""),
(EnableRSIScalpingAPPL ? "RSIScalpingAPPL " : ""),
(EnableRSIScalpingBTCUSD ? "RSIScalpingBTCUSD " : ""),
(EnableRSIScalpingMSFT ? "RSIScalpingMSFT " : ""),
(EnableRSIScalpingNVDA ? "RSIScalpingNVDA " : ""),
(EnableRSIScalpingTSLA ? "RSIScalpingTSLA " : ""),
(EnableRSIScalpingXAUUSD ? "RSIScalpingXAUUSD " : ""),
(EnableRSIReversalAsianEURUSD ? "RSIReversalAsianEURUSD " : ""),
(EnableRSIReversalAsianAUDUSD ? "RSIReversalAsianAUDUSD " : ""));
return initResult;
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
if(EnableDarvasBox)
DeinitDarvasBox();
if(EnableEMASlopeDistance)
DeinitEMASlopeDistance();
if(EnableRSICrossOverReversal)
DeinitRSICrossOverReversal();
if(EnableRSIMidPointHijack)
DeinitRSIMidPointHijack();
if(EnableRSIScalpingAPPL)
DeinitRSIScalping(rsAPPLData);
if(EnableRSIScalpingBTCUSD)
DeinitRSIScalping(rsBTCUSDData);
if(EnableRSIScalpingMSFT)
DeinitRSIScalping(rsMSFTData);
if(EnableRSIScalpingNVDA)
DeinitRSIScalping(rsNVDAData);
if(EnableRSIScalpingTSLA)
DeinitRSIScalping(rsTSLAData);
if(EnableRSIScalpingXAUUSD)
DeinitRSIScalping(rsXAUUSDData);
if(EnableRSIReversalAsianEURUSD)
DeinitRSIReversalAsian(rraEURUSDData);
if(EnableRSIReversalAsianAUDUSD)
DeinitRSIReversalAsian(rraAUDUSDData);
Print("United EA deinitialized. Reason: ", reason);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
if(EnableDarvasBox)
ProcessDarvasBox(DB_Symbol);
if(EnableEMASlopeDistance)
ProcessEMASlopeDistance(ES_Symbol);
if(EnableRSICrossOverReversal)
ProcessRSICrossOverReversal(RC_Symbol);
if(EnableRSIMidPointHijack)
ProcessRSIMidPointHijack(RM_Symbol);
if(EnableRSIScalpingAPPL)
ProcessRSIScalping(rsAPPLData, RS_APPL_Symbol, RS_APPL_TimeFrame, RS_APPL_RSI_Period, RS_APPL_RSI_Applied_Price,
RS_APPL_RSI_Overbought, RS_APPL_RSI_Oversold, RS_APPL_RSI_Target_Buy, RS_APPL_RSI_Target_Sell,
RS_APPL_BarsToWait, RS_APPL_LotSize, RS_APPL_MagicNumber);
if(EnableRSIScalpingBTCUSD)
ProcessRSIScalping(rsBTCUSDData, RS_BTCUSD_Symbol, RS_BTCUSD_TimeFrame, RS_BTCUSD_RSI_Period, RS_BTCUSD_RSI_Applied_Price,
RS_BTCUSD_RSI_Overbought, RS_BTCUSD_RSI_Oversold, RS_BTCUSD_RSI_Target_Buy, RS_BTCUSD_RSI_Target_Sell,
RS_BTCUSD_BarsToWait, RS_BTCUSD_LotSize, RS_BTCUSD_MagicNumber);
if(EnableRSIScalpingMSFT)
ProcessRSIScalping(rsMSFTData, RS_MSFT_Symbol, RS_MSFT_TimeFrame, RS_MSFT_RSI_Period, RS_MSFT_RSI_Applied_Price,
RS_MSFT_RSI_Overbought, RS_MSFT_RSI_Oversold, RS_MSFT_RSI_Target_Buy, RS_MSFT_RSI_Target_Sell,
RS_MSFT_BarsToWait, RS_MSFT_LotSize, RS_MSFT_MagicNumber);
if(EnableRSIScalpingNVDA)
ProcessRSIScalping(rsNVDAData, RS_NVDA_Symbol, RS_NVDA_TimeFrame, RS_NVDA_RSI_Period, RS_NVDA_RSI_Applied_Price,
RS_NVDA_RSI_Overbought, RS_NVDA_RSI_Oversold, RS_NVDA_RSI_Target_Buy, RS_NVDA_RSI_Target_Sell,
RS_NVDA_BarsToWait, RS_NVDA_LotSize, RS_NVDA_MagicNumber);
if(EnableRSIScalpingTSLA)
ProcessRSIScalping(rsTSLAData, RS_TSLA_Symbol, RS_TSLA_TimeFrame, RS_TSLA_RSI_Period, RS_TSLA_RSI_Applied_Price,
RS_TSLA_RSI_Overbought, RS_TSLA_RSI_Oversold, RS_TSLA_RSI_Target_Buy, RS_TSLA_RSI_Target_Sell,
RS_TSLA_BarsToWait, RS_TSLA_LotSize, RS_TSLA_MagicNumber);
if(EnableRSIScalpingXAUUSD)
ProcessRSIScalping(rsXAUUSDData, RS_XAUUSD_Symbol, RS_XAUUSD_TimeFrame, RS_XAUUSD_RSI_Period, RS_XAUUSD_RSI_Applied_Price,
RS_XAUUSD_RSI_Overbought, RS_XAUUSD_RSI_Oversold, RS_XAUUSD_RSI_Target_Buy, RS_XAUUSD_RSI_Target_Sell,
RS_XAUUSD_BarsToWait, RS_XAUUSD_LotSize, RS_XAUUSD_MagicNumber);
if(EnableRSIReversalAsianEURUSD)
ProcessRSIReversalAsian(rraEURUSDData, RRA_EURUSD_MaxLotSize);
if(EnableRSIReversalAsianAUDUSD)
ProcessRSIReversalAsian(rraAUDUSDData, RRA_AUDUSD_MaxLotSize);
}
//+------------------------------------------------------------------+
Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

@@ -0,0 +1,683 @@
//+------------------------------------------------------------------+
//| 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 strict
#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>
#include <Indicators\Trend.mqh>
#include <Indicators\Volumes.mqh>
#include "MagicNumberHelpers.mqh"
#include "PerformanceEvaluator.mqh"
//+------------------------------------------------------------------+
//| Strategy Enable/Disable Switches |
//+------------------------------------------------------------------+
input group "=== Strategy Enable/Disable ==="
input bool EnableDarvasBox = true;
input bool EnableEMASlopeDistance = true;
input bool EnableRSICrossOverReversal = true;
input bool EnableRSIMidPointHijack = true;
input bool EnableRSIScalpingAPPL = true;
input bool EnableRSIScalpingBTCUSD = true;
input bool EnableRSIScalpingMSFT = true;
input bool EnableRSIScalpingNVDA = true;
input bool EnableRSIScalpingTSLA = true;
input bool EnableRSIScalpingXAUUSD = true;
//+------------------------------------------------------------------+
//| Strategy 1: DarvasBoxXAUUSD |
//+------------------------------------------------------------------+
input group "=== DarvasBox Strategy ==="
input string DB_Symbol = "XAUUSD";
input int DB_BoxPeriod = 165;
input double DB_BoxDeviation = 30000; // Increased to allow larger ranges (was 25140)
input int DB_VolumeThreshold = 0; // Set to 0 to disable volume threshold check. Volume data from indicator used instead.
input double DB_StopLoss = 1665;
input double DB_TakeProfit = 3685;
input bool DB_EnableLogging = false;
input color DB_BoxColor = clrBlue;
input int DB_BoxWidth = 1;
input ENUM_TIMEFRAMES DB_TrendTimeframe = PERIOD_H2;
input int DB_MA_Period = 125;
input ENUM_MA_METHOD DB_MA_Method = MODE_EMA;
input ENUM_APPLIED_PRICE DB_MA_Price = PRICE_WEIGHTED;
input double DB_TrendThreshold = 4.94;
input int DB_VolumeMA_Period = 110;
input double DB_VolumeThresholdMultiplier = 1.5;
input int DB_MagicNumber = 135790;
//+------------------------------------------------------------------+
//| Strategy 2: EMASlopeDistanceCocktailXAUUSD |
//| PEPPERSTONE US: Gold symbol is typically "XAUUSD" or "GOLD" |
//+------------------------------------------------------------------+
input group "=== EMA Slope Distance Strategy ==="
input string ES_Symbol = "XAUUSD";
input int ES_EMA_Periode = 46;
input double ES_PreisSchwelle = 600.0;
input double ES_SteigungSchwelle = 80.0;
input int ES_ÜberwachungTimeout = 800;
input double ES_TrailingStop = 250.0;
input double ES_LotGröße = 0.03;
input int ES_MagicNumber = 12350;
input bool ES_UseSpreadAdjustment = true;
input ENUM_TIMEFRAMES ES_Timeframe = PERIOD_H1;
input bool ES_UseBarData = true;
input int ES_MaxTradesPerCrossover = 9;
input int ES_ProfitCheckBars = 18;
input bool ES_CloseUnprofitableTrades = true;
//+------------------------------------------------------------------+
//| Strategy 3: RSICrossOverReversalXAUUSD |
//| PEPPERSTONE US: Gold symbol is typically "XAUUSD" or "GOLD" |
//+------------------------------------------------------------------+
input group "=== RSI CrossOver Reversal Strategy ==="
input string RC_Symbol = "XAUUSD";
input int RC_MagicNumber = 7;
input int RC_rsiPeriod = 19;
input int RC_overboughtLevel = 93;
input int RC_oversoldLevel = 22;
input double RC_entryRSIBuySpread = 0;
input double RC_entryRSISellSpread = 0;
input double RC_lotSize = 0.01;
input int RC_slippage = 3;
input int RC_cooldownSeconds = 209;
input ENUM_TIMEFRAMES RC_TimeFrame1 = PERIOD_M1;
input ENUM_TIMEFRAMES RC_TimeFrame2 = PERIOD_M1;
input ENUM_TIMEFRAMES RC_BarTimeFrame = PERIOD_M12;
input int RC_emaPeriod = 140;
input double RC_emaSlopeThreshold = 105;
input double RC_exitBuyRSI = 86;
input double RC_exitSellRSI = 10;
input double RC_TrailingStop = 295;
input double RC_emaDistanceThreshold = 165;
input int RC_tradingHourOneBegin = 24;
input int RC_tradingHourOneEnd = 22;
input int RC_tradingHourTwoBegin = 6;
input int RC_tradingHourTwoEnd = 19;
input bool RC_Sunday = false;
input bool RC_Monday = false;
input bool RC_Tuesday = true;
input bool RC_Wednesday = true;
input bool RC_Thursday = true;
input bool RC_Friday = false;
input bool RC_Saturday = false;
//+------------------------------------------------------------------+
//| Strategy 4: RSIMidPointHijackXAUUSD |
//| PEPPERSTONE US: Gold symbol is typically "XAUUSD" or "GOLD" |
//+------------------------------------------------------------------+
input group "=== RSI MidPoint Hijack Strategy ==="
input string RM_Symbol = "XAUUSD";
input ENUM_TIMEFRAMES RM_InpTimeframe = PERIOD_H1;
input double RM_InpLotSize = 0.02;
input int RM_InpMagicNumberRSIFollow = 1001;
input int RM_InpMagicNumberRSIReverse = 1002;
input int RM_InpMagicNumberEMACross = 1003;
input bool RM_InpEnableRSIFollow = true;
input bool RM_InpEnableRSIReverse = true;
input bool RM_InpEnableEMACross = true;
input bool RM_InpEnableStrategyLock = false;
input double RM_InpLockProfitThreshold = 0.0;
input bool RM_InpCloseOppositeTrades = false;
input int RM_InpRSIPeriod = 32;
input int RM_InpRSIOverbought = 78;
input int RM_InpRSIOversold = 46;
input int RM_InpRSIExitLevel = 44;
input int RM_InpRSIFollowStartHour = 23;
input int RM_InpRSIFollowEndHour = 8;
input bool RM_InpRSIFollowCloseOutsideHours = false;
input int RM_InpRSIReversePeriod = 59;
input int RM_InpRSIReverseOverbought = 51;
input int RM_InpRSIReverseOversold = 49;
input int RM_InpRSIReverseCrossLevel = 53;
input int RM_InpRSIReverseExitLevel = 48;
input int RM_InpRSIReverseStartHour = 7;
input int RM_InpRSIReverseEndHour = 13;
input bool RM_InpRSIReverseCloseOutsideHours = false;
input int RM_InpRSIReverseCooldownBars = 15;
input bool RM_InpRSIReverseCooldownOnLoss = true;
input int RM_InpEMAPeriod = 120;
input int RM_InpEMACrossStartHour = 8;
input int RM_InpEMACrossEndHour = 14;
input bool RM_InpEMACrossCloseOutsideHours = true;
input bool RM_InpUseEMADistanceEntry = true;
input double RM_InpEMADistancePips = 160.0;
input int RM_InpEMADistancePeriod = 26;
//+------------------------------------------------------------------+
//| Strategy 5-10: RSI Scalping Strategies |
//| Each RSI Scalping strategy trades on its own symbol: |
//| - APPL: Apple stock (AAPL) |
//| - BTCUSD: Bitcoin/USD |
//| - MSFT: Microsoft stock |
//| - NVDA: NVIDIA stock |
//| - TSLA: Tesla stock |
//| - XAUUSD: Gold/USD |
//| |
//| PEPPERSTONE US SYMBOL FORMATS: |
//| - Stocks may use: "AAPL.US", "NASDAQ:AAPL", or just "AAPL" |
//| - To find correct symbols: |
//| 1. Open Market Watch (Ctrl+M) |
//| 2. Right-click > Show All |
//| 3. Search for the stock name |
//| 4. Use the exact symbol name shown |
//+------------------------------------------------------------------+
input group "=== RSI Scalping APPL (AAPL) - Pepperstone US ==="
input string RS_APPL_Symbol = "AAPL.US"; // Try: "AAPL.US", "NASDAQ:AAPL", or "AAPL"
input ENUM_TIMEFRAMES RS_APPL_TimeFrame = PERIOD_M10;
input int RS_APPL_RSI_Period = 14;
input ENUM_APPLIED_PRICE RS_APPL_RSI_Applied_Price = PRICE_CLOSE;
input double RS_APPL_RSI_Overbought = 80;
input double RS_APPL_RSI_Oversold = 78;
input double RS_APPL_RSI_Target_Buy = 94;
input double RS_APPL_RSI_Target_Sell = 44;
input int RS_APPL_BarsToWait = 7;
input double RS_APPL_LotSize = 25;
input int RS_APPL_MagicNumber = 20001;
input int RS_APPL_Slippage = 3;
input group "=== RSI Scalping BTCUSD ==="
input string RS_BTCUSD_Symbol = "BTCUSD"; // Pepperstone may use: "BTCUSD", "BTC/USD", or "BTCUSD.c"
input ENUM_TIMEFRAMES RS_BTCUSD_TimeFrame = PERIOD_H1;
input int RS_BTCUSD_RSI_Period = 14;
input ENUM_APPLIED_PRICE RS_BTCUSD_RSI_Applied_Price = PRICE_CLOSE;
input double RS_BTCUSD_RSI_Overbought = 90;
input double RS_BTCUSD_RSI_Oversold = 73;
input double RS_BTCUSD_RSI_Target_Buy = 88;
input double RS_BTCUSD_RSI_Target_Sell = 48;
input int RS_BTCUSD_BarsToWait = 6;
input double RS_BTCUSD_LotSize = 0.1;
input int RS_BTCUSD_MagicNumber = 123459123;
input int RS_BTCUSD_Slippage = 3;
input group "=== RSI Scalping MSFT - Pepperstone US ==="
input string RS_MSFT_Symbol = "MSFT.US"; // Try: "MSFT.US", "NASDAQ:MSFT", or "MSFT"
input ENUM_TIMEFRAMES RS_MSFT_TimeFrame = PERIOD_H3;
input int RS_MSFT_RSI_Period = 14;
input ENUM_APPLIED_PRICE RS_MSFT_RSI_Applied_Price = PRICE_CLOSE;
input double RS_MSFT_RSI_Overbought = 19;
input double RS_MSFT_RSI_Oversold = 50;
input double RS_MSFT_RSI_Target_Buy = 71;
input double RS_MSFT_RSI_Target_Sell = 70;
input int RS_MSFT_BarsToWait = 1;
input double RS_MSFT_LotSize = 50;
input int RS_MSFT_MagicNumber = 20002;
input int RS_MSFT_Slippage = 3;
input group "=== RSI Scalping NVDA - Pepperstone US ==="
input string RS_NVDA_Symbol = "NVDA.US"; // Try: "NVDA.US", "NASDAQ:NVDA", or "NVDA"
input ENUM_TIMEFRAMES RS_NVDA_TimeFrame = PERIOD_M15;
input int RS_NVDA_RSI_Period = 8;
input ENUM_APPLIED_PRICE RS_NVDA_RSI_Applied_Price = PRICE_CLOSE;
input double RS_NVDA_RSI_Overbought = 36;
input double RS_NVDA_RSI_Oversold = 38;
input double RS_NVDA_RSI_Target_Buy = 90;
input double RS_NVDA_RSI_Target_Sell = 70;
input int RS_NVDA_BarsToWait = 5;
input double RS_NVDA_LotSize = 50;
input int RS_NVDA_MagicNumber = 20003;
input int RS_NVDA_Slippage = 3;
input group "=== RSI Scalping TSLA - Pepperstone US ==="
input string RS_TSLA_Symbol = "TSLA.US"; // Try: "TSLA.US", "NASDAQ:TSLA", or "TSLA"
input ENUM_TIMEFRAMES RS_TSLA_TimeFrame = PERIOD_H1;
input int RS_TSLA_RSI_Period = 14;
input ENUM_APPLIED_PRICE RS_TSLA_RSI_Applied_Price = PRICE_CLOSE;
input double RS_TSLA_RSI_Overbought = 54;
input double RS_TSLA_RSI_Oversold = 73;
input double RS_TSLA_RSI_Target_Buy = 87;
input double RS_TSLA_RSI_Target_Sell = 33;
input int RS_TSLA_BarsToWait = 1;
input double RS_TSLA_LotSize = 50;
input int RS_TSLA_MagicNumber = 125421321;
input int RS_TSLA_Slippage = 3;
input group "=== RSI Scalping XAUUSD ==="
input string RS_XAUUSD_Symbol = "XAUUSD";
input ENUM_TIMEFRAMES RS_XAUUSD_TimeFrame = PERIOD_H1;
input int RS_XAUUSD_RSI_Period = 14;
input ENUM_APPLIED_PRICE RS_XAUUSD_RSI_Applied_Price = PRICE_CLOSE;
input double RS_XAUUSD_RSI_Overbought = 71;
input double RS_XAUUSD_RSI_Oversold = 57;
input double RS_XAUUSD_RSI_Target_Buy = 80;
input double RS_XAUUSD_RSI_Target_Sell = 57;
input int RS_XAUUSD_BarsToWait = 4;
input double RS_XAUUSD_LotSize = 0.1;
input int RS_XAUUSD_MagicNumber = 129102315;
input int RS_XAUUSD_Slippage = 3;
//+------------------------------------------------------------------+
//| Global Variables - DarvasBox |
//+------------------------------------------------------------------+
struct DarvasBoxData {
string symbol;
bool isInitialized;
double boxHigh;
double boxLow;
bool boxFormed;
datetime lastBoxTime;
string boxName;
double minStopLevel;
double point;
CTrade trade;
int maHandle;
int volumeHandle;
datetime lastBarTime;
};
//+------------------------------------------------------------------+
//| Global Variables - EMA Slope Distance |
//+------------------------------------------------------------------+
struct EMASlopeData {
string symbol;
bool isInitialized;
int ema_handle;
double ema_array[];
datetime letzte_überwachung_zeit;
bool überwachung_aktiv;
bool preis_trigger_aktiv;
bool steigung_trigger_aktiv;
int ticket;
CTrade trade;
int trades_in_current_crossover;
bool crossover_detected;
datetime trade_open_time;
datetime last_bar_time;
};
//+------------------------------------------------------------------+
//| Global Variables - RSI CrossOver Reversal |
//+------------------------------------------------------------------+
struct RSICrossOverData {
string symbol;
bool isInitialized;
int rsiHandle;
int emaHandle;
double previousRSIDef;
CTrade trade;
datetime lastTradeTime;
datetime bartime;
bool WeekDays[7];
datetime lastBarTime;
};
//+------------------------------------------------------------------+
//| Global Variables - RSI MidPoint Hijack |
//+------------------------------------------------------------------+
struct RSIMidPointData {
string symbol;
bool isInitialized;
int rsiHandle;
int rsiReverseHandle;
int emaHandle;
bool rsiOverbought;
bool rsiOversold;
bool rsiReverseOverbought;
bool rsiReverseOversold;
CTrade trade;
CPositionInfo positionInfo;
bool emaCrossBuySignal;
bool emaCrossSellSignal;
int emaCrossSignalBar;
datetime lastBarTime;
datetime rsiReverseLastCloseTime;
bool rsiReverseInCooldown;
double lastBarRSI;
double lastBarRSIReverse;
double lastBarEMA;
double lastBarClose;
double lastBarEMAPrev;
double lastBarClosePrev;
};
//+------------------------------------------------------------------+
//| Global Variables - RSI Scalping |
//+------------------------------------------------------------------+
struct RSIScalpingData {
string symbol;
bool isInitialized;
CTrade trade;
int rsi_handle;
double rsi_buffer[];
double rsi_prev;
double rsi_current;
double rsi_two_bars_ago;
bool position_open;
ulong position_ticket;
ENUM_POSITION_TYPE current_position_type;
datetime last_bar_time;
bool rsi_against_position;
int bars_against_count;
};
//+------------------------------------------------------------------+
//| Global Strategy Instances |
//+------------------------------------------------------------------+
DarvasBoxData dbData;
EMASlopeData esData;
RSICrossOverData rcData;
RSIMidPointData rmData;
RSIScalpingData rsAPPLData;
RSIScalpingData rsBTCUSDData;
RSIScalpingData rsMSFTData;
RSIScalpingData rsNVDAData;
RSIScalpingData rsTSLAData;
RSIScalpingData rsXAUUSDData;
//+------------------------------------------------------------------+
//| Global Variables for Dynamic Lot Sizes |
//+------------------------------------------------------------------+
// All strategies start with minimum lot size for safety (will be adjusted by performance evaluator)
double g_DB_LotSize = 0.01; // DarvasBox uses fixed lot size
double g_ES_LotSize = 0.01; // EMA Slope Distance - start with minimum
double g_RC_LotSize = 0.01; // RSI CrossOver Reversal - start with minimum
double g_RM_LotSize = 0.01; // RSI MidPoint Hijack - start with minimum
double g_RS_APPL_LotSize = 5.0; // Stock - start with stock minimum (5.0)
double g_RS_BTCUSD_LotSize = 0.01; // Crypto - start with forex minimum (0.01)
double g_RS_MSFT_LotSize = 5.0; // Stock - start with stock minimum (5.0)
double g_RS_NVDA_LotSize = 5.0; // Stock - start with stock minimum (5.0)
double g_RS_TSLA_LotSize = 5.0; // Stock - start with stock minimum (5.0)
double g_RS_XAUUSD_LotSize = 0.01; // Forex - start with forex minimum (0.01)
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
int initResult = INIT_SUCCEEDED;
// Initialize Performance Evaluator
InitPerformanceTracking();
// Initialize strategies - log warnings but don't fail entire EA if symbol unavailable
if(EnableDarvasBox)
{
if(!InitDarvasBox(DB_Symbol))
Print("Warning: DarvasBox strategy failed to initialize for symbol '", DB_Symbol, "'");
else
RegisterStrategy("DarvasBox", DB_MagicNumber, 0.01, DB_Symbol); // Fixed lot size
}
if(EnableEMASlopeDistance)
{
if(!InitEMASlopeDistance(ES_Symbol))
Print("Warning: EMASlopeDistance strategy failed to initialize for symbol '", ES_Symbol, "'");
else
{
RegisterStrategy("EMASlopeDistance", ES_MagicNumber, ES_LotGröße, ES_Symbol);
// Start with minimum lot size (will be adjusted by performance evaluator)
double minLot = GetMinLotSizeForSymbol(ES_Symbol);
g_ES_LotSize = minLot;
}
}
if(EnableRSICrossOverReversal)
{
if(!InitRSICrossOverReversal(RC_Symbol))
Print("Warning: RSICrossOverReversal strategy failed to initialize for symbol '", RC_Symbol, "'");
else
{
RegisterStrategy("RSICrossOverReversal", RC_MagicNumber, RC_lotSize, RC_Symbol);
// Start with minimum lot size (will be adjusted by performance evaluator)
double minLot = GetMinLotSizeForSymbol(RC_Symbol);
g_RC_LotSize = minLot;
}
}
if(EnableRSIMidPointHijack)
{
if(!InitRSIMidPointHijack(RM_Symbol))
Print("Warning: RSIMidPointHijack strategy failed to initialize for symbol '", RM_Symbol, "'");
else
{
RegisterStrategy("RSIMidPointHijack", RM_InpMagicNumberRSIFollow, RM_InpLotSize, RM_Symbol);
RegisterStrategy("RSIMidPointHijack_Reverse", RM_InpMagicNumberRSIReverse, RM_InpLotSize, RM_Symbol);
RegisterStrategy("RSIMidPointHijack_EMACross", RM_InpMagicNumberEMACross, RM_InpLotSize, RM_Symbol);
// Start with minimum lot size (will be adjusted by performance evaluator)
double minLot = GetMinLotSizeForSymbol(RM_Symbol);
g_RM_LotSize = minLot;
}
}
// Initialize RSI Scalping strategies - don't fail entire EA if symbol unavailable
if(EnableRSIScalpingAPPL)
{
InitRSIScalping(rsAPPLData, RS_APPL_Symbol, RS_APPL_TimeFrame, RS_APPL_RSI_Period, RS_APPL_RSI_Applied_Price, RS_APPL_MagicNumber, RS_APPL_Slippage);
RegisterStrategy("RSIScalpingAPPL", RS_APPL_MagicNumber, RS_APPL_LotSize, RS_APPL_Symbol);
// Start with minimum lot size (will be adjusted by performance evaluator)
double minLot = GetMinLotSizeForSymbol(RS_APPL_Symbol);
g_RS_APPL_LotSize = minLot;
}
if(EnableRSIScalpingBTCUSD)
{
InitRSIScalping(rsBTCUSDData, RS_BTCUSD_Symbol, RS_BTCUSD_TimeFrame, RS_BTCUSD_RSI_Period, RS_BTCUSD_RSI_Applied_Price, RS_BTCUSD_MagicNumber, RS_BTCUSD_Slippage);
RegisterStrategy("RSIScalpingBTCUSD", RS_BTCUSD_MagicNumber, RS_BTCUSD_LotSize, RS_BTCUSD_Symbol);
// Start with minimum lot size (will be adjusted by performance evaluator)
double minLot = GetMinLotSizeForSymbol(RS_BTCUSD_Symbol);
g_RS_BTCUSD_LotSize = minLot;
}
if(EnableRSIScalpingMSFT)
{
InitRSIScalping(rsMSFTData, RS_MSFT_Symbol, RS_MSFT_TimeFrame, RS_MSFT_RSI_Period, RS_MSFT_RSI_Applied_Price, RS_MSFT_MagicNumber, RS_MSFT_Slippage);
RegisterStrategy("RSIScalpingMSFT", RS_MSFT_MagicNumber, RS_MSFT_LotSize, RS_MSFT_Symbol);
// Start with minimum lot size (will be adjusted by performance evaluator)
double minLot = GetMinLotSizeForSymbol(RS_MSFT_Symbol);
g_RS_MSFT_LotSize = minLot;
}
if(EnableRSIScalpingNVDA)
{
InitRSIScalping(rsNVDAData, RS_NVDA_Symbol, RS_NVDA_TimeFrame, RS_NVDA_RSI_Period, RS_NVDA_RSI_Applied_Price, RS_NVDA_MagicNumber, RS_NVDA_Slippage);
RegisterStrategy("RSIScalpingNVDA", RS_NVDA_MagicNumber, RS_NVDA_LotSize, RS_NVDA_Symbol);
// Start with minimum lot size (will be adjusted by performance evaluator)
double minLot = GetMinLotSizeForSymbol(RS_NVDA_Symbol);
g_RS_NVDA_LotSize = minLot;
}
if(EnableRSIScalpingTSLA)
{
InitRSIScalping(rsTSLAData, RS_TSLA_Symbol, RS_TSLA_TimeFrame, RS_TSLA_RSI_Period, RS_TSLA_RSI_Applied_Price, RS_TSLA_MagicNumber, RS_TSLA_Slippage);
RegisterStrategy("RSIScalpingTSLA", RS_TSLA_MagicNumber, RS_TSLA_LotSize, RS_TSLA_Symbol);
// Start with minimum lot size (will be adjusted by performance evaluator)
double minLot = GetMinLotSizeForSymbol(RS_TSLA_Symbol);
g_RS_TSLA_LotSize = minLot;
}
if(EnableRSIScalpingXAUUSD)
{
InitRSIScalping(rsXAUUSDData, RS_XAUUSD_Symbol, RS_XAUUSD_TimeFrame, RS_XAUUSD_RSI_Period, RS_XAUUSD_RSI_Applied_Price, RS_XAUUSD_MagicNumber, RS_XAUUSD_Slippage);
RegisterStrategy("RSIScalpingXAUUSD", RS_XAUUSD_MagicNumber, RS_XAUUSD_LotSize, RS_XAUUSD_Symbol);
// Start with minimum lot size (will be adjusted by performance evaluator)
double minLot = GetMinLotSizeForSymbol(RS_XAUUSD_Symbol);
g_RS_XAUUSD_LotSize = minLot;
}
// Load adjusted lot sizes from performance evaluator
if(PE_EnableAutoAdjustment)
{
double adjustedLot;
adjustedLot = GetStrategyLotSize("EMASlopeDistance", ES_MagicNumber);
if(adjustedLot > 0) g_ES_LotSize = adjustedLot;
adjustedLot = GetStrategyLotSize("RSICrossOverReversal", RC_MagicNumber);
if(adjustedLot > 0) g_RC_LotSize = adjustedLot;
adjustedLot = GetStrategyLotSize("RSIMidPointHijack", RM_InpMagicNumberRSIFollow);
if(adjustedLot > 0) g_RM_LotSize = adjustedLot;
adjustedLot = GetStrategyLotSize("RSIScalpingAPPL", RS_APPL_MagicNumber);
if(adjustedLot > 0) g_RS_APPL_LotSize = adjustedLot;
adjustedLot = GetStrategyLotSize("RSIScalpingBTCUSD", RS_BTCUSD_MagicNumber);
if(adjustedLot > 0) g_RS_BTCUSD_LotSize = adjustedLot;
adjustedLot = GetStrategyLotSize("RSIScalpingMSFT", RS_MSFT_MagicNumber);
if(adjustedLot > 0) g_RS_MSFT_LotSize = adjustedLot;
adjustedLot = GetStrategyLotSize("RSIScalpingNVDA", RS_NVDA_MagicNumber);
if(adjustedLot > 0) g_RS_NVDA_LotSize = adjustedLot;
adjustedLot = GetStrategyLotSize("RSIScalpingTSLA", RS_TSLA_MagicNumber);
if(adjustedLot > 0) g_RS_TSLA_LotSize = adjustedLot;
adjustedLot = GetStrategyLotSize("RSIScalpingXAUUSD", RS_XAUUSD_MagicNumber);
if(adjustedLot > 0) g_RS_XAUUSD_LotSize = adjustedLot;
}
Print("United EA initialized. Active strategies: ",
(EnableDarvasBox ? "DarvasBox " : ""),
(EnableEMASlopeDistance ? "EMASlope " : ""),
(EnableRSICrossOverReversal ? "RSICrossOver " : ""),
(EnableRSIMidPointHijack ? "RSIMidPoint " : ""),
(EnableRSIScalpingAPPL ? "RSIScalpingAPPL " : ""),
(EnableRSIScalpingBTCUSD ? "RSIScalpingBTCUSD " : ""),
(EnableRSIScalpingMSFT ? "RSIScalpingMSFT " : ""),
(EnableRSIScalpingNVDA ? "RSIScalpingNVDA " : ""),
(EnableRSIScalpingTSLA ? "RSIScalpingTSLA " : ""),
(EnableRSIScalpingXAUUSD ? "RSIScalpingXAUUSD " : ""));
if(PE_EnableLogging)
Print(GetPerformanceSummary());
return initResult;
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
if(EnableDarvasBox)
DeinitDarvasBox();
if(EnableEMASlopeDistance)
DeinitEMASlopeDistance();
if(EnableRSICrossOverReversal)
DeinitRSICrossOverReversal();
if(EnableRSIMidPointHijack)
DeinitRSIMidPointHijack();
if(EnableRSIScalpingAPPL)
DeinitRSIScalping(rsAPPLData);
if(EnableRSIScalpingBTCUSD)
DeinitRSIScalping(rsBTCUSDData);
if(EnableRSIScalpingMSFT)
DeinitRSIScalping(rsMSFTData);
if(EnableRSIScalpingNVDA)
DeinitRSIScalping(rsNVDAData);
if(EnableRSIScalpingTSLA)
DeinitRSIScalping(rsTSLAData);
if(EnableRSIScalpingXAUUSD)
DeinitRSIScalping(rsXAUUSDData);
Print("United EA deinitialized. Reason: ", reason);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Process performance evaluation (checks for quarter end and adjusts lot sizes)
ProcessPerformanceEvaluation();
// Update lot sizes from performance evaluator if auto-adjustment is enabled
if(PE_EnableAutoAdjustment)
{
double adjustedLot;
adjustedLot = GetStrategyLotSize("EMASlopeDistance", ES_MagicNumber);
if(adjustedLot > 0) g_ES_LotSize = adjustedLot;
adjustedLot = GetStrategyLotSize("RSICrossOverReversal", RC_MagicNumber);
if(adjustedLot > 0) g_RC_LotSize = adjustedLot;
adjustedLot = GetStrategyLotSize("RSIMidPointHijack", RM_InpMagicNumberRSIFollow);
if(adjustedLot > 0) g_RM_LotSize = adjustedLot;
adjustedLot = GetStrategyLotSize("RSIScalpingAPPL", RS_APPL_MagicNumber);
if(adjustedLot > 0) g_RS_APPL_LotSize = adjustedLot;
adjustedLot = GetStrategyLotSize("RSIScalpingBTCUSD", RS_BTCUSD_MagicNumber);
if(adjustedLot > 0) g_RS_BTCUSD_LotSize = adjustedLot;
adjustedLot = GetStrategyLotSize("RSIScalpingMSFT", RS_MSFT_MagicNumber);
if(adjustedLot > 0) g_RS_MSFT_LotSize = adjustedLot;
adjustedLot = GetStrategyLotSize("RSIScalpingNVDA", RS_NVDA_MagicNumber);
if(adjustedLot > 0) g_RS_NVDA_LotSize = adjustedLot;
adjustedLot = GetStrategyLotSize("RSIScalpingTSLA", RS_TSLA_MagicNumber);
if(adjustedLot > 0) g_RS_TSLA_LotSize = adjustedLot;
adjustedLot = GetStrategyLotSize("RSIScalpingXAUUSD", RS_XAUUSD_MagicNumber);
if(adjustedLot > 0) g_RS_XAUUSD_LotSize = adjustedLot;
}
if(EnableDarvasBox)
ProcessDarvasBox(DB_Symbol);
if(EnableEMASlopeDistance)
ProcessEMASlopeDistance(ES_Symbol);
if(EnableRSICrossOverReversal)
ProcessRSICrossOverReversal(RC_Symbol);
if(EnableRSIMidPointHijack)
ProcessRSIMidPointHijack(RM_Symbol);
if(EnableRSIScalpingAPPL)
ProcessRSIScalping(rsAPPLData, RS_APPL_Symbol, RS_APPL_TimeFrame, RS_APPL_RSI_Period, RS_APPL_RSI_Applied_Price,
RS_APPL_RSI_Overbought, RS_APPL_RSI_Oversold, RS_APPL_RSI_Target_Buy, RS_APPL_RSI_Target_Sell,
RS_APPL_BarsToWait, g_RS_APPL_LotSize, RS_APPL_MagicNumber);
if(EnableRSIScalpingBTCUSD)
ProcessRSIScalping(rsBTCUSDData, RS_BTCUSD_Symbol, RS_BTCUSD_TimeFrame, RS_BTCUSD_RSI_Period, RS_BTCUSD_RSI_Applied_Price,
RS_BTCUSD_RSI_Overbought, RS_BTCUSD_RSI_Oversold, RS_BTCUSD_RSI_Target_Buy, RS_BTCUSD_RSI_Target_Sell,
RS_BTCUSD_BarsToWait, g_RS_BTCUSD_LotSize, RS_BTCUSD_MagicNumber);
if(EnableRSIScalpingMSFT)
ProcessRSIScalping(rsMSFTData, RS_MSFT_Symbol, RS_MSFT_TimeFrame, RS_MSFT_RSI_Period, RS_MSFT_RSI_Applied_Price,
RS_MSFT_RSI_Overbought, RS_MSFT_RSI_Oversold, RS_MSFT_RSI_Target_Buy, RS_MSFT_RSI_Target_Sell,
RS_MSFT_BarsToWait, g_RS_MSFT_LotSize, RS_MSFT_MagicNumber);
if(EnableRSIScalpingNVDA)
ProcessRSIScalping(rsNVDAData, RS_NVDA_Symbol, RS_NVDA_TimeFrame, RS_NVDA_RSI_Period, RS_NVDA_RSI_Applied_Price,
RS_NVDA_RSI_Overbought, RS_NVDA_RSI_Oversold, RS_NVDA_RSI_Target_Buy, RS_NVDA_RSI_Target_Sell,
RS_NVDA_BarsToWait, g_RS_NVDA_LotSize, RS_NVDA_MagicNumber);
if(EnableRSIScalpingTSLA)
ProcessRSIScalping(rsTSLAData, RS_TSLA_Symbol, RS_TSLA_TimeFrame, RS_TSLA_RSI_Period, RS_TSLA_RSI_Applied_Price,
RS_TSLA_RSI_Overbought, RS_TSLA_RSI_Oversold, RS_TSLA_RSI_Target_Buy, RS_TSLA_RSI_Target_Sell,
RS_TSLA_BarsToWait, g_RS_TSLA_LotSize, RS_TSLA_MagicNumber);
if(EnableRSIScalpingXAUUSD)
ProcessRSIScalping(rsXAUUSDData, RS_XAUUSD_Symbol, RS_XAUUSD_TimeFrame, RS_XAUUSD_RSI_Period, RS_XAUUSD_RSI_Applied_Price,
RS_XAUUSD_RSI_Overbought, RS_XAUUSD_RSI_Oversold, RS_XAUUSD_RSI_Target_Buy, RS_XAUUSD_RSI_Target_Sell,
RS_XAUUSD_BarsToWait, g_RS_XAUUSD_LotSize, RS_XAUUSD_MagicNumber);
}
//+------------------------------------------------------------------+
//| Include strategy implementations |
//+------------------------------------------------------------------+
#include "Strategies/DarvasBoxStrategy.mqh"
#include "Strategies/EMASlopeDistanceStrategy.mqh"
#include "Strategies/RSICrossOverReversalStrategy.mqh"
#include "Strategies/RSIMidPointHijackStrategy.mqh"
#include "Strategies/RSIScalpingStrategy.mqh"
//+------------------------------------------------------------------+