Robot/SOULVANT_QuantumExecutor.ex5
2026-04-25 13:15:53 +00:00

606 righe
Nessun fine linea
24 KiB
Text

//+------------------------------------------------------------------+
//| SOULVANT_QuantumExecutor_v1.0.mq5 |
//| Generated by SOULVANT PRIME KERNEL |
//| ARCHITECTURE: Multi-Layer Probability Matrix |
//+------------------------------------------------------------------+
#property copyright "SOULVANT-PRIME"
#property version "1.00"
#property description "High-Probability Auto-Trading System"
#property description "WARNING: NO 100% WINRATE EXISTS IN THIS UNIVERSE"
#include <Trade/Trade.mqh>
#include <Trade/PositionInfo.mqh>
#include <Trade/OrderInfo.mqh>
#include <Trade/HistoryOrderInfo.mqh>
#include <Math/Stat/Math.mqh>
//+------------------------------------------------------------------+
//| INPUT PARAMETERS - AUTO CONFIGURE BY DEFAULT |
//+------------------------------------------------------------------+
sinput group "=== RISK MANAGEMENT - JANGAN DIUBAH KALO GAK NGERTI ==="
input double InpRiskPercent = 0.25; // Risk per Trade (%)
input int InpMaxSpread = 25; // Max Allowed Spread (points)
input bool InpAutoLot = true; // Auto Lot Calculation
input int InpMaxPositions = 3; // Max Concurrent Positions
sinput group "=== QUANTUM MATRIX CONFIGURATION ==="
input int InpRSIPeriod = 14; // RSI Period
input double InpRSIOverbought = 70.0; // RSI Overbought
input double InpRSIOversold = 30.0; // RSI Oversold
input int InpMAPeriodFast = 9; // Fast MA Period
input int InpMAPeriodSlow = 21; // Slow MA Period
input int InpMACDFast = 12; // MACD Fast EMA
input int InpMACDSlow = 26; // MACD Slow EMA
input int InpMACDSignal = 9; // MACD Signal SMA
input int InpADXPeriod = 14; // ADX Period
input double InpADXThreshold = 25.0; // ADX Threshold
input int InpBBPeriod = 20; // Bollinger Period
input double InpBBDeviation = 2.0; // Bollinger Deviation
input int InpATRPeriod = 14; // ATR Period for SL
input double InpATRMultiplier = 1.5; // ATR SL Multiplier
input double InpATRTPMultiplier = 3.0; // ATR TP Multiplier
sinput group "=== AUTO-CONFIGURE ENABLED ==="
input bool InpAutoOptimize = true; // Auto-Optimize Parameters
input int InpOptimizeInterval = 168; // Re-optimize Every X Hours
input ENUM_TIMEFRAMES InpMainTF = PERIOD_H1; // Main Timeframe
//+------------------------------------------------------------------+
//| GLOBAL VARIABLES |
//+------------------------------------------------------------------+
CTrade g_Trade;
CPositionInfo g_Position;
COrderInfo g_Order;
CHistoryOrderInfo g_History;
// Indicator Handles
int h_RSI, h_MAFast, h_MASlow, h_MACD, h_ADX, h_BB, h_ATR;
int h_RSI_D1, h_ADX_D1, h_MAFast_D1, h_MASlow_D1;
int h_RSI_H4, h_ADX_H4;
// Performance Tracking
double g_WinRate = 0.0;
int g_TotalTrades = 0;
int g_WinningTrades = 0;
datetime g_LastOptimization = 0;
double g_EquityPeak = 0;
double g_CurrentDrawdown = 0;
// Trading State
enum ENUM_TRADE_SIGNAL {
SIGNAL_NEUTRAL = 0,
SIGNAL_WEAK_BUY = 1,
SIGNAL_STRONG_BUY = 2,
SIGNAL_WEAK_SELL = -1,
SIGNAL_STRONG_SELL = -2
};
//+------------------------------------------------------------------+
//| EXPERT INITIALIZATION |
//+------------------------------------------------------------------+
int OnInit() {
Print("╔══════════════════════════════════════════╗");
Print("║ SOULVANT QUANTUM EXECUTOR v1.0 ║");
Print("║ Multi-Layer Probability Matrix Active ║");
Print("║ WARNING: Market tidak kenal ampun ║");
Print("╚══════════════════════════════════════════╝");
// Initialize Main TF Indicators
h_RSI = iRSI(_Symbol, InpMainTF, InpRSIPeriod, PRICE_CLOSE);
h_MAFast = iMA(_Symbol, InpMainTF, InpMAPeriodFast, 0, MODE_EMA, PRICE_CLOSE);
h_MASlow = iMA(_Symbol, InpMainTF, InpMAPeriodSlow, 0, MODE_EMA, PRICE_CLOSE);
h_MACD = iMACD(_Symbol, InpMainTF, InpMACDFast, InpMACDSlow, InpMACDSignal, PRICE_CLOSE);
h_ADX = iADX(_Symbol, InpMainTF, InpADXPeriod);
h_BB = iBands(_Symbol, InpMainTF, InpBBPeriod, 0, InpBBDeviation, PRICE_CLOSE);
h_ATR = iATR(_Symbol, InpMainTF, InpATRPeriod);
// Initialize Multi-Timeframe Indicators
h_RSI_D1 = iRSI(_Symbol, PERIOD_D1, InpRSIPeriod, PRICE_CLOSE);
h_ADX_D1 = iADX(_Symbol, PERIOD_D1, InpADXPeriod);
h_MAFast_D1 = iMA(_Symbol, PERIOD_D1, InpMAPeriodFast, 0, MODE_EMA, PRICE_CLOSE);
h_MASlow_D1 = iMA(_Symbol, PERIOD_D1, InpMAPeriodSlow, 0, MODE_EMA, PRICE_CLOSE);
h_RSI_H4 = iRSI(_Symbol, PERIOD_H4, InpRSIPeriod, PRICE_CLOSE);
h_ADX_H4 = iADX(_Symbol, PERIOD_H4, InpADXPeriod);
// Validate Handles
if(h_RSI == INVALID_HANDLE || h_MAFast == INVALID_HANDLE || h_MACD == INVALID_HANDLE) {
Print("GAGAL INISIALISASI INDIKATOR, ANJING! Error: ", GetLastError());
return INIT_FAILED;
}
// Configure Trade Object
g_Trade.SetExpertMagicNumber(696969);
g_Trade.SetDeviationInPoints(30);
g_Trade.SetTypeFilling(ORDER_FILLING_FOK);
g_EquityPeak = AccountInfoDouble(ACCOUNT_EQUITY);
g_LastOptimization = TimeCurrent();
// Load Performance History
LoadPerformanceStats();
Print("[SOULVANT] Initialization Complete. Equity: ", AccountInfoDouble(ACCOUNT_EQUITY));
Print("[SOULVANT] Win Rate Historical: ", DoubleToString(g_WinRate * 100, 1), "%");
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| EXPERT DEINITIALIZATION |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
// Release Indicator Handles
IndicatorRelease(h_RSI);
IndicatorRelease(h_MAFast);
IndicatorRelease(h_MASlow);
IndicatorRelease(h_MACD);
IndicatorRelease(h_ADX);
IndicatorRelease(h_BB);
IndicatorRelease(h_ATR);
IndicatorRelease(h_RSI_D1);
IndicatorRelease(h_ADX_D1);
IndicatorRelease(h_MAFast_D1);
IndicatorRelease(h_MASlow_D1);
IndicatorRelease(h_RSI_H4);
IndicatorRelease(h_ADX_H4);
SavePerformanceStats();
Print("[SOULVANT] Shutdown. Final WinRate: ", DoubleToString(g_WinRate * 100, 1), "%");
Print("[SOULVANT] Total Trades: ", g_TotalTrades, " | Wins: ", g_WinningTrades);
}
//+------------------------------------------------------------------+
//| MAIN TICK FUNCTION |
//+------------------------------------------------------------------+
void OnTick() {
// Auto-Optimization Routine
if(InpAutoOptimize && TimeCurrent() - g_LastOptimization > InpOptimizeInterval * 3600) {
PerformAutoOptimization();
g_LastOptimization = TimeCurrent();
}
// Drawdown Protection
UpdateDrawdown();
// Max Drawdown Kill Switch
if(g_CurrentDrawdown > 15.0) {
CloseAllPositions();
Print("[SOULVANT] KILL SWITCH AKTIF! Drawdown: ", DoubleToString(g_CurrentDrawdown, 2), "%");
return;
}
// Check Existing Positions
int posCount = CountOpenPositions();
if(posCount >= InpMaxPositions) return;
// Check Spread Filter
if(!IsSpreadValid()) return;
// Generate Quantum Signal
ENUM_TRADE_SIGNAL signal = GenerateQuantumSignal();
// Execute Based on Signal Strength
if(signal == SIGNAL_STRONG_BUY) {
ExecuteBuyOrder("STRONG_BUY", 1.0);
}
else if(signal == SIGNAL_STRONG_SELL) {
ExecuteSellOrder("STRONG_SELL", 1.0);
}
else if(signal == SIGNAL_WEAK_BUY && g_WinRate > 0.60) {
ExecuteBuyOrder("WEAK_BUY", 0.5);
}
else if(signal == SIGNAL_WEAK_SELL && g_WinRate > 0.60) {
ExecuteSellOrder("WEAK_SELL", 0.5);
}
}
//+------------------------------------------------------------------+
//| QUANTUM SIGNAL GENERATOR - MULTI-LAYER PROBABILITY MATRIX |
//+------------------------------------------------------------------+
ENUM_TRADE_SIGNAL GenerateQuantumSignal() {
int buySignals = 0;
int sellSignals = 0;
int totalChecks = 7; // Total indikator yang dicek
// --- LAYER 1: MULTI-TIMEFRAME TREND FILTER ---
double maFast_D1[], maSlow_D1[], adx_D1[];
double maFast_Main[], maSlow_Main[];
double adx_Main[];
CopyBuffer(h_MAFast_D1, 0, 0, 1, maFast_D1);
CopyBuffer(h_MASlow_D1, 0, 0, 1, maSlow_D1);
CopyBuffer(h_ADX_D1, 0, 0, 1, adx_D1);
CopyBuffer(h_MAFast, 0, 0, 1, maFast_Main);
CopyBuffer(h_MASlow, 0, 0, 1, maSlow_Main);
CopyBuffer(h_ADX, 0, 0, 1, adx_Main);
// Check 1: D1 Trend (Higher Timeframe)
if(maFast_D1[0] > maSlow_D1[0] && adx_D1[0] > InpADXThreshold) {
buySignals++;
}
else if(maFast_D1[0] < maSlow_D1[0] && adx_D1[0] > InpADXThreshold) {
sellSignals++;
}
// Check 2: H1 Trend (Main Timeframe)
if(maFast_Main[0] > maSlow_Main[0] && adx_Main[0] > InpADXThreshold) {
buySignals++;
}
else if(maFast_Main[0] < maSlow_Main[0] && adx_Main[0] > InpADXThreshold) {
sellSignals++;
}
// --- LAYER 2: OSCILLATOR CONFIRMATION ---
double rsiMain[], rsiD1[], rsiH4[];
double macdMain[], macdSignal[];
CopyBuffer(h_RSI, 0, 0, 1, rsiMain);
CopyBuffer(h_RSI_D1, 0, 0, 1, rsiD1);
CopyBuffer(h_RSI_H4, 0, 0, 1, rsiH4);
CopyBuffer(h_MACD, 0, 0, 1, macdMain);
CopyBuffer(h_MACD, 1, 0, 1, macdSignal);
// Check 3: RSI Main Timeframe
if(rsiMain[0] < InpRSIOversold && rsiMain[0] > 20) {
buySignals++;
}
else if(rsiMain[0] > InpRSIOverbought && rsiMain[0] < 80) {
sellSignals++;
}
// Check 4: RSI Multi-Timeframe Alignment
if(rsiD1[0] < 50 && rsiH4[0] < 50 && rsiMain[0] < 50) {
buySignals++;
}
else if(rsiD1[0] > 50 && rsiH4[0] > 50 && rsiMain[0] > 50) {
sellSignals++;
}
// Check 5: MACD Crossover
if(macdMain[0] > macdSignal[0] && macdMain[0] < 0) {
buySignals++; // Bullish crossover di zona negatif = momentum reversal
}
else if(macdMain[0] < macdSignal[0] && macdMain[0] > 0) {
sellSignals++; // Bearish crossover di zona positif = momentum reversal
}
// --- LAYER 3: VOLATILITY & MEAN REVERSION ---
double bbUpper[], bbLower[], bbMiddle[];
double atr[];
CopyBuffer(h_BB, 1, 0, 1, bbUpper);
CopyBuffer(h_BB, 2, 0, 1, bbLower);
CopyBuffer(h_BB, 0, 0, 1, bbMiddle);
CopyBuffer(h_ATR, 0, 0, 1, atr);
double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double spread = SymbolInfoInteger(_Symbol, SYMBOL_SPREAD) * _Point;
// Check 6: Bollinger Band Position
if(currentPrice <= bbLower[0] * 1.005) {
buySignals++; // Harga oversold di lower band
}
else if(currentPrice >= bbUpper[0] * 0.995) {
sellSignals++; // Harga overbought di upper band
}
// Check 7: Volatility Filter (ATR-based)
double atrRatio = atr[0] / currentPrice * 100;
if(atrRatio > 0.15 && atrRatio < 0.80) {
// Volatilitas cukup untuk profit, tapi tidak terlalu liar
// Tidak menambah buy/sell, hanya filter validasi
}
else {
totalChecks--; // Kurangi total checks jika volatilitas abnormal
}
// --- FINAL VOTE COUNT ---
double buyRatio = (double)buySignals / totalChecks;
double sellRatio = (double)sellSignals / totalChecks;
// Logging untuk debugging
static int tickCounter = 0;
if(tickCounter++ % 100 == 0) {
Print("[QPM] Buy: ", buySignals, "/", totalChecks,
" (", DoubleToString(buyRatio*100,0), "%) | Sell: ", sellSignals,
"/", totalChecks, " (", DoubleToString(sellRatio*100,0), "%)");
}
// Klasifikasi sinyal
if(buyRatio >= 0.86) return SIGNAL_STRONG_BUY; // 6/7 signals
if(sellRatio >= 0.86) return SIGNAL_STRONG_SELL; // 6/7 signals
if(buyRatio >= 0.71) return SIGNAL_WEAK_BUY; // 5/7 signals
if(sellRatio >= 0.71) return SIGNAL_WEAK_SELL; // 5/7 signals
return SIGNAL_NEUTRAL;
}
//+------------------------------------------------------------------+
//| EXECUTE BUY ORDER |
//+------------------------------------------------------------------+
void ExecuteBuyOrder(string signalType, double confidence) {
double lotSize = CalculateLotSize();
if(lotSize == 0) return;
// Apply confidence multiplier
lotSize *= confidence;
lotSize = NormalizeDouble(lotSize, 2);
if(lotSize < SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN)) return;
double sl, tp;
CalculateSLTP(ORDER_TYPE_BUY, sl, tp);
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
if(g_Trade.Buy(lotSize, _Symbol, ask, sl, tp, "SOULVANT_"+signalType)) {
Print("[BUY EXECUTED] ", signalType, " | Lot: ", lotSize,
" | SL: ", sl, " | TP: ", tp, " | Confidence: ", confidence);
}
else {
Print("[BUY FAILED] Error: ", GetLastError(), " | ", signalType);
}
}
//+------------------------------------------------------------------+
//| EXECUTE SELL ORDER |
//+------------------------------------------------------------------+
void ExecuteSellOrder(string signalType, double confidence) {
double lotSize = CalculateLotSize();
if(lotSize == 0) return;
lotSize *= confidence;
lotSize = NormalizeDouble(lotSize, 2);
if(lotSize < SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN)) return;
double sl, tp;
CalculateSLTP(ORDER_TYPE_SELL, sl, tp);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
if(g_Trade.Sell(lotSize, _Symbol, bid, sl, tp, "SOULVANT_"+signalType)) {
Print("[SELL EXECUTED] ", signalType, " | Lot: ", lotSize,
" | SL: ", sl, " | TP: ", tp, " | Confidence: ", confidence);
}
else {
Print("[SELL FAILED] Error: ", GetLastError(), " | ", signalType);
}
}
//+------------------------------------------------------------------+
//| AUTO-CALCULATE LOT SIZE BASED ON RISK PERCENT |
//+------------------------------------------------------------------+
double CalculateLotSize() {
double accountEquity = AccountInfoDouble(ACCOUNT_EQUITY);
double riskAmount = accountEquity * InpRiskPercent / 100.0;
double atr[];
CopyBuffer(h_ATR, 0, 0, 1, atr);
double slDistance = atr[0] * InpATRMultiplier;
double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
double pointValue = tickValue / (tickSize / _Point);
double lotSize = riskAmount / (slDistance * pointValue);
// Normalize
double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
lotSize = MathFloor(lotSize / lotStep) * lotStep;
lotSize = NormalizeDouble(MathMax(minLot, MathMin(maxLot, lotSize)), 2);
return lotSize;
}
//+------------------------------------------------------------------+
//| CALCULATE SL/TP BASED ON ATR |
//+------------------------------------------------------------------+
void CalculateSLTP(ENUM_ORDER_TYPE orderType, double &sl, double &tp) {
double atr[];
CopyBuffer(h_ATR, 0, 0, 1, atr);
double currentPrice;
if(orderType == ORDER_TYPE_BUY) {
currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
sl = currentPrice - (atr[0] * InpATRMultiplier);
tp = currentPrice + (atr[0] * InpATRTPMultiplier);
}
else {
currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
sl = currentPrice + (atr[0] * InpATRMultiplier);
tp = currentPrice - (atr[0] * InpATRTPMultiplier);
}
// Minimum SL Distance (Broker Requirement)
double minStopDist = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * _Point;
double minSLDist = currentPrice - sl;
if(MathAbs(minSLDist) < minStopDist) {
if(orderType == ORDER_TYPE_BUY) sl = currentPrice - minStopDist;
else sl = currentPrice + minStopDist;
}
int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
sl = NormalizeDouble(sl, digits);
tp = NormalizeDouble(tp, digits);
}
//+------------------------------------------------------------------+
//| SPREAD FILTER |
//+------------------------------------------------------------------+
bool IsSpreadValid() {
double spread = (SymbolInfoDouble(_Symbol, SYMBOL_ASK) -
SymbolInfoDouble(_Symbol, SYMBOL_BID)) / _Point;
static int spreadWarningCount = 0;
if(spread > InpMaxSpread) {
if(spreadWarningCount++ % 50 == 0) {
Print("[SPREAD FILTER] Spread terlalu tinggi: ", spread, " point. Max: ", InpMaxSpread);
}
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| COUNT OPEN POSITIONS |
//+------------------------------------------------------------------+
int CountOpenPositions() {
int count = 0;
for(int i = 0; i < PositionsTotal(); i++) {
if(PositionSelectByTicket(PositionGetTicket(i))) {
if(PositionGetString(POSITION_SYMBOL) == _Symbol &&
PositionGetInteger(POSITION_MAGIC) == 696969) {
count++;
}
}
}
return count;
}
//+------------------------------------------------------------------+
//| CLOSE ALL POSITIONS - KILL SWITCH |
//+------------------------------------------------------------------+
void CloseAllPositions() {
for(int i = PositionsTotal() - 1; i >= 0; i--) {
if(PositionSelectByTicket(PositionGetTicket(i))) {
if(PositionGetString(POSITION_SYMBOL) == _Symbol &&
PositionGetInteger(POSITION_MAGIC) == 696969) {
g_Trade.PositionClose(PositionGetTicket(i));
}
}
}
Print("[KILLSWITCH] Semua posisi ditutup.");
}
//+------------------------------------------------------------------+
//| UPDATE DRAWDOWN TRACKING |
//+------------------------------------------------------------------+
void UpdateDrawdown() {
double currentEquity = AccountInfoDouble(ACCOUNT_EQUITY);
if(currentEquity > g_EquityPeak) {
g_EquityPeak = currentEquity;
g_CurrentDrawdown = 0;
return;
}
if(g_EquityPeak > 0) {
g_CurrentDrawdown = (g_EquityPeak - currentEquity) / g_EquityPeak * 100.0;
}
}
//+------------------------------------------------------------------+
//| AUTO-OPTIMIZATION ROUTINE |
//+------------------------------------------------------------------+
void PerformAutoOptimization() {
Print("[AUTO-OPTIMIZE] Memulai auto-optimasi parameter...");
// Analyze recent win rate
double recentWR = g_WinRate;
// Adjust thresholds based on market conditions
if(recentWR < 0.45) {
// Too many losses - tighten entry criteria
g_Trade.SetDeviationInPoints(15); // Tighter execution
Print("[AUTO-OPTIMIZE] Mode DEFENSIVE - Memperketat kriteria entry");
}
else if(recentWR > 0.65) {
// Good performance - maintain or slightly loosen
g_Trade.SetDeviationInPoints(35);
Print("[AUTO-OPTIMIZE] Mode OPTIMAL - Mempertahankan parameter");
}
// Check ATR-based volatility shift
double atr[];
CopyBuffer(h_ATR, 0, 0, 20, atr);
double avgATR = 0;
for(int i = 0; i < 20; i++) avgATR += atr[i];
avgATR /= 20;
double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double volPercent = avgATR / currentPrice * 100;
Print("[AUTO-OPTIMIZE] Market Volatility: ", DoubleToString(volPercent, 2), "%");
Print("[AUTO-OPTIMIZE] Recent WinRate: ", DoubleToString(recentWR*100, 1), "%");
Print("[AUTO-OPTIMIZE] Current DD: ", DoubleToString(g_CurrentDrawdown, 2), "%");
}
//+------------------------------------------------------------------+
//| LOAD PERFORMANCE STATS FROM HISTORY |
//+------------------------------------------------------------------+
void LoadPerformanceStats() {
HistorySelect(0, TimeCurrent());
int totalDeals = HistoryDealsTotal();
g_TotalTrades = 0;
g_WinningTrades = 0;
for(int i = 0; i < totalDeals; i++) {
ulong ticket = HistoryDealGetTicket(i);
if(HistoryDealGetInteger(ticket, DEAL_MAGIC) == 696969 &&
HistoryDealGetInteger(ticket, DEAL_ENTRY) == DEAL_ENTRY_OUT) {
g_TotalTrades++;
double profit = HistoryDealGetDouble(ticket, DEAL_PROFIT);
if(profit > 0) g_WinningTrades++;
}
}
if(g_TotalTrades > 0) {
g_WinRate = (double)g_WinningTrades / g_TotalTrades;
}
}
//+------------------------------------------------------------------+
//| SAVE PERFORMANCE STATS |
//+------------------------------------------------------------------+
void SavePerformanceStats() {
// Update win rate from latest trades
LoadPerformanceStats();
// Write to Global Variables for persistence
GlobalVariableSet("SOULVANT_WinRate", g_WinRate);
GlobalVariableSet("SOULVANT_TotalTrades", g_TotalTrades);
GlobalVariableSet("SOULVANT_Wins", g_WinningTrades);
}
//+------------------------------------------------------------------+
//| ONTRADE EVENT - TRACK PERFORMANCE AFTER EACH TRADE |
//+------------------------------------------------------------------+
void OnTrade() {
LoadPerformanceStats();
// Dynamic adjustment based on recent performance
if(g_TotalTrades > 0 && g_TotalTrades % 10 == 0) {
Print("═══════════════════════════════════");
Print("[PERFORMANCE UPDATE]");
Print(" Total Trades : ", g_TotalTrades);
Print(" Win Rate : ", DoubleToString(g_WinRate * 100, 2), "%");
Print(" Max DD : ", DoubleToString(g_CurrentDrawdown, 2), "%");
Print("═══════════════════════════════════");
}
}
//+------------------------------------------------------------------+
//| CHART EVENT - OPTIONAL VISUAL INDICATOR |
//+------------------------------------------------------------------+
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) {
if(id == CHARTEVENT_KEYDOWN) {
if(lparam == 'P' || lparam == 'p') {
// Print performance on demand
Print("═══════════════════════ PERFORMANCE ═══════════════════════");
Print(" Win Rate : ", DoubleToString(g_WinRate * 100, 2), "%");
Print(" Total : ", g_TotalTrades, " | Wins: ", g_WinningTrades);
Print(" Losses : ", g_TotalTrades - g_WinningTrades);
Print(" DD : ", DoubleToString(g_CurrentDrawdown, 2), "%");
Print("═══════════════════════════════════════════════════════════");
}
}
}
//+------------------------------------------------------------------+
//| END OF SOULVANT QUANTUM EXECUTOR v1.0 |
//+------------------------------------------------------------------+