mql5/Experts/Advisors/ERMT_6.902-DualDash_backup.mq5
2025-09-01 16:55:52 +01:00

735 lines
No EOL
28 KiB
MQL5

//+------------------------------------------------------------------+
//| ERMT_6.9-DualDash.mq5|
//| Enterprise Risk Management Terminal v6.9 |
//| Institutional Grade Risk Management |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Institutional Trading Systems"
#property link "https://example.com"
#property version "6.902" // MQL5 Market compatible format (xxx.yyy)
#property description "Enterprise Risk Management Terminal - Dual Dashboard Edition"
#property description "Professional risk management system with advanced position monitoring"
#property description "Features: Real-time risk metrics, multi-symbol monitoring, dual dashboard display"
// Optional: Keep human-readable version as a constant
#define VERSION_STRING "6.9 Dual Dashboard"
#define VERSION_MAJOR 6
#define VERSION_MINOR 9
#define VERSION_BUILD 0
//--- Include base MQL5 classes
#include <Object.mqh>
#include <Trade/Trade.mqh>
//--- Include system modules
#include "Modules/DataTypes.mqh"
#include "Modules/Utilities.mqh"
#include "Modules/RiskManager.mqh"
#include "Modules/TradeManager.mqh"
#include "Modules/TechnicalAnalysis.mqh"
#include "Modules/EntrySystem.mqh"
#include "Modules/Dashboard.mqh" // Original Dashboard
#include "Modules/Dashboard_SelfContained.mqh" // New Self-Contained Dashboard
#include "Modules/ExternalTradeManager.mqh"
//+------------------------------------------------------------------+
//| INPUT PARAMETERS - GROUPED BY MODULE |
//+------------------------------------------------------------------+
//--- System Configuration
input group "=== SYSTEM CONFIGURATION ==="
input bool SystemEnabled = true; // Enable System
input int TradingMagic = 12345; // EA Magic Number
input ENUM_LOG_LEVEL LogLevel = LOG_INFO; // Logging Level
//--- External Trade Management
input group "=== EXTERNAL TRADE MANAGEMENT ==="
input bool ManageExternalTrades = true; // Manage External Trades
input int MagicNumberFilter = 0; // External Magic Filter (0=all)
input bool ForceStopLoss = true; // Force SL on Unprotected Trades
input bool ForceTakeProfit = true; // Force TP on Unprotected Trades
input bool OverrideExternalSL = false; // Override Existing Stop Loss
input bool OverrideExternalTP = false; // Override Existing Take Profit
input double ExternalDefaultSL_ATR = 2.0; // Default SL (ATR Multiples)
input double ExternalDefaultTP_Ratio = 1.5; // Default TP/SL Ratio
input bool CloseExcessiveRisk = true; // Close Trades Exceeding Risk
input double MaxExternalRiskPercent = 5.0; // Max Risk % for External Trades
input bool RealTimeSync = true; // Real-time Trade Synchronization
input int SyncIntervalMS = 500; // Sync Check Interval (ms)
//--- Entry System Parameters
input group "=== ENTRY SYSTEM ==="
input ENUM_ENTRY_MODE EntryMode = ENTRY_MA_CROSS; // Entry System Type
input bool EnableMultipleEntries = false; // Allow Multiple Entries
input int MaxPositions = 3; // Maximum Positions
input double MinTimeBetweenTrades = 60; // Min Minutes Between Trades
//--- Risk Management
input group "=== RISK MANAGEMENT ==="
input ENUM_POSITION_SIZING SizingMode = SIZING_FIXED_PERCENT; // Position Sizing Method
input double FixedLotSize = 0.01; // Fixed Lot Size
input double RiskPercent = 1.0; // Risk Per Trade (%)
input double MaxRiskPercent = 2.0; // Maximum Risk Per Trade (%)
input double MaxDailyDrawdown = 5.0; // Max Daily Drawdown (%)
input double MaxTotalExposure = 10.0; // Max Total Exposure (%)
//--- Trade Management
input group "=== TRADE MANAGEMENT ==="
input ENUM_TP_MODE TPMode = TP_FIXED_RR; // Take Profit Mode
input ENUM_SL_MODE SLMode = SL_ATR; // Stop Loss Mode
input bool EnableBreakeven = true; // Enable Breakeven
input double BreakevenTrigger = 1.0; // Breakeven Trigger (R)
input bool EnableTrailing = true; // Enable Trailing Stop
input double TrailingStart = 1.5; // Trailing Start (R)
input bool EnablePartialClose = true; // Enable Partial Close
input int PartialLevels = 3; // Number of Partial Levels
//--- Technical Analysis
input group "=== TECHNICAL ANALYSIS ==="
input bool UseSupportResistance = true; // Use S/R Levels
input bool UseFibonacci = false; // Use Fibonacci Levels
input bool UsePivotPoints = true; // Use Pivot Points
input bool UseMarketStructure = true; // Analyze Market Structure
input int TechnicalLookback = 100; // Technical Lookback Period
//--- ORIGINAL Dashboard Parameters
input group "=== ORIGINAL DASHBOARD ==="
input bool ShowOriginalDashboard = true; // Show Original Dashboard
input int OriginalDashboardX = 20; // Original Dashboard X Position
input int OriginalDashboardY = 30; // Original Dashboard Y Position
input color DashboardColor = clrWhiteSmoke; // Dashboard Text Color
input color ProfitColor = clrLime; // Profit Color
input color LossColor = clrRed; // Loss Color
input int UpdateFrequency = 1; // Update Frequency (seconds)
//--- NEW Self-Contained Dashboard Parameters
input group "=== NEW SELF-CONTAINED DASHBOARD ==="
input bool ShowNewDashboard = true; // Show New Dashboard
input int NewDashboardX = 350; // New Dashboard X Position (offset to right)
input int NewDashboardY = 30; // New Dashboard Y Position
input int NewDashboardTheme = 0; // Theme (0=Dark, 1=Light, 2=Contrast, 3=Matrix, 4=Ocean, 5=Auto)
input bool NewDashboardCompact = false; // Start in Compact Mode
//--- Reporting Options
input group "=== REPORTING OPTIONS ==="
input bool SaveTradeLog = true; // Save Trade Log
input bool SendAlerts = true; // Send Alert Notifications
input bool GenerateReports = true; // Generate Periodic Reports
input bool ExportCSV = true; // Export Reports to CSV
//+------------------------------------------------------------------+
//| GLOBAL VARIABLES & OBJECTS |
//+------------------------------------------------------------------+
//--- Module instances
CRiskManager *RiskMgr;
CTradeManager *TradeMgr;
CTechnicalAnalysis *TechAnalysis;
CEntrySystem *EntrySystem;
CDashboard *OriginalDashboard; // Original Dashboard
CDashboardSC *NewDashboard; // New Self-Contained Dashboard
CExternalTradeManager *ExtTradeMgr;
//--- Trade tracking
ManagedTrade g_ManagedTrades[];
int g_TotalTrades;
//--- Performance tracking
PerformanceMetrics g_Performance;
RiskMetrics g_RiskMetrics;
MarketConditions g_MarketConditions;
//--- Timing control
datetime g_LastUpdateTime;
datetime g_LastEntryCheck;
datetime g_LastReportTime;
ulong g_LastSyncTime;
//--- Status flags
bool g_IsInitialized = false;
bool g_InPosition = false;
int g_ConsecutiveLosses = 0;
bool ShowOriginalDashboard = true; // Show original dashboard flag
bool ShowNewDashboard = true; // Show new dashboard flag
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
Print("=== ERMT 6.8 Initializing with Dual Dashboard Support ===");
//--- Initialize modules
RiskMgr = new CRiskManager();
if(!RiskMgr.Initialize(RiskPercent, MaxRiskPercent, MaxDailyDrawdown, MaxTotalExposure))
{
Print("Failed to initialize Risk Manager");
return INIT_FAILED;
}
TradeMgr = new CTradeManager();
if(!TradeMgr.Initialize(TPMode, SLMode, EnableBreakeven, EnableTrailing, EnablePartialClose))
{
Print("Failed to initialize Trade Manager");
return INIT_FAILED;
}
TechAnalysis = new CTechnicalAnalysis();
if(!TechAnalysis.Initialize(TechnicalLookback, UseSupportResistance,
UseFibonacci, UsePivotPoints, UseMarketStructure))
{
Print("Failed to initialize Technical Analysis");
return INIT_FAILED;
}
EntrySystem = new CEntrySystem();
if(!EntrySystem.Initialize(EntryMode, EnableMultipleEntries, MaxPositions))
{
Print("Failed to initialize Entry System");
return INIT_FAILED;
}
//--- Initialize External Trade Manager if enabled
if(ManageExternalTrades)
{
ExtTradeMgr = new CExternalTradeManager();
if(!ExtTradeMgr.Initialize(MagicNumberFilter, ForceStopLoss, ForceTakeProfit,
OverrideExternalSL, OverrideExternalTP))
{
Print("Failed to initialize External Trade Manager");
return INIT_FAILED;
}
Print("External Trade Manager initialized successfully");
}
//--- Initialize ORIGINAL Dashboard
if(ShowOriginalDashboard)
{
OriginalDashboard = new CDashboard();
if(!OriginalDashboard.Create(OriginalDashboardX, OriginalDashboardY,
DashboardColor, ProfitColor, LossColor))
{
Print("Failed to create Original Dashboard");
// Non-critical, continue
}
else
{
Print("Original Dashboard created at position (", OriginalDashboardX, ",", OriginalDashboardY, ")");
}
}
//--- Initialize NEW Self-Contained Dashboard
if(ShowNewDashboard)
{
NewDashboard = new CDashboardSC();
if(!NewDashboard.Create(NewDashboardX, NewDashboardY,
(ENUM_DASH_THEME)NewDashboardTheme, NewDashboardCompact))
{
Print("Failed to create New Self-Contained Dashboard");
// Non-critical, continue
}
else
{
Print("New Self-Contained Dashboard created at position (", NewDashboardX, ",", NewDashboardY, ")");
Print("Theme: ", NewDashboardTheme, ", Compact: ", NewDashboardCompact);
}
}
//--- Initialize performance tracking
InitializePerformanceMetrics();
//--- Set timer for updates
EventSetMillisecondTimer(UpdateFrequency * 1000);
g_IsInitialized = true;
g_LastUpdateTime = TimeCurrent();
g_LastSyncTime = GetMicrosecondCount();
Print("=== ERMT 6.8 Initialization Complete ===");
Print("Original Dashboard: ", ShowOriginalDashboard ? "ENABLED" : "DISABLED");
Print("New Dashboard: ", ShowNewDashboard ? "ENABLED" : "DISABLED");
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Print("=== ERMT 6.8 Shutting Down ===");
EventKillTimer();
//--- Clean up BOTH dashboards
if(OriginalDashboard != NULL)
{
OriginalDashboard.Destroy();
delete OriginalDashboard;
OriginalDashboard = NULL;
Print("Original Dashboard destroyed");
}
if(NewDashboard != NULL)
{
NewDashboard.Destroy();
delete NewDashboard;
NewDashboard = NULL;
Print("New Dashboard destroyed");
}
//--- Clean up modules
if(RiskMgr != NULL) delete RiskMgr;
if(TradeMgr != NULL) delete TradeMgr;
if(TechAnalysis != NULL) delete TechAnalysis;
if(EntrySystem != NULL) delete EntrySystem;
if(ExtTradeMgr != NULL) delete ExtTradeMgr;
Print("=== ERMT 6.8 Shutdown Complete ===");
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
if(!SystemEnabled || !g_IsInitialized) return;
//--- Update market conditions
g_MarketConditions = TechAnalysis.AnalyzeMarket();
//--- Manage external trades with real-time sync
if(ManageExternalTrades && ExtTradeMgr != NULL)
{
if(RealTimeSync)
{
ulong current_time = GetMicrosecondCount();
if(current_time - g_LastSyncTime >= (ulong)(SyncIntervalMS * 1000))
{
ProcessExternalTrades();
g_LastSyncTime = current_time;
}
}
else
{
ProcessExternalTrades();
}
}
//--- Update managed trades
UpdateManagedTrades();
//--- Check for new entry signals
if(!g_InPosition || EnableMultipleEntries)
{
CheckEntrySignals();
}
//--- Update risk metrics
g_RiskMetrics = RiskMgr.CalculateCurrentRisk(g_ManagedTrades);
//--- Check risk limits
if(RiskMgr.IsRiskLimitExceeded(g_RiskMetrics))
{
HandleRiskLimitBreach();
}
//--- Update performance metrics
UpdatePerformanceMetrics();
//--- Update BOTH dashboards
if(TimeCurrent() - g_LastUpdateTime >= UpdateFrequency)
{
UpdateDashboards();
g_LastUpdateTime = TimeCurrent();
}
}
//+------------------------------------------------------------------+
//| Timer function |
//+------------------------------------------------------------------+
void OnTimer()
{
//--- Periodic dashboard updates
UpdateDashboards();
//--- Generate reports if enabled
if(GenerateReports && TimeCurrent() - g_LastReportTime >= 3600) // Hourly
{
GeneratePerformanceReport();
g_LastReportTime = TimeCurrent();
}
}
//+------------------------------------------------------------------+
//| Update BOTH dashboards |
//+------------------------------------------------------------------+
void UpdateDashboards()
{
//--- Prepare data for dashboards
CollectPerformanceMetrics(g_Performance);
CalculateRiskMetrics(g_RiskMetrics);
//--- Update Original Dashboard
if(ShowOriginalDashboard && OriginalDashboard != NULL)
{
OriginalDashboard.Update(g_Performance, g_ManagedTrades, g_MarketConditions);
}
//--- Update New Self-Contained Dashboard
if(ShowNewDashboard && NewDashboard != NULL)
{
NewDashboard.Update(g_Performance, g_RiskMetrics, g_MarketConditions);
}
//--- Optional: Log comparison for testing
if(LogLevel >= LOG_DEBUG)
{
Print("Dashboard Update - Balance: ", g_Performance.current_balance,
", Equity: ", g_Performance.current_equity,
", Exposure: ", g_RiskMetrics.current_exposure, "%",
", Market: ", EnumToString(g_MarketConditions.condition));
}
}
//+------------------------------------------------------------------+
//| Process external trades |
//+------------------------------------------------------------------+
void ProcessExternalTrades()
{
if(ExtTradeMgr == NULL) return;
//--- Scan for external trades
int external_trades = ExtTradeMgr.ScanExternalTrades();
if(external_trades > 0)
{
//--- Process each external trade
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
if(PositionSelectByIndex(i))
{
// Skip our own trades
if(PositionGetInteger(POSITION_MAGIC) == TradingMagic) continue;
// Apply management rules
ExtTradeMgr.ManageExternalTrade(PositionGetInteger(POSITION_TICKET));
}
}
}
}
//+------------------------------------------------------------------+
//| Update managed trades |
//+------------------------------------------------------------------+
void UpdateManagedTrades()
{
g_TotalTrades = 0;
ArrayResize(g_ManagedTrades, 0);
//--- Scan all positions
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
if(PositionSelectByIndex(i))
{
ManagedTrade trade;
trade.ticket = PositionGetInteger(POSITION_TICKET);
trade.symbol = PositionGetString(POSITION_SYMBOL);
trade.type = (ENUM_ORDER_TYPE)PositionGetInteger(POSITION_TYPE);
trade.volume = PositionGetDouble(POSITION_VOLUME);
trade.open_price = PositionGetDouble(POSITION_PRICE_OPEN);
trade.sl = PositionGetDouble(POSITION_SL);
trade.tp = PositionGetDouble(POSITION_TP);
trade.current_profit = PositionGetDouble(POSITION_PROFIT);
trade.open_time = (datetime)PositionGetInteger(POSITION_TIME);
trade.magic = PositionGetInteger(POSITION_MAGIC);
trade.is_external = (trade.magic != TradingMagic);
//--- Calculate risk metrics
if(trade.sl > 0)
{
double risk_points = MathAbs(trade.open_price - trade.sl);
trade.risk_amount = risk_points * trade.volume *
SymbolInfoDouble(trade.symbol, SYMBOL_TRADE_TICK_VALUE);
}
//--- Add to managed trades array
ArrayResize(g_ManagedTrades, g_TotalTrades + 1);
g_ManagedTrades[g_TotalTrades] = trade;
g_TotalTrades++;
//--- Apply trade management
if(!trade.is_external)
{
TradeMgr.ManageTrade(trade, g_MarketConditions);
}
}
}
g_InPosition = (g_TotalTrades > 0);
}
//+------------------------------------------------------------------+
//| Check for entry signals |
//+------------------------------------------------------------------+
void CheckEntrySignals()
{
//--- Rate limiting
if(TimeCurrent() - g_LastEntryCheck < MinTimeBetweenTrades * 60) return;
//--- Get entry signal
EntrySignal signal = EntrySystem.CheckForEntry(g_MarketConditions);
if(signal.signal_type != SIGNAL_NONE)
{
//--- Calculate position size
double lot_size = RiskMgr.CalculatePositionSize(
signal.entry_price,
signal.stop_loss,
RiskPercent
);
//--- Validate lot size
if(lot_size > 0 && RiskMgr.ValidateNewPosition(lot_size, g_RiskMetrics))
{
//--- Execute trade
CTrade trade;
trade.SetExpertMagicNumber(TradingMagic);
bool result = false;
if(signal.signal_type == SIGNAL_BUY)
{
result = trade.Buy(lot_size, _Symbol, signal.entry_price,
signal.stop_loss, signal.take_profit,
"ERMT 6.8 Buy");
}
else if(signal.signal_type == SIGNAL_SELL)
{
result = trade.Sell(lot_size, _Symbol, signal.entry_price,
signal.stop_loss, signal.take_profit,
"ERMT 6.8 Sell");
}
if(result)
{
g_LastEntryCheck = TimeCurrent();
Print("Trade executed: ", EnumToString(signal.signal_type),
" Lot: ", lot_size, " SL: ", signal.stop_loss,
" TP: ", signal.take_profit);
}
}
}
}
//+------------------------------------------------------------------+
//| Handle risk limit breach |
//+------------------------------------------------------------------+
void HandleRiskLimitBreach()
{
Print("WARNING: Risk limit breached! Exposure: ", g_RiskMetrics.current_exposure, "%");
if(CloseExcessiveRisk)
{
//--- Close highest risk positions first
for(int i = 0; i < g_TotalTrades; i++)
{
if(g_ManagedTrades[i].risk_amount > MaxExternalRiskPercent)
{
CTrade trade;
trade.PositionClose(g_ManagedTrades[i].ticket);
Print("Closed excessive risk position: ", g_ManagedTrades[i].ticket);
}
}
}
if(SendAlerts)
{
Alert("ERMT 6.8: Risk limit exceeded! Current exposure: ",
DoubleToString(g_RiskMetrics.current_exposure, 2), "%");
}
}
//+------------------------------------------------------------------+
//| Initialize performance metrics |
//+------------------------------------------------------------------+
void InitializePerformanceMetrics()
{
g_Performance.starting_balance = AccountInfoDouble(ACCOUNT_BALANCE);
g_Performance.current_balance = g_Performance.starting_balance;
g_Performance.current_equity = AccountInfoDouble(ACCOUNT_EQUITY);
g_Performance.peak_balance = g_Performance.starting_balance;
g_Performance.total_trades = 0;
g_Performance.winning_trades = 0;
g_Performance.losing_trades = 0;
g_Performance.total_profit = 0;
g_Performance.total_loss = 0;
g_Performance.largest_win = 0;
g_Performance.largest_loss = 0;
g_Performance.consecutive_wins = 0;
g_Performance.consecutive_losses = 0;
g_Performance.max_drawdown = 0;
g_Performance.current_drawdown = 0;
g_Performance.daily_profit = 0;
g_Performance.weekly_profit = 0;
g_Performance.monthly_profit = 0;
}
//+------------------------------------------------------------------+
//| Update performance metrics |
//+------------------------------------------------------------------+
void UpdatePerformanceMetrics()
{
g_Performance.current_balance = AccountInfoDouble(ACCOUNT_BALANCE);
g_Performance.current_equity = AccountInfoDouble(ACCOUNT_EQUITY);
//--- Update peak and drawdown
if(g_Performance.current_balance > g_Performance.peak_balance)
{
g_Performance.peak_balance = g_Performance.current_balance;
}
double drawdown = (g_Performance.peak_balance - g_Performance.current_balance) /
g_Performance.peak_balance * 100;
g_Performance.current_drawdown = drawdown;
if(drawdown > g_Performance.max_drawdown)
{
g_Performance.max_drawdown = drawdown;
}
}
//+------------------------------------------------------------------+
//| Collect performance metrics |
//+------------------------------------------------------------------+
void CollectPerformanceMetrics(PerformanceMetrics &perf)
{
perf = g_Performance; // Copy current metrics
}
//+------------------------------------------------------------------+
//| Calculate risk metrics |
//+------------------------------------------------------------------+
void CalculateRiskMetrics(RiskMetrics &risk)
{
risk = g_RiskMetrics; // Copy current metrics
//--- Additional calculations if needed
risk.max_daily_drawdown = MaxDailyDrawdown;
risk.max_total_exposure = MaxTotalExposure;
}
//+------------------------------------------------------------------+
//| Generate performance report |
//+------------------------------------------------------------------+
void GeneratePerformanceReport()
{
if(!GenerateReports) return;
string report = "=== ERMT 6.8 Performance Report ===\n";
report += "Time: " + TimeToString(TimeCurrent()) + "\n";
report += "Balance: $" + DoubleToString(g_Performance.current_balance, 2) + "\n";
report += "Equity: $" + DoubleToString(g_Performance.current_equity, 2) + "\n";
report += "Drawdown: " + DoubleToString(g_Performance.current_drawdown, 2) + "%\n";
report += "Total Trades: " + IntegerToString(g_Performance.total_trades) + "\n";
report += "Win Rate: " + DoubleToString(g_Performance.winning_trades * 100.0 /
MathMax(1, g_Performance.total_trades), 1) + "%\n";
report += "Current Exposure: " + DoubleToString(g_RiskMetrics.current_exposure, 2) + "%\n";
report += "Market Condition: " + EnumToString(g_MarketConditions.condition) + "\n";
Print(report);
if(SaveTradeLog)
{
SaveReportToFile(report);
}
}
//+------------------------------------------------------------------+
//| Save report to file |
//+------------------------------------------------------------------+
void SaveReportToFile(string report)
{
string filename = "ERMT_Report_" + TimeToString(TimeCurrent(), TIME_DATE) + ".txt";
int handle = FileOpen(filename, FILE_WRITE | FILE_TXT);
if(handle != INVALID_HANDLE)
{
FileWrite(handle, report);
FileClose(handle);
}
}
//+------------------------------------------------------------------+
//| Chart event handler for dashboard interaction |
//+------------------------------------------------------------------+
void OnChartEvent(const int id, const long &lparam,
const double &dparam, const string &sparam)
{
if(id == CHARTEVENT_KEYDOWN)
{
switch((int)lparam)
{
//--- Toggle Original Dashboard
case 'O':
ShowOriginalDashboard = !ShowOriginalDashboard;
if(ShowOriginalDashboard && OriginalDashboard != NULL)
OriginalDashboard.Show();
else if(OriginalDashboard != NULL)
OriginalDashboard.Hide();
Comment("Original Dashboard: ", ShowOriginalDashboard ? "ON" : "OFF");
break;
//--- Toggle New Dashboard
case 'N':
ShowNewDashboard = !ShowNewDashboard;
if(ShowNewDashboard && NewDashboard != NULL)
NewDashboard.SetVisible(ShowNewDashboard);
Comment("New Dashboard: ", ShowNewDashboard ? "ON" : "OFF");
break;
//--- Cycle themes on New Dashboard
case 'T':
if(NewDashboard != NULL)
{
int current_theme = (int)NewDashboard.GetTheme();
current_theme = (current_theme + 1) % 6;
NewDashboard.SetTheme((ENUM_DASH_THEME)current_theme);
Comment("Theme changed to: ", current_theme);
}
break;
//--- Toggle compact mode on New Dashboard
case 'C':
if(NewDashboard != NULL)
{
NewDashboard.ToggleCompact();
Comment("Compact mode toggled");
}
break;
//--- Show comparison
case 'D':
Comment("Dashboards Comparison:\n",
"Original: ", ShowOriginalDashboard ? "ON" : "OFF", " at (", OriginalDashboardX, ",", OriginalDashboardY, ")\n",
"New: ", ShowNewDashboard ? "ON" : "OFF", " at (", NewDashboardX, ",", NewDashboardY, ")\n",
"Balance: $", DoubleToString(g_Performance.current_balance, 2), "\n",
"Equity: $", DoubleToString(g_Performance.current_equity, 2), "\n",
"Exposure: ", DoubleToString(g_RiskMetrics.current_exposure, 2), "%\n",
"Market: ", EnumToString(g_MarketConditions.condition));
break;
}
}
}
//+------------------------------------------------------------------+
//| Tester function for optimization |
//+------------------------------------------------------------------+
double OnTester()
{
//--- Return profit factor for optimization
if(g_Performance.total_loss > 0)
return g_Performance.total_profit / g_Performance.total_loss;
else
return g_Performance.total_profit;
}