1111 lines
No EOL
87 KiB
Text
1111 lines
No EOL
87 KiB
Text
//+------------------------------------------------------------------+
|
|
//| ERMT_PME.mq5 v1.0 |
|
|
//| Enhanced Risk Management Tool - PME |
|
|
//| Pure Management Edition - No Entry, Exit Only |
|
|
//+------------------------------------------------------------------+
|
|
|
|
#property copyright "ERMT PME v1.0 - Pure Management Edition"
|
|
#property link "https://github.com/ERMT"
|
|
#property version "1.00"
|
|
#property description "Professional position management overlay - Manages ALL positions"
|
|
#property strict
|
|
|
|
// Include modules
|
|
#include "Modules_PME/DataTypes_PME.mqh"
|
|
#include "Modules_PME/Utilities_PME.mqh"
|
|
#include "Modules_PME/RiskManager_PME.mqh"
|
|
//Original - may work with Galileo FX
|
|
//#include "Modules_PME/TechnicalAnalysis_PME.mqh"
|
|
//#include "Modules_PME/PositionManager_PME.mqh"
|
|
// Fix for premature exits
|
|
#include "Modules_PME/TechnicalAnalysis_PME_Optimised.mqh"
|
|
#include "Modules_PME/PositionManager_PME_Complete.mqh"
|
|
#include "Modules/ProfitMaximizer_PME.mqh"
|
|
|
|
////+------------------------------------------------------------------+
|
|
////| Input Parameters |
|
|
////+------------------------------------------------------------------+
|
|
//
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| PROFIT MAXIMIZATION CONFIGURATION |
|
|
//+------------------------------------------------------------------+
|
|
|
|
// === ENHANCED PROFIT SETTINGS (Replace old ones) ===//
|
|
|
|
bool InpManageAllPositions = true; // Manage all positions
|
|
int InpMagicFilter = 0; // 0 = manage all trades
|
|
ENUM_MANAGEMENT_MODE InpDefaultMode = MODE_BREAKEVEN_TRAIL; // Conservative start
|
|
ENUM_MANAGEMENT_LEVEL InpStartLevel = LEVEL_STANDARD; // Standard management
|
|
input group "💰 Profit Maximization Settings"
|
|
|
|
// === RISK PROTECTION (Wider Tolerances) ===
|
|
double InpMaxLossPerTrade = 3.0; // Increased from 2.0%
|
|
double InpMaxDailyLoss = 12.0; // Increased from 6.0%
|
|
double InpMaxDrawdown = 30.0; // Increased from 20.0%
|
|
double InpMaxCorrelation = 0.85; // Increased correlation tolerance
|
|
|
|
// === EMERGENCY PROTECTION (Wider Stops) ===
|
|
bool InpApplyEmergencyStops = true; // Keep protection active
|
|
double InpEmergencySLMultiplier = 3.0; // Increased from 2.0 ATR
|
|
double InpEmergencyTPMultiplier = 5.0; // Increased from 3.0 ATR
|
|
|
|
// === DYNAMIC STOP MANAGEMENT ===
|
|
bool InpDynamicStops = true; // Enable dynamic adjustments
|
|
bool InpTightenOnProfit = true; // Tighten stops as profit grows
|
|
double InpTightenThreshold = 75; // Only tighten after 75 points profit
|
|
bool InpProtectProfits = true; // Protect accumulated profits
|
|
double InpProtectionThreshold = 100; // Start protecting after 100 points
|
|
|
|
// === BREAKEVEN CONFIGURATION (Delayed) ===
|
|
bool InpBreakevenEnabled = true; // Enable breakeven
|
|
double InpBreakevenTrigger = 40; // Increased from 20 points
|
|
double InpBreakevenOffset = 8; // Increased from 2 points
|
|
bool InpMultiLevelBE = true; // Enable multi-level breakeven
|
|
|
|
// Multi-Level Breakeven Thresholds
|
|
double InpBE_Level1_Trigger = 40; // First BE level
|
|
double InpBE_Level1_Offset = 8;
|
|
double InpBE_Level2_Trigger = 80; // Second BE level
|
|
double InpBE_Level2_Offset = 20;
|
|
double InpBE_Level3_Trigger = 150; // Third BE level
|
|
double InpBE_Level3_Offset = 50;
|
|
|
|
// === TRAILING STOP CONFIGURATION (Wider) ===
|
|
ENUM_TRAILING_METHOD InpTrailingMethod = TRAIL_ATR; // ATR-based for volatility adaptation
|
|
double InpTrailStart = 60; // Start trailing after 60 points
|
|
double InpTrailDistance = 40; // Increased from 20 points
|
|
double InpTrailStep = 15; // Minimum step for trail adjustment
|
|
bool InpAdaptiveTrailing = true; // Adapt to market conditions
|
|
|
|
// Volatility-Based Trail Adjustments
|
|
double InpLowVolatilityMultiplier = 0.8; // Tighter trail in quiet markets
|
|
double InpHighVolatilityMultiplier = 1.5; // Wider trail in volatile markets
|
|
double InpVolatilityThreshold = 1.2; // ATR threshold for high volatility
|
|
|
|
// === PARTIAL CLOSE STRATEGY (Optimized) ===
|
|
bool InpPartialEnabled = true; // Enable partial closing
|
|
int InpPartialLevels = 4; // Use 4 partial levels
|
|
|
|
// Progressive Partial Close Levels
|
|
double InpPartialTrigger1 = 50; // First partial at 50 points
|
|
double InpPartialPercent1 = 20; // Only close 20% (keep 80% running)
|
|
double InpPartialTrigger2 = 100; // Second partial at 100 points
|
|
double InpPartialPercent2 = 20; // Close another 20% (60% remaining)
|
|
double InpPartialTrigger3 = 200; // Third partial at 200 points
|
|
double InpPartialPercent3 = 25; // Close 25% (35% remaining)
|
|
double InpPartialTrigger4 = 400; // Fourth partial at 400 points
|
|
double InpPartialPercent4 = 20; // Close 20% (15% for runner)
|
|
|
|
// Runner Configuration
|
|
input double InpRunnerPercentage = 15; // Runner Size (% to keep)
|
|
input double InpRunnerTrailMultiplier = 2.0; // Runner Trail Multiplier
|
|
input double InpRunnerExitThreshold = 500; // Runner Exit (points)
|
|
|
|
// === EXIT MANAGEMENT (Disabled Aggressive Exits) ===
|
|
bool InpUseTechnicalExits = false; // DISABLED - prevent premature exits
|
|
bool InpTimeBasedExits = false; // DISABLED - no time limits
|
|
int InpMaxBarsInTrade = 1000; // Increased from 100 if enabled
|
|
bool InpReduceRiskOverTime = false; // DISABLED - maintain position size
|
|
|
|
// === PROFIT PROTECTION MECHANISM ===
|
|
bool InpProtectProfitEnabled = true; // Enable profit protection
|
|
double InpProfitProtectionStart = 100; // Start protecting after 100 points
|
|
double InpMaxRetracement = 60; // Allow 60% retracement from peak
|
|
double InpLockInProfit = 40; // Lock in 40% of peak profit minimum
|
|
|
|
// === TIME FILTERS (Relaxed) ===
|
|
bool InpUseTimeFilter = false; // Disable time restrictions
|
|
int InpStartHour = 0; // Trade 24 hours if enabled
|
|
int InpEndHour = 24;
|
|
bool InpFridayClose = false; // DISABLED - no Friday close
|
|
int InpFridayCloseHour = 23; // Latest possible if enabled
|
|
|
|
// === SESSION-BASED ADJUSTMENTS ===
|
|
bool InpSessionBasedManagement = true; // Adjust by trading session
|
|
|
|
// Asian Session (Conservative)
|
|
double InpAsianTrailMultiplier = 1.2; // Wider trails
|
|
double InpAsianPartialMultiplier = 1.5; // Delay partials
|
|
|
|
// London Session (Standard)
|
|
double InpLondonTrailMultiplier = 1.0; // Normal settings
|
|
double InpLondonPartialMultiplier = 1.0;
|
|
|
|
// New York Session (Aggressive)
|
|
double InpNewYorkTrailMultiplier = 0.9; // Tighter trails
|
|
double InpNewYorkPartialMultiplier = 0.8; // Earlier partials
|
|
|
|
// === ADVANCED PROFIT MAXIMIZATION ===
|
|
bool InpUseVolumeAnalysis = true; // Consider volume in decisions
|
|
double InpHighVolumeThreshold = 1.5; // 150% of average volume
|
|
bool InpExtendTargetsOnMomentum = true; // Extend TP on strong momentum
|
|
double InpMomentumThreshold = 2.0; // ATR multiplier for momentum
|
|
|
|
// === SMART EXIT FILTERS ===
|
|
bool InpUseSmartExits = true; // Enable intelligent exit logic
|
|
double InpMinProfitForExit = 30; // Minimum profit before any exit
|
|
bool InpCheckSupportResistance = true; // Check S/R before exiting
|
|
double InpSRBuffer = 10; // Points buffer from S/R levels
|
|
|
|
// === SYSTEM SETTINGS ===
|
|
ENUM_LOG_LEVEL InpLogLevel = LOG_INFO; // Logging detail level
|
|
bool InpSaveReports = true; // Save performance reports
|
|
bool InpEmailAlerts = false; // Email notifications
|
|
bool InpPushAlerts = false; // Push notifications
|
|
bool InpSoundAlerts = true;
|
|
|
|
/*
|
|
// Management Control
|
|
input group "=== Management Control ==="
|
|
input string InpInstanceID = "PME1"; // Unique Instance ID
|
|
input bool InpManageAllPositions = true; // Manage ALL positions
|
|
input int InpMagicFilter = 0; // Filter by Magic (0=all)
|
|
input ENUM_MANAGEMENT_MODE InpDefaultMode = MODE_BREAKEVEN_TRAIL; // Default Mode
|
|
input ENUM_MANAGEMENT_LEVEL InpStartLevel = LEVEL_STANDARD; // Starting Level
|
|
|
|
// Risk Protection
|
|
input group "=== Risk Protection ==="
|
|
input double InpMaxLossPerTrade = 3.0; // Max Loss Per Trade (%)
|
|
input double InpMaxDailyLoss = 10.0; // Max Daily Loss (%)
|
|
input double InpMaxDrawdown = 25.0; // Max Drawdown (%)
|
|
input double InpMaxCorrelation = 0.8; // Max Correlation
|
|
|
|
// Emergency Stops
|
|
input group "=== Emergency Protection ==="
|
|
input bool InpApplyEmergencyStops = true; // Apply Emergency Stops
|
|
input double InpEmergencySLMultiplier = 2.5; // Emergency SL (ATR)
|
|
input double InpEmergencyTPMultiplier = 4.0; // Emergency TP (ATR)
|
|
|
|
// Stop Management
|
|
input group "=== Stop Loss Management ==="
|
|
input bool InpDynamicStops = true; // Dynamic Stop Adjustment
|
|
input bool InpTightenOnProfit = true; // Tighten Stops on Profit
|
|
input double InpTightenThreshold = 50; // Tighten Threshold (points)
|
|
input bool InpProtectProfits = true; // Protect Profits
|
|
|
|
// Breakeven
|
|
input group "=== Breakeven Settings ==="
|
|
input bool InpBreakevenEnabled = true; // Enable Breakeven
|
|
input double InpBreakevenTrigger = 30; // BE Trigger (points)
|
|
input double InpBreakevenOffset = 5; // BE Offset (points)
|
|
input bool InpMultiLevelBE = false; // Multi-Level Breakeven
|
|
|
|
// Trailing Stop
|
|
input group "=== Trailing Stop ==="
|
|
input ENUM_TRAILING_METHOD InpTrailingMethod = TRAIL_ATR; // Trailing Method
|
|
input double InpTrailStart = 50; // Trail Start (points)
|
|
input double InpTrailDistance = 30; // Trail Distance
|
|
input double InpTrailStep = 10; // Trail Step
|
|
input bool InpAdaptiveTrailing = true; // Adaptive Trailing
|
|
|
|
// Partial Close
|
|
input group "=== Partial Close ==="
|
|
input bool InpPartialEnabled = true; // Enable Partial Close
|
|
input double InpPartialTrigger1 = 50; // First Trigger (points)
|
|
input double InpPartialPercent1 = 30; // First Close (%)
|
|
input double InpPartialTrigger2 = 100; // Second Trigger (points)
|
|
input double InpPartialPercent2 = 25; // Second Close (%)
|
|
|
|
// Exit Management
|
|
input group "=== Exit Management ==="
|
|
input bool InpUseTechnicalExits = true; // Technical Exit Signals
|
|
input bool InpTimeBasedExits = false; // Time-Based Exits
|
|
input int InpMaxBarsInTrade = 500; // Max Bars in Trade
|
|
input bool InpReduceRiskOverTime = false; // Reduce Risk Over Time
|
|
|
|
// Time Filters
|
|
input group "=== Time Filters ==="
|
|
input bool InpUseTimeFilter = false; // Use Time Filter
|
|
input int InpStartHour = 8; // Start Hour
|
|
input int InpEndHour = 20; // End Hour
|
|
input bool InpFridayClose = true; // Friday Close
|
|
input int InpFridayCloseHour = 21; // Friday Close Hour
|
|
|
|
// Display
|
|
input group "=== Display Settings ==="
|
|
input bool InpShowDashboard = true; // Show Dashboard
|
|
input int InpDashboardX = 20; // Dashboard X
|
|
input int InpDashboardY = 50; // Dashboard Y
|
|
input int InpUpdateFrequency = 2; // Update Frequency (sec)
|
|
|
|
// System
|
|
input group "=== System Settings ==="
|
|
input ENUM_LOG_LEVEL InpLogLevel = LOG_INFO; // Log Level
|
|
input bool InpSaveReports = true; // Save Reports
|
|
input bool InpEmailAlerts = false; // Email Alerts
|
|
input bool InpPushAlerts = false; // Push Notifications
|
|
input bool InpSoundAlerts = true; // Sound Alerts
|
|
|
|
*/
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Global Variables |
|
|
//+------------------------------------------------------------------+
|
|
|
|
// Core components
|
|
CUtilities* g_utils = NULL;
|
|
CRiskManager* g_risk = NULL;
|
|
CTechnicalAnalysis* g_tech = NULL;
|
|
CPositionManager* g_manager = NULL;
|
|
ProfitMaximizer* g_profit_max = NULL;
|
|
|
|
// State tracking
|
|
bool g_initialized = false;
|
|
datetime g_last_update = 0;
|
|
datetime g_session_start = 0;
|
|
double g_session_start_balance = 0;
|
|
double g_session_start_equity = 0;
|
|
|
|
// Performance tracking
|
|
int g_positions_detected = 0;
|
|
int g_positions_managed = 0;
|
|
int g_positions_closed = 0;
|
|
double g_total_prevented = 0;
|
|
double g_total_captured = 0;
|
|
|
|
// Alert management
|
|
datetime g_last_alert = 0;
|
|
int g_alert_count = 0;
|
|
|
|
// Dashboard elements (simplified)
|
|
string g_dashboard_prefix = "PME_" + InpInstanceID + "-";
|
|
int g_dashboard_objects = 0;
|
|
|
|
// Performance tracking
|
|
struct PerformanceTracker
|
|
{
|
|
int trades_managed;
|
|
double total_profit_captured;
|
|
double total_loss_prevented;
|
|
int runners_created;
|
|
int extreme_profits;
|
|
datetime last_update;
|
|
};
|
|
|
|
PerformanceTracker g_performance;_tracker;
|
|
//+------------------------------------------------------------------+
|
|
//| Expert initialization function |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
Print("==================================================");
|
|
Print(" ERMT PME v1.0 - Pure Management Edition");
|
|
Print("==================================================");
|
|
Print("Initializing management system...");
|
|
|
|
// Validate inputs
|
|
if(!ValidateInputs())
|
|
{
|
|
Print("ERROR: Invalid input parameters");
|
|
return INIT_PARAMETERS_INCORRECT;
|
|
}
|
|
|
|
// Create core components
|
|
g_utils = new CUtilities();
|
|
if(g_utils == NULL)
|
|
{
|
|
Print("ERROR: Failed to create Utilities");
|
|
return INIT_FAILED;
|
|
}
|
|
|
|
g_risk = new CRiskManager();
|
|
if(g_risk == NULL)
|
|
{
|
|
Print("ERROR: Failed to create RiskManager");
|
|
Cleanup();
|
|
return INIT_FAILED;
|
|
}
|
|
|
|
g_tech = new CTechnicalAnalysis();
|
|
if(g_tech == NULL)
|
|
{
|
|
Print("ERROR: Failed to create TechnicalAnalysis");
|
|
Cleanup();
|
|
return INIT_FAILED;
|
|
}
|
|
|
|
g_manager = new CPositionManager();
|
|
if(g_manager == NULL)
|
|
{
|
|
Print("ERROR: Failed to create PositionManager");
|
|
Cleanup();
|
|
return INIT_FAILED;
|
|
}
|
|
|
|
// Initialize utilities
|
|
if(!g_utils.Initialize(InpLogLevel, InpSaveReports, InpInstanceID))
|
|
{
|
|
Print("ERROR: Failed to initialize Utilities");
|
|
Cleanup();
|
|
return INIT_FAILED;
|
|
}
|
|
|
|
// Initialize risk manager
|
|
if(!g_risk.Initialize(g_utils, InpMaxLossPerTrade, InpMaxDailyLoss, InpMaxDrawdown))
|
|
{
|
|
Print("ERROR: Failed to initialize RiskManager");
|
|
Cleanup();
|
|
return INIT_FAILED;
|
|
}
|
|
|
|
// Initialize technical analysis
|
|
if(!g_tech.Initialize(g_utils))
|
|
{
|
|
Print("ERROR: Failed to initialize TechnicalAnalysis");
|
|
Cleanup();
|
|
return INIT_FAILED;
|
|
}
|
|
|
|
// Initialize position manager
|
|
if(!g_manager.Initialize(g_utils, g_risk, g_tech, InpMagicFilter))
|
|
{
|
|
Print("ERROR: Failed to initialize PositionManager");
|
|
Cleanup();
|
|
return INIT_FAILED;
|
|
}
|
|
|
|
// Configure position manager
|
|
ManagementConfig config;
|
|
config.apply_default_sl = InpApplyEmergencyStops;
|
|
config.default_sl_atr = InpEmergencySLMultiplier;
|
|
config.apply_default_tp = InpApplyEmergencyStops;
|
|
config.default_tp_atr = InpEmergencyTPMultiplier;
|
|
config.dynamic_sl_adjust = InpDynamicStops;
|
|
config.tighten_on_profit = InpTightenOnProfit;
|
|
config.tighten_threshold = InpTightenThreshold;
|
|
config.breakeven_enabled = InpBreakevenEnabled;
|
|
config.breakeven_trigger = InpBreakevenTrigger;
|
|
config.breakeven_offset = InpBreakevenOffset;
|
|
config.multi_level_be = InpMultiLevelBE;
|
|
config.trailing_method = InpTrailingMethod;
|
|
config.trail_start = InpTrailStart;
|
|
config.trail_distance = InpTrailDistance;
|
|
config.trail_step = InpTrailStep;
|
|
config.adaptive_trailing = InpAdaptiveTrailing;
|
|
config.partial_enabled = InpPartialEnabled;
|
|
config.partial_trigger_1 = InpPartialTrigger1;
|
|
config.partial_percent_1 = InpPartialPercent1;
|
|
config.partial_trigger_2 = InpPartialTrigger2;
|
|
config.partial_percent_2 = InpPartialPercent2;
|
|
config.time_based_mgmt = InpTimeBasedExits;
|
|
config.max_bars_in_trade = InpMaxBarsInTrade;
|
|
config.reduce_risk_overtime = InpReduceRiskOverTime;
|
|
config.friday_close_hour = InpFridayCloseHour;
|
|
config.max_loss_per_trade = InpMaxLossPerTrade;
|
|
config.max_daily_loss = InpMaxDailyLoss;
|
|
config.max_correlation = InpMaxCorrelation;
|
|
config.max_drawdown = InpMaxDrawdown;
|
|
|
|
g_manager.SetConfiguration(config);
|
|
|
|
// Initialize session
|
|
g_session_start = TimeCurrent();
|
|
g_session_start_balance = AccountInfoDouble(ACCOUNT_BALANCE);
|
|
g_session_start_equity = AccountInfoDouble(ACCOUNT_EQUITY);
|
|
|
|
// Initialize dashboard
|
|
if(InpShowDashboard)
|
|
{
|
|
InitializeDashboard();
|
|
}
|
|
|
|
// Log configuration
|
|
LogConfiguration();
|
|
|
|
// Set timer
|
|
EventSetTimer(InpUpdateFrequency);
|
|
|
|
g_initialized = true;
|
|
|
|
// Initial status
|
|
int initial_positions = g_manager.GetManagedCount();
|
|
Print(StringFormat("PME Ready - Managing %d positions", initial_positions));
|
|
g_utils.Log(StringFormat("PME initialized successfully - %d positions detected",
|
|
initial_positions), LOG_INFO);
|
|
|
|
// Sound alert
|
|
if(InpSoundAlerts) PlaySound("alert.wav");
|
|
|
|
return INIT_SUCCEEDED;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert deinitialization function |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
EventKillTimer();
|
|
|
|
string reason_text = GetDeinitReasonText(reason);
|
|
|
|
if(g_utils != NULL)
|
|
{
|
|
g_utils.Log(StringFormat("PME Shutdown: %s", reason_text), LOG_INFO);
|
|
}
|
|
|
|
// Generate final report
|
|
if(g_manager != NULL && g_utils != NULL)
|
|
{
|
|
GenerateFinalReport();
|
|
}
|
|
|
|
// Clean up dashboard
|
|
if(InpShowDashboard)
|
|
{
|
|
RemoveDashboard();
|
|
}
|
|
|
|
// Clean up components
|
|
Cleanup();
|
|
|
|
Comment("");
|
|
Print("==================================================");
|
|
Print(StringFormat("PME Shutdown Complete: %s", reason_text));
|
|
Print("==================================================");
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Expert tick function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTick()
|
|
{
|
|
if(!g_initialized) return;
|
|
|
|
// Check if we should be active
|
|
if(!CheckTradingConditions()) return;
|
|
|
|
// Main management cycle
|
|
g_manager.ManageAllPositions();
|
|
|
|
// Check risk limits
|
|
CheckRiskLimits();
|
|
|
|
// Update dashboard if visible
|
|
if(InpShowDashboard)
|
|
{
|
|
UpdateDashboard();
|
|
}
|
|
|
|
// Check for Friday close
|
|
if(InpFridayClose && IsFridayClose())
|
|
{
|
|
g_utils.Log("Friday close time - closing all positions", LOG_WARNING);
|
|
g_manager.CloseAllPositions(EXIT_TIME);
|
|
|
|
if(InpSoundAlerts) PlaySound("alert2.wav");
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Timer function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTimer()
|
|
{
|
|
if(!g_initialized) return;
|
|
|
|
// Periodic status update
|
|
static int status_counter = 0;
|
|
status_counter++;
|
|
|
|
if(status_counter >= 60 / InpUpdateFrequency) // Every minute
|
|
{
|
|
status_counter = 0;
|
|
LogStatus();
|
|
}
|
|
|
|
// Save snapshot
|
|
static int snapshot_counter = 0;
|
|
snapshot_counter++;
|
|
|
|
if(snapshot_counter >= 300 / InpUpdateFrequency) // Every 5 minutes
|
|
{
|
|
snapshot_counter = 0;
|
|
if(InpSaveReports)
|
|
{
|
|
SaveSnapshot();
|
|
}
|
|
}
|
|
|
|
// Check for alerts
|
|
CheckAlerts();
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Trade function |
|
|
//+------------------------------------------------------------------+
|
|
void OnTrade()
|
|
{
|
|
if(!g_initialized) return;
|
|
|
|
// Update metrics on trade events
|
|
g_positions_closed++;
|
|
|
|
// Log trade event
|
|
if(g_utils != NULL)
|
|
{
|
|
g_utils.Log("Trade event detected", LOG_DEBUG);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Validate Inputs |
|
|
//+------------------------------------------------------------------+
|
|
bool ValidateInputs()
|
|
{
|
|
if(InpMaxLossPerTrade <= 0 || InpMaxLossPerTrade > 10)
|
|
{
|
|
Print("Invalid MaxLossPerTrade: must be between 0 and 10");
|
|
return false;
|
|
}
|
|
|
|
if(InpMaxDailyLoss <= 0 || InpMaxDailyLoss > 20)
|
|
{
|
|
Print("Invalid MaxDailyLoss: must be between 0 and 20");
|
|
return false;
|
|
}
|
|
|
|
if(InpMaxDrawdown <= 0 || InpMaxDrawdown > 50)
|
|
{
|
|
Print("Invalid MaxDrawdown: must be between 0 and 50");
|
|
return false;
|
|
}
|
|
|
|
if(InpBreakevenTrigger < 5 || InpBreakevenTrigger > 1000)
|
|
{
|
|
Print("Invalid BreakevenTrigger: must be between 5 and 1000");
|
|
return false;
|
|
}
|
|
|
|
if(InpTrailDistance < 5 || InpTrailDistance > 1000)
|
|
{
|
|
Print("Invalid TrailDistance: must be between 5 and 1000");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Check Trading Conditions |
|
|
//+------------------------------------------------------------------+
|
|
bool CheckTradingConditions()
|
|
{
|
|
// Check if terminal is connected
|
|
if(!TerminalInfoInteger(TERMINAL_CONNECTED))
|
|
return false;
|
|
|
|
// Check if trade is allowed
|
|
if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
|
|
return false;
|
|
|
|
// Check time filter
|
|
if(InpUseTimeFilter)
|
|
{
|
|
MqlDateTime current;
|
|
TimeToStruct(TimeCurrent(), current);
|
|
|
|
if(current.hour < InpStartHour || current.hour >= InpEndHour)
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Check Risk Limits |
|
|
//+------------------------------------------------------------------+
|
|
void CheckRiskLimits()
|
|
{
|
|
// Check daily loss
|
|
double daily_loss = g_risk.GetDailyLoss();
|
|
if(daily_loss > InpMaxDailyLoss)
|
|
{
|
|
g_utils.Log(StringFormat("Daily loss limit reached: %.2f%%", daily_loss), LOG_ERROR);
|
|
g_manager.CloseAllPositions(EXIT_RISK);
|
|
|
|
// Send alerts
|
|
SendAlert("Daily loss limit reached!");
|
|
}
|
|
|
|
// Check drawdown
|
|
double drawdown = g_risk.GetDrawdown();
|
|
if(drawdown > InpMaxDrawdown)
|
|
{
|
|
g_utils.Log(StringFormat("Max drawdown reached: %.2f%%", drawdown), LOG_ERROR);
|
|
g_manager.CloseAllPositions(EXIT_DRAWDOWN);
|
|
|
|
// Send alerts
|
|
SendAlert("Max drawdown reached!");
|
|
}
|
|
|
|
// Check individual position risks
|
|
double total_risk = g_manager.GetTotalRisk();
|
|
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
|
|
double risk_percent = (total_risk / balance) * 100;
|
|
|
|
if(risk_percent > InpMaxDailyLoss)
|
|
{
|
|
g_utils.Log(StringFormat("Total risk too high: %.2f%%", risk_percent), LOG_WARNING);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Check if Friday Close |
|
|
//+------------------------------------------------------------------+
|
|
bool IsFridayClose()
|
|
{
|
|
MqlDateTime current;
|
|
TimeToStruct(TimeCurrent(), current);
|
|
|
|
return (current.day_of_week == 5 && current.hour >= InpFridayCloseHour);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Initialize Dashboard |
|
|
//+------------------------------------------------------------------+
|
|
void InitializeDashboard()
|
|
{
|
|
int y = InpDashboardY;
|
|
color text_color = clrWhite;
|
|
color header_color = clrGold;
|
|
|
|
// Background
|
|
CreateRectangle(g_dashboard_prefix + "BG", InpDashboardX - 5, y - 5, 250, 400, clrBlack, STYLE_SOLID, 1);
|
|
|
|
// Header
|
|
CreateLabel(g_dashboard_prefix + "HEADER", InpDashboardX, y, "ERMT PME v1.0", header_color, 11);
|
|
y += 20;
|
|
|
|
CreateLabel(g_dashboard_prefix + "LINE1", InpDashboardX, y, "────────────────────", text_color, 9);
|
|
y += 15;
|
|
|
|
// Status section
|
|
CreateLabel(g_dashboard_prefix + "STATUS", InpDashboardX, y, "STATUS", header_color, 10);
|
|
y += 18;
|
|
CreateLabel(g_dashboard_prefix + "ACTIVE", InpDashboardX, y, "Active: 0", text_color, 9);
|
|
y += 15;
|
|
CreateLabel(g_dashboard_prefix + "CLOSED", InpDashboardX, y, "Closed: 0", text_color, 9);
|
|
y += 20;
|
|
|
|
// Risk section
|
|
CreateLabel(g_dashboard_prefix + "RISK", InpDashboardX, y, "RISK", header_color, 10);
|
|
y += 18;
|
|
CreateLabel(g_dashboard_prefix + "EXPOSURE", InpDashboardX, y, "Exposure: 0.00", text_color, 9);
|
|
y += 15;
|
|
CreateLabel(g_dashboard_prefix + "DRAWDOWN", InpDashboardX, y, "Drawdown: 0.0%", text_color, 9);
|
|
y += 20;
|
|
|
|
// Management section
|
|
CreateLabel(g_dashboard_prefix + "MGMT", InpDashboardX, y, "MANAGEMENT", header_color, 10);
|
|
y += 18;
|
|
CreateLabel(g_dashboard_prefix + "BREAKEVENS", InpDashboardX, y, "Breakevens: 0", text_color, 9);
|
|
y += 15;
|
|
CreateLabel(g_dashboard_prefix + "TRAILS", InpDashboardX, y, "Trails: 0", text_color, 9);
|
|
y += 15;
|
|
CreateLabel(g_dashboard_prefix + "PARTIALS", InpDashboardX, y, "Partials: 0", text_color, 9);
|
|
y += 20;
|
|
|
|
// Performance section
|
|
CreateLabel(g_dashboard_prefix + "PERF", InpDashboardX, y, "PERFORMANCE", header_color, 10);
|
|
y += 18;
|
|
CreateLabel(g_dashboard_prefix + "SAVED", InpDashboardX, y, "Saved: $0.00", text_color, 9);
|
|
y += 15;
|
|
CreateLabel(g_dashboard_prefix + "CAPTURED", InpDashboardX, y, "Captured: $0.00", text_color, 9);
|
|
y += 15;
|
|
CreateLabel(g_dashboard_prefix + "EFFICIENCY", InpDashboardX, y, "Efficiency: 0.0%", text_color, 9);
|
|
|
|
g_dashboard_objects = 20; // Track number of objects
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Update Dashboard |
|
|
//+------------------------------------------------------------------+
|
|
void UpdateDashboard()
|
|
{
|
|
SessionMetrics metrics;
|
|
g_manager.GetSessionMetrics(metrics);
|
|
|
|
// Update status
|
|
UpdateLabel(g_dashboard_prefix + "ACTIVE",
|
|
StringFormat("Active: %d", g_manager.GetManagedCount()));
|
|
UpdateLabel(g_dashboard_prefix + "CLOSED",
|
|
StringFormat("Closed: %d", metrics.positions_closed));
|
|
|
|
// Update risk
|
|
UpdateLabel(g_dashboard_prefix + "EXPOSURE",
|
|
StringFormat("Exposure: %.2f", g_manager.GetTotalExposure()));
|
|
UpdateLabel(g_dashboard_prefix + "DRAWDOWN",
|
|
StringFormat("Drawdown: %.1f%%", g_risk.GetDrawdown()));
|
|
|
|
// Update management
|
|
UpdateLabel(g_dashboard_prefix + "BREAKEVENS",
|
|
StringFormat("Breakevens: %d", metrics.breakevens_applied));
|
|
UpdateLabel(g_dashboard_prefix + "TRAILS",
|
|
StringFormat("Trails: %d", metrics.trails_activated));
|
|
UpdateLabel(g_dashboard_prefix + "PARTIALS",
|
|
StringFormat("Partials: %d", metrics.partial_closes));
|
|
|
|
// Update performance
|
|
UpdateLabel(g_dashboard_prefix + "SAVED",
|
|
StringFormat("Saved: $%.2f", metrics.total_prevented_loss));
|
|
UpdateLabel(g_dashboard_prefix + "CAPTURED",
|
|
StringFormat("Captured: $%.2f", metrics.total_captured_profit));
|
|
UpdateLabel(g_dashboard_prefix + "EFFICIENCY",
|
|
StringFormat("Efficiency: %.1f%%", metrics.management_efficiency));
|
|
|
|
// Update comment if dashboard not shown
|
|
if(!InpShowDashboard)
|
|
{
|
|
Comment(StringFormat(
|
|
"PME v1.0 | Active: %d | P/L: %.2f | Saved: %.2f | Efficiency: %.1f%%",
|
|
g_manager.GetManagedCount(),
|
|
g_manager.GetTotalProfit(),
|
|
metrics.total_prevented_loss + metrics.total_captured_profit,
|
|
metrics.management_efficiency
|
|
));
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Remove Dashboard |
|
|
//+------------------------------------------------------------------+
|
|
void RemoveDashboard()
|
|
{
|
|
for(int i = 0; i < g_dashboard_objects + 10; i++)
|
|
{
|
|
string name = g_dashboard_prefix + IntegerToString(i);
|
|
ObjectDelete(0, name);
|
|
}
|
|
|
|
// Remove named objects
|
|
ObjectDelete(0, g_dashboard_prefix + "BG");
|
|
ObjectDelete(0, g_dashboard_prefix + "HEADER");
|
|
ObjectDelete(0, g_dashboard_prefix + "LINE1");
|
|
ObjectDelete(0, g_dashboard_prefix + "STATUS");
|
|
ObjectDelete(0, g_dashboard_prefix + "ACTIVE");
|
|
ObjectDelete(0, g_dashboard_prefix + "CLOSED");
|
|
ObjectDelete(0, g_dashboard_prefix + "RISK");
|
|
ObjectDelete(0, g_dashboard_prefix + "EXPOSURE");
|
|
ObjectDelete(0, g_dashboard_prefix + "DRAWDOWN");
|
|
ObjectDelete(0, g_dashboard_prefix + "MGMT");
|
|
ObjectDelete(0, g_dashboard_prefix + "BREAKEVENS");
|
|
ObjectDelete(0, g_dashboard_prefix + "TRAILS");
|
|
ObjectDelete(0, g_dashboard_prefix + "PARTIALS");
|
|
ObjectDelete(0, g_dashboard_prefix + "PERF");
|
|
ObjectDelete(0, g_dashboard_prefix + "SAVED");
|
|
ObjectDelete(0, g_dashboard_prefix + "CAPTURED");
|
|
ObjectDelete(0, g_dashboard_prefix + "EFFICIENCY");
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Create Label |
|
|
//+------------------------------------------------------------------+
|
|
void CreateLabel(string name, int x, int y, string text, color clr, int size)
|
|
{
|
|
ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
|
|
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
|
|
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
|
|
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
|
|
ObjectSetString(0, name, OBJPROP_TEXT, text);
|
|
ObjectSetString(0, name, OBJPROP_FONT, "Arial");
|
|
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, size);
|
|
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
|
|
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Update Label |
|
|
//+------------------------------------------------------------------+
|
|
void UpdateLabel(string name, string text)
|
|
{
|
|
if(ObjectFind(0, name) >= 0)
|
|
{
|
|
ObjectSetString(0, name, OBJPROP_TEXT, text);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Create Rectangle |
|
|
//+------------------------------------------------------------------+
|
|
void CreateRectangle(string name, int x, int y, int width, int height,
|
|
color clr, ENUM_LINE_STYLE style, int line_width)
|
|
{
|
|
ObjectCreate(0, name, OBJ_RECTANGLE_LABEL, 0, 0, 0);
|
|
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
|
|
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
|
|
ObjectSetInteger(0, name, OBJPROP_XSIZE, width);
|
|
ObjectSetInteger(0, name, OBJPROP_YSIZE, height);
|
|
ObjectSetInteger(0, name, OBJPROP_BGCOLOR, clr);
|
|
ObjectSetInteger(0, name, OBJPROP_BORDER_TYPE, BORDER_FLAT);
|
|
ObjectSetInteger(0, name, OBJPROP_WIDTH, line_width);
|
|
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
|
|
ObjectSetInteger(0, name, OBJPROP_STYLE, style);
|
|
ObjectSetInteger(0, name, OBJPROP_BACK, false);
|
|
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
|
|
ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Log Configuration |
|
|
//+------------------------------------------------------------------+
|
|
void LogConfiguration()
|
|
{
|
|
if(g_utils == NULL) return;
|
|
|
|
g_utils.Log("=== PME Configuration ===", LOG_INFO);
|
|
g_utils.Log(StringFormat("Magic Filter: %d", InpMagicFilter), LOG_INFO);
|
|
g_utils.Log(StringFormat("Management Mode: %s", ManagementModeToString(InpDefaultMode)), LOG_INFO);
|
|
g_utils.Log(StringFormat("Max Loss/Trade: %.2f%%", InpMaxLossPerTrade), LOG_INFO);
|
|
g_utils.Log(StringFormat("Max Daily Loss: %.2f%%", InpMaxDailyLoss), LOG_INFO);
|
|
g_utils.Log(StringFormat("Max Drawdown: %.2f%%", InpMaxDrawdown), LOG_INFO);
|
|
g_utils.Log(StringFormat("Breakeven: %s @ %.0f points",
|
|
InpBreakevenEnabled ? "Enabled" : "Disabled",
|
|
InpBreakevenTrigger), LOG_INFO);
|
|
g_utils.Log(StringFormat("Trailing: %s", TrailingMethodToString(InpTrailingMethod)), LOG_INFO);
|
|
g_utils.Log(StringFormat("Partial Close: %s", InpPartialEnabled ? "Enabled" : "Disabled"), LOG_INFO);
|
|
g_utils.Log(StringFormat("Start Balance: %.2f", g_session_start_balance), LOG_INFO);
|
|
g_utils.Log("========================", LOG_INFO);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Log Status |
|
|
//+------------------------------------------------------------------+
|
|
void LogStatus()
|
|
{
|
|
if(g_utils == NULL || g_manager == NULL) return;
|
|
|
|
SessionMetrics metrics;
|
|
g_manager.GetSessionMetrics(metrics);
|
|
|
|
g_utils.Log(StringFormat(
|
|
"Status: Active=%d | Closed=%d | BE=%d | Trails=%d | Saved=%.2f | Captured=%.2f",
|
|
g_manager.GetManagedCount(),
|
|
metrics.positions_closed,
|
|
metrics.breakevens_applied,
|
|
metrics.trails_activated,
|
|
metrics.total_prevented_loss,
|
|
metrics.total_captured_profit
|
|
), LOG_INFO);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Save Snapshot |
|
|
//+------------------------------------------------------------------+
|
|
void SaveSnapshot()
|
|
{
|
|
if(g_utils == NULL || g_manager == NULL) return;
|
|
|
|
SessionMetrics metrics;
|
|
g_manager.GetSessionMetrics(metrics);
|
|
|
|
string filename = StringFormat("PME_Snapshot_%s.csv",
|
|
TimeToString(TimeCurrent(), TIME_DATE));
|
|
|
|
string content = StringFormat(
|
|
"%s,%d,%d,%d,%d,%d,%.2f,%.2f,%.2f,%.2f\n",
|
|
TimeToString(TimeCurrent(), TIME_DATE|TIME_MINUTES),
|
|
g_manager.GetManagedCount(),
|
|
metrics.positions_closed,
|
|
metrics.breakevens_applied,
|
|
metrics.trails_activated,
|
|
metrics.partial_closes,
|
|
metrics.total_prevented_loss,
|
|
metrics.total_captured_profit,
|
|
metrics.management_efficiency,
|
|
AccountInfoDouble(ACCOUNT_BALANCE)
|
|
);
|
|
|
|
g_utils.SaveToFile(filename, content, true); // Append mode
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Generate Final Report |
|
|
//+------------------------------------------------------------------+
|
|
void GenerateFinalReport()
|
|
{
|
|
if(g_utils == NULL || g_manager == NULL) return;
|
|
|
|
SessionMetrics metrics;
|
|
g_manager.GetSessionMetrics(metrics);
|
|
|
|
double session_duration = (TimeCurrent() - g_session_start) / 3600.0; // Hours
|
|
double final_balance = AccountInfoDouble(ACCOUNT_BALANCE);
|
|
double session_profit = final_balance - g_session_start_balance;
|
|
|
|
string report = "\n";
|
|
report += "==================================================\n";
|
|
report += " ERMT PME - Final Session Report\n";
|
|
report += "==================================================\n";
|
|
report += StringFormat("Session Duration: %.1f hours\n", session_duration);
|
|
report += StringFormat("Starting Balance: $%.2f\n", g_session_start_balance);
|
|
report += StringFormat("Final Balance: $%.2f\n", final_balance);
|
|
report += StringFormat("Session P/L: $%.2f (%.2f%%)\n",
|
|
session_profit,
|
|
(session_profit / g_session_start_balance) * 100);
|
|
report += "\n";
|
|
report += "--- Management Statistics ---\n";
|
|
report += StringFormat("Positions Managed: %d\n", metrics.total_managed);
|
|
report += StringFormat("Positions Closed: %d\n", metrics.positions_closed);
|
|
report += StringFormat("Emergency Closes: %d\n", metrics.emergency_closes);
|
|
report += "\n";
|
|
report += "--- Actions Taken ---\n";
|
|
report += StringFormat("Stops Added: %d\n", metrics.stops_added);
|
|
report += StringFormat("Stops Adjusted: %d\n", metrics.stops_adjusted);
|
|
report += StringFormat("Breakevens Applied: %d\n", metrics.breakevens_applied);
|
|
report += StringFormat("Trails Activated: %d\n", metrics.trails_activated);
|
|
report += StringFormat("Partial Closes: %d\n", metrics.partial_closes);
|
|
report += StringFormat("Total Actions: %d\n", metrics.total_actions);
|
|
report += "\n";
|
|
report += "--- Performance Metrics ---\n";
|
|
report += StringFormat("Loss Prevented: $%.2f\n", metrics.total_prevented_loss);
|
|
report += StringFormat("Profit Captured: $%.2f\n", metrics.total_captured_profit);
|
|
report += StringFormat("Total Value Added: $%.2f\n",
|
|
metrics.total_prevented_loss + metrics.total_captured_profit);
|
|
report += StringFormat("Management Efficiency: %.2f%%\n", metrics.management_efficiency);
|
|
report += StringFormat("Success Rate: %.2f%%\n", metrics.success_rate);
|
|
report += "\n";
|
|
report += "--- Risk Metrics ---\n";
|
|
report += StringFormat("Risk Reduced: $%.2f\n", metrics.total_risk_reduced);
|
|
report += StringFormat("Avg Risk Reduction: %.2f%%\n", metrics.average_risk_reduction);
|
|
report += StringFormat("Max Single Risk: $%.2f\n", metrics.max_single_risk);
|
|
report += StringFormat("Final Exposure: $%.2f\n", metrics.current_exposure);
|
|
report += "==================================================\n";
|
|
|
|
g_utils.Log(report, LOG_INFO);
|
|
|
|
if(InpSaveReports)
|
|
{
|
|
string filename = StringFormat("PME_FinalReport_%s.txt",
|
|
TimeToString(TimeCurrent(), TIME_DATE|TIME_MINUTES));
|
|
g_utils.SaveToFile(filename, report, false);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Check Alerts |
|
|
//+------------------------------------------------------------------+
|
|
void CheckAlerts()
|
|
{
|
|
if(TimeCurrent() - g_last_alert < 60) return; // Max 1 alert per minute
|
|
|
|
// Check for positions without stops
|
|
SessionMetrics metrics;
|
|
g_manager.GetSessionMetrics(metrics);
|
|
|
|
// Alert conditions
|
|
bool alert_needed = false;
|
|
string alert_message = "";
|
|
|
|
// Check drawdown
|
|
double drawdown = g_risk.GetDrawdown();
|
|
if(drawdown > InpMaxDrawdown * 0.8) // 80% of max
|
|
{
|
|
alert_needed = true;
|
|
alert_message = StringFormat("Warning: Drawdown at %.1f%%", drawdown);
|
|
}
|
|
|
|
// Check daily loss
|
|
double daily_loss = g_risk.GetDailyLoss();
|
|
if(daily_loss > InpMaxDailyLoss * 0.8) // 80% of max
|
|
{
|
|
alert_needed = true;
|
|
alert_message = StringFormat("Warning: Daily loss at %.1f%%", daily_loss);
|
|
}
|
|
|
|
if(alert_needed)
|
|
{
|
|
SendAlert(alert_message);
|
|
g_last_alert = TimeCurrent();
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Send Alert |
|
|
//+------------------------------------------------------------------+
|
|
void SendAlert(string message)
|
|
{
|
|
string full_message = StringFormat("PME Alert: %s", message);
|
|
|
|
// Terminal alert
|
|
Alert(full_message);
|
|
|
|
// Sound alert
|
|
if(InpSoundAlerts)
|
|
{
|
|
PlaySound("alert2.wav");
|
|
}
|
|
|
|
// Email alert
|
|
if(InpEmailAlerts)
|
|
{
|
|
SendMail("PME Alert", full_message);
|
|
}
|
|
|
|
// Push notification
|
|
if(InpPushAlerts)
|
|
{
|
|
SendNotification(full_message);
|
|
}
|
|
|
|
// Log
|
|
if(g_utils != NULL)
|
|
{
|
|
g_utils.Log(full_message, LOG_WARNING);
|
|
}
|
|
|
|
g_alert_count++;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Get Deinitialization Reason Text |
|
|
//+------------------------------------------------------------------+
|
|
string GetDeinitReasonText(int reason)
|
|
{
|
|
switch(reason)
|
|
{
|
|
case REASON_PROGRAM: return "Program terminated";
|
|
case REASON_REMOVE: return "Removed from chart";
|
|
case REASON_RECOMPILE: return "Recompiled";
|
|
case REASON_CHARTCHANGE: return "Chart changed";
|
|
case REASON_CHARTCLOSE: return "Chart closed";
|
|
case REASON_PARAMETERS: return "Parameters changed";
|
|
case REASON_ACCOUNT: return "Account changed";
|
|
case REASON_TEMPLATE: return "Template applied";
|
|
case REASON_INITFAILED: return "Initialization failed";
|
|
case REASON_CLOSE: return "Terminal closed";
|
|
default: return StringFormat("Unknown (%d)", reason);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Cleanup |
|
|
//+------------------------------------------------------------------+
|
|
void Cleanup()
|
|
{
|
|
if(g_manager != NULL)
|
|
{
|
|
delete g_manager;
|
|
g_manager = NULL;
|
|
}
|
|
|
|
if(g_tech != NULL)
|
|
{
|
|
delete g_tech;
|
|
g_tech = NULL;
|
|
}
|
|
|
|
if(g_risk != NULL)
|
|
{
|
|
delete g_risk;
|
|
g_risk = NULL;
|
|
}
|
|
|
|
if(g_utils != NULL)
|
|
{
|
|
delete g_utils;
|
|
g_utils = NULL;
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+ |