diff --git a/Scripts/MyScripts/Market_Scanner_Pro.mq5 b/Scripts/MyScripts/Market_Scanner_Pro.mq5 index f2f06a4..07da9c5 100644 --- a/Scripts/MyScripts/Market_Scanner_Pro.mq5 +++ b/Scripts/MyScripts/Market_Scanner_Pro.mq5 @@ -1,12 +1,12 @@ //+------------------------------------------------------------------+ //| Market_Scanner_Pro.mq5 | -//| QuantScan 5.1 - Multi-TF Global Sentiment | +//| QuantScan 6.0 - Full Feature Set | //| Copyright 2026, xxxxxxxx | //+------------------------------------------------------------------+ #property copyright "Copyright 2026, xxxxxxxx" -#property version "5.10" // Global Sentiment on H1, M15, M5 -#property description "Exports 'QuantScan 5.0' for LLM Analysis." -#property description "3-Layer Logic & Multi-TF Risk Sentiment." +#property version "6.00" // Full: Slope, Cost, Session, MTF Align +#property description "Exports 'QuantScan 6.0' dataset for LLM Analysis." +#property description "Complete toolset: Context, Flow, Trigger, Metrics." #property script_show_inputs //--- Include Custom Calculators @@ -22,36 +22,36 @@ #include #include #include +#include +#include //--- Input Parameters --- input group "Scanner Config" -input bool InpUseMarketWatch = false; +input bool InpUseMarketWatch = false; // Scan all Market Watch symbols input string InpSymbolList = "EURUSD,USDJPY,GBPUSD,USDCHF,AUDUSD,XAUUSD,US500,DE40,XTIUSD,ETHUSD"; -input string InpBenchmark = "US500"; -input string InpForexBench = "DX"; +input string InpBenchmark = "US500"; // Global Benchmark +input string InpForexBench = "DX"; // Forex Benchmark input string InpBrokerTimeZone = "EET (UTC+2)"; -input int InpScanHistory = 500; +input int InpScanHistory = 500; // Max History Bars to fetch input group "Benchmark Settings" -input int InpBetaLookback = 60; +input int InpBetaLookback = 60; // Beta Calculation Period -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -input group "Timeframes (3-Layer Model)" -input ENUM_TIMEFRAMES InpTFSlow = PERIOD_H1; // Layer 1: Context/Sentiment Base -input ENUM_TIMEFRAMES InpTFMiddle = PERIOD_M15; // Layer 2: Flow/Session Sentiment -input ENUM_TIMEFRAMES InpTFFast = PERIOD_M5; // Layer 3: Trigger/Shock Sentiment +input group "Timeframes" +input ENUM_TIMEFRAMES InpTFFast = PERIOD_M5; // Layer 3 (Trigger) +input ENUM_TIMEFRAMES InpTFMiddle= PERIOD_M15; // Layer 2 (Flow) +input ENUM_TIMEFRAMES InpTFSlow = PERIOD_H1; // Layer 1 (Context) input group "Metric Settings" input int InpDSMAPeriod = 40; input double InpLaguerreGamma = 0.50; input int InpMurreyPeriod = 64; input int InpATRPeriod = 14; -input int InpRSBars = 24; -input int InpRVOLPeriod = 20; -input int InpERPeriod = 10; -input int InpZScorePeriod = 20; +input int InpRSBars = 24; // Relative Strength Lookback +input int InpRVOLPeriod = 20; // Relative Volume Lookback +input int InpERPeriod = 10; // Efficiency Ratio Lookback +input int InpZScorePeriod = 20; // Z-Score Lookback +input int InpSlopeLookback = 5; // Bars back for Slope calculation input group "TSI Settings" input int InpTSI_Slow = 25; @@ -73,18 +73,24 @@ struct QuantData // --- Layer 1: H1 Context --- double trend_score; double trend_qual; + double trend_slope; string zone; + double dist_pdh; // Dist to Prev High + double dist_pdl; // Dist to Prev Low string rel_strength_str; string beta_str; string alpha_str; + string h1_tsi_dir; // --- Layer 2: M15 Flow --- double m15_momentum; double m15_vol_qual; string m15_squeeze; + double m15_vwap_slope; double m15_z_score; double m15_vola_regime; string m15_tsi_dir; + double spread_cost; // --- Layer 3: M5 Trigger --- double m5_momentum; @@ -95,6 +101,7 @@ struct QuantData // --- Composites --- double rev_prob; string absorption; + string mtf_align; }; //+------------------------------------------------------------------+ @@ -120,17 +127,7 @@ bool IsForexPair(string sym) //+------------------------------------------------------------------+ string GetSentimentForTF(ENUM_TIMEFRAMES tf) { -// Uses Last Closed Bar change vs Prev double u_close[2], d_close[2]; - -// Fetch 2 bars. Index 0=Oldest (Prev), Index 1=Newest (Last Closed) -// Note: If using FetchData logic (ArraySetAsSeries false), copy from end. -// But CopyClose(..., 0, 2) returns: [0]=Bar 1 ago, [1]=Bar 0 (Current) ? -// Docs: CopyClose(..., start_pos, count, buffer) -> start_pos relative to current. -// start_pos=0 is current bar. start_pos=1 is closed bar. -// Let's create array of 2 elements from start_pos=1 (last closed two candles). -// So [0] = Bar 2, [1] = Bar 1. - if(CopyClose(InpBenchmark, tf, 1, 2, u_close) != 2) return "N/A"; if(CopyClose(InpForexBench, tf, 1, 2, d_close) != 2) @@ -155,12 +152,29 @@ string GetSentimentForTF(ENUM_TIMEFRAMES tf) if(dxy_chg < 0 && us500_chg < 0) state = "DEFLATION"; -// Format: "RISK-ON (S: +0.2% D: -0.1%)" string tf_name = EnumToString(tf); StringReplace(tf_name, "PERIOD_", ""); return StringFormat("%s: %s (US:%.2f%% DX:%.2f%%)", tf_name, state, us500_pct, dxy_pct); } +//+------------------------------------------------------------------+ +//| WRAPPER DECLARATIONS (Forward Declaration not strictly needed) | +//+------------------------------------------------------------------+ +bool FetchData(string sym, ENUM_TIMEFRAMES tf, int count, datetime &t[], double &o[], double &h[], double &l[], double &c[], long &v[]); +double Calc_ATR(const double &o[], const double &h[], const double &l[], const double &c[], int p); +double Calc_ER(const double &o[], const double &h[], const double &l[], const double &c[], int p); +double Calc_ZScore(const double &o[], const double &h[], const double &l[], const double &c[], int p); +double Calc_RVOL(const long &vol[], int p); +double Calc_DSMA_Score(const double &o[], const double &h[], const double &l[], const double &c[], double atr); +string Calc_Squeeze(string sym, ENUM_TIMEFRAMES tf, const double &o[], const double &h[], const double &l[], const double &c[]); +double Calc_LaguerreRSI(const double &o[], const double &h[], const double &l[], const double &c[]); +void Calc_TSI_Dir(const double &o[], const double &h[], const double &l[], const double &c[], string &dir); +string Calc_MurreyZone(string symbol, ENUM_TIMEFRAMES tf); +void Calc_DSMA_Series(const double &o[], const double &h[], const double &l[], const double &c[], double &out_buf[]); +void Calc_VWAP_Series(const datetime &t[], const double &o[], const double &h[], const double &l[], const double &c[], const long &v[], ENUM_VWAP_PERIOD p, double &out_buf[]); +double Calc_Velocity(const double &close[], double atr, int period); +double Calc_RVOL_Single_Help(const long &vol[], int period, int index); // Helper proxy + //+------------------------------------------------------------------+ //| Script Start | //+------------------------------------------------------------------+ @@ -169,6 +183,7 @@ void OnStart() string symbols[]; int total_symbols = 0; +// 1. Symbol List Compilation if(InpUseMarketWatch) { total_symbols = SymbolsTotal(true); @@ -183,48 +198,41 @@ void OnStart() total_symbols = StringSplit(InpSymbolList, u_sep, symbols); } -// --- Global Sentiment Analysis (Multi-TF) --- +// 2. Global Sentiment string sentiment_line = "### GLOBAL_SENTIMENT | "; - bool has_us500 = SymbolSelect(InpBenchmark, true); bool has_dxy = SymbolSelect(InpForexBench, true); if(has_us500 && has_dxy) { - string s1 = GetSentimentForTF(InpTFSlow); - string s2 = GetSentimentForTF(InpTFMiddle); - string s3 = GetSentimentForTF(InpTFFast); - - sentiment_line += s1 + " | " + s2 + " | " + s3 + " ###"; + sentiment_line += GetSentimentForTF(InpTFSlow) + " | " + GetSentimentForTF(InpTFMiddle) + " | " + GetSentimentForTF(InpTFFast) + " ###"; } else - { - sentiment_line += "Benchmarks Missing (Check High/Low settings) ###"; - } + sentiment_line += "Benchmarks Missing ###"; -// --- Benchmark for RS (H1 Context) --- double bench_change_pct = 0.0; if(has_us500) { double b_close[], b_open[]; - // Using H1 for RS base if(CopyClose(InpBenchmark, InpTFSlow, 1, 1, b_close) > 0 && CopyOpen(InpBenchmark, InpTFSlow, InpRSBars, 1, b_open) > 0) if(b_open[0] != 0) bench_change_pct = ((b_close[0] - b_open[0]) / b_open[0]) * 100.0; } +// 3. File Setup string filename = "QuantScan_" + TimeToString(TimeCurrent(), TIME_DATE|TIME_MINUTES) + ".csv"; StringReplace(filename, ":", ""); StringReplace(filename, " ", "_"); int file_handle = FileOpen(filename, FILE_CSV|FILE_WRITE|FILE_ANSI, ";"); if(file_handle == INVALID_HANDLE) + { + Print("Error: CSV File."); return; + } -// --- WRITE HEADER --- FileWrite(file_handle, sentiment_line); -// --- DYNAMIC COLUMNS --- string str_slow = EnumToString(InpTFSlow); StringReplace(str_slow, "PERIOD_", ""); string str_mid = EnumToString(InpTFMiddle); @@ -238,40 +246,30 @@ void OnStart() header += "PRICE;"; // Layer 1 - header += StringFormat("TREND_SCORE_%s;", str_slow); - header += StringFormat("TREND_QUAL_%s;", str_slow); - header += StringFormat("ZONE_%s;", str_slow); - header += StringFormat("REL_STRENGTH_%s;", str_slow); - header += StringFormat("BETA_%s;", str_slow); - header += StringFormat("ALPHA_%s;", str_slow); + header += StringFormat("TREND_SC_%s;TREND_QUAL_%s;TREND_SLOPE_%s;ZONE_%s;DIST_PDH_%s;DIST_PDL_%s;REL_STR_%s;BETA_%s;ALPHA_%s;", + str_slow, str_slow, str_slow, str_slow, str_slow, str_slow, str_slow, str_slow, str_slow); // Layer 2 - header += StringFormat("MOMENTUM_%s;", str_mid); - header += StringFormat("VOL_QUAL_%s;", str_mid); - header += StringFormat("SQUEEZE_%s;", str_mid); - header += StringFormat("Z_SCORE_%s;", str_mid); - header += StringFormat("VOL_REGIME_%s;", str_mid); - header += StringFormat("TSI_DIR_%s;", str_mid); + header += StringFormat("MOM_%s;RVOL_%s;SQZ_%s;VWAP_SLOPE_%s;Z_SCORE_%s;VOL_REGIME_%s;COST_ATR_%s;TSI_DIR_%s;", + str_mid, str_mid, str_mid, str_mid, str_mid, str_mid, str_mid, str_mid); // Layer 3 - header += StringFormat("MOMENTUM_%s;", str_fast); - header += StringFormat("VOL_QUAL_%s;", str_fast); - header += StringFormat("TSI_DIR_%s;", str_fast); - header += StringFormat("VELOCITY_%s;", str_fast); + header += StringFormat("MOM_%s;RVOL_%s;TSI_DIR_%s;VEL_%s;", str_fast, str_fast, str_fast, str_fast); // Composites - header += "REVERSION_PROB;"; - header += "ABSORPTION"; + header += "REV_PROB;ABSORPTION;MTF_ALIGN"; FileWrite(file_handle, header); PrintFormat("Scanning %d symbols...", total_symbols); +// 4. Main Loop for(int i=0; i 3.0) score += 40; @@ -442,15 +480,11 @@ bool RunQuantAnalysis(string sym, double bench_change, QuantData &data) score += 30; data.rev_prob = score; -// Absorption based on Flow (M15) or Trig (M5)? Standard is Flow due to volume significance. -// Let's stick to M15 for Absorption to filter M5 noise. int idx_cl = ArraySize(mid_c) - 2; if(idx_cl >= 0 && mid_atr > 0) { double body = MathAbs(mid_c[idx_cl] - mid_o[idx_cl]); - CRelativeVolumeCalculator rv; - rv.Init(InpRVOLPeriod); - double bar_rvol = rv.CalculateSingle(ArraySize(mid_v), mid_v, idx_cl); + double bar_rvol = Calc_RVOL_Single_Help(mid_v, InpRVOLPeriod, idx_cl); if(bar_rvol > 2.0 && body < (0.4 * mid_atr)) data.absorption = "YES"; else @@ -459,33 +493,20 @@ bool RunQuantAnalysis(string sym, double bench_change, QuantData &data) else data.absorption = "-"; +// MTF Align + if(data.h1_tsi_dir == data.m15_tsi_dir && data.m15_tsi_dir == data.m5_tsi_dir) + data.mtf_align = "FULL_" + data.h1_tsi_dir; + else + if(data.h1_tsi_dir == data.m15_tsi_dir) + data.mtf_align = "MAJOR_" + data.h1_tsi_dir; + else + data.mtf_align = "MIXED"; + return true; } //+------------------------------------------------------------------+ -//| Velocity Calculation | -//+------------------------------------------------------------------+ -double Calc_Velocity(const double &close[], double atr, int period) - { - if(atr == 0) - return 0; - int total = ArraySize(close); - if(total <= period+2) - return 0; - - double sum_move = 0; - for(int i=0; i k_lo[idx])) ? "ON" : "OFF"; } - //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ @@ -611,7 +681,6 @@ double Calc_LaguerreRSI(const double &o[], const double &h[], const double &l[], calc.Calculate(total, 0, PRICE_CLOSE, o, h, l, c, lrsi, sig); return lrsi[total-2] / 100.0; } - //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ @@ -630,7 +699,6 @@ void Calc_TSI_Dir(const double &o[], const double &h[], const double &l[], const else dir = "BEAR"; } - //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ @@ -659,3 +727,4 @@ string Calc_MurreyZone(string symbol, ENUM_TIMEFRAMES tf) return "7/8-8/8 (Top)"; } //+------------------------------------------------------------------+ +//+------------------------------------------------------------------+