243 lines
6.8 KiB
Plaintext
243 lines
6.8 KiB
Plaintext
//+------------------------------------------------------------------+
|
|
//| MyProEA.mq5 - Professional Expert Advisor |
|
|
//| Main EA file with clean lifecycle and separation of concerns |
|
|
//+------------------------------------------------------------------+
|
|
|
|
#property copyright "Educational EA - BackTesting Only"
|
|
#property link "https://www.mql5.com"
|
|
#property version "1.00"
|
|
#property strict
|
|
#property description "Professional modular EA with MA crossover strategy"
|
|
#property description "For educational and backtesting purposes only"
|
|
|
|
// Include all class definitions
|
|
#include "Include/Config.mqh"
|
|
#include "Include/Logger.mqh"
|
|
#include "Include/Utilities.mqh"
|
|
#include "Include/MarketData.mqh"
|
|
#include "Include/Signal.mqh"
|
|
#include "Include/Strategy.mqh"
|
|
#include "Include/RiskManager.mqh"
|
|
#include "Include/PositionManager.mqh"
|
|
#include "Include/TradeManager.mqh"
|
|
#include "Include/TrailingStop.mqh"
|
|
|
|
//+------------------------------------------------------------------+
|
|
// Global class instances
|
|
//+------------------------------------------------------------------+
|
|
|
|
CLogger *g_logger = NULL;
|
|
CMarketData *g_market_data = NULL;
|
|
CStrategy *g_strategy = NULL;
|
|
CRiskManager *g_risk_manager = NULL;
|
|
CPositionManager *g_position_manager = NULL;
|
|
CTradeManager *g_trade_manager = NULL;
|
|
CTrailingStop *g_trailing_stop = NULL;
|
|
|
|
//+------------------------------------------------------------------+
|
|
// EA Initialization
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
// Create logger instance
|
|
g_logger = new CLogger(g_debug_mode);
|
|
g_logger.Info("===== EA INITIALIZATION START =====");
|
|
|
|
// Create market data handler
|
|
g_market_data = new CMarketData(_Symbol, g_logger);
|
|
if(!g_market_data.IsTradingAllowed())
|
|
{
|
|
g_logger.Error("Trading not allowed for this symbol");
|
|
return INIT_FAILED;
|
|
}
|
|
|
|
// Create strategy
|
|
g_strategy = new CStrategy(g_market_data, g_logger);
|
|
if(!g_strategy.Init())
|
|
{
|
|
g_logger.Error("Failed to initialize strategy");
|
|
return INIT_FAILED;
|
|
}
|
|
|
|
// Create risk manager
|
|
g_risk_manager = new CRiskManager(g_market_data, g_logger);
|
|
|
|
// Create position manager
|
|
g_position_manager = new CPositionManager(g_logger);
|
|
|
|
// Create trade manager
|
|
g_trade_manager = new CTradeManager(g_logger, g_risk_manager);
|
|
|
|
// Create trailing stop manager
|
|
g_trailing_stop = new CTrailingStop(g_market_data, g_logger, g_trade_manager);
|
|
|
|
// Log configuration
|
|
g_logger.Info(StringFormat("Magic Number: %d", g_magic_number));
|
|
g_logger.Info(StringFormat("Symbol: %s", _Symbol));
|
|
g_logger.Info(StringFormat("Timeframe: %s", EnumToString(PERIOD_CURRENT)));
|
|
g_logger.Info(StringFormat("Lot Mode: %s",
|
|
g_lot_mode == LOT_MODE_FIXED ? "FIXED" : "RISK"));
|
|
g_logger.Info(StringFormat("Stop Loss: %d points, Take Profit: %d points",
|
|
g_stop_loss_points, g_take_profit_points));
|
|
g_logger.Info(StringFormat("Max Positions: %d, Max Spread: %d points",
|
|
g_max_positions, g_max_spread_points));
|
|
|
|
g_logger.Info("===== EA INITIALIZATION COMPLETE =====");
|
|
return INIT_SUCCEEDED;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
// EA Deinitialization
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
g_logger.Info("===== EA DEINITIALIZATION START =====");
|
|
|
|
string reason_text = "";
|
|
switch(reason)
|
|
{
|
|
case REASON_ACCOUNT: reason_text = "Account changed"; break;
|
|
case REASON_CHARTCHANGE: reason_text = "Chart changed"; break;
|
|
case REASON_CHARTCLOSE: reason_text = "Chart closed"; break;
|
|
case REASON_PARAMETERS: reason_text = "Parameters changed"; break;
|
|
case REASON_RECOMPILE: reason_text = "EA recompiled"; break;
|
|
case REASON_REMOVE: reason_text = "EA removed"; break;
|
|
default: reason_text = "Unknown reason"; break;
|
|
}
|
|
|
|
g_logger.Info(StringFormat("Deinit reason: %s (%d)", reason_text, reason));
|
|
|
|
// Clean up strategy (release indicator handles)
|
|
if(g_strategy != NULL)
|
|
{
|
|
delete g_strategy;
|
|
g_strategy = NULL;
|
|
}
|
|
|
|
// Clean up all other objects
|
|
if(g_trailing_stop != NULL)
|
|
{
|
|
delete g_trailing_stop;
|
|
g_trailing_stop = NULL;
|
|
}
|
|
|
|
if(g_trade_manager != NULL)
|
|
{
|
|
delete g_trade_manager;
|
|
g_trade_manager = NULL;
|
|
}
|
|
|
|
if(g_position_manager != NULL)
|
|
{
|
|
delete g_position_manager;
|
|
g_position_manager = NULL;
|
|
}
|
|
|
|
if(g_risk_manager != NULL)
|
|
{
|
|
delete g_risk_manager;
|
|
g_risk_manager = NULL;
|
|
}
|
|
|
|
if(g_market_data != NULL)
|
|
{
|
|
delete g_market_data;
|
|
g_market_data = NULL;
|
|
}
|
|
|
|
if(g_logger != NULL)
|
|
{
|
|
g_logger.Info("===== EA DEINITIALIZATION COMPLETE =====");
|
|
delete g_logger;
|
|
g_logger = NULL;
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
// Main EA Logic - OnTick()
|
|
//+------------------------------------------------------------------+
|
|
void OnTick()
|
|
{
|
|
// Step 1: Update market data (always)
|
|
if(!g_market_data.IsTradingAllowed())
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Step 2: Check spread - if spread is too wide, don't trade
|
|
if(!g_risk_manager.IsSpreadAcceptable())
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Step 3: Check trading hours
|
|
if(!g_risk_manager.IsTradingHourValid())
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Step 4: Manage existing positions (trailing stop, break-even)
|
|
g_trailing_stop.UpdateAllPositions();
|
|
|
|
// Step 5: Only process signals on new bar
|
|
if(!g_market_data.IsNewBar())
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Step 6: Get trading signal from strategy
|
|
E_SIGNAL signal = g_strategy.GetSignal();
|
|
|
|
if(signal == SIGNAL_NONE)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Step 7: Check if we already have a position
|
|
if(g_position_manager.HasOpenPosition(_Symbol))
|
|
{
|
|
if(g_debug_mode)
|
|
g_logger.Info("Already have open position, skipping entry");
|
|
return;
|
|
}
|
|
|
|
// Step 8: Check if new position is allowed
|
|
if(!g_position_manager.IsNewPositionAllowed(_Symbol))
|
|
{
|
|
g_logger.Warning("New position not allowed (max positions reached)");
|
|
return;
|
|
}
|
|
|
|
// Step 9: Calculate lot size
|
|
double lot = g_risk_manager.CalculateLotSize(g_stop_loss_points);
|
|
if(lot <= 0)
|
|
{
|
|
g_logger.Error("Invalid lot size calculated");
|
|
return;
|
|
}
|
|
|
|
// Step 10: Execute trade based on signal
|
|
bool trade_success = false;
|
|
|
|
if(signal == SIGNAL_BUY)
|
|
{
|
|
trade_success = g_trade_manager.OpenBuyTrade(_Symbol, lot);
|
|
}
|
|
else if(signal == SIGNAL_SELL)
|
|
{
|
|
trade_success = g_trade_manager.OpenSellTrade(_Symbol, lot);
|
|
}
|
|
|
|
if(trade_success)
|
|
{
|
|
if(g_logger)
|
|
g_logger.Info("Trade executed successfully");
|
|
}
|
|
else
|
|
{
|
|
if(g_logger)
|
|
g_logger.Error("Trade execution failed");
|
|
}
|
|
}
|
|
|