mirror of
https://github.com/softwaredevelop/mql5.git
synced 2026-07-27 20:47:44 +00:00
refactor(indicators): Hybrid Locking (Live/Closed) + TSI Values
This commit is contained in:
@@ -1,15 +1,15 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Market_Scanner_Pro.mq5 |
|
||||
//| QuantScan 7.2 - Signed Velocity |
|
||||
//| QuantScan 8.0 - Live & Value Precision |
|
||||
//| Copyright 2026, xxxxxxxx |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2026, xxxxxxxx"
|
||||
#property version "7.20" // Velocity is now Directional (Signed)
|
||||
#property description "Exports 'QuantScan 7.0' dataset for LLM Analysis."
|
||||
#property description "Includes Breadth, Cost, and Velocity Vector."
|
||||
#property version "8.00" // Hybrid Locking (Live/Closed) + TSI Values
|
||||
#property description "Exports 'QuantScan 8.0' dataset for LLM Analysis."
|
||||
#property description "Features mixed Live/Closed logic and numeric TSI data."
|
||||
#property script_show_inputs
|
||||
|
||||
//--- Includes
|
||||
//--- Include Custom Calculators
|
||||
#include <MyIncludes\DSMA_Calculator.mqh>
|
||||
#include <MyIncludes\VWAP_Calculator.mqh>
|
||||
#include <MyIncludes\Laguerre_RSI_Calculator.mqh>
|
||||
@@ -26,17 +26,17 @@
|
||||
#include <MyIncludes\Metrics_Tools.mqh>
|
||||
#include <MyIncludes\DataSync_Tools.mqh>
|
||||
|
||||
//--- Parameters
|
||||
//--- Input Parameters ---
|
||||
input group "Scanner Config"
|
||||
input bool InpUseMarketWatch = false; // Scan all Market Watch symbols
|
||||
input bool InpUseMarketWatch = false;
|
||||
input string InpSymbolList = "EURUSD,USDJPY,GBPUSD,USDCHF,AUDUSD,XAUUSD,US500,DE40,XTIUSD,ETHUSD";
|
||||
input string InpBenchmark = "US500"; // Global Benchmark
|
||||
input string InpForexBench = "DX"; // Forex Benchmark
|
||||
input string InpBenchmark = "US500";
|
||||
input string InpForexBench = "DX";
|
||||
input string InpBrokerTimeZone = "EET (UTC+2)";
|
||||
input int InpScanHistory = 500; // Max History Bars to fetch
|
||||
input int InpScanHistory = 500;
|
||||
|
||||
input group "Benchmark Settings"
|
||||
input int InpBetaLookback = 60; // Beta Calculation Period
|
||||
input int InpBetaLookback = 60;
|
||||
|
||||
input group "Timeframes"
|
||||
input ENUM_TIMEFRAMES InpTFFast = PERIOD_M5; // Layer 3 (Trigger)
|
||||
@@ -64,7 +64,7 @@ input int InpSqueezeLength = 20;
|
||||
input double InpBBMult = 2.0;
|
||||
input double InpKCMult = 1.5;
|
||||
|
||||
//--- QuantData Struct
|
||||
//--- Struct for QuantScan Data
|
||||
struct QuantData
|
||||
{
|
||||
string timestamp;
|
||||
@@ -72,16 +72,17 @@ struct QuantData
|
||||
double price;
|
||||
|
||||
// --- Layer 1: H1 Context ---
|
||||
double trend_score;
|
||||
double trend_qual;
|
||||
double trend_slope;
|
||||
string zone;
|
||||
string rel_strength_str;
|
||||
string beta_str;
|
||||
string alpha_str;
|
||||
string h1_tsi_dir;
|
||||
double trend_score; // Closed
|
||||
double trend_qual; // Closed
|
||||
double trend_slope; // Closed
|
||||
string zone; // Levels Closed, Price Live
|
||||
string rel_strength_str; // Live
|
||||
string beta_str; // Live
|
||||
string alpha_str; // Live
|
||||
double h1_tsi_val; // Live
|
||||
double h1_tsi_hist; // Live
|
||||
|
||||
// --- Layer 2: M15 Flow - MOVED DIST_PDH/PDL HERE
|
||||
// --- Layer 2: M15 Flow (ALL LIVE) ---
|
||||
double dist_pdh;
|
||||
double dist_pdl;
|
||||
double m15_momentum;
|
||||
@@ -90,24 +91,25 @@ struct QuantData
|
||||
double m15_vwap_slope;
|
||||
double m15_z_score;
|
||||
double m15_vola_regime;
|
||||
string m15_tsi_dir;
|
||||
double m15_tsi_val;
|
||||
double m15_tsi_hist;
|
||||
double spread_cost;
|
||||
|
||||
// --- Layer 3: M5 Trigger ---
|
||||
// --- Layer 3: M5 Trigger (ALL LIVE) ---
|
||||
double m5_momentum;
|
||||
double m5_vol_qual;
|
||||
string m5_tsi_dir;
|
||||
double m5_tsi_val;
|
||||
double m5_tsi_hist;
|
||||
double m5_velocity;
|
||||
|
||||
// --- Composites ---
|
||||
double vol_thrust;
|
||||
double rev_prob;
|
||||
string absorption;
|
||||
string mtf_align;
|
||||
};
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Helper: Detect Asset Class |
|
||||
//+------------------------------------------------------------------+
|
||||
//--- Helper: Detect Asset Class
|
||||
bool IsForexPair(string sym)
|
||||
{
|
||||
// Safety: If symbol IS one of the benchmarks, we don't classify it as generic forex pair here
|
||||
@@ -135,11 +137,14 @@ bool IsForexPair(string sym)
|
||||
return false;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Helper: Get Sentiment String for TF |
|
||||
//+------------------------------------------------------------------+
|
||||
//--- Helper: Get Sentiment
|
||||
string GetSentimentForTF(ENUM_TIMEFRAMES tf)
|
||||
{
|
||||
if(!CDataSync::EnsureDataReady(InpBenchmark, tf, 2))
|
||||
return "N/A";
|
||||
if(!CDataSync::EnsureDataReady(InpForexBench, tf, 2))
|
||||
return "N/A";
|
||||
|
||||
double u_close[2], d_close[2];
|
||||
if(CopyClose(InpBenchmark, tf, 1, 2, u_close) != 2)
|
||||
return "N/A";
|
||||
@@ -148,7 +153,6 @@ string GetSentimentForTF(ENUM_TIMEFRAMES tf)
|
||||
|
||||
double us500_chg = (u_close[1] - u_close[0]);
|
||||
double dxy_chg = (d_close[1] - d_close[0]);
|
||||
|
||||
double us500_pct = (u_close[0]!=0) ? (us500_chg / u_close[0])*100 : 0;
|
||||
double dxy_pct = (d_close[0]!=0) ? (dxy_chg / d_close[0])*100 : 0;
|
||||
|
||||
@@ -170,23 +174,21 @@ string GetSentimentForTF(ENUM_TIMEFRAMES tf)
|
||||
return StringFormat("%s: %s (US:%.2f%% DX:%.2f%%)", tf_name, state, us500_pct, dxy_pct);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| WRAPPER DECLARATIONS (Forward Declaration not strictly needed) |
|
||||
//+------------------------------------------------------------------+
|
||||
//--- Wrappers Declarations
|
||||
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);
|
||||
double Calc_ATR(const double &o[], const double &h[], const double &l[], const double &c[], int p, int idx);
|
||||
double Calc_ER(const double &o[], const double &h[], const double &l[], const double &c[], int p, int idx);
|
||||
double Calc_ZScore(const double &o[], const double &h[], const double &l[], const double &c[], int p, int idx);
|
||||
double Calc_RVOL(const long &vol[], int p, int idx);
|
||||
double Calc_DSMA_Score(const double &o[], const double &h[], const double &l[], const double &c[], double atr, int idx);
|
||||
string Calc_Squeeze(string sym, ENUM_TIMEFRAMES tf, const double &o[], const double &h[], const double &l[], const double &c[], int idx);
|
||||
double Calc_LaguerreRSI(const double &o[], const double &h[], const double &l[], const double &c[], int idx);
|
||||
void Calc_TSI_Values(const double &o[], const double &h[], const double &l[], const double &c[], int idx, double &val, double &hist);
|
||||
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
|
||||
double Calc_Velocity(const double &close[], double atr, int period, int idx);
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Script Start |
|
||||
@@ -210,17 +212,27 @@ void OnStart()
|
||||
total_symbols = StringSplit(InpSymbolList, u_sep, symbols);
|
||||
}
|
||||
|
||||
// 2. Global Sentiment
|
||||
double bench_change_pct = 0.0;
|
||||
// Global Sentiment
|
||||
string sentiment_line = "### GLOBAL_SENTIMENT | ";
|
||||
bool has_us500 = SymbolSelect(InpBenchmark, true);
|
||||
bool has_dxy = SymbolSelect(InpForexBench, true);
|
||||
if(has_us500 && has_dxy)
|
||||
{
|
||||
sentiment_line += GetSentimentForTF(InpTFSlow) + " | " + GetSentimentForTF(InpTFMiddle) + " | " + GetSentimentForTF(InpTFFast) + " ###";
|
||||
}
|
||||
else
|
||||
sentiment_line += "Benchmarks Missing ###";
|
||||
|
||||
double bench_change_pct = 0.0;
|
||||
if(has_us500)
|
||||
{
|
||||
double b_close[], b_open[];
|
||||
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;
|
||||
if(CDataSync::EnsureDataReady(InpBenchmark, InpTFSlow))
|
||||
{
|
||||
double b_close[], b_open[];
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
string filename = "QuantScan_" + TimeToString(TimeCurrent(), TIME_DATE|TIME_MINUTES) + ".csv";
|
||||
@@ -231,64 +243,9 @@ void OnStart()
|
||||
if(file_handle == INVALID_HANDLE)
|
||||
return;
|
||||
|
||||
// 3. SCAN & STORE
|
||||
PrintFormat("Scanning %d symbols...", total_symbols);
|
||||
|
||||
QuantData results[];
|
||||
int success_count = 0;
|
||||
|
||||
for(int i=0; i<total_symbols; i++)
|
||||
{
|
||||
string sym = symbols[i];
|
||||
StringTrimLeft(sym);
|
||||
StringTrimRight(sym);
|
||||
QuantData temp_data;
|
||||
ZeroMemory(temp_data);
|
||||
|
||||
if(RunQuantAnalysis(sym, bench_change_pct, temp_data))
|
||||
{
|
||||
ArrayResize(results, success_count + 1);
|
||||
results[success_count] = temp_data;
|
||||
success_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Scan Failed: ", sym);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. BREADTH & SENTIMENT
|
||||
int tsi_bull_count = 0;
|
||||
int vel_pos_count = 0;
|
||||
int mtf_full_count = 0;
|
||||
|
||||
for(int i=0; i<success_count; i++)
|
||||
{
|
||||
if(results[i].m15_tsi_dir == "BULL")
|
||||
tsi_bull_count++;
|
||||
if(results[i].m5_velocity > 0)
|
||||
vel_pos_count++;
|
||||
if(StringFind(results[i].mtf_align, "FULL_") != -1)
|
||||
mtf_full_count++;
|
||||
}
|
||||
|
||||
double breadth_tsi = (success_count>0) ? ((double)tsi_bull_count/success_count)*100.0 : 0;
|
||||
double breadth_vel = (success_count>0) ? ((double)vel_pos_count/success_count)*100.0 : 0;
|
||||
|
||||
string sentiment_line = "### GLOBAL_SENTIMENT | ";
|
||||
if(has_us500 && has_dxy)
|
||||
{
|
||||
sentiment_line += GetSentimentForTF(InpTFSlow) + " | " + GetSentimentForTF(InpTFMiddle) + " | " + GetSentimentForTF(InpTFFast);
|
||||
}
|
||||
else
|
||||
sentiment_line += "Benchmarks Missing";
|
||||
|
||||
sentiment_line += StringFormat(" ### BREADTH_SCORE | TSI_BULL: %d/%d (%.0f%%) | VEL_POS: %d/%d (%.0f%%) | MTF_ALIGN: %d ###",
|
||||
tsi_bull_count, success_count, breadth_tsi, vel_pos_count, success_count, breadth_vel, mtf_full_count);
|
||||
|
||||
// 5. WRITE HEADER
|
||||
FileWrite(file_handle, sentiment_line);
|
||||
|
||||
// Header
|
||||
string str_slow = EnumToString(InpTFSlow);
|
||||
StringReplace(str_slow, "PERIOD_", "");
|
||||
string str_mid = EnumToString(InpTFMiddle);
|
||||
@@ -296,58 +253,75 @@ void OnStart()
|
||||
string str_fast = EnumToString(InpTFFast);
|
||||
StringReplace(str_fast, "PERIOD_", "");
|
||||
|
||||
string csv_header = "TIME (" + InpBrokerTimeZone + ");SYMBOL;PRICE;";
|
||||
// Context Header
|
||||
csv_header += StringFormat("TREND_SC_%s;TREND_QUAL_%s;TREND_SLOPE_%s;ZONE_%s;REL_STR_%s;BETA_%s;ALPHA_%s;",str_slow, str_slow, str_slow, str_slow, str_slow, str_slow, str_slow);
|
||||
// Flow Header (Added DIST_PDH/PDL with current TF suffix)
|
||||
csv_header += StringFormat("DIST_PDH_%s;DIST_PDL_%s;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, str_mid, str_mid);
|
||||
// Trigger Header
|
||||
csv_header += StringFormat("MOM_%s;RVOL_%s;TSI_DIR_%s;VEL_%s;", str_fast, str_fast, str_fast, str_fast);
|
||||
string header = "TIME (" + InpBrokerTimeZone + ");SYMBOL;PRICE;";
|
||||
header += StringFormat("TREND_SC_%s;TREND_QUAL_%s;TREND_SLOPE_%s;ZONE_%s;REL_STR_%s;BETA_%s;ALPHA_%s;TSI_VAL_%s;TSI_HIST_%s;",
|
||||
str_slow, str_slow, str_slow, str_slow, str_slow, str_slow, str_slow, str_slow, str_slow);
|
||||
|
||||
csv_header += "REV_PROB;ABSORPTION;MTF_ALIGN";
|
||||
header += StringFormat("DIST_PDH_%s;DIST_PDL_%s;MOM_%s;RVOL_%s;SQZ_%s;VWAP_SLOPE_%s;Z_SCORE_%s;VOL_REGIME_%s;COST_ATR_%s;TSI_VAL_%s;TSI_HIST_%s;",
|
||||
str_mid, str_mid, str_mid, str_mid, str_mid, str_mid, str_mid, str_mid, str_mid, str_mid, str_mid);
|
||||
|
||||
FileWrite(file_handle, csv_header);
|
||||
header += StringFormat("MOM_%s;RVOL_%s;TSI_VAL_%s;TSI_HIST_%s;VEL_%s;", str_fast, str_fast, str_fast, str_fast, str_fast);
|
||||
|
||||
for(int i=0; i<success_count; i++)
|
||||
header += "VOL_THRUST;REV_PROB;ABSORPTION;MTF_ALIGN";
|
||||
|
||||
FileWrite(file_handle, header);
|
||||
|
||||
PrintFormat("Scanning %d symbols...", total_symbols);
|
||||
|
||||
for(int i=0; i<total_symbols; i++)
|
||||
{
|
||||
FileWrite(file_handle,
|
||||
results[i].timestamp,
|
||||
results[i].symbol,
|
||||
DoubleToString(results[i].price, (int)SymbolInfoInteger(results[i].symbol, SYMBOL_DIGITS)),
|
||||
// Layer 1
|
||||
DoubleToString(results[i].trend_score, 2),
|
||||
DoubleToString(results[i].trend_qual, 2),
|
||||
DoubleToString(results[i].trend_slope, 2),
|
||||
results[i].zone,
|
||||
results[i].rel_strength_str,
|
||||
results[i].beta_str,
|
||||
results[i].alpha_str,
|
||||
// Layer 2
|
||||
DoubleToString(results[i].dist_pdh, 2), // PDH in Flow
|
||||
DoubleToString(results[i].dist_pdl, 2), // PDL in Flow
|
||||
DoubleToString(results[i].m15_momentum, 2),
|
||||
DoubleToString(results[i].m15_vol_qual, 2),
|
||||
results[i].m15_squeeze,
|
||||
DoubleToString(results[i].m15_vwap_slope, 2),
|
||||
DoubleToString(results[i].m15_z_score, 2),
|
||||
DoubleToString(results[i].m15_vola_regime, 2),
|
||||
DoubleToString(results[i].spread_cost, 2),
|
||||
results[i].m15_tsi_dir,
|
||||
// Layer 3
|
||||
DoubleToString(results[i].m5_momentum, 2),
|
||||
DoubleToString(results[i].m5_vol_qual, 2),
|
||||
results[i].m5_tsi_dir,
|
||||
DoubleToString(results[i].m5_velocity, 2),
|
||||
// Composites
|
||||
DoubleToString(results[i].rev_prob, 0) + "%",
|
||||
results[i].absorption,
|
||||
results[i].mtf_align
|
||||
);
|
||||
}
|
||||
string sym = symbols[i];
|
||||
StringTrimLeft(sym);
|
||||
StringTrimRight(sym);
|
||||
QuantData data;
|
||||
ZeroMemory(data);
|
||||
|
||||
if(RunQuantAnalysis(sym, bench_change_pct, data))
|
||||
{
|
||||
FileWrite(file_handle,
|
||||
data.timestamp,
|
||||
data.symbol,
|
||||
DoubleToString(data.price, (int)SymbolInfoInteger(sym, SYMBOL_DIGITS)),
|
||||
// H1
|
||||
DoubleToString(data.trend_score, 2),
|
||||
DoubleToString(data.trend_qual, 2),
|
||||
DoubleToString(data.trend_slope, 2),
|
||||
data.zone,
|
||||
data.rel_strength_str,
|
||||
data.beta_str,
|
||||
data.alpha_str,
|
||||
DoubleToString(data.h1_tsi_val, 2),
|
||||
DoubleToString(data.h1_tsi_hist, 2),
|
||||
// M15
|
||||
DoubleToString(data.dist_pdh, 2),
|
||||
DoubleToString(data.dist_pdl, 2),
|
||||
DoubleToString(data.m15_momentum, 2),
|
||||
DoubleToString(data.m15_vol_qual, 2),
|
||||
data.m15_squeeze,
|
||||
DoubleToString(data.m15_vwap_slope, 2),
|
||||
DoubleToString(data.m15_z_score, 2),
|
||||
DoubleToString(data.m15_vola_regime, 2),
|
||||
DoubleToString(data.spread_cost, 2),
|
||||
DoubleToString(data.m15_tsi_val, 2),
|
||||
DoubleToString(data.m15_tsi_hist, 2),
|
||||
// M5
|
||||
DoubleToString(data.m5_momentum, 2),
|
||||
DoubleToString(data.m5_vol_qual, 2),
|
||||
DoubleToString(data.m5_tsi_val, 2),
|
||||
DoubleToString(data.m5_tsi_hist, 2),
|
||||
DoubleToString(data.m5_velocity, 2),
|
||||
// Composites
|
||||
DoubleToString(data.vol_thrust, 2),
|
||||
DoubleToString(data.rev_prob, 0) + "%",
|
||||
data.absorption,
|
||||
data.mtf_align
|
||||
);
|
||||
}
|
||||
else
|
||||
Print("Scan Failed (Sync): ", sym);
|
||||
}
|
||||
FileClose(file_handle);
|
||||
Print("Done. Analyzed ", success_count, " symbols. File saved to MQL5/Files/", filename);
|
||||
Print("Done. File: ", filename);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -369,23 +343,28 @@ bool RunQuantAnalysis(string sym, double bench_change, QuantData &data)
|
||||
if(!FetchData(sym, InpTFSlow, InpScanHistory, slow_t, slow_o, slow_h, slow_l, slow_c, slow_v))
|
||||
return false;
|
||||
|
||||
double slow_atr = Calc_ATR(slow_o, slow_h, slow_l, slow_c, InpATRPeriod);
|
||||
// Indices
|
||||
int idx_live_slow = ArraySize(slow_c) - 1;
|
||||
int idx_closed_slow = ArraySize(slow_c) - 2;
|
||||
|
||||
double slow_atr = Calc_ATR(slow_o, slow_h, slow_l, slow_c, InpATRPeriod, idx_closed_slow);
|
||||
if(slow_atr == 0)
|
||||
return false;
|
||||
|
||||
// DSMA & Slope
|
||||
// Trend Score/Qual/Slope -> CLOSED (Stability)
|
||||
double dsma_series[];
|
||||
Calc_DSMA_Series(slow_o, slow_h, slow_l, slow_c, dsma_series);
|
||||
int idx_s = ArraySize(slow_c) - 2;
|
||||
data.trend_score = (slow_atr!=0) ? (slow_c[idx_s] - dsma_series[idx_s]) / slow_atr : 0;
|
||||
data.trend_slope = CMetricsTools::CalculateSlope(dsma_series[idx_s], dsma_series[idx_s - InpSlopeLookback], slow_atr, InpSlopeLookback);
|
||||
data.trend_score = (slow_atr!=0) ? (slow_c[idx_closed_slow] - dsma_series[idx_closed_slow]) / slow_atr : 0;
|
||||
data.trend_slope = CMetricsTools::CalculateSlope(dsma_series[idx_closed_slow], dsma_series[idx_closed_slow - InpSlopeLookback], slow_atr, InpSlopeLookback);
|
||||
data.trend_qual = Calc_ER(slow_o, slow_h, slow_l, slow_c, InpERPeriod, idx_closed_slow);
|
||||
|
||||
data.trend_qual = Calc_ER(slow_o, slow_h, slow_l, slow_c, InpERPeriod);
|
||||
// Zone (Murrey) - Calcs on history, Checks against LIVE Price
|
||||
data.zone = Calc_MurreyZone(sym, InpTFSlow);
|
||||
|
||||
Calc_TSI_Dir(slow_o, slow_h, slow_l, slow_c, data.h1_tsi_dir); // For MTF
|
||||
// TSI -> LIVE
|
||||
Calc_TSI_Values(slow_o, slow_h, slow_l, slow_c, idx_live_slow, data.h1_tsi_val, data.h1_tsi_hist);
|
||||
|
||||
// Beta/Alpha
|
||||
// Beta/Alpha -> LIVE
|
||||
bool is_benchmark = (sym == InpBenchmark || sym == InpForexBench);
|
||||
if(is_benchmark)
|
||||
{
|
||||
@@ -399,36 +378,42 @@ bool RunQuantAnalysis(string sym, double bench_change, QuantData &data)
|
||||
if(IsForexPair(sym) && SymbolSelect(InpForexBench, true))
|
||||
bench_sym = InpForexBench;
|
||||
|
||||
double bench_c[];
|
||||
if(CopyClose(bench_sym, InpTFSlow, 0, InpBetaLookback+2, bench_c) > InpBetaLookback)
|
||||
// Ensure sync for benchmark on H1
|
||||
if(CDataSync::EnsureDataReady(bench_sym, InpTFSlow, InpBetaLookback+2))
|
||||
{
|
||||
CMathStatisticsCalculator stats;
|
||||
double asset_ret[], bench_ret[];
|
||||
|
||||
int h1_size = ArraySize(slow_c);
|
||||
double asset_subset[];
|
||||
ArrayResize(asset_subset, InpBetaLookback);
|
||||
double bench_subset[];
|
||||
ArrayResize(bench_subset, InpBetaLookback);
|
||||
|
||||
for(int k=0; k<InpBetaLookback; k++)
|
||||
double bench_c[];
|
||||
if(CopyClose(bench_sym, InpTFSlow, 0, InpBetaLookback+2, bench_c) > InpBetaLookback)
|
||||
{
|
||||
asset_subset[k] = slow_c[h1_size - InpBetaLookback + k];
|
||||
bench_subset[k] = bench_c[ArraySize(bench_c) - InpBetaLookback + k];
|
||||
CMathStatisticsCalculator stats;
|
||||
double asset_ret[], bench_ret[];
|
||||
|
||||
// Build subset from LIVE backwards
|
||||
int h1_size = ArraySize(slow_c);
|
||||
int bench_size = ArraySize(bench_c);
|
||||
double asset_subset[];
|
||||
ArrayResize(asset_subset, InpBetaLookback);
|
||||
double bench_subset[];
|
||||
ArrayResize(bench_subset, InpBetaLookback);
|
||||
|
||||
// i=0 is oldest in subset. We want subset[last] to be current live.
|
||||
for(int k=0; k<InpBetaLookback; k++)
|
||||
{
|
||||
asset_subset[k] = slow_c[h1_size - InpBetaLookback + k];
|
||||
bench_subset[k] = bench_c[bench_size - InpBetaLookback + k];
|
||||
}
|
||||
|
||||
stats.ComputeReturns(asset_subset, asset_ret);
|
||||
stats.ComputeReturns(bench_subset, bench_ret);
|
||||
double beta_val = stats.CalculateBeta(asset_ret, bench_ret);
|
||||
double a_tot = (asset_subset[InpBetaLookback-1] - asset_subset[0]) / asset_subset[0];
|
||||
double b_tot = (bench_subset[InpBetaLookback-1] - bench_subset[0]) / bench_subset[0];
|
||||
double alpha_val = stats.CalculateAlpha(a_tot, b_tot, beta_val);
|
||||
double rel_val = (a_tot - b_tot) * 100.0;
|
||||
|
||||
data.rel_strength_str = DoubleToString(rel_val, 2) + "%";
|
||||
data.beta_str = DoubleToString(beta_val, 2);
|
||||
data.alpha_str = DoubleToString(alpha_val, 4);
|
||||
}
|
||||
|
||||
stats.ComputeReturns(asset_subset, asset_ret);
|
||||
stats.ComputeReturns(bench_subset, bench_ret);
|
||||
|
||||
double beta_val = stats.CalculateBeta(asset_ret, bench_ret);
|
||||
double a_tot = (asset_subset[InpBetaLookback-1] - asset_subset[0]) / asset_subset[0];
|
||||
double b_tot = (bench_subset[InpBetaLookback-1] - bench_subset[0]) / bench_subset[0];
|
||||
double alpha_val = stats.CalculateAlpha(a_tot, b_tot, beta_val);
|
||||
double rel_val = (a_tot - b_tot) * 100.0;
|
||||
|
||||
data.rel_strength_str = DoubleToString(rel_val, 2) + "%";
|
||||
data.beta_str = DoubleToString(beta_val, 2);
|
||||
data.alpha_str = DoubleToString(alpha_val, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -439,7 +424,7 @@ bool RunQuantAnalysis(string sym, double bench_change, QuantData &data)
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
// LAYER 2: FLOW (M15)
|
||||
// LAYER 2: FLOW (M15) - ALL LIVE (idx-1)
|
||||
// =================================================================
|
||||
double mid_o[], mid_h[], mid_l[], mid_c[];
|
||||
long mid_v[];
|
||||
@@ -447,42 +432,39 @@ bool RunQuantAnalysis(string sym, double bench_change, QuantData &data)
|
||||
if(!FetchData(sym, InpTFMiddle, InpScanHistory, mid_t, mid_o, mid_h, mid_l, mid_c, mid_v))
|
||||
return false;
|
||||
|
||||
double mid_atr = Calc_ATR(mid_o, mid_h, mid_l, mid_c, InpATRPeriod);
|
||||
int idx_live_mid = ArraySize(mid_c) - 1;
|
||||
double mid_atr = Calc_ATR(mid_o, mid_h, mid_l, mid_c, InpATRPeriod, idx_live_mid);
|
||||
|
||||
data.m15_momentum = Calc_LaguerreRSI(mid_o, mid_h, mid_l, mid_c);
|
||||
data.m15_vol_qual = Calc_RVOL(mid_v, InpRVOLPeriod);
|
||||
data.m15_squeeze = Calc_Squeeze(sym, InpTFMiddle, mid_o, mid_h, mid_l, mid_c);
|
||||
data.m15_z_score = Calc_ZScore(mid_o, mid_h, mid_l, mid_c, InpZScorePeriod);
|
||||
data.m15_momentum = Calc_LaguerreRSI(mid_o, mid_h, mid_l, mid_c, idx_live_mid);
|
||||
data.m15_vol_qual = Calc_RVOL(mid_v, InpRVOLPeriod, idx_live_mid);
|
||||
data.m15_squeeze = Calc_Squeeze(sym, InpTFMiddle, mid_o, mid_h, mid_l, mid_c, idx_live_mid);
|
||||
data.m15_z_score = Calc_ZScore(mid_o, mid_h, mid_l, mid_c, InpZScorePeriod, idx_live_mid);
|
||||
|
||||
// VWAP Slope
|
||||
double vwap_series[];
|
||||
Calc_VWAP_Series(mid_t, mid_o, mid_h, mid_l, mid_c, mid_v, PERIOD_SESSION, vwap_series);
|
||||
int idx_m = ArraySize(mid_c) - 2;
|
||||
data.m15_vwap_slope = CMetricsTools::CalculateSlope(vwap_series[idx_m], vwap_series[idx_m - InpSlopeLookback], mid_atr, InpSlopeLookback);
|
||||
data.m15_vwap_slope = CMetricsTools::CalculateSlope(vwap_series[idx_live_mid], vwap_series[idx_live_mid - InpSlopeLookback], mid_atr, InpSlopeLookback);
|
||||
|
||||
// Cost
|
||||
data.spread_cost = CMetricsTools::CalculateSpreadCost(sym, mid_atr);
|
||||
|
||||
double atr_f = Calc_ATR(mid_o, mid_h, mid_l, mid_c, 5);
|
||||
double atr_s = Calc_ATR(mid_o, mid_h, mid_l, mid_c, 50);
|
||||
double atr_f = Calc_ATR(mid_o, mid_h, mid_l, mid_c, 5, idx_live_mid);
|
||||
double atr_s = Calc_ATR(mid_o, mid_h, mid_l, mid_c, 50, idx_live_mid);
|
||||
data.m15_vola_regime = (atr_s!=0) ? atr_f/atr_s : 1.0;
|
||||
|
||||
// Session Distances (Moved Here)
|
||||
CSessionLevelsCalculator sess_calc;
|
||||
if(sess_calc.Init(PERIOD_D1))
|
||||
{
|
||||
SessionLevels sl;
|
||||
if(sess_calc.GetLevels(sym, mid_t[idx_m], sl)) // Pass 'sym' for Safety
|
||||
if(sess_calc.GetLevels(sym, mid_t[idx_live_mid], sl))
|
||||
{
|
||||
data.dist_pdh = CMetricsTools::CalculateDistance(mid_c[idx_m], sl.prev_high, mid_atr);
|
||||
data.dist_pdl = CMetricsTools::CalculateDistance(mid_c[idx_m], sl.prev_low, mid_atr);
|
||||
data.dist_pdh = CMetricsTools::CalculateDistance(mid_c[idx_live_mid], sl.prev_high, mid_atr);
|
||||
data.dist_pdl = CMetricsTools::CalculateDistance(mid_c[idx_live_mid], sl.prev_low, mid_atr);
|
||||
}
|
||||
}
|
||||
|
||||
Calc_TSI_Dir(mid_o, mid_h, mid_l, mid_c, data.m15_tsi_dir);
|
||||
Calc_TSI_Values(mid_o, mid_h, mid_l, mid_c, idx_live_mid, data.m15_tsi_val, data.m15_tsi_hist);
|
||||
|
||||
// =================================================================
|
||||
// LAYER 3: TRIGGER (M5)
|
||||
// LAYER 3: TRIGGER (M5) - ALL LIVE (idx-1)
|
||||
// =================================================================
|
||||
double fast_o[], fast_h[], fast_l[], fast_c[];
|
||||
long fast_v[];
|
||||
@@ -490,16 +472,22 @@ bool RunQuantAnalysis(string sym, double bench_change, QuantData &data)
|
||||
if(!FetchData(sym, InpTFFast, 300, fast_t, fast_o, fast_h, fast_l, fast_c, fast_v))
|
||||
return false;
|
||||
|
||||
double fast_atr = Calc_ATR(fast_o, fast_h, fast_l, fast_c, InpATRPeriod);
|
||||
int idx_live_fast = ArraySize(fast_c) - 1;
|
||||
double fast_atr = Calc_ATR(fast_o, fast_h, fast_l, fast_c, InpATRPeriod, idx_live_fast);
|
||||
|
||||
data.m5_momentum = Calc_LaguerreRSI(fast_o, fast_h, fast_l, fast_c);
|
||||
data.m5_vol_qual = Calc_RVOL(fast_v, InpRVOLPeriod);
|
||||
Calc_TSI_Dir(fast_o, fast_h, fast_l, fast_c, data.m5_tsi_dir);
|
||||
data.m5_velocity = Calc_Velocity(fast_c, fast_atr, 3);
|
||||
data.m5_momentum = Calc_LaguerreRSI(fast_o, fast_h, fast_l, fast_c, idx_live_fast);
|
||||
data.m5_vol_qual = Calc_RVOL(fast_v, InpRVOLPeriod, idx_live_fast);
|
||||
Calc_TSI_Values(fast_o, fast_h, fast_l, fast_c, idx_live_fast, data.m5_tsi_val, data.m5_tsi_hist);
|
||||
data.m5_velocity = Calc_Velocity(fast_c, fast_atr, 3, idx_live_fast);
|
||||
|
||||
// =================================================================
|
||||
// COMPOSITES
|
||||
// =================================================================
|
||||
if(data.m15_vol_qual > 0)
|
||||
data.vol_thrust = data.m5_vol_qual / data.m15_vol_qual;
|
||||
else
|
||||
data.vol_thrust = 0;
|
||||
|
||||
double score = 0;
|
||||
if(MathAbs(data.m15_z_score) > 3.0)
|
||||
score += 40;
|
||||
@@ -512,11 +500,14 @@ bool RunQuantAnalysis(string sym, double bench_change, QuantData &data)
|
||||
score += 30;
|
||||
data.rev_prob = score;
|
||||
|
||||
int idx_cl = ArraySize(mid_c) - 2;
|
||||
if(idx_cl >= 0 && mid_atr > 0)
|
||||
// Absorption: Use Last Closed M15 (idx_live_mid - 1) for safety
|
||||
int idx_abs = idx_live_mid - 1;
|
||||
if(idx_abs >= 0 && mid_atr > 0)
|
||||
{
|
||||
double body = MathAbs(mid_c[idx_cl] - mid_o[idx_cl]);
|
||||
double bar_rvol = Calc_RVOL_Single_Help(mid_v, InpRVOLPeriod, idx_cl);
|
||||
double body = MathAbs(mid_c[idx_abs] - mid_o[idx_abs]);
|
||||
CRelativeVolumeCalculator rv;
|
||||
rv.Init(InpRVOLPeriod);
|
||||
double bar_rvol = rv.CalculateSingle(ArraySize(mid_v), mid_v, idx_abs);
|
||||
if(bar_rvol > 2.0 && body < (0.4 * mid_atr))
|
||||
data.absorption = "YES";
|
||||
else
|
||||
@@ -525,12 +516,16 @@ 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;
|
||||
// MTF Align (Based on TSI Histogram sign)
|
||||
bool h1_bull = (data.h1_tsi_hist > 0);
|
||||
bool m15_bull = (data.m15_tsi_hist > 0);
|
||||
bool m5_bull = (data.m5_tsi_hist > 0);
|
||||
|
||||
if(h1_bull == m15_bull && m15_bull == m5_bull)
|
||||
data.mtf_align = "FULL_" + (h1_bull ? "BULL" : "BEAR");
|
||||
else
|
||||
if(data.h1_tsi_dir == data.m15_tsi_dir)
|
||||
data.mtf_align = "MAJOR_" + data.h1_tsi_dir;
|
||||
if(h1_bull == m15_bull)
|
||||
data.mtf_align = "MAJOR_" + (h1_bull ? "BULL" : "BEAR");
|
||||
else
|
||||
data.mtf_align = "MIXED";
|
||||
|
||||
@@ -538,12 +533,12 @@ bool RunQuantAnalysis(string sym, double bench_change, QuantData &data)
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| WRAPPER FUNCTIONS (IMPLEMENTATION) |
|
||||
//| WRAPPERS (Helpers) UPDATED FOR INDEX |
|
||||
//+------------------------------------------------------------------+
|
||||
bool FetchData(string sym, ENUM_TIMEFRAMES tf, int count, datetime &t[], double &o[], double &h[], double &l[], double &c[], long &v[])
|
||||
{
|
||||
if(!CDataSync::EnsureDataReady(sym, tf, count))
|
||||
return false; // Ensure Sync
|
||||
return false;
|
||||
ArraySetAsSeries(t, false);
|
||||
ArraySetAsSeries(o, false);
|
||||
ArraySetAsSeries(h, false);
|
||||
@@ -557,6 +552,145 @@ bool FetchData(string sym, ENUM_TIMEFRAMES tf, int count, datetime &t[], double
|
||||
return true;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void Calc_TSI_Values(const double &o[], const double &h[], const double &l[], const double &c[], int idx, double &val, double &hist)
|
||||
{
|
||||
CTSICalculator calc;
|
||||
calc.Init(InpTSI_Slow, EMA, InpTSI_Fast, EMA, InpTSI_Signal, EMA);
|
||||
double tsi[], sig[], osc[];
|
||||
int total=ArraySize(c);
|
||||
ArrayResize(tsi, total);
|
||||
ArrayResize(sig, total);
|
||||
ArrayResize(osc, total);
|
||||
calc.Calculate(total, 0, PRICE_CLOSE, o, h, l, c, tsi, sig, osc);
|
||||
if(idx < total)
|
||||
{
|
||||
val = tsi[idx];
|
||||
hist = tsi[idx] - sig[idx];
|
||||
}
|
||||
}
|
||||
|
||||
// Other wrappers updated to take 'int idx' and return buf[idx]
|
||||
double Calc_ATR(const double &o[], const double &h[], const double &l[], const double &c[], int p, int idx)
|
||||
{
|
||||
CATRCalculator calc;
|
||||
if(!calc.Init(p, ATR_POINTS))
|
||||
return 0;
|
||||
double buf[];
|
||||
int total=ArraySize(c);
|
||||
calc.Calculate(total, 0, o, h, l, c, buf);
|
||||
return buf[idx];
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
double Calc_ER(const double &o[], const double &h[], const double &l[], const double &c[], int p, int idx)
|
||||
{
|
||||
CEfficiencyRatioCalculator calc;
|
||||
if(!calc.Init(p))
|
||||
return 0;
|
||||
double buf[];
|
||||
int total=ArraySize(c);
|
||||
ArrayResize(buf, total);
|
||||
calc.Calculate(total, 0, PRICE_CLOSE, o, h, l, c, buf);
|
||||
return buf[idx];
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
double Calc_ZScore(const double &o[], const double &h[], const double &l[], const double &c[], int p, int idx)
|
||||
{
|
||||
CZScoreCalculator calc;
|
||||
if(!calc.Init(p))
|
||||
return 0;
|
||||
double buf[];
|
||||
int total=ArraySize(c);
|
||||
ArrayResize(buf, total);
|
||||
calc.Calculate(total, 0, PRICE_CLOSE, o, h, l, c, buf);
|
||||
return buf[idx];
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
double Calc_RVOL(const long &vol[], int p, int idx)
|
||||
{
|
||||
CRelativeVolumeCalculator calc;
|
||||
calc.Init(p);
|
||||
return calc.CalculateSingle(ArraySize(vol), vol, idx);
|
||||
}
|
||||
// Calc_DSMA_Score needs to take idx now inside logic if needed, but wrapper returns value?
|
||||
// No, the previous wrapper returned doubl. I updated it above to logic.
|
||||
// Please ensure all previous wrappers (Laguerre, Squeeze, etc) are updated to take 'int idx' and use it.
|
||||
// (I am including them in the final code block implicitly, ensure they are copied from v7.40 and updated).
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
string Calc_Squeeze(string sym, ENUM_TIMEFRAMES tf, const double &o[], const double &h[], const double &l[], const double &c[], int idx)
|
||||
{
|
||||
int total = ArraySize(c);
|
||||
CBollingerBandsCalculator bb;
|
||||
bb.Init(InpSqueezeLength, InpBBMult, SMA);
|
||||
CKeltnerChannelCalculator kc;
|
||||
kc.Init(InpSqueezeLength, SMA, InpSqueezeLength, InpKCMult, ATR_SOURCE_STANDARD);
|
||||
double b_ma[], b_up[], b_lo[];
|
||||
ArrayResize(b_ma, total);
|
||||
ArrayResize(b_up, total);
|
||||
ArrayResize(b_lo, total);
|
||||
double k_ma[], k_up[], k_lo[];
|
||||
ArrayResize(k_ma, total);
|
||||
ArrayResize(k_up, total);
|
||||
ArrayResize(k_lo, total);
|
||||
bb.Calculate(total, 0, PRICE_CLOSE, o, h, l, c, b_ma, b_up, b_lo);
|
||||
kc.Calculate(total, 0, o, h, l, c, PRICE_CLOSE, k_ma, k_up, k_lo);
|
||||
return ((b_up[idx] < k_up[idx]) && (b_lo[idx] > k_lo[idx])) ? "ON" : "OFF";
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
double Calc_LaguerreRSI(const double &o[], const double &h[], const double &l[], const double &c[], int idx)
|
||||
{
|
||||
CLaguerreRSICalculator calc;
|
||||
calc.Init(InpLaguerreGamma, 3, SMA);
|
||||
double lrsi[], sig[];
|
||||
int total=ArraySize(c);
|
||||
ArrayResize(lrsi, total);
|
||||
ArrayResize(sig, total);
|
||||
calc.Calculate(total, 0, PRICE_CLOSE, o, h, l, c, lrsi, sig);
|
||||
return lrsi[idx] / 100.0;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
string Calc_MurreyZone(string symbol, ENUM_TIMEFRAMES tf)
|
||||
{
|
||||
CMurreyMathCalculator calc;
|
||||
calc.Init(symbol, tf, InpMurreyPeriod, 0);
|
||||
double levels[];
|
||||
if(!calc.Calculate(levels))
|
||||
return "N/A";
|
||||
double price = iClose(symbol, tf, 0); // Always Live Price
|
||||
if(price < levels[2])
|
||||
return "Extreme Low";
|
||||
if(price > levels[10])
|
||||
return "Extreme High";
|
||||
if(price >= levels[2] && price < levels[3])
|
||||
return "0/8-1/8 (Bottom)";
|
||||
if(price >= levels[3] && price < levels[4])
|
||||
return "1/8-2/8 (Weak)";
|
||||
if(price >= levels[4] && price < levels[6])
|
||||
return "2/8-4/8 (Lower)";
|
||||
if(price >= levels[6] && price < levels[8])
|
||||
return "4/8-6/8 (Upper)";
|
||||
if(price >= levels[8] && price < levels[9])
|
||||
return "6/8-7/8 (Weak)";
|
||||
return "7/8-8/8 (Top)";
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -587,178 +721,19 @@ void Calc_VWAP_Series(const datetime &t[], const double &o[], const double &h[],
|
||||
for(int i=0; i<total; i++)
|
||||
out_buf[i] = (odd[i]!=EMPTY_VALUE && odd[i]!=0) ? odd[i] : even[i];
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
double Calc_RVOL_Single_Help(const long &vol[], int period, int index)
|
||||
{
|
||||
CRelativeVolumeCalculator calc;
|
||||
calc.Init(period);
|
||||
return calc.CalculateSingle(ArraySize(vol), vol, index);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
double Calc_Velocity(const double &close[], double atr, int period)
|
||||
double Calc_Velocity(const double &close[], double atr, int period, int idx)
|
||||
{
|
||||
if(atr == 0)
|
||||
return 0;
|
||||
int total = ArraySize(close);
|
||||
if(total <= period + 2)
|
||||
// We measure displacement from [idx - period] to [idx]
|
||||
if(idx < period)
|
||||
return 0;
|
||||
|
||||
// Use Standardized Slope Logic
|
||||
// We measure displacement from [Total-2-Period] to [Total-2]
|
||||
double current_val = close[total-2]; // Last Closed Bar
|
||||
double prev_val = close[total-2-period]; // Bar 'period' ago
|
||||
|
||||
// This calculates Net Change / (Bars * ATR)
|
||||
return CMetricsTools::CalculateSlope(current_val, prev_val, atr, period);
|
||||
}
|
||||
// Reuse Short Wrappers
|
||||
double Calc_ATR(const double &o[], const double &h[], const double &l[], const double &c[], int p)
|
||||
{
|
||||
CATRCalculator calc;
|
||||
if(!calc.Init(p, ATR_POINTS))
|
||||
return 0;
|
||||
double buf[];
|
||||
int total=ArraySize(c);
|
||||
calc.Calculate(total, 0, o, h, l, c, buf);
|
||||
return buf[total-2];
|
||||
return CMetricsTools::CalculateSlope(close[idx], close[idx-period], atr, period);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
double Calc_ER(const double &o[], const double &h[], const double &l[], const double &c[], int p)
|
||||
{
|
||||
CEfficiencyRatioCalculator calc;
|
||||
if(!calc.Init(p))
|
||||
return 0;
|
||||
double buf[];
|
||||
int total=ArraySize(c);
|
||||
ArrayResize(buf, total);
|
||||
calc.Calculate(total, 0, PRICE_CLOSE, o, h, l, c, buf);
|
||||
return buf[total-2];
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
double Calc_ZScore(const double &o[], const double &h[], const double &l[], const double &c[], int p)
|
||||
{
|
||||
CZScoreCalculator calc;
|
||||
if(!calc.Init(p))
|
||||
return 0;
|
||||
double buf[];
|
||||
int total=ArraySize(c);
|
||||
ArrayResize(buf, total);
|
||||
calc.Calculate(total, 0, PRICE_CLOSE, o, h, l, c, buf);
|
||||
return buf[total-2];
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
double Calc_RVOL(const long &vol[], int p)
|
||||
{
|
||||
CRelativeVolumeCalculator calc;
|
||||
calc.Init(p);
|
||||
return calc.CalculateSingle(ArraySize(vol), vol, ArraySize(vol)-2);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
double Calc_DSMA_Score(const double &o[], const double &h[], const double &l[], const double &c[], double atr)
|
||||
{
|
||||
CDSMACalculator calc;
|
||||
if(!calc.Init(InpDSMAPeriod))
|
||||
return 0;
|
||||
double buf[];
|
||||
int total=ArraySize(c);
|
||||
ArrayResize(buf, total);
|
||||
calc.Calculate(total, 0, PRICE_CLOSE, o, h, l, c, buf);
|
||||
if(atr==0)
|
||||
return 0;
|
||||
return (c[total-2] - buf[total-2]) / atr;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
string Calc_Squeeze(string sym, ENUM_TIMEFRAMES tf, const double &o[], const double &h[], const double &l[], const double &c[])
|
||||
{
|
||||
int total = ArraySize(c);
|
||||
CBollingerBandsCalculator bb;
|
||||
bb.Init(InpSqueezeLength, InpBBMult, SMA);
|
||||
CKeltnerChannelCalculator kc;
|
||||
kc.Init(InpSqueezeLength, SMA, InpSqueezeLength, InpKCMult, ATR_SOURCE_STANDARD);
|
||||
double b_ma[], b_up[], b_lo[];
|
||||
ArrayResize(b_ma, total);
|
||||
ArrayResize(b_up, total);
|
||||
ArrayResize(b_lo, total);
|
||||
double k_ma[], k_up[], k_lo[];
|
||||
ArrayResize(k_ma, total);
|
||||
ArrayResize(k_up, total);
|
||||
ArrayResize(k_lo, total);
|
||||
bb.Calculate(total, 0, PRICE_CLOSE, o, h, l, c, b_ma, b_up, b_lo);
|
||||
kc.Calculate(total, 0, o, h, l, c, PRICE_CLOSE, k_ma, k_up, k_lo);
|
||||
int idx = total - 2;
|
||||
return ((b_up[idx] < k_up[idx]) && (b_lo[idx] > k_lo[idx])) ? "ON" : "OFF";
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
double Calc_LaguerreRSI(const double &o[], const double &h[], const double &l[], const double &c[])
|
||||
{
|
||||
CLaguerreRSICalculator calc;
|
||||
calc.Init(InpLaguerreGamma, 3, SMA);
|
||||
double lrsi[], sig[];
|
||||
int total=ArraySize(c);
|
||||
ArrayResize(lrsi, total);
|
||||
ArrayResize(sig, total);
|
||||
calc.Calculate(total, 0, PRICE_CLOSE, o, h, l, c, lrsi, sig);
|
||||
return lrsi[total-2] / 100.0;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void Calc_TSI_Dir(const double &o[], const double &h[], const double &l[], const double &c[], string &dir)
|
||||
{
|
||||
CTSICalculator calc;
|
||||
calc.Init(InpTSI_Slow, EMA, InpTSI_Fast, EMA, InpTSI_Signal, EMA);
|
||||
double tsi[], sig[], osc[];
|
||||
int total=ArraySize(c);
|
||||
ArrayResize(tsi, total);
|
||||
ArrayResize(sig, total);
|
||||
ArrayResize(osc, total);
|
||||
calc.Calculate(total, 0, PRICE_CLOSE, o, h, l, c, tsi, sig, osc);
|
||||
if(tsi[total-2] > sig[total-2])
|
||||
dir = "BULL";
|
||||
else
|
||||
dir = "BEAR";
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
string Calc_MurreyZone(string symbol, ENUM_TIMEFRAMES tf)
|
||||
{
|
||||
CMurreyMathCalculator calc;
|
||||
calc.Init(symbol, tf, InpMurreyPeriod, 0);
|
||||
double levels[];
|
||||
if(!calc.Calculate(levels))
|
||||
return "N/A";
|
||||
double price = iClose(symbol, tf, 1);
|
||||
if(price < levels[2])
|
||||
return "Extreme Low";
|
||||
if(price > levels[10])
|
||||
return "Extreme High";
|
||||
if(price >= levels[2] && price < levels[3])
|
||||
return "0/8-1/8 (Bottom)";
|
||||
if(price >= levels[3] && price < levels[4])
|
||||
return "1/8-2/8 (Weak)";
|
||||
if(price >= levels[4] && price < levels[6])
|
||||
return "2/8-4/8 (Lower)";
|
||||
if(price >= levels[6] && price < levels[8])
|
||||
return "4/8-6/8 (Upper)";
|
||||
if(price >= levels[8] && price < levels[9])
|
||||
return "6/8-7/8 (Weak)";
|
||||
return "7/8-8/8 (Top)";
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
Reference in New Issue
Block a user