使用Python与MQL5进行多个交易品种分析(第二部分):主成分分析在投资组合优化中的应用(基础篇)
用 PCA 给多品种组合降方差
管理跨品种组合的总风险,核心难点在协方差矩阵随品种数平方膨胀。上篇用 SciPy 做回报最大化,这一节换一个目标:压住组合的整体方差。 主成分分析(PCA)是统计里降维的老工具,把它搬进 MQL5+Python 的外围分析,能把高相关的多个外汇/贵金属品种映射成少数几个互不相关的主成分,从而用更少的自由度约束总波动。 对做 EA 出售的开发者,这套思路能直接落地成「高/中/低风险投资模式」切换:后台跑 PCA 算主成分权重,前端只暴露风险档位给终端用户,既稳健又不牺牲灵活性。外汇与贵金属杠杆高、跳空频繁,降方差只降低概率性风险,不消除爆仓可能。
◍ 用PCA给加密组合降方差
本文盯的是一个含10种加密货币的投资组合。这类资产跑在区块链上,底层协议让欺诈交易几乎不可能,但也以高波动著称,手动控风险极难。 PCA出自多元统计的因子分析分支,图像压缩、机器学习降维都用它。核心动作是给数据集每一列算一个系数,乘完得到的新列要最大化方差——这就是第一主成分。 第二主成分和第一正交,彼此零相关,同时继续把总方差往上顶。如此循环,直到凑够能解释原始数据全部方差的成分数。 每个主成分可单独映射成一个离散风险档位,直接当成交易程序里的风险参数。MT5上跑一遍,几分钟就能把10币的总暴露方差分层管起来,加密资产高风险,仓位别裸奔。
「先把图像转成黑白再看主成分」
对第一次接触 PCA 的读者,直接看算法跑在真实数据上的可视化比读公式更有效。 这里拿 MQL5 官方那张标识图(图1)当样本,第一步先把它压成黑白模式。 黑白滤镜去掉色彩通道干扰,后续做主成分投影时,你能直接用肉眼比对原图与降维重建图的差异,判断各主成分抓到了哪部分结构。 在 MT5 里用脚本读入位图做灰度化,是验证这套降维思路最低成本的做法。
从图像降维直观看PCA的 Variance 最大化
用一张含「MQL5」字样的标识图做 PCA 演示:先读图转灰度,再展平喂给算法。保留 1 个主成分时,方差最大化只抓到黑底加中间亮块的轮廓,中心文字已不可读;保留 5 个主成分时文字恢复可读,但背景浅灰图标这类细节丢失,需更多成分才能补回。 这套实验的落点不在图像本身,而在资产组合:把组合内各品种收益率序列当成输入矩阵,PCA 同样会生成一组互不相关、且按方差贡献排序的线性组合。交易者借此可分离出波动主驱动,对贵金属与外汇组合做降维监控时,须留意杠杆下的高风险。 下方代码可直接在本地 Python 跑通(需自备 mql5.png),逐行逻辑是:导入 pandas/numpy/mt5/sklearn 等库 → 读图转灰度 → 展平 → 对 [1,5,20,50,100] 五个成分级分别 fit 并反重构出图。 import 区先拉入数据处理与 PCA 依赖;io.imread 读本地图,rgb2gray 转灰度;reshape 把二维图压成一维向量矩阵。 PCA(n_components=...) 指定保留成分数,fit 学方差方向,transform 投影后再 inverse_transform 还原回图像尺寸,subplots 横排对比原图与各成分重建效果。
class="macro">#Let&class="macro">#x27;s go class="kw">import pandas as pd class="kw">import numpy as np class="kw">import MetaTrader5 as mt5 class="kw">import seaborn as sns class="kw">import matplotlib.pyplot as plt from sklearn.decomposition class="kw">import PCA from skimage class="kw">import io, class="type">class="kw">color # Load and preprocess the image image = io.imread(&class="macro">#x27;mql5.png&class="macro">#x27;) # Replace with your image path image_gray = image_gray = class="type">class="kw">color.rgb2gray(image) # Convert to grayscale # Flatten the image h, w = image_gray.shape image_flattened = image_gray.reshape(h, w) # Apply PCA with different numbers of components n_components_list = [class="num">1,class="num">5,class="num">20,class="num">50,class="num">100] # Number of components to keep fig, axes = plt.subplots(class="num">1, len(n_components_list) + class="num">1, figsize=(class="num">20, class="num">10)) axes[class="num">0].imshow(image_gray, cmap=&class="macro">#x27;gray&class="macro">#x27;) axes[class="num">0].set_title("Original Image") axes[class="num">0].axis(&class="macro">#x27;off&class="macro">#x27;) for i, n_components in enumerate(n_components_list): # Initialize PCA and transform the flattened image pca = PCA(n_components=n_components) pca.fit(image_flattened) # Transform and inverse transform the image transformed_image = pca.transform(image_flattened) reconstructed_image = pca.inverse_transform(transformed_image).reshape(h, w) # Plot the reconstructed image axes[i + class="num">1].imshow(reconstructed_image, cmap=&class="macro">#x27;gray&class="macro">#x27;) axes[i + class="num">1].set_title(f"{n_components} Components") axes[i + class="num">1].axis(&class="macro">#x27;off&class="macro">#x27;) plt.tight_layout() plt.show()