//+------------------------------------------------------------------+ //| NNDataLogger.mqh| //| Logs training samples ONLY when SignalCluster is trade-ready | //| Derived from AlgoForge repo: SahrJohn/RSI-Stoch-MA-EA | //| (kept local so we can integrate with our coordinator cleanly) | //+------------------------------------------------------------------+ #property strict #include #include "NNFeatures.mqh" #include "InputParams.mqh" // ===================== INTERNAL ====================== datetime g_nn_last_log_time = 0; // Conservative “first hit” label using OHLC of future bars. // If both TP and SL occur in same bar -> SL wins (tp_first=0). int NN_LabelTPBeforeSL(bool is_buy, double entry, double tp_pts, double sl_pts, int lookaheadBars) { double tp = is_buy ? (entry + tp_pts * _Point) : (entry - tp_pts * _Point); double sl = is_buy ? (entry - sl_pts * _Point) : (entry + sl_pts * _Point); for(int i=1; i<=lookaheadBars; i++) { double hi = iHigh(_Symbol, PERIOD_CURRENT, i); double lo = iLow(_Symbol, PERIOD_CURRENT, i); bool hitTP = false, hitSL = false; if(is_buy) { if(hi >= tp) hitTP = true; if(lo <= sl) hitSL = true; } else { if(lo <= tp) hitTP = true; if(hi >= sl) hitSL = true; } // Conservative tie-break: SL wins if(hitSL) return 0; if(hitTP) return 1; } return 0; } // Public function: call this ONLY when your cluster is trade-ready. void NN_LogSignalReadySample( bool is_buy, int category, // 0 continuation, 1 counter double cluster_strength, // 0..100 double conflict_score // 0..100 ) { if(!NN_LogData) return; datetime now = TimeCurrent(); if(g_nn_last_log_time > 0 && (now - g_nn_last_log_time) < NN_MinSecondsBetweenLogs) return; if(conflict_score > NN_MaxConflictToLog) return; // Feature vector from your globals (Indicators/Warn/Praise/State) double feat[]; int n = BuildNNFeatures(feat); if(n <= 0) return; // Use current open price (you can change to bid/ask if you prefer) double entry = iOpen(_Symbol, PERIOD_CURRENT, 0); // Pick SL/TP based on category and current EA config double sl_pts = (category == 0 ? (double)Continuation_SL_Points : (double)Counter_SL_Points); double tp_pts = (category == 0 ? (double)Continuation_TP_Points : (double)Counter_TP_Points); int tp_first = NN_LabelTPBeforeSL(is_buy, entry, tp_pts, sl_pts, NN_LabelLookaheadBars); int h = FileOpen(NN_LogFileName, FILE_READ|FILE_WRITE|FILE_CSV|FILE_ANSI); if(h == INVALID_HANDLE) return; FileSeek(h, 0, SEEK_END); if(FileSize(h) == 0) { FileWrite(h, "time","symbol","tf", "is_buy","category", "cluster_strength","conflict_score", "entry","tp_points","sl_points", "tp_first", "n_features","features_json" ); } // Serialize features string fjson = "["; for(int k=0; k