Преглед на файлове

Fix MT5 EA: precision, instrument type, and cleanup improvements

- Increase candle price precision from %.5f to %.8f to match API requirements
- Change instrument type from 'metal' to 'commodity' for XAU/XAG symbols (API validation)
- Fix cleanup function to handle all timeframes instead of just default '1h'
- Update timer comments to accurately reflect 10-minute sync interval
- Improve cleanup to iterate through all timeframes (15m, 30m, 1h, 1D, 1W, 1M)

These fixes ensure:
- Candle data is sent with correct precision (8 decimals)
- Symbol creation won't fail for metal instruments
- Old candles are properly cleaned up across all timeframes
Hussain Afzal преди 2 месеца
родител
ревизия
2b037e3119
променени са 1 файла, в които са добавени 19 реда и са изтрити 13 реда
  1. 19 13
      MT5/Experts/MarketDataSender.mq5

+ 19 - 13
MT5/Experts/MarketDataSender.mq5

@@ -35,8 +35,8 @@ int OnInit()
35 35
 
36 36
    Print("✅ Symbols initialized: ", ArraySize(symbols));
37 37
    SendAllHistoricalCandles();
38
-   EventSetTimer(60);  // ⏱️ Trigger OnTimer() every 30 minutes
39
-   Print("✅ Timer set: SendAllHistoricalCandles() will run every 30 minutes.");
38
+   EventSetTimer(60);  // ⏱️ Trigger OnTimer() every 60 seconds
39
+   Print("✅ Timer set: SendAllHistoricalCandles() will run every 10 minutes (checked every 60 seconds).");
40 40
    return(INIT_SUCCEEDED);
41 41
 }
42 42
 
@@ -253,7 +253,7 @@ int CreateSymbolInDatabase(string symbolName)
253 253
    if(StringFind(symbolName, "BTC") == 0 || StringFind(symbolName, "ETH") == 0)
254 254
       instrumentType = "crypto";
255 255
    else if(StringFind(symbolName, "XAU") == 0 || StringFind(symbolName, "XAG") == 0)
256
-      instrumentType = "metal";
256
+      instrumentType = "commodity";  // ✅ Fixed: "metal" not in API validation, use "commodity"
257 257
    else if(StringFind(symbolName, "US30") == 0 || StringFind(symbolName, "NAS") == 0)
258 258
       instrumentType = "index";
259 259
    else
@@ -611,7 +611,7 @@ string BuildCandleJSONFromRates(int symbolId, MqlRates &rates[], int startIndex,
611 611
       double quoteVolume  = (r.real_volume > 0 ? r.real_volume : volume);
612 612
 
613 613
       string one = StringFormat(
614
-         "{\"symbolId\":%d,\"timeframe\":\"%s\",\"openTime\":\"%s\",\"closeTime\":\"%s\",\"open\":%.5f,\"high\":%.5f,\"low\":%.5f,\"close\":%.5f,\"volume\":%.5f,\"tradesCount\":%d,\"quoteVolume\":%.5f}",
614
+         "{\"symbolId\":%d,\"timeframe\":\"%s\",\"openTime\":\"%s\",\"closeTime\":\"%s\",\"open\":%.8f,\"high\":%.8f,\"low\":%.8f,\"close\":%.8f,\"volume\":%.8f,\"tradesCount\":%d,\"quoteVolume\":%.8f}",
615 615
          symbolId, timeframe, openTime, closeTime,
616 616
          r.open, r.high, r.low, r.close,
617 617
          volume, (int)volume, quoteVolume
@@ -668,11 +668,11 @@ bool SendJSON(string url, string json, string &response)
668 668
 
669 669
 //+------------------------------------------------------------------+
670 670
 //+------------------------------------------------------------------+
671
-//| Cleanup old candles (keep only last 1000)                        |
671
+//| Cleanup old candles (keep only last 1000) for a specific timeframe |
672 672
 //+------------------------------------------------------------------+
673
-void CleanupOldCandles(int symbolId)
673
+void CleanupOldCandles(int symbolId, string timeframe)
674 674
 {
675
-   string url = ApiBaseUrl + "/api/candles/cleanup/" + IntegerToString(symbolId) + "?keep=1000";
675
+   string url = ApiBaseUrl + "/api/candles/cleanup/" + IntegerToString(symbolId) + "?timeframe=" + timeframe + "&keep=1000";
676 676
    string headers = "Content-Type: application/json\r\n";
677 677
    string resultHeaders = "";
678 678
    char result[];
@@ -683,9 +683,9 @@ void CleanupOldCandles(int symbolId)
683 683
 
684 684
    string response = CharArrayToString(result);
685 685
    if(res == 200 || res == 204)
686
-      Print("🧹 Cleanup successful for symbolId=", symbolId, " → kept last 1000 candles.");
686
+      Print("🧹 Cleanup successful for symbolId=", symbolId, " timeframe=", timeframe, " → kept last 1000 candles.");
687 687
    else
688
-      Print("⚠️ Cleanup failed for symbolId=", symbolId, " HTTP=", res, " Response=", response);
688
+      Print("⚠️ Cleanup failed for symbolId=", symbolId, " timeframe=", timeframe, " HTTP=", res, " Response=", response);
689 689
 }
690 690
 
691 691
 //+------------------------------------------------------------------+
@@ -695,19 +695,25 @@ void OnTimer()
695 695
 {
696 696
    datetime now = TimeCurrent();
697 697
 
698
-   // ✅ Run full candle sync only once every minute
698
+   // ✅ Run full candle sync only once every 10 minutes (600 seconds)
699 699
    if(now - lastCandleSync >= 600)
700 700
    {
701 701
       Print("⏰ Running scheduled candle sync and cleanup...");
702 702
       SendAllHistoricalCandles();
703 703
 
704
-      // ✅ After uploading candles, clean up old ones
704
+      // ✅ After uploading candles, clean up old ones for all timeframes
705 705
       for(int i = 0; i < ArraySize(symbols); i++)
706 706
       {
707 707
          int symId = symbolIds[i];
708 708
          if(symId <= 0) continue;
709
-         CleanupOldCandles(symId);
710
-         Sleep(500); // small delay to avoid API overload
709
+         
710
+         // Clean up for each timeframe
711
+         for(int tfIndex = 0; tfIndex < ArraySize(Timeframes); tfIndex++)
712
+         {
713
+            string tfStr = TimeframeStrings[tfIndex];
714
+            CleanupOldCandles(symId, tfStr);
715
+            Sleep(300); // small delay to avoid API overload
716
+         }
711 717
       }
712 718
 
713 719
       lastCandleSync = now;