|
|
@@ -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;
|