1516 lines
59 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
| |||
| |||
/**
| |||
* @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>
| |||
| |||
// Forward declarations for our custom components
| |||
class CRiskManager;
| |||
class CTradeExecutor;
| |||
class CPaperTrading;
| |||
class CEnhancedSecurity;
| |||
| |||
// Include our custom components from Include/Experts directory
| |||
#include <Experts/RiskManager.mqh>
| |||
#include <Experts/TradeExecutor.mqh>
| |||
#include <Experts/PaperTrading.mqh>
| |||
#include <Experts/EnhancedSecurity.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
| |||
};
| |||
| |||
//--- Global Variables
| |||
// 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
| |||
CPaperTrading *ExtPaperTrading = NULL; // Paper trading system
| |||
CEnhancedSecurity *ExtSecurity = NULL; // Security manager
| |||
| |||
// 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
| |||
| |||
// Chart Objects
| |||
#define OBJ_PREFIX "EscapeEA_" // Prefix for chart objects
| |||
| |||
//--- Strategy Parameters
| |||
input group "=== Strategy Settings ==="
| |||
input ENUM_TIMEFRAMES InpTimeframe = PERIOD_M15; // Chart timeframe
| |||
input int InpMAPeriod = 20; // MA Period
| |||
input int InpMAFastPeriod = 10; // Fast MA Period
| |||
input int InpMASlowPeriod = 50; // Slow MA Period
| |||
input int InpATRPeriod = 14; // ATR Period for volatility
| |||
input double InpATRMultiplier = 2.0; // ATR Multiplier for SL/TP
| |||
| |||
//--- Risk Management
| |||
input group "=== Risk Management ==="
| |||
input double InpRiskPerTrade = 1.0; // Risk per trade (% of balance)
| |||
input bool InpUseFixedLot = false; // Use fixed lot size
| |||
input double InpLotSize = 0.1; // Fixed lot size (if UseFixedLot = true)
| |||
input double InpMaxLotSize = 10.0; // Maximum lot size
| |||
input int InpMaxOpenTrades = 5; // Maximum number of open trades
| |||
input bool InpHedgeAllowed = false; // Allow hedging positions
| |||
input double InpMaxDailyLoss = 5.0; // Max daily loss (% of balance)
| |||
input double InpMaxPortfolioRisk = 20.0; // Max portfolio risk (%)
| |||
input double InpMaxLeverage = 30.0; // Maximum leverage (1:30 by default)
| |||
| |||
//--- Trade Execution
| |||
input group "=== Trade Execution ==="
| |||
input int InpMaxSlippage = 10; // Maximum allowed slippage (points)
| |||
input bool InpUseTrailingStop = true; // Use Trailing Stop
| |||
input int InpTrailingStop = 50; // Trailing Stop in points
| |||
input int InpTrailingStep = 10; // Trailing Step in points
| |||
input bool InpUseBreakeven = true; // Use breakeven after reaching target
| |||
input int InpBreakevenPoints = 30; // Points in profit to activate breakeven
| |||
input bool InpUsePartialFills = true; // Allow partial order fills
| |||
input int InpMaxOrderRetries = 3; // Maximum order retry attempts
| |||
input int InpOrderRetryDelay = 100; // Delay between retries (ms)
| |||
| |||
//--- Time Filters
| |||
input group "=== Time Filters ==="
| |||
input bool InpUseTimeFilter = false; // Use Time Filter
| |||
input int InpStartHour = 8; // Trading Start Hour (server time)
| |||
input int InpEndHour = 20; // Trading End Hour (server time)
| |||
input bool InpFridayClose = true; // Close on Friday
| |||
input int InpFridayCloseHour = 16; // Friday Close Hour (server time)
| |||
| |||
//--- Notifications
| |||
input group "=== Notifications ==="
| |||
input bool InpUseSound = true; // Use Sound Alerts
| |||
input string InpSoundFile = "alert.wav"; // Sound File
| |||
input bool InpSendEmail = false; // Send email notifications
| |||
input bool InpSendPush = false; // Send push notifications
| |||
| |||
//--- Paper Trading
| |||
input group "=== Paper Trading ==="
| |||
input bool InpEnablePaperTrading = true; // Enable paper trading
| |||
input int InpPaperTradesRequired = 5; // Total paper trades to evaluate
| |||
input int InpPaperWinsRequired = 3; // Required wins for live trading
| |||
input double InpPaperInitialBalance = 10000.0; // Initial paper balance
| |||
input bool InpSimulateSlippage = true; // Simulate slippage in paper trading
| |||
input bool InpSimulatePartialFills = true; // Simulate partial fills
| |||
input double InpMaxSlippagePips = 1.0; // Max slippage in pips
| |||
input int InpFillProbability = 90; // Fill probability (%)
| |||
| |||
//--- Security Settings
| |||
input group "=== Security Settings ==="
| |||
input bool InpEnableSecurity = true; // Enable security features
| |||
input int InpMaxOrderRate = 10; // Max orders per minute
| |||
input bool InpEnableTamperDetection = true; // Enable tamper detection
| |||
input bool InpEnableRateLimiting = true; // Enable rate limiting
| |||
input int InpMaxDailyTrades = 50; // Max trades per day
| |||
| |||
//--- Indicator Handles
| |||
int ExtHandleMA = INVALID_HANDLE; // MA indicator handle
| |||
int ExtHandleFastMA = INVALID_HANDLE; // Fast MA indicator handle
| |||
int ExtHandleSlowMA = INVALID_HANDLE; // Slow MA indicator handle
| |||
int ExtHandleATR = INVALID_HANDLE; // ATR indicator handle
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Expert initialization function |
| |||
//+------------------------------------------------------------------+
| |||
int OnInit()
| |||
{
| |||
// Initialize random seed
| |||
MathSrand(GetTickCount());
| |||
| |||
// Initialize symbol info
| |||
if(!ExtSymbol.Name(_Symbol)) {
| |||
Print("Failed to initialize symbol info");
| |||
return INIT_FAILED;
| |||
}
| |||
ExtSymbol.RefreshRates();
| |||
| |||
// Initialize trade object
| |||
ExtTrade = new CTrade();
| |||
if(ExtTrade == NULL) {
| |||
Print("Failed to create trade object");
| |||
return INIT_FAILED;
| |||
}
| |||
ExtTrade.SetDeviationInPoints(InpMaxSlippage);
| |||
ExtTrade.SetTypeFilling(ORDER_FILLING_FOK);
| |||
| |||
// Initialize security manager
| |||
if(InpEnableSecurity) {
| |||
ExtSecurity = new CEnhancedSecurity();
| |||
if(ExtSecurity == NULL) {
| |||
Print("Failed to create security manager");
| |||
return INIT_FAILED;
| |||
}
| |||
| |||
if(!ExtSecurity.Initialize(&ExtAccount)) {
| |||
Print("Failed to initialize security manager");
| |||
return INIT_FAILED;
| |||
}
| |||
}
| |||
| |||
// Initialize risk manager
| |||
ExtRiskManager = new CRiskManager();
| |||
if(ExtRiskManager == NULL) {
| |||
Print("Failed to create risk manager");
| |||
return INIT_FAILED;
| |||
}
| |||
| |||
if(!ExtRiskManager.Initialize(&ExtSymbol, &ExtAccount)) {
| |||
Print("Failed to initialize risk manager");
| |||
return INIT_FAILED;
| |||
}
| |||
| |||
// Initialize paper trading system
| |||
if(InpEnablePaperTrading) {
| |||
ExtPaperTrading = new CPaperTrading();
| |||
if(ExtPaperTrading == NULL) {
| |||
Print("Failed to create paper trading system");
| |||
return INIT_FAILED;
| |||
}
| |||
| |||
// Initialize paper trading with symbol info and parameters
| |||
if(!ExtPaperTrading->Initialize(&ExtSymbol, InpPaperInitialBalance,
| |||
InpSimulateSlippage, InpSimulatePartialFills,
| |||
InpMaxSlippagePips, InpFillProbability/100.0)) {
| |||
Print("Failed to initialize paper trading");
| |||
return INIT_FAILED;
| |||
}
| |||
| |||
ExtPaperTradingActive = true;
| |||
Print("Paper trading mode activated");
| |||
}
| |||
| |||
// Initialize indicators
| |||
ExtHandleMA = iMA(_Symbol, InpTimeframe, InpMAPeriod, 0, MODE_SMA, PRICE_CLOSE);
| |||
ExtHandleFastMA = iMA(_Symbol, InpTimeframe, InpMAFastPeriod, 0, MODE_EMA, PRICE_CLOSE);
| |||
ExtHandleSlowMA = iMA(_Symbol, InpTimeframe, InpMASlowPeriod, 0, MODE_EMA, PRICE_CLOSE);
| |||
ExtHandleATR = iATR(_Symbol, InpTimeframe, InpATRPeriod);
| |||
| |||
if(ExtHandleMA == INVALID_HANDLE || ExtHandleFastMA == INVALID_HANDLE ||
| |||
ExtHandleSlowMA == INVALID_HANDLE || ExtHandleATR == INVALID_HANDLE) {
| |||
Print("Failed to create indicator handles");
| |||
return INIT_FAILED;
| |||
}
| |||
| |||
// Set up timer for periodic updates (every 1 second)
| |||
ExtTimerId = EventSetTimer(1);
| |||
if(ExtTimerId == -1) {
| |||
Print("Warning: Failed to create timer, continuing without timer updates");
| |||
}
| |||
| |||
// Initialize chart objects for visualization
| |||
if(!InitializeChartObjects()) {
| |||
Print("Warning: Failed to initialize chart objects");
| |||
}
| |||
| |||
// Log successful initialization
| |||
Print("=== ", EXPERT_NAME, " v", EXPERT_VERSION, " ===");
| |||
Print("Symbol: ", _Symbol, " | Timeframe: ", EnumToString(InpTimeframe));
| |||
Print("Account: ", ExtAccount.Login(), " | Balance: ", ExtAccount.Balance());
| |||
Print("Risk per trade: ", InpRiskPerTrade, "% | Max daily loss: ", InpMaxDailyLoss, "%");
| |||
| |||
if(ExtPaperTradingActive) {
| |||
Print("=== PAPER TRADING MODE ACTIVE ===");
| |||
Print("Initial balance: ", InpPaperInitialBalance);
| |||
Print("Required wins for live trading: ", InpPaperWinsRequired,
| |||
" out of ", InpPaperTradesRequired);
| |||
} else {
| |||
Print("=== LIVE TRADING MODE ACTIVE ===");
| |||
}
| |||
| |||
Print("Expert initialized successfully");
| |||
return INIT_SUCCEEDED;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Check if trading is allowed |
| |||
//+------------------------------------------------------------------+
| |||
bool IsTradingAllowed()
| |||
{
| |||
// Check if EA is properly initialized
| |||
if(!ExtIsTradingAllowed) {
| |||
return false;
| |||
}
| |||
| |||
// Check if market is open
| |||
if(!ExtSymbol.IsTradeAllowed()) {
| |||
return false;
| |||
}
| |||
| |||
// Check if we're in the strategy tester
| |||
if(MQLInfoInteger(MQL_TESTER) || MQLInfoInteger(MQL_VISUAL_MODE) || MQLInfoInteger(MQL_OPTIMIZATION)) {
| |||
return true;
| |||
}
| |||
| |||
// Check if we're connected to the server
| |||
if(!TerminalInfoInteger(TERMINAL_CONNECTED)) {
| |||
Print("No connection to the server");
| |||
return false;
| |||
}
| |||
| |||
// Check if expert is allowed to trade
| |||
if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) {
| |||
Print("Trading is not allowed in the terminal settings");
| |||
return false;
| |||
}
| |||
| |||
// Check if auto-trading is allowed
| |||
if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) {
| |||
Print("AutoTrading is not allowed in the terminal settings");
| |||
return false;
| |||
}
| |||
| |||
// Check if the symbol is selected in MarketWatch
| |||
if(!SymbolSelect(_Symbol, true)) {
| |||
Print(_Symbol, " is not selected in MarketWatch");
| |||
return false;
| |||
}
| |||
| |||
// Check if the symbol is visible on the chart
| |||
if(!SymbolInfoInteger(_Symbol, SYMBOL_VISIBLE)) {
| |||
Print(_Symbol, " is not visible on the chart");
| |||
return false;
| |||
}
| |||
| |||
// Check if the symbol is tradeable
| |||
if(SymbolInfoInteger(_Symbol, SYMBOL_TRADE_MODE) == SYMBOL_TRADE_MODE_DISABLED) {
| |||
Print(_Symbol, " trading is disabled");
| |||
return false;
| |||
}
| |||
| |||
return true;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Check if we can open new positions |
| |||
//+------------------------------------------------------------------+
| |||
bool CanOpenNewPosition()
| |||
{
| |||
// Check if trading is allowed
| |||
if(!IsTradingAllowed()) {
| |||
return false;
| |||
}
| |||
| |||
// Check if we've reached the maximum number of open positions
| |||
if(PositionsTotal() >= InpMaxOpenTrades) {
| |||
return false;
| |||
}
| |||
| |||
// Check if we've exceeded the daily trade limit
| |||
if(ExtOrderCount >= InpMaxOrderRate) {
| |||
datetime now = TimeCurrent();
| |||
if(now - ExtLastOrderCountReset >= 60) { // Reset counter every minute
| |||
ExtOrderCount = 0;
| |||
ExtLastOrderCountReset = now;
| |||
} else {
| |||
return false;
| |||
}
| |||
}
| |||
| |||
// Check if we've exceeded the maximum daily loss
| |||
if(ExtRiskManager != NULL) {
| |||
double dailyProfit = ExtAccount.Profit() - ExtAccount.Balance() + ExtAccount.Equity();
| |||
double maxDailyLoss = ExtAccount.Balance() * (InpMaxDailyLoss / 100.0);
| |||
| |||
if(dailyProfit <= -maxDailyLoss) {
| |||
Print("Daily loss limit reached");
| |||
return false;
| |||
}
| |||
}
| |||
| |||
return true;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Check for trading signals |
| |||
//+------------------------------------------------------------------+
| |||
ENUM_ORDER_TYPE CheckTradingSignals()
| |||
{
| |||
// Get current market conditions
| |||
double ma, fastMA, slowMA, atr;
| |||
if(!GetMarketConditions(ma, fastMA, slowMA, atr)) {
| |||
return WRONG_VALUE;
| |||
}
| |||
| |||
// Get current price
| |||
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
| |||
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
| |||
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
| |||
| |||
// Check for buy signal (fast MA crosses above slow MA)
| |||
if(fastMA > slowMA && ask > ma + (atr * 0.5)) {
| |||
// Additional confirmation: price is above the MA
| |||
return ORDER_TYPE_BUY;
| |||
}
| |||
| |||
// Check for sell signal (fast MA crosses below slow MA)
| |||
if(fastMA < slowMA && bid < ma - (atr * 0.5)) {
| |||
// Additional confirmation: price is below the MA
| |||
return ORDER_TYPE_SELL;
| |||
}
| |||
| |||
return WRONG_VALUE;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Manage open positions |
| |||
//+------------------------------------------------------------------+
| |||
void ManagePositions()
| |||
{
| |||
if(!InpUseTrailingStop && !InpUseBreakeven) {
| |||
return; // No position management needed
| |||
}
| |||
| |||
if(ExtTradeExecutor == NULL) {
| |||
Print("Error: Trade Executor not initialized in ManagePositions()");
| |||
return;
| |||
}
| |||
| |||
for(int i = PositionsTotal() - 1; i >= 0; i--) {
| |||
if(ExtPosition.SelectByIndex(i)) {
| |||
if(ExtPosition.Symbol() != _Symbol) {
| |||
continue; // Skip positions for other symbols
| |||
}
| |||
| |||
double currentBid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
| |||
double currentAsk = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
| |||
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
| |||
| |||
// Get position details
| |||
ulong ticket = ExtPosition.Ticket();
| |||
double openPrice = ExtPosition.PriceOpen();
| |||
double currentSL = ExtPosition.StopLoss();
| |||
double currentTP = ExtPosition.TakeProfit();
| |||
| |||
// Calculate new stop loss for trailing stop
| |||
if(InpUseTrailingStop && ExtPosition.PositionType() == POSITION_TYPE_BUY) {
| |||
double newSL = NormalizeDouble(currentBid - InpTrailingStop * point, _Digits);
| |||
| |||
// Only move stop loss up
| |||
if(newSL > currentSL + (InpTrailingStep * point)) {
| |||
ExtTradeExecutor->ModifyPosition(ticket, newSL, currentTP);
| |||
}
| |||
}
| |||
else if(InpUseTrailingStop && ExtPosition.PositionType() == POSITION_TYPE_SELL) {
| |||
double newSL = NormalizeDouble(currentAsk + InpTrailingStop * point, _Digits);
| |||
| |||
// Only move stop loss down
| |||
if(newSL < currentSL - (InpTrailingStep * point) || currentSL == 0) {
| |||
ExtTradeExecutor->ModifyPosition(ticket, newSL, currentTP);
| |||
}
| |||
}
| |||
| |||
// Check for breakeven
| |||
if(InpUseBreakeven) {
| |||
double profitInPoints = 0;
| |||
| |||
if(ExtPosition.PositionType() == POSITION_TYPE_BUY) {
| |||
profitInPoints = (currentBid - openPrice) / point;
| |||
| |||
if(profitInPoints >= InpBreakevenPoints &&
| |||
(currentSL < openPrice || currentSL == 0)) {
| |||
double newSL = openPrice + (point * 10); // Small buffer above entry
| |||
ExtTradeExecutor->ModifyPosition(ticket, newSL, currentTP);
| |||
}
| |||
}
| |||
else if(ExtPosition.PositionType() == POSITION_TYPE_SELL) {
| |||
profitInPoints = (openPrice - currentAsk) / point;
| |||
| |||
if(profitInPoints >= InpBreakevenPoints &&
| |||
(currentSL > openPrice || currentSL == 0)) {
| |||
double newSL = openPrice - (point * 10); // Small buffer below entry
| |||
ExtTradeExecutor->ModifyPosition(ticket, newSL, currentTP);
| |||
}
| |||
}
| |||
}
| |||
}
| |||
}
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Initialize chart objects |
| |||
//+------------------------------------------------------------------+
| |||
bool InitializeChartObjects()
| |||
{
| |||
// Remove any existing objects
| |||
ObjectsDeleteAll(0, OBJ_PREFIX);
| |||
| |||
// Create info panel background
| |||
if(!ObjectCreate(0, OBJ_PREFIX + "Panel", OBJ_RECTANGLE_LABEL, 0, 0, 0)) {
| |||
Print("Failed to create panel object");
| |||
return false;
| |||
}
| |||
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Panel", OBJPROP_XDISTANCE, 20);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Panel", OBJPROP_YDISTANCE, 20);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Panel", OBJPROP_XSIZE, 200);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Panel", OBJPROP_YSIZE, 150);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Panel", OBJPROP_BGCOLOR, clrWhiteSmoke);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Panel", OBJPROP_BORDER_TYPE, BORDER_FLAT);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Panel", OBJPROP_CORNER, CORNER_LEFT_UPPER);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Panel", OBJPROP_COLOR, clrDimGray);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Panel", OBJPROP_BACK, false);
| |||
| |||
// Create title label
| |||
if(!ObjectCreate(0, OBJ_PREFIX + "Title", OBJ_LABEL, 0, 0, 0)) {
| |||
Print("Failed to create title object");
| |||
return false;
| |||
}
| |||
| |||
ObjectSetString(0, OBJ_PREFIX + "Title", OBJPROP_TEXT, EXPERT_NAME + " v" + EXPERT_VERSION);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Title", OBJPROP_XDISTANCE, 30);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Title", OBJPROP_YDISTANCE, 30);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Title", OBJPROP_COLOR, clrBlack);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Title", OBJPROP_FONTSIZE, 10);
| |||
| |||
// Create mode label
| |||
if(!ObjectCreate(0, OBJ_PREFIX + "Mode", OBJ_LABEL, 0, 0, 0)) {
| |||
Print("Failed to create mode object");
| |||
return false;
| |||
}
| |||
| |||
ObjectSetString(0, OBJ_PREFIX + "Mode", OBJPROP_TEXT, "Mode: " + (ExtPaperTradingActive ? "PAPER" : "LIVE"));
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Mode", OBJPROP_XDISTANCE, 30);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Mode", OBJPROP_YDISTANCE, 50);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Mode", OBJPROP_COLOR, ExtPaperTradingActive ? clrBlue : clrGreen);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Mode", OBJPROP_FONTSIZE, 9);
| |||
| |||
// Create balance label
| |||
if(!ObjectCreate(0, OBJ_PREFIX + "Balance", OBJ_LABEL, 0, 0, 0)) {
| |||
Print("Failed to create balance object");
| |||
return false;
| |||
}
| |||
| |||
ObjectSetString(0, OBJ_PREFIX + "Balance", OBJPROP_TEXT, "Balance: " + DoubleToString(ExtAccount.Balance(), 2));
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Balance", OBJPROP_XDISTANCE, 30);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Balance", OBJPROP_YDISTANCE, 70);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Balance", OBJPROP_COLOR, clrBlack);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Balance", OBJPROP_FONTSIZE, 9);
| |||
| |||
// Create equity label
| |||
if(!ObjectCreate(0, OBJ_PREFIX + "Equity", OBJ_LABEL, 0, 0, 0)) {
| |||
Print("Failed to create equity object");
| |||
return false;
| |||
}
| |||
| |||
ObjectSetString(0, OBJ_PREFIX + "Equity", OBJPROP_TEXT, "Equity: " + DoubleToString(ExtAccount.Equity(), 2));
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Equity", OBJPROP_XDISTANCE, 30);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Equity", OBJPROP_YDISTANCE, 90);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Equity", OBJPROP_COLOR, clrBlack);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Equity", OBJPROP_FONTSIZE, 9);
| |||
| |||
// Create profit label
| |||
if(!ObjectCreate(0, OBJ_PREFIX + "Profit", OBJ_LABEL, 0, 0, 0)) {
| |||
Print("Failed to create profit object");
| |||
return false;
| |||
}
| |||
| |||
double profit = ExtAccount.Profit();
| |||
color profitColor = profit >= 0 ? clrGreen : clrRed;
| |||
| |||
ObjectSetString(0, OBJ_PREFIX + "Profit", OBJPROP_TEXT, "Profit: " + DoubleToString(profit, 2));
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Profit", OBJPROP_XDISTANCE, 30);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Profit", OBJPROP_YDISTANCE, 110);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Profit", OBJPROP_COLOR, profitColor);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Profit", OBJPROP_FONTSIZE, 9);
| |||
| |||
// Create status label
| |||
if(!ObjectCreate(0, OBJ_PREFIX + "Status", OBJ_LABEL, 0, 0, 0)) {
| |||
Print("Failed to create status object");
| |||
return false;
| |||
}
| |||
| |||
ObjectSetString(0, OBJ_PREFIX + "Status", OBJPROP_TEXT, "Status: Ready");
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Status", OBJPROP_XDISTANCE, 30);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Status", OBJPROP_YDISTANCE, 130);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Status", OBJPROP_COLOR, clrBlack);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Status", OBJPROP_FONTSIZE, 9);
| |||
| |||
// Create signal objects (initially hidden)
| |||
if(!ObjectCreate(0, OBJ_PREFIX + "Signal_Buy", OBJ_ARROW_BUY, 0, 0, 0)) {
| |||
Print("Failed to create buy signal object");
| |||
return false;
| |||
}
| |||
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Signal_Buy", OBJPROP_TIME, 0);
| |||
ObjectSetDouble(0, OBJ_PREFIX + "Signal_Buy", OBJPROP_PRICE, 0);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Signal_Buy", OBJPROP_COLOR, clrLime);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Signal_Buy", OBJPROP_WIDTH, 2);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Signal_Buy", OBJPROP_HIDDEN, true);
| |||
| |||
if(!ObjectCreate(0, OBJ_PREFIX + "Signal_Sell", OBJ_ARROW_SELL, 0, 0, 0)) {
| |||
Print("Failed to create sell signal object");
| |||
return false;
| |||
}
| |||
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Signal_Sell", OBJPROP_TIME, 0);
| |||
ObjectSetDouble(0, OBJ_PREFIX + "Signal_Sell", OBJPROP_PRICE, 0);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Signal_Sell", OBJPROP_COLOR, clrRed);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Signal_Sell", OBJPROP_WIDTH, 2);
| |||
ObjectSetInteger(0, OBJ_PREFIX + "Signal_Sell", OBJPROP_HIDDEN, true);
| |||
| |||
// Update the chart
| |||
ChartRedraw();
| |||
| |||
return true;
| |||
}
| |||
| |||
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Remove all chart objects |
| |||
//+------------------------------------------------------------------+
| |||
void RemoveChartObjects()
| |||
{
| |||
ObjectsDeleteAll(0, OBJ_PREFIX);
| |||
ChartRedraw();
| |||
}
| |||
| |||
| |||
| |||
// This code should be inside a function, not in global scope
| |||
}
| |||
}
| |||
| |||
// Removed duplicate OnTimer function - keeping the more comprehensive one below
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Update account information |
| |||
//+------------------------------------------------------------------+
| |||
void ExtAccountInfo()
| |||
{
| |||
// This is a placeholder for account info updates
| |||
// The actual account info is accessed directly from the CAccountInfo object
| |||
// This function is called periodically to refresh the display
| |||
| |||
// Update the account info object
| |||
ExtAccount.RefreshRates();
| |||
| |||
// Update the symbol info
| |||
ExtSymbol.RefreshRates();
| |||
| |||
// Update the position info
| |||
ExtPosition.Select(_Symbol);
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Execute trade based on signal |
| |||
//+------------------------------------------------------------------+
| |||
bool ExecuteTrade(ENUM_ORDER_TYPE signalType)
| |||
{
| |||
if(signalType == WRONG_VALUE) {
| |||
return false;
| |||
}
| |||
| |||
// Get current market conditions
| |||
double ma, fastMA, slowMA, atr;
| |||
if(!GetMarketConditions(ma, fastMA, slowMA, atr)) {
| |||
return false;
| |||
}
| |||
| |||
// Calculate position size based on risk
| |||
double stopLossPips = atr * 2.0; // 2x ATR for stop loss
| |||
double lotSize = ExtRiskManager.CalculatePositionSize(stopLossPips);
| |||
| |||
if(lotSize <= 0) {
| |||
Print("Invalid lot size calculated: ", lotSize);
| |||
return false;
| |||
}
| |||
| |||
// Calculate stop loss and take profit levels
| |||
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
| |||
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
| |||
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
| |||
double stopLoss = 0, takeProfit = 0;
| |||
| |||
if(signalType == ORDER_TYPE_BUY) {
| |||
stopLoss = NormalizeDouble(bid - stopLossPips * point, _Digits);
| |||
takeProfit = NormalizeDouble(ask + (stopLossPips * 1.5 * point), _Digits);
| |||
} else {
| |||
stopLoss = NormalizeDouble(ask + stopLossPips * point, _Digits);
| |||
takeProfit = NormalizeDouble(bid - (stopLossPips * 1.5 * point), _Digits);
| |||
}
| |||
| |||
// Execute the trade
| |||
bool result = false;
| |||
string comment = StringFormat("%s v%s | %s", EXPERT_NAME, EXPERT_VERSION, EnumToString(signalType));
| |||
| |||
if(ExtPaperTradingActive && ExtPaperTrading != NULL) {
| |||
// Execute paper trade
| |||
result = ExtPaperTrading->OpenPosition(
| |||
(signalType == ORDER_TYPE_BUY) ? ORDER_TYPE_BUY : ORDER_TYPE_SELL,
| |||
lotSize,
| |||
(signalType == ORDER_TYPE_BUY) ? ask : bid,
| |||
stopLoss,
| |||
takeProfit,
| |||
comment
| |||
);
| |||
| |||
if(result) {
| |||
Print("Paper trade executed: ", EnumToString(signalType), " ", lotSize, " lots");
| |||
| |||
// Check if we can switch to live trading
| |||
if(ExtPaperTrading->GetWinningTrades() >= InpPaperWinsRequired &&
| |||
ExtPaperTrading->GetTotalTrades() >= InpPaperTradesRequired) {
| |||
ExtPaperTradingActive = false;
| |||
Print("=== SWITCHING TO LIVE TRADING ===");
| |||
Print("Paper trading requirements met");
| |||
Print("Total Trades: ", ExtPaperTrading->GetTotalTrades());
| |||
Print("Winning Trades: ", ExtPaperTrading->GetWinningTrades());
| |||
Print("Win Rate: ", DoubleToString(ExtPaperTrading->GetWinRate(), 2), "%");
| |||
}
| |||
}
| |||
} else if(ExtTradeExecutor != NULL) {
| |||
// Execute live trade
| |||
if(signalType == ORDER_TYPE_BUY) {
| |||
result = ExtTradeExecutor->Buy(lotSize, ask, stopLoss, takeProfit, comment);
| |||
} else {
| |||
result = ExtTradeExecutor->Sell(lotSize, bid, stopLoss, takeProfit, comment);
| |||
}
| |||
| |||
if(result) {
| |||
ExtOrderCount++;
| |||
ExtLastOrderTime = TimeCurrent();
| |||
Print("Live trade executed: ", EnumToString(signalType), " ", lotSize, " lots");
| |||
} else {
| |||
Print("Failed to execute trade: ", ExtTradeExecutor->GetLastErrorMsg());
| |||
}
| |||
}
| |||
| |||
return result;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Get current market conditions |
| |||
//+------------------------------------------------------------------+
| |||
bool GetMarketConditions(double &ma, double &fastMA, double &slowMA, double &atr)
| |||
{
| |||
// Get MA values
| |||
double maBuffer[];
| |||
ArraySetAsSeries(maBuffer, true);
| |||
| |||
// Get current MA values
| |||
if(CopyBuffer(ExtHandleMA, 0, 0, 2, maBuffer) != 2) {
| |||
Print("Error getting MA values");
| |||
return false;
| |||
}
| |||
ma = maBuffer[1]; // Previous bar's MA
| |||
| |||
// Get fast MA values
| |||
if(CopyBuffer(ExtHandleFastMA, 0, 0, 2, maBuffer) != 2) {
| |||
Print("Error getting Fast MA values");
| |||
return false;
| |||
}
| |||
fastMA = maBuffer[1];
| |||
| |||
// Get slow MA values
| |||
if(CopyBuffer(ExtHandleSlowMA, 0, 0, 2, maBuffer) != 2) {
| |||
Print("Error getting Slow MA values");
| |||
return false;
| |||
}
| |||
slowMA = maBuffer[1];
| |||
| |||
// Get ATR value
| |||
double atrBuffer[];
| |||
ArraySetAsSeries(atrBuffer, true);
| |||
if(CopyBuffer(ExtHandleATR, 0, 0, 1, atrBuffer) != 1) {
| |||
Print("Error getting ATR value");
| |||
return false;
| |||
}
| |||
atr = atrBuffer[0];
| |||
| |||
return true;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Expert deinitialization function |
| |||
//+------------------------------------------------------------------+
| |||
void OnDeinit(const int reason)
| |||
{
| |||
// Stop the timer
| |||
if(ExtTimerId != -1) {
| |||
EventKillTimer(ExtTimerId);
| |||
ExtTimerId = -1;
| |||
}
| |||
| |||
// Clean up components
| |||
if(ExtSecurity != NULL) {
| |||
delete ExtSecurity;
| |||
ExtSecurity = NULL;
| |||
}
| |||
| |||
if(ExtPaperTrading != NULL) {
| |||
delete ExtPaperTrading;
| |||
ExtPaperTrading = NULL;
| |||
}
| |||
| |||
if(ExtTradeExecutor != NULL) {
| |||
delete ExtTradeExecutor;
| |||
ExtTradeExecutor = NULL;
| |||
}
| |||
| |||
if(ExtRiskManager != NULL) {
| |||
delete ExtRiskManager;
| |||
ExtRiskManager = NULL;
| |||
}
| |||
| |||
// Remove all chart objects
| |||
ObjectsDeleteAll(0, OBJ_PREFIX);
| |||
| |||
// Release indicator handles
| |||
if(ExtHandleMA != INVALID_HANDLE) {
| |||
IndicatorRelease(ExtHandleMA);
| |||
ExtHandleMA = INVALID_HANDLE;
| |||
}
| |||
if(ExtHandleFastMA != INVALID_HANDLE) {
| |||
IndicatorRelease(ExtHandleFastMA);
| |||
ExtHandleFastMA = INVALID_HANDLE;
| |||
}
| |||
if(ExtHandleSlowMA != INVALID_HANDLE) {
| |||
IndicatorRelease(ExtHandleSlowMA);
| |||
ExtHandleSlowMA = INVALID_HANDLE;
| |||
}
| |||
if(ExtHandleATR != INVALID_HANDLE) {
| |||
IndicatorRelease(ExtHandleATR);
| |||
ExtHandleATR = INVALID_HANDLE;
| |||
}
| |||
| |||
// Clean up dynamically allocated objects
| |||
if(ExtTrade != NULL) {
| |||
delete ExtTrade;
| |||
ExtTrade = NULL;
| |||
}
| |||
| |||
if(ExtTradeExecutor != NULL) {
| |||
delete ExtTradeExecutor;
| |||
ExtTradeExecutor = NULL;
| |||
}
| |||
| |||
if(ExtRiskManager != NULL) {
| |||
delete ExtRiskManager;
| |||
ExtRiskManager = NULL;
| |||
}
| |||
| |||
if(ExtPaperTrading != NULL) {
| |||
delete ExtPaperTrading;
| |||
ExtPaperTrading = NULL;
| |||
}
| |||
| |||
if(ExtSecurity != NULL) {
| |||
delete ExtSecurity;
| |||
ExtSecurity = NULL;
| |||
}
| |||
| |||
// Remove chart objects
| |||
RemoveChartObjects();
| |||
| |||
// Log shutdown information
| |||
string reasonText;
| |||
switch(reason) {
| |||
case REASON_PROGRAM: reasonText = "Program"; break;
| |||
case REASON_REMOVE: reasonText = "Removed from chart"; break;
| |||
case REASON_RECOMPILE: reasonText = "Recompiled"; break;
| |||
case REASON_CHARTCHANGE:reasonText = "Chart changed"; break;
| |||
case REASON_CHARTCLOSE: reasonText = "Chart closed"; break;
| |||
case REASON_PARAMETERS: reasonText = "Input parameters changed"; break;
| |||
case REASON_ACCOUNT: reasonText = "Account changed"; break;
| |||
default: reasonText = "Unknown";
| |||
}
| |||
| |||
// Log final statistics
| |||
if(ExtTotalTrades > 0) {
| |||
double winRate = (double)ExtWinningTrades / ExtTotalTrades * 100.0;
| |||
PrintFormat("Trading statistics: %d trades, %.2f%% win rate, %.2f total profit",
| |||
ExtTotalTrades, winRate, ExtTotalProfit);
| |||
}
| |||
| |||
Print(EXPERT_NAME, " v", EXPERT_VERSION, " deinitialized (Reason: ", reasonText, ")");
| |||
| |||
// Release indicators
| |||
if(ExtHandleMA != INVALID_HANDLE) IndicatorRelease(ExtHandleMA);
| |||
if(ExtHandleFastMA != INVALID_HANDLE) IndicatorRelease(ExtHandleFastMA);
| |||
if(ExtHandleSlowMA != INVALID_HANDLE) IndicatorRelease(ExtHandleSlowMA);
| |||
if(ExtHandleATR != INVALID_HANDLE) IndicatorRelease(ExtHandleATR);
| |||
| |||
// Clean up paper trading
| |||
if(ExtPaperTrading != NULL) {
| |||
ExtPaperTrading->Deinitialize();
| |||
delete ExtPaperTrading;
| |||
ExtPaperTrading = NULL;
| |||
}
| |||
| |||
// Clean up security manager
| |||
if(ExtSecurity != NULL) {
| |||
ExtSecurity->Deinitialize();
| |||
delete ExtSecurity;
| |||
ExtSecurity = NULL;
| |||
}
| |||
| |||
// Clear chart objects
| |||
ObjectsDeleteAll(0, "EscapeEA_");
| |||
ChartRedraw();
| |||
| |||
Print("EscapeEA Enhanced deinitialized");
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Expert tick function |
| |||
//+------------------------------------------------------------------+
| |||
void OnTick()
| |||
{
| |||
// Update market data
| |||
ExtSymbol.RefreshRates();
| |||
| |||
// Skip if not enough bars
| |||
if(Bars(_Symbol, InpTimeframe) < InpMAPeriod + 1) {
| |||
Print("Not enough bars");
| |||
return;
| |||
}
| |||
| |||
// Check if trading is allowed
| |||
if(!IsTradingAllowed()) {
| |||
return;
| |||
}
| |||
| |||
// Update paper trading system
| |||
if(ExtPaperTrading != NULL) {
| |||
ExtPaperTrading->Update();
| |||
| |||
// Check if we can switch to live trading
| |||
if(ExtPaperTradingActive && ExtPaperTrading->IsLiveTradingAllowed()) {
| |||
ExtPaperTradingActive = false;
| |||
Print("Switching to LIVE TRADING mode!");
| |||
| |||
// Optional: Play sound or send notification
| |||
if(InpUseSound) PlaySound(InpSoundFile);
| |||
if(InpSendEmail) SendMail("EscapeEA: Live Trading Activated",
| |||
"Paper trading completed successfully.\n" +
| |||
"Win rate: " + DoubleToString(ExtPaperTrading->GetWinRate(), 1) + "%\n" +
| |||
"Switching to LIVE TRADING mode.");
| |||
}
| |||
}
| |||
| |||
// Get indicator values
| |||
double ma[], fastMA[], slowMA[], atr[];
| |||
ArraySetAsSeries(ma, true);
| |||
ArraySetAsSeries(fastMA, true);
| |||
ArraySetAsSeries(slowMA, true);
| |||
ArraySetAsSeries(atr, true);
| |||
| |||
if(CopyBuffer(ExtHandleMA, 0, 0, 3, ma) <= 0 ||
| |||
CopyBuffer(ExtHandleFastMA, 0, 0, 3, fastMA) <= 0 ||
| |||
CopyBuffer(ExtHandleSlowMA, 0, 0, 3, slowMA) <= 0 ||
| |||
CopyBuffer(ExtHandleATR, 0, 0, 1, atr) <= 0) {
| |||
Print("Error copying indicator buffers");
| |||
return;
| |||
}
| |||
| |||
// Check for trading signals
| |||
bool buySignal = (fastMA[1] > slowMA[1] && fastMA[2] <= slowMA[2]); // Fast MA crosses above Slow MA
| |||
bool sellSignal = (fastMA[1] < slowMA[1] && fastMA[2] >= slowMA[2]); // Fast MA crosses below Slow MA
| |||
| |||
// Calculate position size based on ATR
| |||
double atrValue = atr[0];
| |||
double stopLoss = atrValue * InpATRMultiplier;
| |||
double takeProfit = stopLoss * 2.0; // 1:2 risk-reward ratio
| |||
| |||
// Calculate position size based on risk
| |||
double positionSize = ExtRiskManager->CalculatePositionSize(stopLoss, InpRiskPerTrade);
| |||
positionSize = MathMin(positionSize, InpMaxLotSize);
| |||
| |||
// Execute trades based on signals
| |||
if(buySignal && !HasOpenPosition(POSITION_TYPE_BUY)) {
| |||
double ask = ExtSymbol.Ask();
| |||
double sl = ask - stopLoss * ExtSymbol.Point();
| |||
double tp = ask + takeProfit * ExtSymbol.Point();
| |||
| |||
if(ExtPaperTradingActive) {
| |||
// Execute paper trade
| |||
ExtPaperTrading->OpenPosition(ORDER_TYPE_BUY, positionSize, ask, sl, tp, "Buy Signal");
| |||
} else if(ExtTradeExecutor->OpenPosition(ORDER_TYPE_BUY, positionSize, ask, sl, tp, "Buy Signal")) {
| |||
ExtLastTradeTime = TimeCurrent();
| |||
Print("Buy order executed");
| |||
}
| |||
}
| |||
| |||
if(sellSignal && !HasOpenPosition(POSITION_TYPE_SELL)) {
| |||
double bid = ExtSymbol.Bid();
| |||
double sl = bid + stopLoss * ExtSymbol.Point();
| |||
double tp = bid - takeProfit * ExtSymbol.Point();
| |||
| |||
if(ExtPaperTradingActive) {
| |||
// Execute paper trade
| |||
ExtPaperTrading->OpenPosition(ORDER_TYPE_SELL, positionSize, bid, sl, tp, "Sell Signal");
| |||
} else if(ExtTradeExecutor->OpenPosition(ORDER_TYPE_SELL, positionSize, bid, sl, tp, "Sell Signal")) {
| |||
ExtLastTradeTime = TimeCurrent();
| |||
Print("Sell order executed");
| |||
}
| |||
}
| |||
| |||
// Manage open positions
| |||
ManagePositions();
| |||
| |||
// Update chart
| |||
UpdateChart();
| |||
| |||
ExtIsFirstTick = false;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Timer function - handles periodic updates |
| |||
//+------------------------------------------------------------------+
| |||
void OnTimer()
| |||
{
| |||
static datetime lastUpdate = 0;
| |||
datetime currentTime = TimeCurrent();
| |||
| |||
// Update account information (every 5 seconds)
| |||
if(currentTime - lastUpdate >= 5) {
| |||
// Update account information
| |||
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
| |||
double equity = AccountInfoDouble(ACCOUNT_EQUITY);
| |||
double margin = AccountInfoDouble(ACCOUNT_MARGIN);
| |||
double freeMargin = AccountInfoDouble(ACCOUNT_MARGIN_FREE);
| |||
| |||
// Update risk metrics
| |||
if(ExtRiskManager != NULL) {
| |||
ExtRiskManager->UpdateMetrics();
| |||
}
| |||
| |||
// Update paper trading metrics if active
| |||
if(ExtPaperTradingActive && ExtPaperTrading != NULL) {
| |||
ExtPaperTrading->UpdateMetrics();
| |||
}
| |||
| |||
// Update the display
| |||
UpdateAccountInfoDisplay(balance, equity, margin, freeMargin);
| |||
| |||
lastUpdate = currentTime;
| |||
}
| |||
| |||
// Check for news events (every 30 seconds)
| |||
static datetime lastNewsCheck = 0;
| |||
if(currentTime - lastNewsCheck >= 30) {
| |||
CheckNewsEvents();
| |||
lastNewsCheck = currentTime;
| |||
}
| |||
| |||
// Update visualization (every second)
| |||
UpdateVisualization();
| |||
| |||
// Force chart redraw
| |||
ChartRedraw();
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Update account information display on the chart |
| |||
//+------------------------------------------------------------------+
| |||
void UpdateAccountInfoDisplay(double balance, double equity, double margin, double freeMargin)
| |||
{
| |||
// Create or update account info panel
| |||
string prefix = "EscapeEA_Account_";
| |||
| |||
// Panel background
| |||
ObjectCreate(0, prefix + "BG", OBJ_RECTANGLE_LABEL, 0, 0, 0);
| |||
ObjectSetInteger(0, prefix + "BG", OBJPROP_XDISTANCE, 10);
| |||
ObjectSetInteger(0, prefix + "BG", OBJPROP_YDISTANCE, 70);
| |||
ObjectSetInteger(0, prefix + "BG", OBJPROP_XSIZE, 200);
| |||
ObjectSetInteger(0, prefix + "BG", OBJPROP_YSIZE, 100);
| |||
ObjectSetInteger(0, prefix + "BG", OBJPROP_BGCOLOR, clrWhiteSmoke);
| |||
ObjectSetInteger(0, prefix + "BG", OBJPROP_BORDER_TYPE, BORDER_FLAT);
| |||
ObjectSetInteger(0, prefix + "BG", OBJPROP_CORNER, CORNER_RIGHT_UPPER);
| |||
ObjectSetInteger(0, prefix + "BG", OBJPROP_COLOR, clrDimGray);
| |||
ObjectSetInteger(0, prefix + "BG", OBJPROP_BACK, false);
| |||
| |||
// Panel title
| |||
ObjectCreate(0, prefix + "Title", OBJ_LABEL, 0, 0, 0);
| |||
ObjectSetString(0, prefix + "Title", OBJPROP_TEXT, "ACCOUNT INFO");
| |||
ObjectSetInteger(0, prefix + "Title", OBJPROP_COLOR, clrBlack);
| |||
ObjectSetInteger(0, prefix + "Title", OBJPROP_CORNER, CORNER_RIGHT_UPPER);
| |||
ObjectSetInteger(0, prefix + "Title", OBJPROP_XDISTANCE, 20);
| |||
ObjectSetInteger(0, prefix + "Title", OBJPROP_YDISTANCE, 80);
| |||
ObjectSetInteger(0, prefix + "Title", OBJPROP_FONTSIZE, 10);
| |||
| |||
// Balance
| |||
ObjectCreate(0, prefix + "Balance", OBJ_LABEL, 0, 0, 0);
| |||
ObjectSetString(0, prefix + "Balance", OBJPROP_TEXT, "Balance: " + DoubleToString(balance, 2));
| |||
ObjectSetInteger(0, prefix + "Balance", OBJPROP_COLOR, clrBlack);
| |||
ObjectSetInteger(0, prefix + "Balance", OBJPROP_CORNER, CORNER_RIGHT_UPPER);
| |||
ObjectSetInteger(0, prefix + "Balance", OBJPROP_XDISTANCE, 20);
| |||
ObjectSetInteger(0, prefix + "Balance", OBJPROP_YDISTANCE, 100);
| |||
| |||
// Equity
| |||
ObjectCreate(0, prefix + "Equity", OBJ_LABEL, 0, 0, 0);
| |||
ObjectSetString(0, prefix + "Equity", OBJPROP_TEXT, "Equity: " + DoubleToString(equity, 2));
| |||
ObjectSetInteger(0, prefix + "Equity", OBJPROP_COLOR, clrBlack);
| |||
ObjectSetInteger(0, prefix + "Equity", OBJPROP_CORNER, CORNER_RIGHT_UPPER);
| |||
ObjectSetInteger(0, prefix + "Equity", OBJPROP_XDISTANCE, 20);
| |||
ObjectSetInteger(0, prefix + "Equity", OBJPROP_YDISTANCE, 120);
| |||
| |||
// Margin
| |||
ObjectCreate(0, prefix + "Margin", OBJ_LABEL, 0, 0, 0);
| |||
ObjectSetString(0, prefix + "Margin", OBJPROP_TEXT, "Margin: " + DoubleToString(margin, 2));
| |||
ObjectSetInteger(0, prefix + "Margin", OBJPROP_COLOR, clrBlack);
| |||
ObjectSetInteger(0, prefix + "Margin", OBJPROP_CORNER, CORNER_RIGHT_UPPER);
| |||
ObjectSetInteger(0, prefix + "Margin", OBJPROP_XDISTANCE, 20);
| |||
ObjectSetInteger(0, prefix + "Margin", OBJPROP_YDISTANCE, 140);
| |||
| |||
// Free Margin
| |||
ObjectCreate(0, prefix + "FreeMargin", OBJ_LABEL, 0, 0, 0);
| |||
ObjectSetString(0, prefix + "FreeMargin", OBJPROP_TEXT, "Free Margin: " + DoubleToString(freeMargin, 2));
| |||
ObjectSetInteger(0, prefix + "FreeMargin", OBJPROP_COLOR, clrBlack);
| |||
ObjectSetInteger(0, prefix + "FreeMargin", OBJPROP_CORNER, CORNER_RIGHT_UPPER);
| |||
ObjectSetInteger(0, prefix + "FreeMargin", OBJPROP_XDISTANCE, 20);
| |||
ObjectSetInteger(0, prefix + "FreeMargin", OBJPROP_YDISTANCE, 160);
| |||
| |||
// Update the chart to show the changes
| |||
ChartRedraw();
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Update visualization elements on the chart |
| |||
//+------------------------------------------------------------------+
| |||
void UpdateVisualization()
| |||
{
| |||
// Update the main chart with any necessary visual elements
| |||
// This function is called from OnTimer() to refresh the display
| |||
| |||
// Update the trading mode display (Paper/Live)
| |||
string modeText = ExtPaperTradingActive ? "PAPER TRADING" : "LIVE TRADING";
| |||
color modeColor = ExtPaperTradingActive ? clrDodgerBlue : clrLime;
| |||
| |||
// Update the mode label on the chart
| |||
ObjectCreate(0, "EscapeEA_Mode", OBJ_LABEL, 0, 0, 0);
| |||
ObjectSetString(0, "EscapeEA_Mode", OBJPROP_TEXT, modeText);
| |||
ObjectSetInteger(0, "EscapeEA_Mode", OBJPROP_COLOR, modeColor);
| |||
ObjectSetInteger(0, "EscapeEA_Mode", OBJPROP_CORNER, CORNER_RIGHT_UPPER);
| |||
ObjectSetInteger(0, "EscapeEA_Mode", OBJPROP_XDISTANCE, 10);
| |||
ObjectSetInteger(0, "EscapeEA_Mode", OBJPROP_YDISTANCE, 20);
| |||
ObjectSetInteger(0, "EscapeEA_Mode", OBJPROP_FONTSIZE, 10);
| |||
ObjectSetInteger(0, "EscapeEA_Mode", OBJPROP_SELECTABLE, false);
| |||
| |||
// Update the paper trading display if active
| |||
if(ExtPaperTradingActive && ExtPaperTrading != NULL) {
| |||
ExtPaperTrading->UpdateVisualization();
| |||
}
| |||
| |||
// Update any other visualization elements
| |||
UpdateSignalVisualization(false, false, 0, 0, 0);
| |||
| |||
// Force chart redraw
| |||
ChartRedraw();
| |||
}
| |||
| |||
| |||
}
| |||
| |||
// Check for minimum account balance
| |||
if(AccountInfoDouble(ACCOUNT_BALANCE) < 100.0) { // Minimum $100 balance
| |||
Print("Account balance too low");
| |||
return false;
| |||
}
| |||
| |||
// Check time filter
| |||
if(InpUseTimeFilter && !IsTradingTime()) {
| |||
return false;
| |||
}
| |||
| |||
// Check for maximum open trades
| |||
if(PositionsTotal() >= InpMaxOpenTrades) {
| |||
return false;
| |||
}
| |||
| |||
// Check security restrictions
| |||
if(ExtSecurity != NULL && !ExtSecurity->IsTradingAllowed()) {
| |||
return false;
| |||
}
| |||
| |||
return true;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Check if current time is within trading hours |
| |||
//+------------------------------------------------------------------+
| |||
bool IsTradingTime()
| |||
{
| |||
MqlDateTime time;
| |||
TimeToStruct(TimeCurrent(), time);
| |||
| |||
// Check for weekend
| |||
if(time.day_of_week == 0 || time.day_of_week == 6) {
| |||
return false;
| |||
}
| |||
| |||
// Check for Friday early close
| |||
if(InpFridayClose && time.day_of_week == 5 && time.hour >= InpFridayCloseHour) {
| |||
return false;
| |||
}
| |||
| |||
// Check trading hours
| |||
if(time.hour < InpStartHour || time.hour >= InpEndHour) {
| |||
return false;
| |||
}
| |||
| |||
return true;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Check if there's already an open position |
| |||
//+------------------------------------------------------------------+
| |||
bool HasOpenPosition(ENUM_POSITION_TYPE positionType)
| |||
{
| |||
for(int i = PositionsTotal() - 1; i >= 0; i--) {
| |||
if(ExtPosition.SelectByIndex(i)) {
| |||
if(ExtPosition.Symbol() == _Symbol && ExtPosition.PositionType() == positionType) {
| |||
return true;
| |||
}
| |||
}
| |||
}
| |||
return false;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Manage open positions (trailing stop, breakeven, etc.) |
| |||
//+------------------------------------------------------------------+
| |||
void ManagePositions()
| |||
{
| |||
for(int i = PositionsTotal() - 1; i >= 0; i--) {
| |||
if(ExtPosition.SelectByIndex(i) && ExtPosition.Symbol() == _Symbol) {
| |||
double currentBid = ExtSymbol.Bid();
| |||
double currentAsk = ExtSymbol.Ask();
| |||
double positionOpenPrice = ExtPosition.PriceOpen();
| |||
double currentSL = ExtPosition.StopLoss();
| |||
double currentTP = ExtPosition.TakeProfit();
| |||
| |||
// Skip if no stop loss or take profit
| |||
if(currentSL == 0 || currentTP == 0) continue;
| |||
| |||
// Calculate trailing stop
| |||
if(InpUseTrailingStop) {
| |||
double newSL = currentSL;
| |||
double points = ExtPosition.PositionType() == POSITION_TYPE_BUY ?
| |||
(currentBid - currentSL) / ExtSymbol.Point() :
| |||
(currentSL - currentAsk) / ExtSymbol.Point();
| |||
| |||
if(points > InpTrailingStop) {
| |||
double trailAmount = (points - InpTrailingStop + InpTrailingStep) / ExtSymbol.Point();
| |||
newSL = ExtPosition.PositionType() == POSITION_TYPE_BUY ?
| |||
currentBid - InpTrailingStop * ExtSymbol.Point() :
| |||
currentAsk + InpTrailingStop * ExtSymbol.Point();
| |||
| |||
// Only move stop loss in profit direction
| |||
if((ExtPosition.PositionType() == POSITION_TYPE_BUY && newSL > currentSL) ||
| |||
(ExtPosition.PositionType() == POSITION_TYPE_SELL && (newSL < currentSL || currentSL == 0))) {
| |||
ExtTradeExecutor->ModifyPosition(ExtPosition.Ticket(), newSL, currentTP);
| |||
}
| |||
}
| |||
}
| |||
| |||
// Check for breakeven
| |||
if(InpUseBreakeven) {
| |||
double profitInPoints = ExtPosition.PositionType() == POSITION_TYPE_BUY ?
| |||
(currentBid - positionOpenPrice) / ExtSymbol.Point() :
| |||
(positionOpenPrice - currentAsk) / ExtSymbol.Point();
| |||
| |||
if(profitInPoints >= InpBreakevenPoints &&
| |||
((ExtPosition.PositionType() == POSITION_TYPE_BUY && currentSL < positionOpenPrice) ||
| |||
(ExtPosition.PositionType() == POSITION_TYPE_SELL && (currentSL > positionOpenPrice || currentSL == 0)))) {
| |||
ExtTradeExecutor->ModifyPosition(ExtPosition.Ticket(), positionOpenPrice, currentTP);
| |||
}
| |||
}
| |||
}
| |||
}
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Check for important news events |
| |||
//+------------------------------------------------------------------+
| |||
void CheckNewsEvents()
| |||
{
| |||
// This is a placeholder for news event checking
| |||
// In a real implementation, you would integrate with a news API or economic calendar
| |||
| |||
// Example: Check for high-impact news in the next 30 minutes
| |||
// This is a simplified example - replace with actual news checking logic
| |||
static datetime lastNewsCheck = 0;
| |||
if(TimeCurrent() - lastNewsCheck < 300) { // Check every 5 minutes
| |||
return;
| |||
}
| |||
| |||
lastNewsCheck = TimeCurrent();
| |||
| |||
// In a real implementation, you would check for upcoming news
| |||
// and adjust trading behavior accordingly
| |||
bool highImpactNews = false; // Replace with actual news check
| |||
| |||
if(highImpactNews) {
| |||
Print("High impact news detected - adjusting trading parameters");
| |||
// Reduce position sizes, widen stops, or disable trading
| |||
}
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Update chart with trading information |
| |||
//+------------------------------------------------------------------+
| |||
void UpdateChart()
| |||
{
| |||
// Update the main chart with any necessary visual elements
| |||
// This function is called from OnTick() to refresh the display
| |||
| |||
// Update the trading mode display (Paper/Live)
| |||
string modeText = ExtPaperTradingActive ? "PAPER TRADING" : "LIVE TRADING";
| |||
color modeColor = ExtPaperTradingActive ? clrDodgerBlue : clrLime;
| |||
| |||
// Update the mode label on the chart
| |||
ObjectCreate(0, "EscapeEA_Mode", OBJ_LABEL, 0, 0, 0);
| |||
ObjectSetString(0, "EscapeEA_Mode", OBJPROP_TEXT, modeText);
| |||
ObjectSetInteger(0, "EscapeEA_Mode", OBJPROP_COLOR, modeColor);
| |||
ObjectSetInteger(0, "EscapeEA_Mode", OBJPROP_CORNER, CORNER_RIGHT_UPPER);
| |||
ObjectSetInteger(0, "EscapeEA_Mode", OBJPROP_XDISTANCE, 10);
| |||
ObjectSetInteger(0, "EscapeEA_Mode", OBJPROP_YDISTANCE, 20);
| |||
ObjectSetInteger(0, "EscapeEA_Mode", OBJPROP_FONTSIZE, 10);
| |||
ObjectSetInteger(0, "EscapeEA_Mode", OBJPROP_SELECTABLE, false);
| |||
| |||
// Update the account information display
| |||
if(ExtPaperTradingActive && ExtPaperTrading != NULL) {
| |||
ExtPaperTrading->UpdateVisualization();
| |||
}
| |||
| |||
// Force chart redraw
| |||
ChartRedraw();
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| 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();
| |||
color signalColor = clrNONE;
| |||
string signalText = "";
| |||
| |||
if(buySignal) {
| |||
signalColor = clrLime;
| |||
signalText = "BUY";
| |||
| |||
// Draw buy signal arrow
| |||
string arrowName = "EscapeEA_Signal_Buy_" + TimeToString(currentTime, TIME_DATE|TIME_SECONDS);
| |||
ObjectCreate(0, arrowName, OBJ_ARROW_BUY, 0, currentTime, currentPrice - stopLoss);
| |||
ObjectSetInteger(0, arrowName, OBJPROP_COLOR, signalColor);
| |||
ObjectSetInteger(0, arrowName, OBJPROP_WIDTH, 2);
| |||
| |||
// Draw stop loss and take profit levels
| |||
string slLine = "EscapeEA_SL_" + TimeToString(currentTime, TIME_DATE|TIME_SECONDS);
| |||
string tpLine = "EscapeEA_TP_" + TimeToString(currentTime, TIME_DATE|TIME_SECONDS);
| |||
| |||
// Stop loss line
| |||
ObjectCreate(0, slLine, OBJ_HLINE, 0, 0, currentPrice - stopLoss);
| |||
ObjectSetInteger(0, slLine, OBJPROP_COLOR, clrRed);
| |||
ObjectSetInteger(0, slLine, OBJPROP_STYLE, STYLE_DASH);
| |||
ObjectSetInteger(0, slLine, OBJPROP_WIDTH, 1);
| |||
| |||
// Take profit line
| |||
ObjectCreate(0, tpLine, OBJ_HLINE, 0, 0, currentPrice + takeProfit);
| |||
ObjectSetInteger(0, tpLine, OBJPROP_COLOR, clrGreen);
| |||
ObjectSetInteger(0, tpLine, OBJPROP_STYLE, STYLE_DASH);
| |||
ObjectSetInteger(0, tpLine, OBJPROP_WIDTH, 1);
| |||
| |||
// Add signal label
| |||
string labelName = "EscapeEA_Label_" + TimeToString(currentTime, TIME_DATE|TIME_SECONDS);
| |||
ObjectCreate(0, labelName, OBJ_TEXT, 0, currentTime, currentPrice - stopLoss * 1.5);
| |||
ObjectSetString(0, labelName, OBJPROP_TEXT, "BUY @ " + DoubleToString(currentPrice, _Digits));
| |||
ObjectSetInteger(0, labelName, OBJPROP_COLOR, signalColor);
| |||
ObjectSetInteger(0, labelName, OBJPROP_FONTSIZE, 8);
| |||
}
| |||
| |||
if(sellSignal) {
| |||
signalColor = clrRed;
| |||
signalText = "SELL";
| |||
| |||
// Draw sell signal arrow
| |||
string arrowName = "EscapeEA_Signal_Sell_" + TimeToString(currentTime, TIME_DATE|TIME_SECONDS);
| |||
ObjectCreate(0, arrowName, OBJ_ARROW_SELL, 0, currentTime, currentPrice + stopLoss);
| |||
ObjectSetInteger(0, arrowName, OBJPROP_COLOR, signalColor);
| |||
ObjectSetInteger(0, arrowName, OBJPROP_WIDTH, 2);
| |||
| |||
// Draw stop loss and take profit levels
| |||
string slLine = "EscapeEA_SL_" + TimeToString(currentTime, TIME_DATE|TIME_SECONDS);
| |||
string tpLine = "EscapeEA_TP_" + TimeToString(currentTime, TIME_DATE|TIME_SECONDS);
| |||
| |||
// Stop loss line
| |||
ObjectCreate(0, slLine, OBJ_HLINE, 0, 0, currentPrice + stopLoss);
| |||
ObjectSetInteger(0, slLine, OBJPROP_COLOR, clrRed);
| |||
ObjectSetInteger(0, slLine, OBJPROP_STYLE, STYLE_DASH);
| |||
ObjectSetInteger(0, slLine, OBJPROP_WIDTH, 1);
| |||
| |||
// Take profit line
| |||
ObjectCreate(0, tpLine, OBJ_HLINE, 0, 0, currentPrice - takeProfit);
| |||
ObjectSetInteger(0, tpLine, OBJPROP_COLOR, clrGreen);
| |||
ObjectSetInteger(0, tpLine, OBJPROP_STYLE, STYLE_DASH);
| |||
ObjectSetInteger(0, tpLine, OBJPROP_WIDTH, 1);
| |||
| |||
// Add signal label
| |||
string labelName = "EscapeEA_Label_" + TimeToString(currentTime, TIME_DATE|TIME_SECONDS);
| |||
ObjectCreate(0, labelName, OBJ_TEXT, 0, currentTime, currentPrice + stopLoss * 1.5);
| |||
ObjectSetString(0, labelName, OBJPROP_TEXT, "SELL @ " + DoubleToString(currentPrice, _Digits));
| |||
ObjectSetInteger(0, labelName, OBJPROP_COLOR, signalColor);
| |||
ObjectSetInteger(0, labelName, OBJPROP_FONTSIZE, 8);
| |||
}
| |||
| |||
// Update the signal status label
| |||
if(buySignal || sellSignal) {
| |||
string statusText = signalText + " SIGNAL " + TimeToString(currentTime, TIME_MINUTES|TIME_SECONDS);
| |||
ObjectCreate(0, "EscapeEA_Signal_Status", OBJ_LABEL, 0, 0, 0);
| |||
ObjectSetString(0, "EscapeEA_Signal_Status", OBJPROP_TEXT, statusText);
| |||
ObjectSetInteger(0, "EscapeEA_Signal_Status", OBJPROP_COLOR, signalColor);
| |||
ObjectSetInteger(0, "EscapeEA_Signal_Status", OBJPROP_CORNER, CORNER_RIGHT_UPPER);
| |||
ObjectSetInteger(0, "EscapeEA_Signal_Status", OBJPROP_XDISTANCE, 10);
| |||
ObjectSetInteger(0, "EscapeEA_Signal_Status", OBJPROP_YDISTANCE, 40);
| |||
ObjectSetInteger(0, "EscapeEA_Signal_Status", OBJPROP_FONTSIZE, 10);
| |||
}
| |||
| |||
// 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();
| |||
}
| |||
//+------------------------------------------------------------------+
|