mql5/Experts/EscapeEA_Enhanced.mq5
2025-08-05 01:57:33 -04:00

1265 lines
44 KiB
MQL5

//+------------------------------------------------------------------+
//| EscapeEA_Enhanced.mq5 |
//| Copyright 2025, EscapeEA |
//| https://www.escapeea.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, EscapeEA"
#property link "https://www.escapeea.com"
#property version "3.01" // Updated version with integrated components
#property strict
// +------------------------------------------------------------------+
// | SecurityEnhancements.mqh inputs migrated to main EA |
// +------------------------------------------------------------------+
input group "=== News Filter Settings ==="
input bool InpEnableNewsFilter = true; // Enable news event filtering
input string InpAffectedSymbols = ""; // Comma-separated list of symbols affected by news (empty = all)
input datetime InpNewsStartTime = 0; // Start time of news blackout period
input datetime InpNewsEndTime = 0; // End time of news blackout period
input group "=== Rate Limiting ==="
input bool InpEnableRateLimiting = true; // Enable rate limiting
input int InpMaxTradesPerMinute = 5; // Maximum trades per minute
input group "=== Price Validation ==="
input bool InpValidatePrices = true; // Enable price validation
input int InpMaxPriceDeviation = 10; // Maximum price deviation in points
input int InpMaxSlippage = 3; // Maximum allowed slippage in points
input group "=== Anomaly Detection ==="
input bool InpEnableAnomalyDetection = true; // Enable anomaly detection
input int InpMaxAnomalyCount = 3; // Maximum allowed anomalies before blocking
/**
* @file EscapeEA_Enhanced.mq5
* @brief Advanced Expert Advisor with integrated Paper Trading and Security
*
* This EA implements a sophisticated trading strategy with the following features:
* - Multi-timeframe analysis using moving averages
* - Advanced paper trading simulation with win requirement for live trading
* - Comprehensive risk management with position sizing
* - Secure trade execution with circuit breaker protection
* - Real-time adaptive learning from trade outcomes
* - Visual feedback for paper and live trades
*
* @see PaperTrading.mqh For paper trading simulation
* @see TradeExecutor.mqh For trade execution details
* @see RiskManager.mqh For risk management
* @see EnhancedSecurity.mqh For security features
*/
//--- Required Includes
#include <Trade\PositionInfo.mqh>
#include <Trade\SymbolInfo.mqh>
#include <Trade\DealInfo.mqh>
#include <Trade\Trade.mqh>
#include <Arrays\ArrayObj.mqh>
// Include our custom security components
#include <Escape/SecureMemory.mqh>
#include <Escape/InputValidation.mqh>
#include <Escape/SecurityManager.mqh>
// News Impact Analysis System
#include <Escape/MarketAnalyzer.mqh>
#include <Escape/NewsFeedHandler.mqh>
#include <Escape/VolatilityManager.mqh>
// Forward declarations for our custom components
class CRiskManager;
class CTradeExecutor;
class CPaperTrading;
class CEnhancedSecurity;
class CSignalGenerator;
class CPositionManager;
class CSecurityManager;
class CConfigManager;
// Include our custom components from Include/Escape directory
#include <Escape/RiskManager.mqh>
#include <Escape/TradeExecutor.mqh>
#include <Escape/PaperTrading.mqh>
#include <Escape/EnhancedSecurity.mqh>
#include <Escape/SignalGenerator.mqh>
#include <Escape/PositionManager.mqh>
// Include security components
#include <Escape/RAII.mqh>
#include <Escape/ConfigManager.mqh>
//--- Constants
#define EXPERT_NAME "EscapeEA_Enhanced"
#define EXPERT_VERSION "3.01"
//--- Enums
enum ENUM_TRADE_MODE {
TRADE_MODE_PAPER, // Paper trading only
TRADE_MODE_LIVE, // Live trading only
TRADE_MODE_BOTH // Both paper and live
};
// Scaling profiles for position management
enum ENUM_SCALING_PROFILE {
SCALING_NONE, // No scaling
SCALING_CONSERVATIVE, // Conservative scaling
SCALING_MODERATE, // Moderate scaling
SCALING_AGGRESSIVE // Aggressive scaling
};
// Exit profiles for position management
enum ENUM_EXIT_PROFILE {
EXIT_AGGRESSIVE, // Aggressive exit (tighter stops)
EXIT_BALANCED, // Balanced exit
EXIT_CONSERVATIVE // Conservative exit (wider stops)
};
//+------------------------------------------------------------------+
//| Global Variables and Input Parameters |
//+------------------------------------------------------------------+
//--- Trading Components
CPositionInfo ExtPosition; // Position info object
CSymbolInfo ExtSymbol; // Symbol info object
CAccountInfo ExtAccount; // Account info object
CDealInfo ExtDeal; // Deal info object
CTrade* ExtTrade = NULL; // Trade object
CTradeExecutor* ExtTradeExecutor = NULL; // Trade executor
CRiskManager* ExtRiskManager = NULL; // Risk manager
CPositionManager* ExtPositionManager = NULL; // Position manager
CPaperTrading* ExtPaperTrading = NULL; // Paper trading system
CSignalGenerator* ExtSignalGenerator = NULL; // Signal generator
CEnhancedSecurity* ExtSecurity = NULL; // Security manager
CConfigManager* ExtConfig = NULL; // Configuration manager
//--- News Impact Analysis System
CVolatilityManager* ExtVolatilityManager = NULL; // Volatility manager
CNewsFeedHandler* ExtNewsHandler = NULL; // News feed handler
CMarketAnalyzer* ExtMarketAnalyzer = NULL; // Market analyzer
//--- Trading State
bool ExtPaperTradingActive = false; // Paper trading mode flag
PaperTradeStats ExtPaperStats; // Paper trading statistics
//--- Indicator Handles
int ExtHandleMA = INVALID_HANDLE; // MA indicator handle
int ExtHandleATR = INVALID_HANDLE; // ATR indicator handle
//+------------------------------------------------------------------+
//| Input Parameters |
//+------------------------------------------------------------------+
//--- Trade Settings
input group "=== Trade Settings ==="
input ENUM_TRADE_MODE InpTradeMode = TRADE_MODE_BOTH; // Trading mode
input double InpLotSize = 0.1; // Lot size
input int InpStopLoss = 200; // Stop Loss in points
input int InpTakeProfit = 400; // Take Profit in points
input int InpMagicNumber = 123456; // Magic Number
input double InpRiskPerTrade = 1.0; // Risk per trade (% of balance)
input bool InpUseFixedLot = false; // Use fixed lot size
//--- Paper Trading Settings
input group "=== Paper Trading ==="
input bool InpEnablePaperTrading = true; // Enable paper trading
input int InpPaperTradesRequired = 5; // Required paper trades
input int InpPaperWinsRequired = 3; // Required winning trades
input double InpPaperInitialBalance = 10000; // Initial paper balance
//--- Risk Management
input group "=== Risk Management ==="
input double InpMaxRiskPerTrade = 2.0; // Max risk per trade (%)
input double InpMaxDailyDrawdown = 5.0; // Max daily drawdown (%)
input int InpMaxOpenTrades = 5; // Max open trades
//--- Indicator Parameters
input group "=== Indicator Settings ==="
input int InpMAPeriod = 14; // MA Period
input int InpMAShift = 0; // MA Shift
input ENUM_MA_METHOD InpMAMethod = MODE_SMA; // MA Method
input ENUM_APPLIED_PRICE InpMAApplied = PRICE_CLOSE; // MA Applied Price
input int InpATRPeriod = 14; // ATR Period
//--- Trading Hours
input group "=== Trading Hours ==="
input bool InpUseTradingHours = false; // Use trading hours
input int InpStartHour = 8; // Trading start hour (server time)
input int InpEndHour = 20; // Trading end hour (server time)
//--- Advanced Settings
input group "=== Advanced Settings ==="
input int InpMaxSlippage = 30; // Max Slippage (points)
input bool InpUseTrailingStop = true; // Use Trailing Stop
input int InpTrailingStop = 100; // Trailing Stop (points)
input int InpTrailingStep = 10; // Trailing Step (points)
input bool InpUseBreakEven = true; // Use Break Even
input int InpBreakEven = 100; // Break Even (points)
input int InpBreakEvenProfit = 50; // Break Even Profit (points)
//--- Visual Settings
input group "=== Visual Settings ==="
color InpBuyColor = clrDodgerBlue; // Buy signal color
color InpSellColor = clrCrimson; // Sell signal color
int InpSignalWidth = 2; // Signal line width
ENUM_LINE_STYLE InpSignalStyle = STYLE_SOLID; // Signal line style
// Paper Trading Statistics
struct PaperTradeStats {
int totalTrades; // Total paper trades taken
int winningTrades; // Number of winning paper trades
int losingTrades; // Number of losing paper trades
double totalProfit; // Total profit from paper trades
double totalLoss; // Total loss from paper trades
double winRate; // Current win rate
double profitFactor; // Profit factor (gross profit / gross loss)
datetime lastTradeTime; // Time of last trade
// Adaptive learning parameters
double positionSizeMultiplier; // Adjusts position size based on performance
double riskMultiplier; // Adjusts risk based on performance
double stopLossMultiplier; // Adjusts stop loss based on performance
double takeProfitMultiplier; // Adjusts take profit based on performance
// Initialize with default values
PaperTradeStats() {
totalTrades = 0;
winningTrades = 0;
losingTrades = 0;
totalProfit = 0.0;
totalLoss = 0.0;
winRate = 0.0;
profitFactor = 0.0;
lastTradeTime = 0;
positionSizeMultiplier = 1.0;
riskMultiplier = 1.0;
stopLossMultiplier = 1.0;
takeProfitMultiplier = 1.0;
}
// Update statistics after a trade
void UpdateStats(bool isWin, double profit) {
totalTrades++;
if(isWin) {
winningTrades++;
totalProfit += MathAbs(profit);
} else {
losingTrades++;
totalLoss += MathAbs(profit);
}
winRate = (double)winningTrades / totalTrades * 100.0;
profitFactor = (totalLoss > 0) ? totalProfit / totalLoss : 0.0;
lastTradeTime = TimeCurrent();
}
// Check if live trading is allowed (3/5 win rule)
bool IsLiveTradingAllowed() {
if(totalTrades < InpPaperTradesRequired) return false;
return (winningTrades >= InpPaperWinsRequired);
}
// Adaptive learning - adjust parameters based on trade outcomes
void LearnFromTrade(bool isWin, double profit, double learningRate) {
if(!InpEnableAdaptiveLearning) return;
// Adjust position size multiplier based on win/loss
if(isWin) {
// Increase position size multiplier on wins, but cap it
positionSizeMultiplier = MathMin(2.0, positionSizeMultiplier * (1.0 + learningRate));
} else {
// Decrease position size multiplier on losses, but keep it above 0.1
positionSizeMultiplier = MathMax(0.1, positionSizeMultiplier * (1.0 - learningRate));
}
// Adjust risk multiplier based on recent performance
double recentWinRate = (winningTrades > 0) ? (double)winningTrades / totalTrades : 0.5;
riskMultiplier = 0.5 + recentWinRate; // Range: 0.5 to 1.5
// Adjust stop loss and take profit based on volatility
// (This is a simplified example - you can make this more sophisticated)
if(isWin) {
// On wins, we can be more aggressive with take profit
takeProfitMultiplier = MathMin(2.0, takeProfitMultiplier * (1.0 + learningRate * 0.5));
} else {
// On losses, tighten stop loss
stopLossMultiplier = MathMax(0.5, stopLossMultiplier * (1.0 - learningRate * 0.5));
}
// Ensure multipliers stay within reasonable bounds
positionSizeMultiplier = MathMax(0.1, MathMin(2.0, positionSizeMultiplier));
riskMultiplier = MathMax(0.5, MathMin(1.5, riskMultiplier));
stopLossMultiplier = MathMax(0.5, MathMin(1.5, stopLossMultiplier));
takeProfitMultiplier = MathMax(0.5, MathMin(2.0, takeProfitMultiplier));
}
};
PaperTradeStats ExtPaperStats; // Global instance of paper trading statistics
// Trading State
ENUM_TRADE_MODE ExtTradeMode = TRADE_MODE_PAPER; // Trading mode
bool ExtIsTradingAllowed = true; // Global trading flag
bool ExtIsFirstTick = true; // First tick flag
bool ExtPaperTradingActive = true; // Paper trading mode flag
datetime ExtLastTradeTime = 0; // Last trade time
datetime ExtLastOrderTime = 0; // Last order time
int ExtOrderCount = 0; // Order counter for rate limiting
datetime ExtLastOrderCountReset = 0; // Last order count reset time
int ExtTimerId = -1; // Timer ID
// Trading Statistics
double ExtTotalProfit = 0.0; // Total profit
int ExtTotalTrades = 0; // Total trades
int ExtWinningTrades = 0; // Winning trades
int ExtLosingTrades = 0; // Losing trades
#define OBJ_PREFIX "EscapeEA_" // Prefix for chart objects
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Initialize security components
if(!InitializeSecurity())
{
Print("Failed to initialize security components");
return INIT_FAILED;
}
// Initialize indicators
if(!InitializeIndicators())
{
Print("Failed to initialize indicators");
return INIT_FAILED;
}
// Initialize trading components
if(!InitializeTradingComponents())
{
Print("Failed to initialize trading components");
return INIT_FAILED;
}
// Initialize News Impact Analysis System
if(!InitializeNewsImpactAnalysis())
{
Print("Warning: News Impact Analysis System initialization failed. Continuing without it.");
// Don't fail initialization if news system fails
}
// Initialize visualization
if(!InitializeVisualization())
{
Print("Warning: Failed to initialize visualization components");
// Don't fail initialization if visualization fails
}
// Set up timer for periodic updates
EventSetTimer(1);
Print(EXPERT_NAME " v" + EXPERT_VERSION + " initialized successfully");
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Initialize News Impact Analysis System |
//+------------------------------------------------------------------+
bool InitializeNewsImpactAnalysis()
{
// Initialize Volatility Manager
ExtVolatilityManager = new CVolatilityManager();
if(ExtVolatilityManager == NULL)
{
Print("Failed to create Volatility Manager");
return false;
}
// Initialize News Feed Handler
ExtNewsHandler = new CNewsFeedHandler();
if(ExtNewsHandler == NULL)
{
Print("Failed to create News Feed Handler");
delete ExtVolatilityManager;
ExtVolatilityManager = NULL;
return false;
}
// Initialize Market Analyzer with dependencies
ExtMarketAnalyzer = new CMarketAnalyzer(ExtNewsHandler, ExtVolatilityManager);
if(ExtMarketAnalyzer == NULL)
{
Print("Failed to create Market Analyzer");
delete ExtVolatilityManager;
delete ExtNewsHandler;
ExtVolatilityManager = NULL;
ExtNewsHandler = NULL;
return false;
}
// Configure news filter settings
if(InpEnableNewsFilter)
{
// Set up affected symbols
if(StringLen(InpAffectedSymbols) > 0)
{
string symbols[];
StringSplit(InpAffectedSymbols, ',', symbols);
for(int i = 0; i < ArraySize(symbols); i++)
{
string symbol = StringTrimRight(StringTrimLeft(symbols[i]));
if(symbol != "")
ExtMarketAnalyzer.AddAffectedSymbol(symbol);
}
}
// Set up news blackout period if specified
if(InpNewsStartTime > 0 && InpNewsEndTime > 0 && InpNewsStartTime < InpNewsEndTime)
{
ExtMarketAnalyzer.SetNewsBlackoutPeriod(InpNewsStartTime, InpNewsEndTime);
}
}
// Initialize components
if(!ExtVolatilityManager.Initialize())
{
Print("Failed to initialize Volatility Manager");
return false;
}
if(!ExtNewsHandler.Initialize())
{
Print("Failed to initialize News Feed Handler");
return false;
}
if(!ExtMarketAnalyzer.Initialize())
{
Print("Failed to initialize Market Analyzer");
return false;
}
Print("News Impact Analysis System initialized successfully");
return true;
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// Stop the timer
EventKillTimer();
// Clean up trading components
if(ExtTrade != NULL)
{
delete ExtTrade;
ExtTrade = NULL;
}
if(ExtTradeExecutor != NULL)
{
delete ExtTradeExecutor;
ExtTradeExecutor = NULL;
}
if(ExtRiskManager != NULL)
{
delete ExtRiskManager;
ExtRiskManager = NULL;
}
if(ExtPositionManager != NULL)
{
delete ExtPositionManager;
ExtPositionManager = NULL;
}
if(ExtSignalGenerator != NULL)
{
delete ExtSignalGenerator;
ExtSignalGenerator = NULL;
}
if(ExtPaperTrading != NULL)
{
delete ExtPaperTrading;
ExtPaperTrading = NULL;
}
// Release indicator handles
if(ExtHandleMA != INVALID_HANDLE)
{
IndicatorRelease(ExtHandleMA);
ExtHandleMA = INVALID_HANDLE;
}
if(ExtHandleATR != INVALID_HANDLE)
{
IndicatorRelease(ExtHandleATR);
ExtHandleATR = INVALID_HANDLE;
}
// Clean up visualization objects
ObjectsDeleteAll(0, OBJ_PREFIX);
Print("EscapeEA successfully deinitialized");
}
//+------------------------------------------------------------------+
//| Initialize trading components |
//+------------------------------------------------------------------+
bool InitializeTradingComponents()
{
// Initialize trade object
ExtTrade = new CTrade();
if(ExtTrade == NULL)
{
Print("Failed to create trade object");
return false;
}
// Set trade parameters
ExtTrade.SetDeviationInPoints(InpMaxSlippage);
ExtTrade.SetTypeFilling(ORDER_FILLING_FOK);
ExtTrade.SetExpertMagicNumber(InpMagicNumber);
// Initialize trade executor
ExtTradeExecutor = new CTradeExecutor(ExtTrade);
if(ExtTradeExecutor == NULL)
{
Print("Failed to create trade executor");
return false;
}
// Initialize risk manager
ExtRiskManager = new CRiskManager(InpRiskPerTrade, InpMaxRiskPerTrade, InpMaxDailyDrawdown);
if(ExtRiskManager == NULL)
{
Print("Failed to create risk manager");
return false;
}
// Initialize position manager
ExtPositionManager = new CPositionManager(ExtTrade, InpMagicNumber);
if(ExtPositionManager == NULL)
{
Print("Failed to create position manager");
return false;
}
// Initialize signal generator
ExtSignalGenerator = new CSignalGenerator(ExtHandleMA, ExtHandleATR, InpMAPeriod);
if(ExtSignalGenerator == NULL)
{
Print("Failed to create signal generator");
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| Initialize technical indicators |
//+------------------------------------------------------------------+
bool InitializeIndicators()
{
// Initialize MA indicator
ExtHandleMA = iMA(_Symbol, PERIOD_CURRENT, InpMAPeriod, InpMAShift, InpMAMethod, InpMAApplied);
if(ExtHandleMA == INVALID_HANDLE)
{
Print("Failed to create MA indicator");
return false;
}
// Initialize ATR indicator
ExtHandleATR = iATR(_Symbol, PERIOD_CURRENT, InpATRPeriod);
if(ExtHandleATR == INVALID_HANDLE)
{
Print("Failed to create ATR indicator");
return false;
}
// All indicators initialized successfully
return true;
}
//+------------------------------------------------------------------+
//| Initialize paper trading system |
//+------------------------------------------------------------------+
bool InitializePaperTrading()
{
ExtPaperTrading = new CPaperTrading(InpPaperInitialBalance, InpMagicNumber);
if(ExtPaperTrading == NULL)
{
Print("Failed to create paper trading system");
return false;
}
// Set paper trading mode based on input parameters
ExtPaperTradingActive = (InpTradeMode == TRADE_MODE_PAPER ||
(InpTradeMode == TRADE_MODE_BOTH && !ExtPaperStats.IsLiveTradingAllowed()));
Print("Paper trading ", ExtPaperTradingActive ? "enabled" : "disabled");
return true;
}
//+------------------------------------------------------------------+
//| Initialize security components |
//+------------------------------------------------------------------+
bool InitializeSecurity()
{
// Initialize input validator first
ExtInputValidator = CInputValidator::Instance();
if(ExtInputValidator == NULL)
{
Print("Failed to create input validator");
return false;
}
// Create security manager instance
ExtSecurity = CSecurityManager::Instance();
if(ExtSecurity == NULL)
{
Print("Failed to create security manager");
return false;
}
// Initialize with current symbol and log path
string logPath = StringFormat("%s\\%s", TerminalInfoString(TERMINAL_DATA_PATH), "Logs\\EscapeEA_Security_Log.txt");
if(!ExtSecurity->Initialize(_Symbol, logPath))
{
Print("Failed to initialize security manager");
return false;
}
// Validate environment
if(!ExtSecurity->ValidateEnvironment())
{
Print("Security validation failed");
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| Update trading statistics |
//+------------------------------------------------------------------+
void UpdateTradingStats()
{
// Update total trades count
int totalTrades = TradesTotal();
// If no trades, nothing to update
if(totalTrades == 0)
return;
// Loop through closed trades
for(int i = totalTrades - 1; i >= 0; i--)
{
if(ExtDeal.SelectByIndex(i))
{
// Check if this is our trade
if(ExtDeal.Magic() == InpMagicNumber &&
ExtDeal.Symbol() == _Symbol)
{
// Update statistics
ExtTotalTrades++;
double profit = ExtDeal.Profit();
if(profit > 0)
ExtWinningTrades++;
else
ExtLosingTrades++;
ExtTotalProfit += profit;
}
}
}
}
//+------------------------------------------------------------------+
//| Update account info panel |
//+------------------------------------------------------------------+
bool UpdateAccountInfoPanel()
{
string panelName = OBJ_PREFIX + "AccountInfo";
string text = "";
// Format account info
text += "Balance: " + DoubleToString(AccountInfoDouble(ACCOUNT_BALANCE), 2) + "\n";
text += "Equity: " + DoubleToString(AccountInfoDouble(ACCOUNT_EQUITY), 2) + "\n";
text += "Margin: " + DoubleToString(AccountInfoDouble(ACCOUNT_MARGIN), 2) + "\n";
text += "Free Margin: " + DoubleToString(AccountInfoDouble(ACCOUNT_MARGIN_FREE), 2) + "\n\n";
// Add trading statistics
text += "=== Trading Stats ===\n";
text += "Total Trades: " + IntegerToString(ExtTotalTrades) + "\n";
text += "Win Rate: " + (ExtTotalTrades > 0 ?
DoubleToString((double)ExtWinningTrades / ExtTotalTrades * 100, 2) + "%" : "N/A") + "\n";
text += "Total Profit: " + DoubleToString(ExtTotalProfit, 2) + " " + AccountInfoString(ACCOUNT_CURRENCY) + "\n";
// Add paper trading info if enabled
if(InpEnablePaperTrading)
{
text += "\n=== Paper Trading ===\n";
text += "Mode: " + (ExtPaperTradingActive ? "ACTIVE" : "INACTIVE") + "\n";
text += "Trades: " + IntegerToString(ExtPaperStats.totalTrades) + "\n";
text += "Wins: " + IntegerToString(ExtPaperStats.winningTrades) + "\n";
text += "Win Rate: " + (ExtPaperStats.totalTrades > 0 ?
DoubleToString((double)ExtPaperStats.winningTrades / ExtPaperStats.totalTrades * 100, 2) + "%" : "N/A") + "\n";
}
// Create or update the panel
if(ObjectFind(0, panelName) < 0)
{
if(!ObjectCreate(0, panelName, OBJ_LABEL, 0, 0, 0))
{
Print("Failed to create account info panel");
return false;
}
// Set panel properties
ObjectSetInteger(0, panelName, OBJPROP_CORNER, CORNER_LEFT_UPPER);
ObjectSetInteger(0, panelName, OBJPROP_XDISTANCE, 10);
ObjectSetInteger(0, panelName, OBJPROP_YDISTANCE, 20);
ObjectSetInteger(0, panelName, OBJPROP_COLOR, clrWhite);
ObjectSetInteger(0, panelName, OBJPROP_FONTSIZE, 8);
}
// Update panel text
ObjectSetString(0, panelName, OBJPROP_TEXT, text);
return true;
}
//+------------------------------------------------------------------+
//| Display current trading mode (Paper/Live) |
//+------------------------------------------------------------------+
bool DisplayMode()
{
string modeText = ExtPaperTradingActive ? "PAPER TRADING" : "LIVE TRADING";
string modeColor = ExtPaperTradingActive ? clrDodgerBlue : clrLime;
// Create or update mode label
string labelName = OBJ_PREFIX + "ModeLabel";
if(ObjectFind(0, labelName) < 0)
{
if(!ObjectCreate(0, labelName, OBJ_LABEL, 0, 0, 0))
{
Print("Failed to create mode label");
return false;
}
// Set label properties
ObjectSetInteger(0, labelName, OBJPROP_CORNER, CORNER_RIGHT_UPPER);
ObjectSetInteger(0, labelName, OBJPROP_XDISTANCE, 10);
ObjectSetInteger(0, labelName, OBJPROP_YDISTANCE, 20);
ObjectSetInteger(0, labelName, OBJPROP_COLOR, modeColor);
ObjectSetInteger(0, labelName, OBJPROP_FONTSIZE, 10);
ObjectSetInteger(0, labelName, OBJPROP_FONT, "Arial Bold");
}
// Update label text and color
ObjectSetString(0, labelName, OBJPROP_TEXT, modeText);
ObjectSetInteger(0, labelName, OBJPROP_COLOR, modeColor);
return true;
}
//+------------------------------------------------------------------+
//| Update signal visualization on the chart |
//+------------------------------------------------------------------+
bool UpdateSignalVisualization(bool buySignal, bool sellSignal, double price, double stopLoss, double takeProfit)
{
// Remove any existing signal objects
ObjectsDeleteAll(0, OBJ_PREFIX + "Signal_");
// If no signals, exit
if(!buySignal && !sellSignal)
return true;
// Calculate the current time and price for the signal arrow
datetime currentTime = TimeCurrent();
// Create signal arrow
string arrowName = OBJ_PREFIX + "Signal_Arrow";
if(!ObjectCreate(0, arrowName, OBJ_ARROW, 0, currentTime, price))
{
Print("Failed to create signal arrow");
return false;
}
// Set arrow properties based on signal type
if(buySignal)
{
ObjectSetInteger(0, arrowName, OBJPROP_ARROWCODE, 233); // Up arrow
ObjectSetInteger(0, arrowName, OBJPROP_COLOR, clrLime);
ObjectSetInteger(0, arrowName, OBJPROP_WIDTH, 2);
}
else if(sellSignal)
{
ObjectSetInteger(0, arrowName, OBJPROP_ARROWCODE, 234); // Down arrow
ObjectSetInteger(0, arrowName, OBJPROP_COLOR, clrRed);
ObjectSetInteger(0, arrowName, OBJPROP_WIDTH, 2);
}
// Add stop loss and take profit levels if provided
if(stopLoss > 0)
{
string slName = OBJ_PREFIX + "Signal_SL";
if(!ObjectCreate(0, slName, OBJ_HLINE, 0, 0, stopLoss))
{
Print("Failed to create stop loss line");
return false;
}
ObjectSetInteger(0, slName, OBJPROP_COLOR, clrRed);
ObjectSetInteger(0, slName, OBJPROP_STYLE, STYLE_DOT);
ObjectSetString(0, slName, OBJPROP_TEXT, "SL: " + DoubleToString(stopLoss, _Digits));
}
if(takeProfit > 0)
{
string tpName = OBJ_PREFIX + "Signal_TP";
if(!ObjectCreate(0, tpName, OBJ_HLINE, 0, 0, takeProfit))
{
Print("Failed to create take profit line");
return false;
}
ObjectSetInteger(0, tpName, OBJPROP_COLOR, clrLime);
ObjectSetInteger(0, tpName, OBJPROP_STYLE, STYLE_DOT);
ObjectSetString(0, tpName, OBJPROP_TEXT, "TP: " + DoubleToString(takeProfit, _Digits));
}
return true;
}
//+------------------------------------------------------------------+
//| Timer function for periodic updates |
//+------------------------------------------------------------------+
void OnTimer()
{
// Update visualization periodically
UpdateVisualization();
// Check for news events if enabled
if(ExtSecurity != NULL)
{
ExtSecurity->CheckNewsEvents();
}
// Update trading statistics
UpdateTradingStats();
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Check if we're properly initialized
if(!IsInitialized())
{
Print("EA not properly initialized");
return;
}
// Check if trading is allowed
if(!IsTradeAllowed())
{
Print("Trading is not allowed at this time");
return;
}
// Update account and symbol info
if(!ExtAccount.RefreshRates() || !ExtSymbol.RefreshRates())
{
Print("Failed to refresh rates");
return;
}
// Update indicators
if(!UpdateIndicators())
{
Print("Failed to update indicators");
return;
}
// Process trading signals based on current mode
ProcessTradingMode();
// Manage open positions
ManagePositions();
// Update visualization
UpdateVisualization();
}
//+------------------------------------------------------------------+
//| Check if trading is allowed |
//+------------------------------------------------------------------+
bool IsTradeAllowed()
{
// Check if trading is allowed by the expert
if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
{
Print("Trading is not allowed in the terminal settings");
return false;
}
// Check if the expert is allowed to trade
if(!MQLInfoInteger(MQL_TRADE_ALLOWED))
{
Print("Trading is not allowed for this expert");
return false;
}
// Check if we're in paper trading mode
if(ExtPaperTradingActive && !ExtPaperStats.IsLiveTradingAllowed())
{
Print("Paper trading: " + string(ExtPaperStats.winningTrades) +
" out of " + string(ExtPaperStats.totalTrades) + " required trades are winners");
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| Check if the expert is properly initialized |
//+------------------------------------------------------------------+
bool IsInitialized()
{
if(ExtTrade == NULL || ExtTradeExecutor == NULL ||
ExtRiskManager == NULL || ExtPositionManager == NULL)
{
Print("One or more components are not initialized");
return false;
}
// Check if indicators are properly initialized
if(ExtHandleMA == INVALID_HANDLE || ExtHandleATR == INVALID_HANDLE)
{
Print("One or more indicators are not initialized");
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| Update market indicators |
//+------------------------------------------------------------------+
bool UpdateIndicators()
{
// Update MA indicator
if(CopyBuffer(ExtHandleMA, 0, 0, 3, ExtMABuffer) != 3)
{
Print("Failed to copy MA buffer: ", GetLastError());
return false;
}
// Update ATR indicator
if(CopyBuffer(ExtHandleATR, 0, 0, 1, &ExtATRValue) != 1)
{
Print("Failed to copy ATR buffer: ", GetLastError());
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| Process trading based on current mode |
//+------------------------------------------------------------------+
void ProcessTradingMode()
{
// Check if we have any open positions
if(PositionsTotal() > 0)
{
// Manage existing positions
return;
}
// Generate trading signals
bool buySignal = false, sellSignal = false;
double stopLoss = 0.0, takeProfit = 0.0;
if(ExtSignalGenerator != NULL &&
ExtSignalGenerator.GenerateSignals(buySignal, sellSignal, stopLoss, takeProfit))
{
// Execute trade based on signal
if(buySignal)
{
ExecuteTrade(ORDER_TYPE_BUY, stopLoss, takeProfit);
}
else if(sellSignal)
{
ExecuteTrade(ORDER_TYPE_SELL, stopLoss, takeProfit);
}
}
}
//+------------------------------------------------------------------+
//| Execute a trade with proper risk management |
//+------------------------------------------------------------------+
void ExecuteTrade(ENUM_ORDER_TYPE orderType, double stopLoss, double takeProfit)
{
// Calculate position size based on risk management
double lotSize = ExtRiskManager.CalculatePositionSize(stopLoss);
if(lotSize <= 0)
{
Print("Invalid position size calculated");
return;
}
// Execute the trade
if(ExtPaperTradingActive)
{
// Execute paper trade
if(ExtPaperTrading.ExecutePaperTrade(orderType, lotSize, stopLoss, takeProfit))
{
Print("Paper trade executed successfully");
}
else
{
Print("Failed to execute paper trade");
}
}
else
{
// Execute live trade
if(ExtTradeExecutor.ExecuteTrade(orderType, lotSize, stopLoss, takeProfit))
{
Print("Live trade executed successfully");
}
else
{
Print("Failed to execute live trade: ", GetLastError());
}
}
}
//+------------------------------------------------------------------+
//| Manage open positions |
//+------------------------------------------------------------------+
void ManagePositions()
{
// Check if we have any open positions
if(PositionsTotal() == 0)
return;
// Loop through all open positions
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
if(ExtPosition.SelectByIndex(i))
{
// Check if this is our position
if(ExtPosition.Magic() == InpMagicNumber &&
ExtPosition.Symbol() == _Symbol)
{
// Update trailing stop if enabled
if(InpUseTrailingStop)
{
ExtPositionManager.UpdateTrailingStop(ExtPosition.Ticket(),
InpTrailingStop,
InpTrailingStep);
}
// Check for break even
if(InpUseBreakEven)
{
ExtPositionManager.CheckBreakEven(ExtPosition.Ticket(),
InpBreakEven,
InpBreakEvenProfit);
}
}
}
}
}
//+------------------------------------------------------------------+
//| Update visualization on the chart |
//+------------------------------------------------------------------+
void UpdateVisualization()
{
// Update account info panel
if(!UpdateAccountInfoPanel())
{
Print("Failed to update account info panel");
}
// Update mode display (Paper/Live)
if(!DisplayMode())
{
Print("Failed to update mode display");
}
// Update signal visualization if needed
if(ExtSignalGenerator != NULL)
{
bool buySignal = false, sellSignal = false;
double stopLoss = 0.0, takeProfit = 0.0;
if(ExtSignalGenerator.GenerateSignals(buySignal, sellSignal, stopLoss, takeProfit))
{
double price = SymbolInfoDouble(_Symbol, buySignal ? SYMBOL_ASK : SYMBOL_BID);
if(!UpdateSignalVisualization(buySignal, sellSignal, price, stopLoss, takeProfit))
{
Print("Failed to update signal visualization");
}
}
}
// Force chart redraw
ChartRedraw(0);
}
//+------------------------------------------------------------------+
//| Update signal visualization on the chart |
//+------------------------------------------------------------------+
void UpdateSignalVisualization(bool buySignal, bool sellSignal, double currentPrice, double stopLoss, double takeProfit)
{
// Remove any existing signal objects
ObjectsDeleteAll(0, "EscapeEA_Signal_");
// If no signals, exit
if(!buySignal && !sellSignal) {
return;
}
// Calculate the current time and price for the signal arrow
datetime currentTime = TimeCurrent();
// Create signal arrow
string arrowName = "EscapeEA_Signal_Arrow";
if(!ObjectCreate(0, arrowName, OBJ_ARROW, 0, currentTime, currentPrice - stopLoss))
{
Print("Failed to create signal arrow");
return;
}
// Set arrow properties based on signal type
if(buySignal)
{
ObjectSetInteger(0, arrowName, OBJPROP_ARROWCODE, 233); // Up arrow
ObjectSetInteger(0, arrowName, OBJPROP_COLOR, clrLime);
ObjectSetInteger(0, arrowName, OBJPROP_WIDTH, 2);
}
else if(sellSignal)
{
ObjectSetInteger(0, arrowName, OBJPROP_ARROWCODE, 234); // Down arrow
ObjectSetInteger(0, arrowName, OBJPROP_COLOR, clrRed);
ObjectSetInteger(0, arrowName, OBJPROP_WIDTH, 2);
}
// Add stop loss and take profit levels if provided
if(stopLoss > 0)
{
string slName = "EscapeEA_SL";
if(!ObjectCreate(0, slName, OBJ_HLINE, 0, 0, currentPrice - stopLoss))
{
Print("Failed to create stop loss line");
return;
}
ObjectSetInteger(0, slName, OBJPROP_COLOR, clrRed);
ObjectSetInteger(0, slName, OBJPROP_STYLE, STYLE_DOT);
ObjectSetString(0, slName, OBJPROP_TEXT, "SL: " + DoubleToString(currentPrice - stopLoss, _Digits));
}
if(takeProfit > 0)
{
string tpName = "EscapeEA_TP";
if(!ObjectCreate(0, tpName, OBJ_HLINE, 0, 0, currentPrice + takeProfit))
{
Print("Failed to create take profit line");
return;
}
ObjectSetInteger(0, tpName, OBJPROP_COLOR, clrLime);
ObjectSetInteger(0, tpName, OBJPROP_STYLE, STYLE_DOT);
ObjectSetString(0, tpName, OBJPROP_TEXT, "TP: " + DoubleToString(currentPrice + takeProfit, _Digits));
}
// Force chart redraw
ChartRedraw();
}
//+------------------------------------------------------------------+
//| Display current mode (Paper/Live) |
//+------------------------------------------------------------------+
void DisplayMode()
{
string modeText = ExtPaperTradingActive ? "PAPER TRADING" : "LIVE TRADING";
string modeColor = ExtPaperTradingActive ? clrDodgerBlue : clrLime;
// Create or update mode label
string modeLabel = "EscapeEA_Mode";
if(ObjectFind(0, modeLabel) < 0) {
ObjectCreate(0, modeLabel, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, modeLabel, OBJPROP_CORNER, CORNER_RIGHT_UPPER);
ObjectSetInteger(0, modeLabel, OBJPROP_XDISTANCE, 10);
ObjectSetInteger(0, modeLabel, OBJPROP_YDISTANCE, 10);
ObjectSetInteger(0, modeLabel, OBJPROP_COLOR, modeColor);
ObjectSetInteger(0, modeLabel, OBJPROP_FONTSIZE, 12);
ObjectSetString(0, modeLabel, OBJPROP_FONT, "Arial");
ObjectSetInteger(0, modeLabel, OBJPROP_BACK, false);
}
ObjectSetString(0, modeLabel, OBJPROP_TEXT, modeText);
ObjectSetInteger(0, modeLabel, OBJPROP_COLOR, modeColor);
// Display paper trading info if active
if(ExtPaperTradingActive && ExtPaperTrading != NULL) {
string infoText = StringFormat("Paper Balance: %.2f\n" +
"Equity: %.2f\n" +
"Trades: %d (%dW/%dL)\n" +
"Win Rate: %.1f%%",
ExtPaperTrading->GetBalance(),
ExtPaperTrading->GetEquity(),
ExtPaperTrading->GetTotalTrades(),
ExtPaperTrading->GetWinningTrades(),
ExtPaperTrading->GetLosingTrades(),
ExtPaperTrading->GetWinRate());
string infoLabel = "EscapeEA_PaperInfo";
if(ObjectFind(0, infoLabel) < 0) {
ObjectCreate(0, infoLabel, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, infoLabel, OBJPROP_CORNER, CORNER_LEFT_UPPER);
ObjectSetInteger(0, infoLabel, OBJPROP_XDISTANCE, 10);
ObjectSetInteger(0, infoLabel, OBJPROP_YDISTANCE, 30);
ObjectSetInteger(0, infoLabel, OBJPROP_COLOR, clrWhite);
ObjectSetInteger(0, infoLabel, OBJPROP_FONTSIZE, 10);
ObjectSetString(0, infoLabel, OBJPROP_FONT, "Arial");
ObjectSetInteger(0, infoLabel, OBJPROP_BACK, true);
}
ObjectSetString(0, infoLabel, OBJPROP_TEXT, infoText);
}
// Update account info
string accountInfo = StringFormat("Balance: %.2f %s\n" +
"Equity: %.2f %s\n" +
"Margin: %.2f %s\n" +
"Free Margin: %.2f %s",
AccountInfoDouble(ACCOUNT_BALANCE),
AccountInfoString(ACCOUNT_CURRENCY),
AccountInfoDouble(ACCOUNT_EQUITY),
AccountInfoString(ACCOUNT_CURRENCY),
AccountInfoDouble(ACCOUNT_MARGIN),
AccountInfoString(ACCOUNT_CURRENCY),
AccountInfoDouble(ACCOUNT_MARGIN_FREE),
AccountInfoString(ACCOUNT_CURRENCY));
string accountLabel = "EscapeEA_AccountInfo";
if(ObjectFind(0, accountLabel) < 0) {
ObjectCreate(0, accountLabel, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, accountLabel, OBJPROP_CORNER, CORNER_RIGHT_UPPER);
ObjectSetInteger(0, accountLabel, OBJPROP_XDISTANCE, 10);
ObjectSetInteger(0, accountLabel, OBJPROP_YDISTANCE, 30);
ObjectSetInteger(0, accountLabel, OBJPROP_COLOR, clrWhite);
ObjectSetInteger(0, accountLabel, OBJPROP_FONTSIZE, 10);
ObjectSetString(0, accountLabel, OBJPROP_FONT, "Arial");
ObjectSetInteger(0, accountLabel, OBJPROP_BACK, true);
}
ObjectSetString(0, accountLabel, OBJPROP_TEXT, accountInfo);
// Update chart
ChartRedraw();
}
//+------------------------------------------------------------------+