diff --git a/OI_MeanReversion_Pro_XAUUSD_A.mq5 b/OI_MeanReversion_Pro_XAUUSD_A.mq5 index 66a7a9b..9d0fd1a 100644 Binary files a/OI_MeanReversion_Pro_XAUUSD_A.mq5 and b/OI_MeanReversion_Pro_XAUUSD_A.mq5 differ diff --git a/OI_OrderFlow_Absorption_XAUUSD.mq5 b/OI_OrderFlow_Absorption_XAUUSD.mq5 index 8f77632..42c5caf 100644 --- a/OI_OrderFlow_Absorption_XAUUSD.mq5 +++ b/OI_OrderFlow_Absorption_XAUUSD.mq5 @@ -194,6 +194,10 @@ double CurrentBarHigh = 0.0; double CurrentBarLow = 0.0; double LastPrice = 0.0; +double CachedFuturePrice = -1; // -1 = not loaded, 0 = loaded but failed, >0 = success +string LoadedCSVPath = ""; // Path from which CSV was successfully loaded +bool CSVLoadLogged = false; // Track if we've logged the result + int OnInit() { Trade.SetExpertMagicNumber(InpMagicNumber); Trade.SetDeviationInPoints(InpMaxSlippage); @@ -432,16 +436,7 @@ void UpdateMarketData() { SpotPrice = SymbolInfo.Bid(); SymbolInfo.RefreshRates(); - double csvFuturePrice = LoadFuturePriceFromCSV(); - if(csvFuturePrice > 0) { - FuturePrice = csvFuturePrice; - } else if(DynamicFuturePrice > 0) { - FuturePrice = DynamicFuturePrice; - } else if(InpManualFuturePrice > 0) { - FuturePrice = InpManualFuturePrice; - } else { - FuturePrice = SpotPrice; - } + FuturePrice = LoadFuturePriceFromCSV(); } bool IsPriceNearPutStrike() { @@ -485,6 +480,13 @@ bool IsInMiddleOfRange() { bool CheckGlobalConditions() { if(!TradingEnabled) return false; + if(CachedFuturePrice < 0) { + return false; + } + if(CachedFuturePrice == 0) { + return false; + } + if(!TerminalInfoInteger(TERMINAL_CONNECTED)) return false; if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) || !MQLInfoInteger(MQL_TRADE_ALLOWED)) return false; @@ -983,33 +985,83 @@ bool InitializeIndicators() { } double LoadFuturePriceFromCSV() { - string path = InpOICsvPath; - int filehandle = FileOpen(path, FILE_READ | FILE_CSV, ','); - + if(CachedFuturePrice >= 0) { + return CachedFuturePrice; + } + + 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++) { + filehandle = FileOpen(paths[i], FILE_READ | FILE_CSV, ','); + if(filehandle != INVALID_HANDLE) { + foundPath = paths[i]; + 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; + } + CachedFuturePrice = 0; return 0.0; } - + double futurePrice = 0.0; - + int dataLineCount = 0; + while(!FileIsEnding(filehandle)) { string line = FileReadString(filehandle); + dataLineCount++; + + if(line == "") continue; + string parts[]; int split = StringSplit(line, ',', parts); - + if(split >= 2) { - string dateStr = parts[0]; - double future = StringToDouble(parts[1]); - - if(future > 0) { - futurePrice = future; + double price = StringToDouble(parts[1]); + if(price > 0) { + futurePrice = price; break; } } } - + FileClose(filehandle); - return futurePrice; + + if(futurePrice > 0) { + CachedFuturePrice = futurePrice; + LoadedCSVPath = foundPath; + if(!CSVLoadLogged) { + Print("CSV SUCCESS: FuturePrice=", futurePrice, " loaded from ", foundPath); + CSVLoadLogged = true; + } + } else { + if(!CSVLoadLogged) { + Print("CSV ERROR: No valid price found in ", foundPath); + Print(" - File exists but contains no parseable price data"); + CSVLoadLogged = true; + } + CachedFuturePrice = 0; + } + + return CachedFuturePrice; } void CheckExistingPositions() { @@ -1028,74 +1080,88 @@ void CheckExistingPositions() { } void CreateDashboard() { - int panelWidth = 280; - int panelHeight = 280; - - CreatePanel("DashboardPanel", 10, 10, panelWidth, panelHeight, C'25,25,35', BORDER_FLAT); - - CreateLabel("DB_Title", 20, 20, "ORDER FLOW ABSORPTION EA", clrYellow, 10); - - UpdateDashboard(); + int panelWidth = 280; + int panelHeight = 300; + + CreatePanel("DashboardPanel", 10, 10, panelWidth, panelHeight, C'25,25,35', BORDER_FLAT); + + CreateLabel("DB_Title", 20, 20, "ORDER FLOW ABSORPTION EA", clrYellow, 10); + + UpdateDashboard(); } void UpdateDashboard() { - MqlRates rates[]; - int copied = CopyRates(_Symbol, PERIOD_M1, 0, 1, rates); + MqlRates rates[]; + int copied = CopyRates(_Symbol, PERIOD_M1, 0, 1, rates); + + UpdateLabel("DB_Symbol", 20, 45, "Symbol: " + _Symbol, clrWhite, 8); + UpdateLabel("DB_Price", 20, 65, "Price: " + DoubleToString(SpotPrice, 2), clrCyan, 8); - UpdateLabel("DB_Symbol", 20, 45, "Symbol: " + _Symbol, clrWhite, 8); - UpdateLabel("DB_Price", 20, 65, "Price: " + DoubleToString(SpotPrice, 2), clrCyan, 8); - - string deltaText = DoubleToString(OrderFlowDeltaPercent, 1) + "%"; - color deltaColor = OrderFlowDeltaPercent > 0 ? clrLime : (OrderFlowDeltaPercent < 0 ? clrRed : clrGray); - UpdateLabel("DB_Delta", 20, 85, "Delta: " + deltaText, deltaColor, 8); - - string absorptionText = ""; - color absorptionColor = clrGray; - - switch(CurrentAbsorptionState) { - case ABSORPTION_BUY: - absorptionText = "BUY ABSORPTION"; - absorptionColor = clrLime; - break; - case ABSORPTION_SELL: - absorptionText = "SELL ABSORPTION"; - absorptionColor = clrRed; - break; - default: - absorptionText = "NONE"; - break; - } - - UpdateLabel("DB_Absorption", 20, 105, "Absorption: " + absorptionText, absorptionColor, 8); - - int currentVol = CurrentBarVolume > 0 ? CurrentBarVolume : (copied > 0 ? (int)rates[0].tick_volume : 0); - UpdateLabel("DB_Volume", 20, 125, "Volume: " + IntegerToString(currentVol) + - " (Avg: " + IntegerToString((int)VolumeEmaValue) + ")", clrWhite, 8); - - string driftText = DoubleToString(PriceDrift / _Point, 1) + " pts"; - color driftColor = PriceDrift < InpMaxPriceDriftPoints * _Point ? clrLime : clrOrange; - UpdateLabel("DB_PriceDrift", 20, 145, "Drift: " + driftText, driftColor, 8); - - UpdateLabel("DB_Trades", 20, 170, "Daily: " + IntegerToString(DailyTradeCount) + - "/" + IntegerToString(InpMaxDailyTrades), clrWhite, 8); - - UpdateLabel("DB_PnL", 20, 190, "Daily PnL: " + DoubleToString(DailyPnL, 2), - DailyPnL >= 0 ? clrLime : clrRed, 8); - - string tradingStatus = TradingEnabled ? "ENABLED" : "DISABLED"; - color statusColor = TradingEnabled ? clrLime : clrRed; - UpdateLabel("DB_Status", 20, 215, "Trading: " + tradingStatus, statusColor, 8); - - string nearZone = ""; - if(IsPriceNearPutStrike()) nearZone = "NEAR PUT"; - else if(IsPriceNearCallStrike()) nearZone = "NEAR CALL"; - else nearZone = "MIDDLE"; - - color zoneColor = (nearZone == "MIDDLE") ? clrOrange : clrCyan; - UpdateLabel("DB_Zone", 20, 235, "Zone: " + nearZone, zoneColor, 8); - - string ticksText = "Ticks: " + IntegerToString(CurrentBarUpTicks) + "/" + IntegerToString(CurrentBarDownTicks); - UpdateLabel("DB_Ticks", 20, 255, ticksText, clrWhite, 8); + string deltaText = DoubleToString(OrderFlowDeltaPercent, 1) + "%"; + color deltaColor = OrderFlowDeltaPercent > 0 ? clrLime : (OrderFlowDeltaPercent < 0 ? clrRed : clrGray); + UpdateLabel("DB_Delta", 20, 85, "Delta: " + deltaText, deltaColor, 8); + + string absorptionText = ""; + color absorptionColor = clrGray; + + switch(CurrentAbsorptionState) { + case ABSORPTION_BUY: + absorptionText = "BUY ABSORPTION"; + absorptionColor = clrLime; + break; + case ABSORPTION_SELL: + absorptionText = "SELL ABSORPTION"; + absorptionColor = clrRed; + break; + default: + absorptionText = "NONE"; + break; + } + + UpdateLabel("DB_Absorption", 20, 105, "Absorption: " + absorptionText, absorptionColor, 8); + + int currentVol = CurrentBarVolume > 0 ? CurrentBarVolume : (copied > 0 ? (int)rates[0].tick_volume : 0); + UpdateLabel("DB_Volume", 20, 125, "Volume: " + IntegerToString(currentVol) + + " (Avg: " + IntegerToString((int)VolumeEmaValue) + ")", clrWhite, 8); + + string driftText = DoubleToString(PriceDrift / _Point, 1) + " pts"; + color driftColor = PriceDrift < InpMaxPriceDriftPoints * _Point ? clrLime : clrOrange; + UpdateLabel("DB_PriceDrift", 20, 145, "Drift: " + driftText, driftColor, 8); + + string csvText = ""; + color csvColor = clrGray; + if(CachedFuturePrice < 0) { + csvText = "CSV: LOADING..."; + csvColor = clrYellow; + } else if(CachedFuturePrice > 0) { + csvText = "CSV: OK (" + DoubleToString(CachedFuturePrice, 2) + ")"; + csvColor = clrLime; + } else { + csvText = "CSV: FAILED"; + csvColor = clrRed; + } + UpdateLabel("DB_CSVStatus", 20, 160, csvText, csvColor, 8); + + UpdateLabel("DB_Trades", 20, 180, "Daily: " + IntegerToString(DailyTradeCount) + + "/" + IntegerToString(InpMaxDailyTrades), clrWhite, 8); + + UpdateLabel("DB_PnL", 20, 200, "Daily PnL: " + DoubleToString(DailyPnL, 2), + DailyPnL >= 0 ? clrLime : clrRed, 8); + + string tradingStatus = TradingEnabled ? "ENABLED" : "DISABLED"; + color statusColor = TradingEnabled ? clrLime : clrRed; + UpdateLabel("DB_Status", 20, 220, "Trading: " + tradingStatus, statusColor, 8); + + string nearZone = ""; + if(IsPriceNearPutStrike()) nearZone = "NEAR PUT"; + else if(IsPriceNearCallStrike()) nearZone = "NEAR CALL"; + else nearZone = "MIDDLE"; + + color zoneColor = (nearZone == "MIDDLE") ? clrOrange : clrCyan; + UpdateLabel("DB_Zone", 20, 240, "Zone: " + nearZone, zoneColor, 8); + + string ticksText = "Ticks: " + IntegerToString(CurrentBarUpTicks) + "/" + IntegerToString(CurrentBarDownTicks); + UpdateLabel("DB_Ticks", 20, 260, ticksText, clrWhite, 8); } void CreateControlPanel() { diff --git a/oi_scraper/main.py b/oi_scraper/main.py index 8798592..fe895d3 100644 --- a/oi_scraper/main.py +++ b/oi_scraper/main.py @@ -9,6 +9,7 @@ Requires: pip install -r requirements.txt import os import logging import json +from datetime import datetime from playwright.sync_api import sync_playwright from dotenv import load_dotenv import pandas as pd @@ -290,9 +291,8 @@ def export_to_csv(df, future_price=0.0): output_path = CSV_OUTPUT_PATH with open(output_path, "w") as f: - df.to_csv(f, index=False) - f.write("\n[Price]\n") - f.write(f"FuturePrice,{future_price}\n") + f.write("date,future_price\n") + f.write(f"{datetime.now().strftime('%Y-%m-%d')},{future_price}\n") logger.info(f"Exported OI data and price to {output_path}") diff --git a/oi_scraper/run_with_venv.bat b/oi_scraper/run_with_venv.bat index 8119539..1aaa2f4 100644 --- a/oi_scraper/run_with_venv.bat +++ b/oi_scraper/run_with_venv.bat @@ -16,6 +16,9 @@ call venv\Scripts\activate.bat REM Run Python scraper python main.py +MOVE "oi_data.csv" "C:\Users\limitrack\AppData\Roaming\MetaQuotes\Terminal\53785E099C927DB68A545C249CDBCE06\MQL5\Files\" + + echo. echo Scraper completed. Check oi_data.csv for results. timeout /t 5