机器学习在资产管理中的应用:从策略生成到组合优化实战指南
1. 从零到一理解机器学习在资产管理中的核心价值如果你对量化金融和机器学习感兴趣但面对海量的论文和零散的代码库感到无从下手那么你很可能已经听说过或接触过 firmai/machine-learning-asset-management 这个项目。这个在 GitHub 上开源的资源集合更像是一个由资深从业者精心整理的“藏宝图”它没有直接给你一个可以一键运行的“圣杯”策略而是系统地梳理了机器学习在资产组合构建与权重优化两大核心环节中的应用全景。我花了相当长的时间去研读、复现和测试其中的内容发现它的真正价值在于提供了一个结构化的学习框架和可操作的代码起点让你能避开那些华而不实的理论直接切入实战。简单来说这个项目回答了量化领域一个根本性问题当传统的多因子模型和现代投资组合理论MPT遇到瓶颈时机器学习能带来哪些新的可能性它把答案分成了两部分交易策略生成和组合权重优化。前者关乎如何利用算法发现市场中的“阿尔法”超额收益后者则解决在给定一组资产或策略后如何更智能地分配资金以控制风险并提升收益。对于刚入行的量化研究员、希望转型的数据科学家或是独立交易者这个项目就像一位经验丰富的导师为你指明了学习路径并提供了可以直接上手的“脚手架”代码。2. 项目全景解析两大支柱与十五种策略变体这个项目的结构非常清晰核心就是其论文《Machine Learning in Asset Management》中阐述的两大部分。理解这个框架是你有效利用其中资源的第一步。2.1 支柱一交易策略生成这部分对应论文的第一部分聚焦于使用机器学习模型来生成交易信号。它并非提供一个终极策略而是展示了15种不同思路的策略原型。我们可以将其大致归为几类经典量化策略的机器学习增强这类策略将传统量化思想与机器学习模型结合。例如“Tiny CTA”借鉴了商品交易顾问的趋势跟踪逻辑但用更简洁的规则和信号处理方式实现“Factor Investing”则是在行业轮动预测中应用机器学习模型试图超越简单的线性回归。另类数据与事件驱动这体现了现代量化金融的前沿。比如“Quantamental”策略它涉及爬取新闻、财报等文本数据使用自然语言处理技术提取情感信号“Earnings Surprise”和“Filing Outcomes”则专注于公司财报发布、监管文件披露等特定事件前后的价格模式预测。前沿算法探索这部分更具实验性质展示了强化学习、进化算法等在交易中的应用。“Tiny RL”是一个简化的强化学习交易框架“Evolutionary”和“Agent Strategy”则分别探索了遗传算法和智能体模拟在策略寻优中的作用“Deep Trading”则汇集了各种深度学习模型如LSTM、CNN用于价格预测。注意项目中的“策略”更多是方法论演示和可行性验证。每个笔记本的代码量都不大旨在阐明核心思想。你需要明白将这些原型打磨成实盘策略还需要大量的特征工程、参数优化、过拟合检验和风险管理模块的加入。2.2 支柱二组合权重优化在通过第一部分或其他方法得到一系列资产或策略的信号后我们面临下一个问题如何分配资金传统的均值-方差优化因其对输入参数预期收益和协方差矩阵极度敏感而饱受诟病。项目的第二部分展示了7种利用机器学习进行权重优化的方法旨在获得更稳健的组合。监督学习视角“Deep Portfolio”尝试用自编码器等深度学习模型直接学习从资产特征到最优权重的映射“Linear Regression”则是一种基于回归的简洁权重分配方法。无监督学习与降维“PCA and Hierarchical”利用主成分分析进行风险因子降维并结合层次聚类进行资产分类在此基础上构建组合“HRP”是近年来非常流行的层次风险平价方法它通过层次聚类重新定义资产间的相关性结构从而得到比传统风险平价更分散的权重“Network Graph”则更进一步将资产视为网络中的节点用图论方法分析其关联并优化权重。强化学习与控制理论“RL Deep Deterministic”展示了如何使用深度确定性策略梯度这类强化学习算法以最大化夏普比率等指标为目标动态学习权重调整策略。在线学习“Online Portfolio Selection”是一类重要的算法家族它假设市场序列是逐个到来的算法需要在线地、根据历史信息实时调整权重这类方法对交易成本和非平稳市场环境有更好的适应性。3. 环境搭建与数据准备实操指南要运行这个项目的代码你需要一个合适的Python环境。项目代码大多以Jupyter Notebook形式提供并标注了可在Google Colab中运行这对初学者非常友好避免了复杂的本地环境配置问题。3.1 本地环境配置尽管Colab方便但对于需要长期迭代、处理敏感数据或使用自定义包的项目本地环境仍是首选。我推荐使用conda创建独立的虚拟环境。# 创建并激活一个名为ml_finance的虚拟环境 conda create -n ml_finance python3.8 conda activate ml_finance # 安装核心依赖 pip install numpy pandas matplotlib scipy scikit-learn pip install jupyter notebook # 如果你习惯用Jupyter # 对于深度学习相关策略需要安装TensorFlow或PyTorch pip install tensorflow # 或根据你的CUDA版本选择 tensorflow-gpu # 对于需要雅虎财经数据的部分安装yfinance pip install yfinance # 安装用于金融数据分析和回测的常用库 pip install empyrical pyfolio # 注意pyfolio可能已不再维护但许多旧代码仍在使用 pip install backtrader # 一个功能强大的回测框架3.2 数据获取与处理项目中的许多Notebook提供了Google Drive的数据链接但有些链接可能已失效。更可靠的实践是掌握如何自己获取和准备数据。价格数据获取对于美股yfinance库是免费且稳定的选择。import yfinance as yf import pandas as pd # 下载标普500成分股一段时间内的日线数据 sp500_tickers pd.read_html(https://en.wikipedia.org/wiki/List_of_S%26P_500_companies)[0][Symbol].tolist() # 注意yfinance的ticker可能与维基百科列表略有不同可能需要简单清洗 data yf.download(sp500_tickers, start2015-01-01, end2023-12-31, group_byticker) # 数据会以多级索引的DataFrame返回需要进一步处理为面板数据格式另类数据准备对于“Quantamental”这类策略你需要文本数据。可以从金融新闻API如Alpha Vantage News、EOD Historical Data的新闻端点获取或者使用开源数据集。一个常见的起点是使用requests和BeautifulSoup进行简单的网络爬取但务必遵守网站robots.txt和服务条款。import requests from bs4 import BeautifulSoup import time def fetch_financial_news(url, headers): 一个简单的新闻抓取示例 try: response requests.get(url, headersheaders) soup BeautifulSoup(response.content, html.parser) # 根据目标网站的HTML结构解析新闻标题和内容 # 此处为示例实际结构需具体分析 articles soup.find_all(article) news_list [] for art in articles: title art.find(h2).text.strip() if art.find(h2) else content art.find(p).text.strip() if art.find(p) else news_list.append({title: title, content: content}) return news_list except Exception as e: print(fError fetching {url}: {e}) return []数据预处理核心步骤清洗处理缺失值。对于价格数据前向填充或删除是常见做法。对于因子数据可能需要更复杂的方法如行业中性化后的中位数填充。对齐确保所有时间序列数据价格、因子、宏观经济数据的日期索引完全对齐缺失的交易日需要进行填充或插值。标准化在将数据输入机器学习模型前通常需要进行标准化或归一化。对于金融数据我更喜欢使用RobustScaler因为它对异常值不那么敏感。标签制作对于监督学习策略你需要定义预测目标。常见的有分类标签未来N日的收益率是否超过某个阈值如0或基准。回归标签未来N日的具体收益率。重要提示严防未来信息泄露任何用于生成标签的信息如未来价格都不能在特征中被使用。通常采用滞后特征和提前标签的方法。4. 核心策略案例深度拆解与复现让我们选取项目中两个有代表性的策略进行深入剖析看看如何从Notebook代码走向一个更健壮的策略框架。4.1 案例一“Tiny CTA”趋势跟踪策略的强化“Tiny CTA”的核心思想非常简洁它计算资产价格的短期和长期移动平均线当短期均线上穿长期均线时产生买入信号下穿时产生卖出或做空信号。项目中的代码可能只有寥寥数行但一个实盘可用的CTA策略远不止于此。第一步基础信号生成import pandas as pd import numpy as np def compute_ma_signal(prices, short_window20, long_window50): 计算双均线交叉信号。 参数 prices: 价格序列pd.Series short_window: 短周期窗口 long_window: 长周期窗口 返回 signals: 包含信号1: 做多 -1: 做空 0: 平仓的DataFrame signals pd.DataFrame(indexprices.index) signals[price] prices signals[short_ma] prices.rolling(windowshort_window, min_periods1).mean() signals[long_ma] prices.rolling(windowlong_window, min_periods1).mean() signals[signal] 0 # 金叉短线上穿长线做多 signals.loc[signals[short_ma] signals[long_ma], signal] 1 # 死叉短线下穿长线做空 signals.loc[signals[short_ma] signals[long_ma], signal] -1 # 为了简化这里假设信号变化时才交易。实际中需要处理持仓。 signals[positions] signals[signal].diff() return signals第二步添加过滤器与风险管理原始策略在震荡市中会频繁产生亏损交易“鞭锯效应”。我们需要增加过滤器。波动率过滤器在市场波动率极高如恐慌期或极低如假日时不交易或降低仓位。def add_volatility_filter(signals, prices, window20, threshold_high2.0, threshold_low0.5): 基于波动率过滤信号 returns prices.pct_change() volatility returns.rolling(window).std() # 标准化波动率Z-score vol_zscore (volatility - volatility.rolling(252).mean()) / volatility.rolling(252).std() # 高波动期和低波动期均不交易 filter_condition (vol_zscore.abs() threshold_high) (vol_zscore.abs() threshold_low) signals[filtered_signal] signals[signal] signals.loc[~filter_condition, filtered_signal] 0 return signals趋势强度确认引入ADX平均趋向指数等指标只在趋势明确时采纳均线交叉信号。动态仓位管理根据波动率如ATR动态调整仓位大小风险恒定。第三步多资产组合与相关性分析单一的资产策略风险集中。一个真正的CTA基金策略会应用于数十个流动性好的期货品种股指、国债、商品、外汇。这时权重优化第二部分的内容就至关重要。你需要计算各策略信号的相关性避免在高度相关的资产上同时建立大额头寸。4.2 案例二“Quantamental”情感分析策略的落地难点“Quantamental”策略试图从新闻、社交媒体、财报电话会议记录中提取情感并预测其对股价的影响。这是当前的热点也是难点。核心流程数据采集获取高质量的文本数据源。免费源有限且嘈杂商用API如Reuters, Bloomberg成本高昂。文本预处理分词、去除停用词、词形还原/词干提取。金融文本中有大量专业术语和缩写需要定制的词典。情感特征提取词典法使用金融情感词典如Loughran-McDonald词典计算正负面词汇比例。模型法使用预训练的Transformer模型如FinBERT一个在金融文本上微调的BERT模型进行细粒度情感分类积极、消极、中性和情感强度打分。# 使用transformers库调用FinBERT示例 from transformers import AutoTokenizer, AutoModelForSequenceClassification import torch tokenizer AutoTokenizer.from_pretrained(ProsusAI/finbert) model AutoModelForSequenceClassification.from_pretrained(ProsusAI/finbert) def analyze_sentiment(text): inputs tokenizer(text, return_tensorspt, truncationTrue, paddingTrue, max_length512) outputs model(**inputs) predictions torch.nn.functional.softmax(outputs.logits, dim-1) # 类别positive, negative, neutral sentiment_score predictions[0][0].item() - predictions[0][1].item() # 简单用正-负作为分数 return sentiment_score特征工程与建模将情感分数与传统的量价特征、基本面特征结合。这里的关键是时间对齐。新闻发布的时间戳必须精确到分钟甚至秒级并与股价变动窗口仔细对齐以确定因果关系的方向是新闻影响股价还是股价变动引发了新闻。通常我们会使用新闻发布后5分钟、30分钟、1交易日等不同窗口的收益率作为预测目标进行测试。策略实施基于模型预测的未来收益方向或强度生成交易信号。由于新闻数据是稀疏的不是每个交易日都有重大新闻该策略可能无法提供连续的信号需要与其他策略结合使用。实操心得情感分析策略最大的坑在于数据质量和过拟合。新闻情感与股价的关系非常微妙且市场会快速消化信息。回测中表现优异的模型实盘中可能因为新闻源变化、市场情绪结构转变而迅速失效。因此必须使用严格的样本外测试和滚动时间窗口验证。5. 组合权重优化方法的选择与实战调参当你拥有多个策略或资产信号后如何分配资金就成了决定整体绩效的关键。项目第二部分列举了多种方法这里我对比几种最实用的并分享调参经验。5.1 方法对比与适用场景方法核心思想优点缺点适用场景均值-方差优化最大化夏普比率收益/风险理论经典目标明确对输入参数极度敏感结果集中且不稳定作为理论基准或在参数估计非常准确时风险平价让各资产对组合风险的贡献相等分散化好对收益预测依赖低假设资产相关性稳定可能过度配置低风险资产大类资产配置股、债、商品层次风险平价先聚类资产再在簇内和簇间做风险平价比传统RP更稳健考虑了相关性结构计算稍复杂聚类结果受方法和参数影响股票行业内配置、多策略组合等权重每个资产分配相同权重简单完全无需预测无参数未考虑资产间的差异风险、相关性作为简单基准或初始探索阶段强化学习优化让智能体通过与市场环境交互学习权重分配策略灵活能处理复杂、非线性的目标训练复杂不稳定样本外风险高可解释性差研究探索或作为其他方法的补充信号5.2 HRP实战步骤与代码详解HRP是近年来非常受欢迎的方法下面是一个基于scipy和numpy的简化实现步骤import numpy as np import pandas as pd from scipy.cluster.hierarchy import linkage, dendrogram, fcluster from scipy.spatial.distance import squareform def hrp(cov, corr): 层次风险平价核心算法。 参数 cov: 协方差矩阵pd.DataFrame corr: 相关性矩阵pd.DataFrame 返回 weights: 优化后的权重pd.Series # 1. 层次聚类 dist np.sqrt((1 - corr) / 2) # 将相关性转化为距离 link linkage(squareform(dist.values), methodward) # 2. 准对角化 # 根据聚类树状图的顺序对协方差矩阵的行和列进行重排 # 这里简化处理实际需要递归地根据聚类顺序重排矩阵 # 可以使用 scipy.cluster.hierarchy.leaves_list 获取叶子节点顺序 order leaves_list(link) cov_sorted cov.iloc[order, order] # 3. 递归二分法分配权重 def recursive_bisection(cov_matrix): n cov_matrix.shape[0] if n 1: return np.array([1.0]) # 将矩阵分为两个子集群前一半和后一半 mid n // 2 cov_a cov_matrix.iloc[:mid, :mid] cov_b cov_matrix.iloc[mid:, mid:] # 计算子组合的方差 var_a np.sum(cov_a.values) var_b np.sum(cov_b.values) # 计算子组合的初始权重逆方差分配 w_a 1 / var_a w_b 1 / var_b sum_iv w_a w_b w_a / sum_iv w_b / sum_iv # 递归计算子组合内部权重 weights_a recursive_bisection(cov_a) weights_b recursive_bisection(cov_b) # 合并权重 return np.concatenate([weights_a * w_a, weights_b * w_b]) weights recursive_bisection(cov_sorted) # 将权重按原始资产顺序还原 final_weights pd.Series(weights, indexcov_sorted.index) final_weights final_weights.reindex(cov.index).fillna(0) # 归一化确保权重和为1 final_weights / final_weights.sum() return final_weights # 使用示例 # 假设 returns 是一个资产收益率DataFrame cov_matrix returns.cov() corr_matrix returns.corr() hrp_weights hrp(cov_matrix, corr_matrix)关键调参点聚类方法linkage函数中的method参数。ward方法最小化簇内方差在金融中常用single或complete链接法可能对噪声更敏感。协方差估计使用简单的历史协方差可能不稳定。可以考虑指数加权移动平均协方差、Ledoit-Wolf收缩估计等更稳健的方法。再平衡频率HRP权重不是固定不变的。需要定期如每月、每季度根据新的数据重新计算协方差矩阵并优化权重。频率太高会产生过多交易成本太低则可能偏离最优配置。6. 回测、评估与常见陷阱全解析无论策略听起来多美妙都必须经过严格、可靠的回测检验。这是区分“纸上谈兵”和“实战利器”的关键一步。6.1 构建一个健壮的回测框架不要急于用项目中的简单示例代码直接评估策略。你需要一个考虑周全的回测环境。以下是核心要素数据质量确保价格数据已经过复权处理对于股票包含了分红、拆股等信息。使用yfinance时auto_adjustTrue参数通常可以处理。交易逻辑清晰定义信号生成、仓位计算、订单执行市价单/限价单的规则。特别注意信号延迟使用t时刻的信息最早只能在t1时刻开盘交易。交易成本这是许多策略从盈利变为亏损的元凶。至少考虑佣金固定费用或按交易金额比例收取。滑点预期交易价格与实际成交价格的差异。可以设置为固定比例如0.1%或与波动率挂钩。def apply_transaction_costs(returns, turnover, commission_rate0.001, slippage_rate0.0005): 简化版交易成本计算。 returns: 原始收益率序列 turnover: 换手率序列仓位变化的绝对值 cost_per_period turnover * (commission_rate slippage_rate) net_returns returns - cost_per_period return net_returns基准对比将你的策略收益与一个合适的基准如买入持有SPY、等权重组合进行对比。6.2 绩效评估指标解读不要只看总收益率。一套全面的评估指标能帮你识别策略的真实质量年化收益率 年化波动率基础指标。夏普比率最常用的风险调整后收益指标。Sharpe (年化收益 - 无风险利率) / 年化波动率。假设无风险利率为0通常夏普大于1算不错大于2是顶级策略。最大回撤策略净值从峰值到谷底的最大跌幅。这是衡量策略极端风险和投资者心理承受能力的关键指标。卡尔玛比率Calmar 年化收益 / 最大回撤。衡量收益与最大风险的比值。胜率盈利交易次数占总交易次数的比例。盈亏比平均盈利金额 / 平均亏损金额。高胜率低盈亏比或低胜率高盈亏比都可能构成一个盈利策略。信息比率如果你的策略是相对于基准的主动管理信息比率衡量超额收益的稳定性。IR (策略收益 - 基准收益) / 跟踪误差。6.3 机器学习策略特有的陷阱与应对过拟合数据窥探偏差这是量化策略尤其是机器学习策略的“头号杀手”。你的模型完美地拟合了历史噪声却在未来失效。应对严格区分训练集、验证集和测试集样本外。使用时间序列交叉验证如滚动窗口或扩展窗口验证而不是随机划分。始终保持测试集在时间上位于训练集之后。简化模型在能达到相近效果的情况下优先选择更简单的模型线性模型 vs 深度神经网络。简单模型的泛化能力通常更强。幸存者偏差回测中只使用了至今仍然存在的股票数据忽略了那些已经退市、被并购的股票这会高估历史收益。应对使用包含退市股票的全量历史数据库或者使用专业的金融数据平台如CRSP, Compustat它们通常包含了退市信息。未来函数在特征中不小心使用了未来的信息。例如使用当日的收盘价来计算当日的移动平均线信号是合理的但如果使用了当日收盘价本身作为特征来预测当日收益就是未来函数。应对在特征工程阶段对所有数据都进行严格的滞后处理。确保在时间点t模型只能看到t-1及之前的信息。交易成本与流动性低估回测假设你可以瞬间以收盘价买卖任意数量的股票这在实际中对于小盘股或大额订单是不可能的。应对引入更精细的订单执行模型考虑成交量、市场冲击成本。对于小盘股策略要格外谨慎。7. 从研究到实盘的最后一公里当你有了一个回测表现不错的策略后切勿急于投入实盘。从研究到实盘还有一段被称为“死亡之谷”的路要走。模拟交易在实盘交易前必须进行至少3-6个月的模拟交易。使用实时或延迟的市场数据但用虚拟资金运行你的策略。这能检验整个交易系统的稳定性包括数据接口、信号计算、订单发送、风险监控等所有环节。任何在回测中未考虑的细微问题如网络延迟、API限制、数据格式突变都会在这里暴露。小资金实盘模拟交易稳定后用一笔你完全输得起的资金进行实盘测试。这是检验策略心理承受能力的阶段。你会亲眼看到策略在真实亏损时的表现以及你自己能否坚持执行既定的交易规则而不进行人为干预。持续监控与迭代市场是动态变化的没有永远有效的策略。你需要建立一套监控体系每日/每周绩效归因分析收益来源是市场贝塔、风格因子还是真正的阿尔法风险监控实时监控组合的风险敞口、集中度、VaR等指标是否超出预设阈值。策略健康度检查定期检查策略的核心假设是否依然成立。例如因子有效性是否衰减交易成本假设是否依然合理组合与风控不要把所有资金押注在一个策略上。将你的策略作为整个投资组合的一部分与其他低相关性的策略或资产结合。建立严格的风控规则如单策略最大回撤达到15%时暂停达到20%时强制清盘复盘。firmai/machine-learning-asset-management 项目为你打开了一扇门展示了机器学习在资管领域的广阔应用图景。但门后的道路需要你用自己的知识、经验和严谨的态度去铺设。记住在这个领域对市场保持敬畏对模型保持怀疑对风险保持警惕远比找到一个复杂的模型更重要。最好的策略往往是那些你能完全理解、能清晰解释其盈利逻辑并且能在市场逆境中依然坚定执行的策略。从这个项目提供的众多“乐高积木”开始结合扎实的金融理论、严谨的工程实践和持续的学习你才能逐步搭建起属于自己的稳健交易系统。