基于主成分的特征选择与降维·综合运用
(3/3)·PCA遇高度相关变量会稀释单变量贡献,FSCA贪婪筛选让降维与特征选择一次到位
FSCA 类的内部构造与标准化入口
CFsca 类把「前向选择成分分析」整套计算封进了 fsca.mqh,外面调用的人只需要关心 fit() 和一堆 getter。它旁边还放了一个独立的 stdmat() 例程,专门做列级标准化,不依赖类实例,方便单独拿去预处理行情矩阵。 stdmat() 的逻辑很直白:先按列求均值和标准差,给标准差加 1e-10 防止除零,再逐行做 (x-mean)/std 写回新矩阵。外汇或贵金属多品种收益率矩阵直接丢进去,就能得到均值 0、方差 1 的输入,降低量纲差异带来的主成分偏移。 类里面私有成员装的全是中间产物——相关矩阵 m_corrmat、因子载荷 m_structmat、主成分 m_principal_components,还有 FSCA 专用的 m_Fsca 和 m_coeffs。fit() 必须先跑:标准化后算相关矩阵,提取特征向量和累积特征值,把非零特征值个数记进 m_num_comps。 若 m_structmat 只有一行,说明因子结构算崩了,fit() 直接返 false。遇到负特征值时会微调相关矩阵重算,直到全为正,再算 FSCA 与 FSCV 成分,成功才把 m_fitted 置 true。MT5 里 new 一个 CFsca 后记得先判 fit() 返回值再读 getter,否则拿到的是空矩阵。 这类多变量降维用于贵金属跨品种联动分析时属高风险探究,样本外稳定性需自测。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| standardize a matrix | class=class="str">"cmt">//+------------------------------------------------------------------+ matrix stdmat(matrix &in) { vector mean = in.Mean(class="num">0); vector std = in.Std(class="num">0); std += class="num">1e-10; matrix out = in; for (class="type">ulong row = class="num">0; row < out.Rows(); row++) { if (!out.Row((in.Row(row) - mean) / std, row)) { Print(__FUNCTION__, " error ", GetLastError()); class="kw">return matrix::Zeros(in.Rows(), in.Cols()); } } class="kw">return out; } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| fsca class implementation | class=class="str">"cmt">//+------------------------------------------------------------------+ class CFsca { class="kw">private: class="type">bool m_fitted; class=class="str">"cmt">//flag showing if principal factors were extracted matrix m_corrmat, class=class="str">"cmt">//correlation matrix m_covar, class=class="str">"cmt">//altered correlation matrix m_data, class=class="str">"cmt">//standardized data is here m_eigvectors, class=class="str">"cmt">//matrix of eigen vectors of m_corrmat matrix m_structmat, class=class="str">"cmt">//factor loading matrix of m_corrmat matrix m_principal_components, class=class="str">"cmt">//principal components m_fscv_struct, class=class="str">"cmt">//fsca factor structure m_fscv_eigvects, class=class="str">"cmt">//fsca eigen structure m_Fsca, class=class="str">"cmt">//ordered fsca variables m_coeffs; class=class="str">"cmt">//fsca component coefficients
◍ 前向选择成分分析的内部变量与拟合入口
做前向选择成分分析(FSCA)时,类里先要挂一批状态向量:m_eigvalues 存相关系数矩阵的特征值,m_sqcorr 存均值平方相关,m_fscv_eigvals 与 m_fscv_cumeigvals 分别对应 FSCA 的特征值和累计方差贡献。m_num_comps 记录数据中冗余变动的独立个数,m_preds 则是数据集列数,也就是变量个数。 m_keptorderedcolumns、m_keptrefinedcolumns、m_keptcolumns 三个 ulong 数组分别存有序 FSCA、后向精炼 FSCA、以及通用分析里被选中的列索引;m_bestcolumn 记首个被选列,m_best_crit 存最优准则值。这些变量不初始化干净,后面 ArrayResize 很容易返回 -1。 fit() 是真正跑分析的入口。它先读 data.Cols() 赋值 m_preds,把 m_fitted 置 false,再用 stdmat(data) 标准化数据、用 CorrCoef(false) 算相关矩阵。若 compute_factor_structure 只返回 1 行,说明矩阵退化,直接 return false。 下面的代码把三个保留列数组按 m_num_comps 长度扩容,并用 ULONG_MAX 初始化 m_keptcolumns;任一步 ArrayResize 或 ArrayInitialize 失败就打印错误并返回。随后算主成分,并用 (compute_criterion(...) - 1.0) / (m_preds - 1) 填 m_sqcorr——这一步把每列相对已选集的相关冗余度归一化,是判断下个该进哪列的依据。
m_Fscv; class=class="str">"cmt">//refined fsca variables vector m_eigvalues, class=class="str">"cmt">//vector of eigen values of m_corrmat matrix m_sqcorr, class=class="str">"cmt">//mean squared correlation matrix m_fscv_eigvals, class=class="str">"cmt">//fsca eigen values m_fscv_cumeigvals, class=class="str">"cmt">//fsca cumulative variance contribution m_cumeigvalues; class=class="str">"cmt">//cumulative variance contributions of m_corrmat matrix class="type">ulong m_num_comps; class=class="str">"cmt">//unique instances of redundent variation in m_data class="type">ulong m_preds; class=class="str">"cmt">//number of variables(columns) in dataset(m_data) class="type">ulong m_keptorderedcolumns[],class=class="str">"cmt">//indices of columns upon which components are calculated for ordered fsca m_keptrefinedcolumns[],class=class="str">"cmt">//indices of columns upon which components are calculated for backward refined fsca m_keptcolumns[], m_bestcolumn; class=class="str">"cmt">//index of first selected column in analysis class="type">class="kw">double m_best_crit; class=class="str">"cmt">//best criterion value class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| perform forward selection component analysis on a raw dataset | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool fit(matrix &data) { m_preds = data.Cols(); m_fitted = false; m_sqcorr = vector::Zeros(m_preds); m_data = stdmat(data); m_corrmat = m_data.CorrCoef(false); m_structmat = compute_factor_structure(m_corrmat, m_eigvectors, m_eigvalues, m_cumeigvalues); if (m_structmat.Rows() == class="num">1) class="kw">return false; m_num_comps = m_cumeigvalues.Size(); if (ArrayResize(m_keptorderedcolumns, class="type">int(m_num_comps)) < class="num">0 || ArrayResize(m_keptrefinedcolumns, class="type">int(m_num_comps)) < class="num">0 || ArrayResize(m_keptcolumns, class="type">int(m_num_comps)) < class="num">0 || ArrayInitialize(m_keptcolumns, ULONG_MAX) < class="num">0) { Print(__FUNCTION__, " array error ", GetLastError()); class="kw">return false; } m_principal_components = compute_principal_components(); for (class="type">ulong i = class="num">0; i < m_preds; i++) m_sqcorr[i] = (compute_criterion(m_corrmat, m_keptcolumns, class="num">0, i) - class="num">1.0) / class="type">class="kw">double(m_preds - class="num">1); vector evd_vals = m_eigvalues; class="kw">while (evd_vals[m_preds - class="num">1] <= class="num">0.0) { for (class="type">ulong j = class="num">1; j < m_preds; j++) { for (class="type">ulong k = class="num">0; k < j; k++) {
「相关系数矩阵的特征分解与成分提取接口」
在主分析流程里,相关系数矩阵做完对称化后会乘上一个 0.99999 的衰减系数,目的是轻微压低对角线外相关性,避免数值层面出现退化导致特征分解失败。 随后调用 EigenSymmetricDC 做对称矩阵特征分解,只取特征值向量 evd_vals,特征向量矩阵用 empty 占位丢弃。若分解返回 false,会打印函数名与 GetLastError() 并直接 return false,这一步是后续所有成分计算能否继续的硬门槛。 拟合标志 m_fitted 取决于 m_Fsca 与 m_Fscv 的行数是否都大于 1,也就是说至少要算出两组成分才算分析成功。外汇与贵金属市场的高波动可能让样本协方差奇异,这种情形下 m_fitted 倾向为 false。 对外暴露的四个 getter 都先检查 m_fitted:未拟合时打印提示并返回空矩阵或 false。get_principal_components 返回主成分,get_fsca_components 返回有序 FSCA 成分,get_fscv_components 返回回代精修后的 FSCA 成分,get_fsca_var_indices 则通过 ArrayCopy 把保留的列索引拷出,拷贝长度以 m_num_comps 为准。开 MT5 把这段接进自己的分析类,就能直接拿到可用于可视化的成分矩阵。
m_corrmat[j][k] *= class="num">0.99999; m_corrmat[k][j] = m_corrmat[j][k]; } } matrix empty; if (!m_corrmat.EigenSymmetricDC(EIGVALUES_N, evd_vals, empty)) { Print(__FUNCTION__, " failed eig decomp ", GetLastError()); class="kw">return false; } } m_Fsca = compute_fsca_components(m_data); m_Fscv = compute_fscv_components(m_data); m_fitted = (m_Fsca.Rows() > class="num">1 && m_Fscv.Rows() > class="num">1); class="kw">return m_fitted; } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| get the principal components | class=class="str">"cmt">//+------------------------------------------------------------------+ matrix get_principal_components(class="type">void) { if (!m_fitted) { Print(__FUNCTION__, " either analyze() returned an error or it was not called "); class="kw">return matrix::Zeros(class="num">0, class="num">0); } class="kw">return m_principal_components; } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| get the ordered fsca components | class=class="str">"cmt">//+------------------------------------------------------------------+ matrix get_fsca_components(class="type">void) { if (!m_fitted) { Print(__FUNCTION__, " either analyze() returned an error or it was not called "); class="kw">return matrix::Zeros(class="num">0, class="num">0); } class="kw">return m_Fsca; } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| get the backward refined fsca components | class=class="str">"cmt">//+------------------------------------------------------------------+ matrix get_fscv_components(class="type">void) { if (!m_fitted) { Print(__FUNCTION__, " either analyze() returned an error or it was not called "); class="kw">return matrix::Zeros(class="num">0, class="num">0); } class="kw">return m_Fscv; } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| get indices of variables defining the ordered fsca components | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool get_fsca_var_indices(class="type">ulong &indices[]) { if (!m_fitted) { Print(__FUNCTION__, " either analyze() returned an error or it was not called "); class="kw">return false; } class="kw">return (ArrayCopy(indices, m_keptorderedcolumns, class="num">0, class="num">0, class="type">int(m_num_comps)) > class="num">0); }
从拟合状态里抠出降维中间结果
做主成分降维时,analyze() 跑完会把中间产物锁在类内部,外部想复核只能靠一组 getter。核心前提就一个:m_fitted 必须为 true,否则所有接口直接 Print 报错并返回空对象或 false。 get_fscv_var_indices() 把反向精炼后的成分列下标拷进 ulong 数组,靠 ArrayCopy 从 m_keptrefinedcolumns 取前 m_num_comps 个;返回值大于 0 才算成功,说明至少有 1 个成分被保留。 方差贡献有两条线:get_principal_components_cumulative_variance_contribution() 返回 m_cumeigvalues,get_fscv_cumulative_variance_contribution() 返回 m_fscv_cumeigvals。两者都是 vector,未拟合时给 Zeros(0),你可以用 Size() 判断是否为空再画图。 特征结构分两套:主成分用 get_principal_components_eigstructure() 吐出 m_eigvectors 和 m_eigvalues;FSC 用 get_fscv_eigstructure() 吐出 m_fscv_eigvects 和 m_fscv_eigvals。都是引用传参直接赋值,返回 true 即拿到矩阵和向量,可在 MT5 里用 matrix.Print() 肉眼核对正交性。 外汇与贵金属行情具有高杠杆与跳空风险,降维结果只描述历史协方差结构,对后续走势无预测保证,参数改动前先在策略测试器跑一遍。
class="type">bool get_fscv_var_indices(class="type">ulong &indices[]) { if (!m_fitted) { Print(__FUNCTION__, " either analyze() returned an error or it was not called "); class="kw">return false; } class="kw">return (ArrayCopy(indices, m_keptrefinedcolumns, class="num">0, class="num">0, class="type">int(m_num_comps)) > class="num">0); } vector get_principal_components_cumulative_variance_contribution(class="type">void) { if (!m_fitted) { Print(__FUNCTION__, " either analyze() returned an error or it was not called "); class="kw">return vector::Zeros(class="num">0); } class="kw">return m_cumeigvalues; } vector get_fscv_cumulative_variance_contribution(class="type">void) { if (!m_fitted) { Print(__FUNCTION__, " either analyze() returned an error or it was not called "); class="kw">return vector::Zeros(class="num">0); } class="kw">return m_fscv_cumeigvals; } class="type">bool get_principal_components_eigstructure(matrix &vectors, vector &values) { if (!m_fitted) { Print(__FUNCTION__, " either analyze() returned an error or it was not called "); class="kw">return false; } vectors = m_eigvectors; values = m_eigvalues; class="kw">return true; } class="type">bool get_fscv_eigstructure(matrix &vectors, vector &values) { if (!m_fitted) { Print(__FUNCTION__, " either analyze() returned an error or it was not called "); class="kw">return false; } vectors = m_fscv_eigvects; values = m_fscv_eigvals; class="kw">return true; }
◍ 因子结构提取的四个访问接口
在 MT5 里做主成分或因子分析类指标时,模型拟合状态决定了一切取值的合法性。上面四个方法都先判断 m_fitted 标志,未拟合就直接返回空矩阵或空向量,并在终端打印函数名加错误说明,避免后续计算踩到零维数据。 get_principal_components_factorstructure 返回 m_structmat,即标准主成分载荷矩阵;get_fscv_factorstructure 返回 m_fscv_struct,对应带后向精炼的 FSC 因子结构。两者都是 matrix 类型,列数等于提取的因子数,行数等于原始变量数。 get_avg_correlations 给的是 m_sqcorr,一个 vector,存各因子平均平方相关,用来粗看因子间冗余度。get_fsca_component_coeffs 吐出 m_coeffs,是前向筛选下的成分系数矩阵,可直接用于新样本打分。 实盘接这些接口前,先在 EA 里确认 analyze() 已跑通:若 m_fitted 为 false,四个调用全返回 0 维对象,EURUSD 或 XAUUSD 这类高杠杆品种上误用可能引发数组越界报警。外汇和贵金属波动剧烈,因子结构随 regime 切换会漂移,定期重拟合更稳妥。
matrix get_principal_components_factorstructure(class="type">void) { if (!m_fitted) { Print(__FUNCTION__, " either analyze() returned an error or it was not called "); class="kw">return matrix::Zeros(class="num">0, class="num">0); } class="kw">return m_structmat; } class=class="str">"cmt">//+-------------------------------------------------------------------+ class=class="str">"cmt">//| get the factor structure of FSC with backward refinement | class=class="str">"cmt">//+-------------------------------------------------------------------+ matrix get_fscv_factorstructure(class="type">void) { if (!m_fitted) { Print(__FUNCTION__, " either analyze() returned an error or it was not called "); class="kw">return matrix::Zeros(class="num">0, class="num">0); } class="kw">return m_fscv_struct; } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| get mean squared correlations | class=class="str">"cmt">//+------------------------------------------------------------------+ vector get_avg_correlations(class="type">void) { if (!m_fitted) { Print(__FUNCTION__, " either analyze() returned an error or it was not called "); class="kw">return vector::Zeros(class="num">0); } class="kw">return m_sqcorr; } class=class="str">"cmt">//+-------------------------------------------------------------------+ class=class="str">"cmt">//| get forward selection component coefficients matrix | class=class="str">"cmt">//+-------------------------------------------------------------------+ matrix get_fsca_component_coeffs(class="type">void) { if (!m_fitted) { Print(__FUNCTION__, " either analyze() returned an error or it was not called "); class="kw">return matrix::Zeros(class="num">0, class="num">0); } class="kw">return m_coeffs; }
「用脚本拆开随机变量里的隐性依赖」
下面这段 MQL5 脚本(FSCA_Demo.mq5)直接跑一遍,就能看清一个 100×9 的随机矩阵里到底藏了几条独立变异来源。它先引入 fsca.mqh 里的 CFsca 类,再手造三个由现有列求和而来的新向量,把依赖关系埋进数据里。 脚本固定随机种子 120,生成 100 个样本、9 个特征,其中后 3 列是第 0~3 列的线性组合,其余相互独立。拟合后提取累积方差贡献率、因子结构和均方相关系数等结果。 实跑结论很直白:9 个变量只析出 6 个独立变异来源,和「后 3 列是组合变量」的设定吻合。第一主成分约占三分之一总变异,前两个主成分合起来解释超 55%;最后三列的平均相关系数最高,第 4、5 列最低。 前向选择索引把贡献最大的变量排在最前——本例里最后一列(索引 8)排头,说明它捕获了最多变异。系数表里越靠后的变量系数越接近 0,最重要的变量系数近 1。 反向精炼 FSCA 不讲究顺序,但能自动剔除依赖变量、只留独立随机项。对比标准前向选择,这种组合筛选的解释性明显更好,读者可以改种子或列数自行验证。外汇与贵金属市场高风险,此类降维方法仅用于样本结构认知,不预示任何价格方向。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| FSCA_Demo.mq5 | class=class="str">"cmt">//| Copyright class="num">2024, MetaQuotes Ltd. | class=class="str">"cmt">//| [MQL5官方文档] | class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#class="kw">property copyright "Copyright class="num">2024, MetaQuotes Ltd." class="macro">#class="kw">property link "[MQL5官方文档] class="macro">#class="kw">property version "class="num">1.00" class="macro">#include<fsca.mqh> class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Script program start function | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnStart() { class=class="str">"cmt">//--- MathSrand(class="num">120); class=class="str">"cmt">//--- matrix mat(class="num">100,class="num">9); class=class="str">"cmt">//--- mat.Random(class="num">0.0,class="num">1.0); class=class="str">"cmt">//--- vector var1 = mat.Col(class="num">0) + mat.Col(class="num">1); class=class="str">"cmt">// --- vector var2 = mat.Col(class="num">2) + mat.Col(class="num">3); class=class="str">"cmt">//--- vector var3 = var1 + var2; class=class="str">"cmt">//--- if(!mat.Col(var1,class="num">6) || !mat.Col(var2,class="num">7) || !mat.Col(var3,class="num">8)) { Print("failed column assignment ", GetLastError()); class="kw">return; } class=class="str">"cmt">//--- CFsca fsca; class=class="str">"cmt">//--- if(!fsca.fit(mat)) class="kw">return; class=class="str">"cmt">//--- class="type">ulong index[]; Print("Principal components cumulative variance conributions \n", fsca.get_principal_components_cumulative_variance_contribution()); Print(" Principal components factor structure \n", fsca.get_principal_components_factorstructure()); Print("Mean squared correlation of each variable with all others \n", fsca.get_avg_correlations()); class=class="str">"cmt">//--- if(fsca.get_fsca_var_indices(index)) { Print(" Ordered FSCA components based on variables located in column indices "); ArrayPrint(index); } class=class="str">"cmt">//---
从日志反推 BTCUSD 日线的主成分收敛
跑完 FSCA 向后精炼后,真正有用的不是代码本身,而是终端里那几行 Print 出来的矩阵。下面这段调用把系数、入选变量索引、特征值和累积方差一股脑打了出来,可直接粘进 EA 的 OnStart 里验证。 Print(" Ordered FSCA component coefficients matrix \n", fsca.get_fsca_component_coeffs()); if(fsca.get_fscv_var_indices(index)) { Print(" Backward refined FSCA components based on variables located in column indices "); ArrayPrint(index); } matrix vects; vector vals; if(fsca.get_fscv_eigstructure(vects,vals)) Print("Backward refined fsca component eigenvalues \n", vals); Print(" Backward refined cumulative variance contributions \n", fsca.get_fscv_cumulative_variance_contribution()); Print(" Backward refined fsca components factor structure \n", fsca.get_fscv_factorstructure()); 在 BTCUSD 的 D1 周期上,累积方差贡献打印出来是 [31.72, 54.98, 70.21, 82.35, 91.91, 100],意味着前 5 个主成分已经吃掉 91.9% 的信息量,第 6 个直接补满。做降维时留 5 列大概率够用,再多加反而引入噪声。 因子结构矩阵里最后三列系数落在 1e-9 量级、基本为 0,说明那几个原始变量在向后剔除后被压缩成无效维度。外汇和贵金属品种的高杠杆属性下,用这种稀疏结构做信号过滤时仍要警惕过拟合,回测漂亮不等于实盘概率占优。
Print(" Ordered FSCA component coefficients matrix \n", fsca.get_fsca_component_coeffs()); class=class="str">"cmt">//--- if(fsca.get_fscv_var_indices(index)) { Print(" Backward refined FSCA components based on variables located in column indices "); ArrayPrint(index); } class=class="str">"cmt">//--- matrix vects; vector vals; class=class="str">"cmt">//--- if(fsca.get_fscv_eigstructure(vects,vals)) Print("Backward refined fsca component eigenvalues \n", vals); class=class="str">"cmt">//--- Print(" Backward refined cumulative variance contributions \n", fsca.get_fscv_cumulative_variance_contribution()); class=class="str">"cmt">//--- Print(" Backward refined fsca components factor structure \n", fsca.get_fscv_factorstructure());
◍ 从日志读出 BTCUSD 日线的因子载荷
在 MT5 策略测试器日志里,FSCA_Demo 对 BTCUSD 日线跑完一轮后,会吐出 DO/IP/NE/NO/RM 五组九维向量,每组对应一个提取出的因子方向。以 NE 行 [-0.7598, 0.6347, -0.0987, -0.0479, -0.0705, 0.0529, -1.36e-10, 1.33e-9, 0] 为例,前两维绝对值远超其余维度,说明该因子主要由前两个原始变量线性组合驱动,后面六个变量权重可视为噪声级。
QK 行给出各变量与所有其他变量的均方相关:第 9 列 0.22915 最高,第 5 列 0.00923 最低。这意味着第 9 个输入特征在日线样本里和其他特征纠缠最深,而第 5 个特征相对孤立,做降维时优先砍第 5 列可能损失最小。
QQ 行输出排序后的列索引 8 6 2 4 1 5,即 FSCA 按变量重要性把原矩阵重排了。LR 行说这是基于列索引的有序组件,QJ 行紧接着输出有序系数矩阵——你直接把 QQ 的顺序套到自己的特征数组上,就能复现它的降维投影,不用重跑整个 FSCA。
外汇与贵金属之外的 BTCUSD 同样属高波动品种,因子结论仅基于该 demo 的 D1 历史样本,换周期或换平台数据结论可能偏移,验证前先确认点差与滑点环境。
「BTCUSD日线因子矩阵的逆向解析」
上面这段日志来自 MT5 专家顾问在 BTCUSD 日线图表上的运行输出,同一时间戳 07:16:46.014 下打印了六组因子向量(DM/IR/LF/EM/JM/KK),每组都是 6 维数组。 DM 行首维接近 1(0.9999999989356357),其余维度普遍在 ±1 附近,说明该主成分主要由第 0 列变量驱动;而 KK 行仅在末维为 1.0489、其余五维都是 1e-10 量级的极小值,是典型的单位基向量特征。 ND 行给出了变量列索引的重排顺序:3 0 2 4 1 5,结合 CM 行「Backward refined FSCA components based on variables located in column indices」可知,这是逆向精炼后因子对应原变量的映射。 在 MT5 里把这段日志贴进专家顾问的 Print 输出,对照 ND 的重排顺序,就能反推出每个精炼因子实际挂钩的是哪一根原始序列——外汇与贵金属同理,但 BTCUSD 这种高波动品种请务必注意高风险,因子稳定性可能随行情结构断裂。
DM class="num">0 class="num">07:class="num">16:class="num">46.014 FSCA_Demo(BTCUSD,D1) [[class="num">0.9999999989356357,-class="num">0.9551778313323678,-class="num">1.196676438579672,-class="num">0.163265209103464,-class="num">0.1301792726137802,class="num">0.0741114239785734] IR class="num">0 class="num">07:class="num">16:class="num">46.014 FSCA_Demo(BTCUSD,D1) [class="num">7.62883988565579e-10,class="num">1.382882745177175,class="num">0.7080052470472653,class="num">0.1327136589445282,-class="num">0.8962870520067646,-class="num">0.01038862969019799] LF class="num">0 class="num">07:class="num">16:class="num">46.014 FSCA_Demo(BTCUSD,D1) [class="num">6.044914586250671e-10,-class="num">1.162965671680505e-09,class="num">1.327736785211269,class="num">0.1291890234653878,class="num">0.1244453203448803,-class="num">0.2315140872599129] EM class="num">0 class="num">07:class="num">16:class="num">46.014 FSCA_Demo(BTCUSD,D1) [class="num">5.84342504938995e-11,-class="num">9.115276242144255e-11,-class="num">1.685031073006549e-10,class="num">1.005785752630206,class="num">0.08917398176616295,class="num">0.2288955899392838] JM class="num">0 class="num">07:class="num">16:class="num">46.014 FSCA_Demo(BTCUSD,D1) [class="num">6.626278020206711e-11,class="num">8.05911615654048e-10,class="num">2.135397240976555e-10,-class="num">3.939133914887538e-11,class="num">1.404086244047662,class="num">0.03569800251260542] KK class="num">0 class="num">07:class="num">16:class="num">46.014 FSCA_Demo(BTCUSD,D1) [-class="num">2.859616016204214e-11,class="num">3.48387846349496e-11,class="num">2.600743786995707e-10,-class="num">1.479500966183878e-10,-class="num">3.333024481411151e-11,class="num">1.048952273510343]] CM class="num">0 class="num">07:class="num">16:class="num">46.014 FSCA_Demo(BTCUSD,D1) Backward refined FSCA components based on variables located in column indices ND class="num">0 class="num">07:class="num">16:class="num">46.014 FSCA_Demo(BTCUSD,D1) class="num">3 class="num">0 class="num">2 class="num">4 class="num">1 class="num">5
别急着下结论
FSCA 这套前向选择成分分析在 MT5 里跑通了,降维和特征挑选的活它能接,顺带把数据集的因子结构也扒了出来,对摸清楚价格背后的驱动机制有点用。代码都摊在三个文件里:np.mqh 管向量矩阵基础运算(74.16 KB),fsca.mqh 是 CFsca 类本体(26.89 KB),FSCA_Demo.mq5 是可直接加载的演示脚本(2.46 KB),整套打包才 16.32 KB。 有用户拿 5000 个特征、10000 行数据去压,三天没跑完——这说明实盘前你得先在小样本上摸清计算开销,别一上来就怼全品种 tick 数据。外汇和贵金属波动杂、跳空多,这类降维结果只能当概率参考,实盘前务必用历史数据回测验证。 真要落地,先把 FSCA_Demo.mq5 拖进 MT5 脚本目录跑一遍,看因子排序和你手动挑的指标重合度有多少,再决定要不要接进自己的 EA。