forked from MasoodIqbal/RSI-Stoch-MA-EA
137 lines
4.2 KiB
MQL5
137 lines
4.2 KiB
MQL5
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| NNDataLogger.mqh|
|
||
|
|
//| Logs training samples ONLY when SignalCluster is trade-ready |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
#property strict
|
||
|
|
#include <Files\File.mqh>
|
||
|
|
#include "NNFeatures.mqh"
|
||
|
|
|
||
|
|
// ===================== INPUTS ======================
|
||
|
|
input bool NN_LogData = true;
|
||
|
|
input string NN_LogFileName = "nn_dataset_signalready.csv";
|
||
|
|
input int NN_LabelLookaheadBars = 180; // lookahead window for label
|
||
|
|
input int NN_MinSecondsBetweenLogs = 10; // avoid spam
|
||
|
|
|
||
|
|
// SL/TP mapping (points) — match your bot defaults
|
||
|
|
input double NN_Cont_SL_Points = 150;
|
||
|
|
input double NN_Cont_TP_Points = 4000;
|
||
|
|
|
||
|
|
input double NN_Counter_SL_Points = 50;
|
||
|
|
input double NN_Counter_TP_Points = 3000;
|
||
|
|
|
||
|
|
// Optional: only log if conflict <= this (extra safety gate)
|
||
|
|
input double NN_MaxConflictToLog = 40.0;
|
||
|
|
|
||
|
|
// ===================== 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; // TP is below entry for sell
|
||
|
|
if(hi >= sl) hitSL = true; // SL is above entry for sell
|
||
|
|
}
|
||
|
|
|
||
|
|
// Conservative tie-break: SL wins
|
||
|
|
if(hitSL) return 0;
|
||
|
|
if(hitTP) return 1;
|
||
|
|
}
|
||
|
|
return 0; // no TP within window => treat as fail
|
||
|
|
}
|
||
|
|
|
||
|
|
// Public function: call this ONLY when your cluster is trade-ready.
|
||
|
|
void NN_LogSignalReadySample(
|
||
|
|
bool is_buy,
|
||
|
|
int category, // 0 continuation, 1 counter (use your TRADE_CATEGORY)
|
||
|
|
double cluster_strength, // 0..100 if you have it
|
||
|
|
double conflict_score // 0..100 if you have it
|
||
|
|
)
|
||
|
|
{
|
||
|
|
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 existing 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
|
||
|
|
double sl_pts = (category == 0 ? NN_Cont_SL_Points : NN_Counter_SL_Points);
|
||
|
|
double tp_pts = (category == 0 ? NN_Cont_TP_Points : NN_Counter_TP_Points);
|
||
|
|
|
||
|
|
int tp_first = NN_LabelTPBeforeSL(is_buy, entry, tp_pts, sl_pts, NN_LabelLookaheadBars);
|
||
|
|
|
||
|
|
// Write CSV row
|
||
|
|
int h = FileOpen(NN_LogFileName, FILE_READ|FILE_WRITE|FILE_CSV|FILE_ANSI);
|
||
|
|
if(h == INVALID_HANDLE) return;
|
||
|
|
|
||
|
|
FileSeek(h, 0, SEEK_END);
|
||
|
|
|
||
|
|
// Header
|
||
|
|
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<n; k++)
|
||
|
|
{
|
||
|
|
fjson += DoubleToString(feat[k], 8);
|
||
|
|
if(k < n-1) fjson += ",";
|
||
|
|
}
|
||
|
|
fjson += "]";
|
||
|
|
|
||
|
|
FileWrite(h,
|
||
|
|
(string)iTime(_Symbol, PERIOD_CURRENT, 0),
|
||
|
|
_Symbol,
|
||
|
|
(string)Period(),
|
||
|
|
(is_buy ? 1 : 0),
|
||
|
|
category,
|
||
|
|
DoubleToString(cluster_strength, 2),
|
||
|
|
DoubleToString(conflict_score, 2),
|
||
|
|
DoubleToString(entry, _Digits),
|
||
|
|
DoubleToString(tp_pts, 1),
|
||
|
|
DoubleToString(sl_pts, 1),
|
||
|
|
tp_first,
|
||
|
|
n,
|
||
|
|
fjson
|
||
|
|
);
|
||
|
|
|
||
|
|
FileClose(h);
|
||
|
|
g_nn_last_log_time = now;
|
||
|
|
}
|