diff --git a/OI_MeanReversion_Pro_XAUUSD.mq5 b/OI_MeanReversion_Pro_XAUUSD.mq5 index 1b9d322..3f212db 100644 --- a/OI_MeanReversion_Pro_XAUUSD.mq5 +++ b/OI_MeanReversion_Pro_XAUUSD.mq5 @@ -38,6 +38,7 @@ enum ENUM_OI_SOURCE { }; input ENUM_OI_SOURCE InpOISource = OI_SOURCE_MANUAL; input string InpOICsvPath = "\\Files\\oi_data.csv"; // Path to CSV file +input int InpCSVReloadInterval = 60; // CSV reload interval (minutes, 0=disabled) input double InpManualFuturePrice = 0.0; // Manual future price input // OI Levels (Manual Input - สามารถใส่ได้ถึง 3 ระดับ) @@ -170,6 +171,12 @@ bool NewsBlockActive = false; datetime NewsBlockStart = 0; datetime NewsBlockEnd = 0; +// CSV Cache Variables +double CachedFuturePrice = -1; +string LoadedCSVPath = ""; +bool CSVLoadLogged = false; +datetime LastCSVReloadTime = 0; + //=== NEW: Control Panel Variables === // Control Panel Position - Moved below dashboard int ControlPanelX = 10; @@ -357,21 +364,31 @@ void OnTick() //+------------------------------------------------------------------+ void OnTimer() { - //--- Update dashboard periodically - if(InpEnableDashboard) - { - UpdateDashboard(); - UpdateControlPanel(); - } - - //--- Check news events - if(InpAvoidHighImpactNews) - { - CheckNewsEvents(); - } - - //--- Reset daily statistics if new day - CheckDailyReset(); + //--- Update dashboard periodically + if(InpEnableDashboard) + { + UpdateDashboard(); + UpdateControlPanel(); + } + + //--- Check news events + if(InpAvoidHighImpactNews) + { + CheckNewsEvents(); + } + + //--- Reset daily statistics if new day + CheckDailyReset(); + + //--- CSV reload check + if(InpOISource == OI_SOURCE_CSV_FILE && InpCSVReloadInterval > 0) { + if(TimeCurrent() - LastCSVReloadTime >= InpCSVReloadInterval * 60) { + Print("CSV Reload: Scheduled reload triggered"); + LastCSVReloadTime = TimeCurrent(); + CachedFuturePrice = -1; + LoadOIFromCSV(); + } + } } //+------------------------------------------------------------------+ @@ -1094,64 +1111,91 @@ void InitializeOILevels() //+------------------------------------------------------------------+ void LoadOIFromCSV() { - string filename = InpOICsvPath; - int filehandle = FileOpen(filename, FILE_READ|FILE_CSV|FILE_ANSI, ','); - - if(filehandle == INVALID_HANDLE) - { - Print("Error opening CSV file: ", filename); - // Fall back to manual levels - InitializeOILevels(); - return; - } - - // Skip header if exists - FileReadString(filehandle); - - int callIndex = 0; - int putIndex = 0; - - while(!FileIsEnding(filehandle) && (callIndex < 3 || putIndex < 3)) - { - string row = FileReadString(filehandle); - string data[]; - int count = StringSplit(row, ',', data); - - if(count >= 3) - { - string type = data[0]; - double strike = StringToDouble(data[1]); - int oi = (int)StringToInteger(data[2]); - - if(type == "CALL" && callIndex < 3) - { - CallLevels[callIndex] = strike; - CallOI[callIndex] = oi; - callIndex++; - } - else if(type == "PUT" && putIndex < 3) - { - PutLevels[putIndex] = strike; - PutOI[putIndex] = oi; - putIndex++; - } - } - } - - FileClose(filehandle); - - // Fill any missing levels with zeros - for(int i = callIndex; i < 3; i++) - { - CallLevels[i] = 0; - CallOI[i] = 0; - } - - for(int i = putIndex; i < 3; i++) - { - PutLevels[i] = 0; - PutOI[i] = 0; - } + string filename = InpOICsvPath; + int filehandle = FileOpen(filename, FILE_READ|FILE_CSV|FILE_ANSI, ','); + + if(filehandle == INVALID_HANDLE) + { + Print("Error opening CSV file: ", filename); + InitializeOILevels(); + return; + } + + int callIndex = 0; + int putIndex = 0; + double futurePrice = 0.0; + bool isFirstLine = true; + + while(!FileIsEnding(filehandle) && (callIndex < 3 || putIndex < 3)) + { + string row = FileReadString(filehandle); + + if(isFirstLine) { + isFirstLine = false; + if(StringFind(row, "Type") >= 0 || StringFind(row, "Strike") >= 0 || StringFind(row, "OI") >= 0) { + continue; + } + } + + string data[]; + int count = StringSplit(row, ',', data); + + if(count >= 3) + { + string type = data[0]; + double strike = StringToDouble(data[1]); + int oi = (int)StringToInteger(data[2]); + + if(StringFind(type, "Future") >= 0) + { + futurePrice = strike; + if(!CSVLoadLogged) { + Print("DEBUG: Parsed Future price: ", futurePrice); + } + } + else if(type == "CALL" && callIndex < 3) + { + CallLevels[callIndex] = strike; + CallOI[callIndex] = oi; + callIndex++; + } + else if(type == "PUT" && putIndex < 3) + { + PutLevels[putIndex] = strike; + PutOI[putIndex] = oi; + putIndex++; + } + } + } + + FileClose(filehandle); + + for(int i = callIndex; i < 3; i++) + { + CallLevels[i] = 0; + CallOI[i] = 0; + } + + for(int i = putIndex; i < 3; i++) + { + PutLevels[i] = 0; + PutOI[i] = 0; + } + + if(futurePrice > 0) { + CachedFuturePrice = futurePrice; + DynamicFuturePrice = futurePrice; + FuturePrice = futurePrice; + LoadedCSVPath = filename; + CSVLoadLogged = true; + Print("CSV SUCCESS: FuturePrice=", futurePrice, ", CALL=[", CallLevels[0], ",", CallLevels[1], ",", CallLevels[2], "], PUT=[", PutLevels[0], ",", PutLevels[1], ",", PutLevels[2], "] loaded from ", filename); + } else { + if(!CSVLoadLogged) { + Print("CSV ERROR: No valid price found in ", filename); + CSVLoadLogged = true; + } + CachedFuturePrice = 0; + } } //+------------------------------------------------------------------+ @@ -1214,32 +1258,36 @@ bool InitializeIndicators() //+------------------------------------------------------------------+ bool UpdateMarketData() { - // Get current prices - SpotPrice = SymbolInfo.Bid(); - SymbolInfo.RefreshRates(); - - // Get future price (manual or from symbol) - if(DynamicFuturePrice > 0) - { - FuturePrice = DynamicFuturePrice; - } - else if(InpManualFuturePrice > 0) - { - FuturePrice = InpManualFuturePrice; - } - else - { - // In real implementation, you might get this from a different symbol - // For now, use spot price with a small offset - FuturePrice = SpotPrice; - } - - // Calculate Delta - double previousDelta = DeltaPrice; - DeltaPrice = FuturePrice - SpotPrice; - - // Update Delta EMA - UpdateDeltaEMA(); + // Get current prices + SpotPrice = SymbolInfo.Bid(); + SymbolInfo.RefreshRates(); + + // Get future price (CSV cache, manual or from symbol) + if(CachedFuturePrice > 0) + { + FuturePrice = CachedFuturePrice; + } + else if(DynamicFuturePrice > 0) + { + FuturePrice = DynamicFuturePrice; + } + else if(InpManualFuturePrice > 0) + { + FuturePrice = InpManualFuturePrice; + } + else + { + // In real implementation, you might get this from a different symbol + // For now, use spot price with a small offset + FuturePrice = SpotPrice; + } + + // Calculate Delta + double previousDelta = DeltaPrice; + DeltaPrice = FuturePrice - SpotPrice; + + // Update Delta EMA + UpdateDeltaEMA(); // Calculate Deviation DeltaDeviation = DeltaPrice - DeltaEMA; diff --git a/OI_OrderFlow_Absorption_XAUUSD.mq5 b/OI_OrderFlow_Absorption_XAUUSD.mq5 index 96f9df8..b93b02f 100644 --- a/OI_OrderFlow_Absorption_XAUUSD.mq5 +++ b/OI_OrderFlow_Absorption_XAUUSD.mq5 @@ -98,6 +98,7 @@ input int InpTrailingStepPoints = 50; input bool InpUseSoftStopLoss = true; input bool InpUseAutoRecovery = true; input bool InpEnableDashboard = true; +input int InpCSVReloadInterval = 60; CTrade Trade; CSymbolInfo SymbolInfo; @@ -199,6 +200,7 @@ double LastPrice = 0.0; double CachedFuturePrice = -1; string LoadedCSVPath = ""; bool CSVLoadLogged = false; +datetime LastCSVReloadTime = 0; int OnInit() { Trade.SetExpertMagicNumber(InpMagicNumber); @@ -301,13 +303,22 @@ void OnTick() { } void OnTimer() { - if(InpEnableDashboard && TimeCurrent() - LastDashboardUpdate >= 1) { - UpdateDashboard(); - UpdateControlPanel(); - LastDashboardUpdate = TimeCurrent(); - } - - CheckDailyReset(); + if(InpEnableDashboard && TimeCurrent() - LastDashboardUpdate >= 1) { + UpdateDashboard(); + UpdateControlPanel(); + LastDashboardUpdate = TimeCurrent(); + } + + CheckDailyReset(); + + if(InpOISource == OI_SOURCE_CSV_FILE && InpCSVReloadInterval > 0) { + if(TimeCurrent() - LastCSVReloadTime >= InpCSVReloadInterval * 60) { + Print("CSV Reload: Scheduled reload triggered"); + LastCSVReloadTime = TimeCurrent(); + CachedFuturePrice = -1; + LoadOIFromCSV(); + } + } } void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { @@ -1007,111 +1018,71 @@ bool InitializeIndicators() { void LoadOIFromCSV() { - string paths[]; - int pathCount = 0; - - ArrayResize(paths, 5); - paths[pathCount++] = InpOICsvPath; - paths[pathCount++] = "oi_data.csv"; - paths[pathCount++] = "\\Files\\oi_data.csv"; - paths[pathCount++] = "..\\oi_scraper\\oi_data.csv"; - paths[pathCount++] = "../oi_scraper/oi_data.csv"; - - int filehandle = INVALID_HANDLE; - string foundPath = ""; - - for(int i = 0; i < pathCount; i++) { - if(!CSVLoadLogged) { - Print("Trying CSV path: ", paths[i]); - } - filehandle = FileOpen(paths[i], FILE_READ | FILE_CSV | FILE_ANSI, ','); - if(filehandle != INVALID_HANDLE) { - foundPath = paths[i]; - if(!CSVLoadLogged) { - Print("Found CSV file at: ", foundPath); - } - break; - } - } - - if(filehandle == INVALID_HANDLE) { - if(!CSVLoadLogged) { - Print("CSV ERROR: File not found. Searched paths:"); - for(int i = 0; i < pathCount; i++) { - Print(" - ", paths[i]); - } - CSVLoadLogged = true; - } - return; - } - - int callIndex = 0; - int putIndex = 0; - double futurePrice = 0.0; - - while(!FileIsEnding(filehandle) && (callIndex < 3 || putIndex < 3)) - { - string row = FileReadString(filehandle); - string data[]; - int count = StringSplit(row, ',', data); - - if(count >= 3) - { - string type = data[0]; - double strike = StringToDouble(data[1]); - int oi = (int)StringToInteger(data[2]); - - if(StringFind(type, "Future") >= 0) - { - futurePrice = strike; - if(!CSVLoadLogged) { - Print("DEBUG: Parsed Future price: ", futurePrice); - } - } - else if(type == "CALL" && callIndex < 3) - { - CallLevels[callIndex] = strike; - CallOI[callIndex] = oi; - callIndex++; - } - else if(type == "PUT" && putIndex < 3) - { - PutLevels[putIndex] = strike; - PutOI[putIndex] = oi; - putIndex++; - } - } - } - - FileClose(filehandle); - - for(int i = callIndex; i < 3; i++) - { - CallLevels[i] = 0; - CallOI[i] = 0; - } - - for(int i = putIndex; i < 3; i++) - { - PutLevels[i] = 0; - PutOI[i] = 0; - } - - if(futurePrice > 0) { - CachedFuturePrice = futurePrice; - DynamicFuturePrice = futurePrice; - LoadedCSVPath = foundPath; - CSVLoadLogged = true; - Print("CSV SUCCESS: FuturePrice=", futurePrice, ", CALL=[", CallLevels[0], ",", CallLevels[1], ",", CallLevels[2], "], PUT=[", PutLevels[0], ",", PutLevels[1], ",", PutLevels[2], "] loaded from ", foundPath); - } else { - if(!CSVLoadLogged) { - Print("CSV ERROR: No valid price found in ", foundPath); - CSVLoadLogged = true; - } - CachedFuturePrice = 0; - } - - InitializeKeyLevels(); + int filehandle = FileOpen(InpOICsvPath, FILE_READ | FILE_CSV | FILE_ANSI, ','); + + if(filehandle == INVALID_HANDLE) + { + Print("CSV ERROR: Cannot open ", InpOICsvPath); + return; + } + + int callIndex = 0; + int putIndex = 0; + double futurePrice = 0.0; + bool isFirstLine = true; + + while(!FileIsEnding(filehandle) && (callIndex < 3 || putIndex < 3)) + { + string row = FileReadString(filehandle); + + if(isFirstLine) { + isFirstLine = false; + if(StringFind(row, "Type") >= 0 || StringFind(row, "Strike") >= 0 || StringFind(row, "OI") >= 0) { + continue; + } + } + + string data[]; + int count = StringSplit(row, ',', data); + + if(count >= 3) + { + string type = data[0]; + double strike = StringToDouble(data[1]); + int oi = (int)StringToInteger(data[2]); + + if(StringFind(type, "Future") >= 0) + { + futurePrice = strike; + } + else if(type == "CALL" && callIndex < 3) + { + CallLevels[callIndex] = strike; + CallOI[callIndex] = oi; + callIndex++; + } + else if(type == "PUT" && putIndex < 3) + { + PutLevels[putIndex] = strike; + PutOI[putIndex] = oi; + putIndex++; + } + } + } + + FileClose(filehandle); + + for(int i = callIndex; i < 3; i++) { CallLevels[i] = 0; CallOI[i] = 0; } + for(int i = putIndex; i < 3; i++) { PutLevels[i] = 0; PutOI[i] = 0; } + + if(futurePrice > 0) { + CachedFuturePrice = futurePrice; + DynamicFuturePrice = futurePrice; + FuturePrice = futurePrice; + Print("CSV SUCCESS: FuturePrice=", futurePrice); + } + + InitializeKeyLevels(); } void CheckExistingPositions() { @@ -1355,34 +1326,6 @@ void UpdateInputValues() { DynamicFuturePrice = StringToDouble(value); } - if(ObjectGetString(chart_id, "CP_CallStrike1", OBJPROP_TEXT, 0, value)) { - DynamicCallStrike1 = StringToDouble(value); - } - if(ObjectGetString(chart_id, "CP_CallStrike2", OBJPROP_TEXT, 0, value)) { - DynamicCallStrike2 = StringToDouble(value); - } - if(ObjectGetString(chart_id, "CP_CallStrike3", OBJPROP_TEXT, 0, value)) { - DynamicCallStrike3 = StringToDouble(value); - } - if(ObjectGetString(chart_id, "CP_PutStrike1", OBJPROP_TEXT, 0, value)) { - DynamicPutStrike1 = StringToDouble(value); - } - if(ObjectGetString(chart_id, "CP_PutStrike2", OBJPROP_TEXT, 0, value)) { - DynamicPutStrike2 = StringToDouble(value); - } - if(ObjectGetString(chart_id, "CP_PutStrike3", OBJPROP_TEXT, 0, value)) { - DynamicPutStrike3 = StringToDouble(value); - } - - InitializeOILevels(); - InitializeKeyLevels(); - - if(InpOISource == OI_SOURCE_CSV_FILE) { - CachedFuturePrice = -1; - LoadOIFromCSV(); - } - } - if(ObjectGetString(chart_id, "CP_CallStrike1", OBJPROP_TEXT, 0, value)) { DynamicCallStrike1 = StringToDouble(value); } @@ -1403,9 +1346,10 @@ void UpdateInputValues() { } InitializeOILevels(); - InitializeKeyLevels(); - - if(InpOISource == OI_SOURCE_CSV_FILE) { - LoadOIFromCSV(); - } - } \ No newline at end of file + InitializeKeyLevels(); + + if(InpOISource == OI_SOURCE_CSV_FILE) { + CachedFuturePrice = -1; + LoadOIFromCSV(); + } +} \ No newline at end of file