2
1
Çatalla 0
şundan çatallanmış SahrJohn/RSI-Stoch-MA-EA
RSI-Stoch-MA-EA/NNFeatures.mqh
2026-01-21 08:25:11 +00:00

164 satır
5,7 KiB
MQL5

//+------------------------------------------------------------------+
//| NNFeatures.mqh |
//| Feature engineering for QuarterTheory NeuralNet integration |
//+------------------------------------------------------------------+
#property strict
#include "Config.mqh"
#include "GlobalVariables.mqh"
// Clamp helper
double NN_Clamp(const double x, const double lo, const double hi)
{
if(x < lo) return lo;
if(x > hi) return hi;
return x;
}
// Safe divide
double NN_SafeDiv(const double a, const double b, const double fallback=0.0)
{
if(MathAbs(b) < 1e-9) return fallback;
return a / b;
}
// Normalize distance by ATR (if ATR is 0, fallback)
double NN_DistByATR(const double price, const double level)
{
double atr = (Current_ATR > 0.0 ? Current_ATR : 1.0);
return NN_Clamp((price - level) / atr, -10.0, 10.0);
}
// Encode enums
double NN_EncodeBias(TREND_BIAS b)
{
if(b == BIAS_BULL) return 1.0;
if(b == BIAS_BEAR) return -1.0;
return 0.0;
}
double NN_EncodeFamily(MODE_FAMILY f)
{
if(f == FAMILY_TRENDING) return 1.0;
if(f == FAMILY_CHOP) return -1.0;
if(f == FAMILY_RANGING) return 0.0;
return 0.0;
}
// ✅ Updated to match YOUR enum: WEAK / CONFIRMED / STRONG
double NN_EncodeStrength(TREND_STRENGTH s)
{
if(s == STRENGTH_WEAK) return 0.25;
if(s == STRENGTH_CONFIRMED) return 0.55;
if(s == STRENGTH_STRONG) return 0.85;
return 0.55;
}
// ✅ Optional but recommended: encode your PRICE_STATE into a compact signal
double NN_EncodePriceState(PRICE_STATE s)
{
// continuation=+1, pullback/retrace=~0, reversal=-1, range/chop negative, unknown=0
if(s == STATE_CONTINUATION) return 1.0;
if(s == STATE_PULLBACK) return 0.2;
if(s == STATE_DEEP_RETRACEMENT) return 0.0;
if(s == STATE_REVERSAL_ATTEMPT) return -0.5;
if(s == STATE_REVERSAL_CONFIRMED) return -1.0;
if(s >= STATE_RANGE_MID_DRIFT && s <= STATE_RANGE_BREAK_CONFIRMED)
return -0.25;
if(s >= STATE_CHOP_NOISE && s <= STATE_CHOP_FAKEOUT_LOOP)
return -0.50;
return 0.0;
}
// Build features array. Returns number of features written.
int BuildNNFeatures(double &feat[])
{
ArrayResize(feat, 0);
// --- Get bid/ask safely ---
MqlTick t;
if(!SymbolInfoTick(_Symbol, t))
return 0;
const double bid = t.bid;
const double ask = t.ask;
const double mid = (bid + ask) * 0.5;
const double spreadPts = (ask - bid) / _Point;
// --- Core market/context ---
ArrayResize(feat, ArraySize(feat)+1);
feat[ArraySize(feat)-1] = NN_Clamp(spreadPts / 50.0, 0.0, 5.0); // scaled spread
ArrayResize(feat, ArraySize(feat)+1);
feat[ArraySize(feat)-1] = NN_Clamp(Current_ATR / (_Point * 1000.0), 0.0, 20.0);
ArrayResize(feat, ArraySize(feat)+1);
feat[ArraySize(feat)-1] = NN_Clamp(Current_ADX / 100.0, 0.0, 1.0);
ArrayResize(feat, ArraySize(feat)+1);
feat[ArraySize(feat)-1] = NN_EncodeBias(Current_Bias);
ArrayResize(feat, ArraySize(feat)+1);
feat[ArraySize(feat)-1] = NN_EncodeFamily(Current_Family);
ArrayResize(feat, ArraySize(feat)+1);
feat[ArraySize(feat)-1] = NN_EncodeStrength(Current_Strength);
// ✅ price state
ArrayResize(feat, ArraySize(feat)+1);
feat[ArraySize(feat)-1] = NN_EncodePriceState(Current_State);
// --- Stochastic ---
ArrayResize(feat, ArraySize(feat)+1);
feat[ArraySize(feat)-1] = NN_Clamp(Stoch_K_Current / 100.0, 0.0, 1.0);
ArrayResize(feat, ArraySize(feat)+1);
feat[ArraySize(feat)-1] = NN_Clamp(Stoch_D_Current / 100.0, 0.0, 1.0);
ArrayResize(feat, ArraySize(feat)+1);
feat[ArraySize(feat)-1] = NN_Clamp((Stoch_K_Current - Stoch_K_Previous) / 10.0, -5.0, 5.0);
// --- MA distances (7,14,21,50,140,230,500,1220) ---
// Assumes your Indicators.mqh maps these into MA_Current[0..7]
int maCount = MathMin(8, ArraySize(MA_Current));
for(int i=0; i<maCount; i++)
{
ArrayResize(feat, ArraySize(feat)+1);
feat[ArraySize(feat)-1] = NN_DistByATR(mid, MA_Current[i]);
}
// MA stack alignment: +1 fully above, -1 fully below
int above=0, below=0;
for(int i=0; i<maCount; i++)
{
if(mid > MA_Current[i]) above++;
if(mid < MA_Current[i]) below++;
}
ArrayResize(feat, ArraySize(feat)+1);
feat[ArraySize(feat)-1] = NN_SafeDiv((double)(above - below), (double)maCount, 0.0);
// --- MFIB distances ---
ArrayResize(feat, ArraySize(feat)+1); feat[ArraySize(feat)-1] = NN_DistByATR(mid, MFIB_Level_236);
ArrayResize(feat, ArraySize(feat)+1); feat[ArraySize(feat)-1] = NN_DistByATR(mid, MFIB_Level_382);
ArrayResize(feat, ArraySize(feat)+1); feat[ArraySize(feat)-1] = NN_DistByATR(mid, MFIB_Level_050);
ArrayResize(feat, ArraySize(feat)+1); feat[ArraySize(feat)-1] = NN_DistByATR(mid, MFIB_Level_618);
ArrayResize(feat, ArraySize(feat)+1); feat[ArraySize(feat)-1] = NN_DistByATR(mid, MFIB_Level_786);
ArrayResize(feat, ArraySize(feat)+1);
feat[ArraySize(feat)-1] = NN_EncodeBias(MFIB_Bias);
// --- Key flags ---
ArrayResize(feat, ArraySize(feat)+1); feat[ArraySize(feat)-1] = (MFIB_Reject_Warning ? 1.0 : 0.0);
ArrayResize(feat, ArraySize(feat)+1); feat[ArraySize(feat)-1] = (MFIB_Reclaim_Warning ? 1.0 : 0.0);
ArrayResize(feat, ArraySize(feat)+1); feat[ArraySize(feat)-1] = (MA_Reclaim_Warning ? 1.0 : 0.0);
ArrayResize(feat, ArraySize(feat)+1); feat[ArraySize(feat)-1] = (MA_Reject_Warning ? 1.0 : 0.0);
ArrayResize(feat, ArraySize(feat)+1); feat[ArraySize(feat)-1] = (Pullback_Warning ? 1.0 : 0.0);
ArrayResize(feat, ArraySize(feat)+1); feat[ArraySize(feat)-1] = (Retracement_Warning ? 1.0 : 0.0);
ArrayResize(feat, ArraySize(feat)+1);
feat[ArraySize(feat)-1] = NN_Clamp((double)Praise_Count / 8.0, 0.0, 1.0);
return ArraySize(feat);
}