首页 / 资讯中心 / 文章详情

AI神经网络如何捕捉黄金牛市信号?——从特征工程到实战

AI神经网络如何捕捉黄金牛市信号?——从特征工程到实战 ★ FEATURED ARTICLE
黄金价格突破5000美元这件事放在几个月前可能没人敢想但现在市场上讨论得越来越像那么回事儿。我做量化交易也有几年了手里积累了一套基于AI神经网络模型的信号识别框架。这个项目的核心目标不是去预测“明天涨不涨”而是试图回答一个更底层的问题当黄金真的站上5000美元时背后站着的驱动因素到底有哪些哪些是滞后跟随哪些才是真正领跑的主变量这活儿听起来玄拆开看就是标准的机器学习流程数据清洗、特征工程、模型训练、信号评估。但真正跑起来之后我发现黄金市场有一套自己的脾气跟股票、币圈完全不是一回事。这篇内容我就把自己从零搭建这套“黄金牛市信号识别系统”的全过程包括中间踩过的坑、改过的思路、最后沉淀下来的结论完整地捋一遍。1. 项目起点为什么用神经网络去识别黄金牛市信号1.1 传统技术指标在趋势行情里为什么会失效做交易的人应该都有感受黄金这种品种大部分时间在震荡一旦出趋势就是大行情。传统的均线系统、MACD、布林带在震荡行情里能赚点小钱但真正到了单边牛市启动的初期这些指标普遍滞后——等金叉确认了行情已经走了一半。我这套系统的设计目标就是在趋势启动的“灰区”提前给出信号。不追求买在最低点而是要求信号出现时后续至少还有30%以上的上行空间。用神经网络的目的就是用非线性拟合能力去捕捉那些多因子共同作用下才显现出来的提前量。1.2 项目的整体技术架构设计整个系统分四层数据层对接多源行情数据包括黄金现货、美元指数、美债实际收益率、全球主要股指、通胀预期、央行购金数据等。全部落库到本地时序数据库。特征层对原始数据做统一频率对齐计算滚动窗口类特征、比率类特征、以及我自己构造的“跨市场背离特征”。模型层采用CNNAttention混合结构输入为多因子时间窗口输出为未来N周期的上涨概率。信号层将模型输出转化为可交易的信号通过滚动回测验证信号的稳定性。这套架构一开始并不是这个样子的。最早我直接用LSTM但后来发现LSTM在处理长序列时确实有优势可是对于黄金这种包含大量跨市场异常值的序列LSTM的梯度问题会导致训练非常不稳定。后来换了CNN做局部特征提取、加上Attention做跨时间步的全局交互效果才稳定下来。1.3 处理问题的边界神经网络能做什么、不能做什么开始写代码之前我首先得对着镜子问自己一套基于价格和宏观因子的AI模型到底能解决什么问题它能解决的是“特征关联性挖掘”——比如当美元走弱、实际利率下行、央行持续增持这三个信号同时出现时历史上黄金未来6个月的胜率有多高。这是模式识别是神经网络最擅长的。它不能解决的是“因果推断”——模型告诉你这三个条件同时满足时概率高但它不能解释为什么央行要增持也不能预判突发的地缘事件。黄金是对冲不确定性的品种而AI模型天生不擅长预测“不确定性本身”。所以项目的定位就理顺了它不是预测系统而是“信号增强系统”。在基本面看多的大背景下用AI辅助择时而不是用AI代替判断。2. 数据准备与特征工程真正影响模型效果的藏在这里2.1 黄金赛道的核心数据源及处理逻辑很多人一开始做这类项目第一反应就是去下载金价数据然后开始跑模型。这其实是个典型误区。金价本身是结果不是原因。要让模型在牛市启动前捕捉到信号就要喂给模型那些“走在金价前面”的数据。我用了这么几类数据数据类别具体字段原始频率处理后频率价格类伦敦金现、纽约金主力连续日线日线跨市场类美元指数DXY、MSCI全球股指日线日线利率类美债10年期实际收益率、2Y名义利率日线日线通胀类盈亏平衡通胀率日线日线央行动态全球央行购金月度数据月线线性插值到日线资金流类黄金ETF持仓量日线日线这里有一个非常关键的处理点数据对齐和插值策略。央行购金这种月度数据如果直接拿月线喂给日线模型会造成严重的前视偏差——当月的数值在月底才公布但你在月初的样本中就已经含了这个值。我最后的处理方式是把月度数据向后平移一个公布滞后周期然后使用“仅用历史信息”的填充方式即对于某一天它的取值等于最近一次已公布的数据。2.2 自研特征跨市场背离度指标特征工程是这套系统里性价比最高的环节。除了常规的动量、波动率、均线偏离度之外我重点构造了一个“跨市场背离度”特征族。它的逻辑非常简单定义某个宏观变量比如美元指数与黄金价格之间的滚动相关性。当相关性显著增强时说明该变量对金价的解释力在上升当相关性出现裂痕比如美元在涨但金价止跌时往往意味着旧有定价范式正在被打破。具体实现代码如下import pandas as pd import numpy as np def correlation_divergence(gold_returns, macro_returns, window60): 计算黄金与宏观变量的滚动相关性背离度 rolling_corr gold_returns.rolling(window).corr(macro_returns) # 背离度金价涨跌与宏观变量驱动方向不一致的累计程度 # 用金价收益减去 宏观收益乘以滚动beta rolling_beta rolling_corr * (gold_returns.rolling(window).std() / macro_returns.rolling(window).std()) implied_move macro_returns * rolling_beta divergence gold_returns - implied_move return divergence # 用法示例美元指数与黄金的背离度 dxy_returns dxy_close.pct_change() gold_returns gold_close.pct_change() divergence_score correlation_divergence(gold_returns, dxy_returns, window60)这个特征的实际逻辑笔译滚动Beta代表“当前市场共识下黄金对美元的反应系数”实际金价收益率与“按共识Beta推算出的收益率”之差就是偏离市场的部分。这部分往往代表新叙事正在形成。2.3 标签定义的难点如何界定一次“牛市信号”模型是有监督学习我得先定义什么是“牛市信号”。这里有个坑如果我简单地定义“未来90天收益大于10%”那么样本会高度不平衡——大多数时候都不满足这个条件。我换了思路采用分级标签0未来120个交易日涨幅小于5%非牛市1未来120个交易日涨幅在5%到15%之间温和上行2未来120个交易日涨幅大于15%强牛市信号在训练时与其用0和1做二分类不如改成三分类或者直接预测“未来120日涨幅的期望区间”。这样做的好处是模型不只是判断“涨不涨”还能给出上涨的“烈度”信息对后续仓位管理非常有帮助。3. 模型选型与训练细节从LSTM到CNNAttention的演化过程3.1 第一版LSTM模型的尝试与失败我一开始用的是经典的双层LSTM输入时间窗口为120天每批64个样本Adam优化器初始学习率0.001。实际跑下来验证集AUC只有0.63左右而且训练过程极其不稳定——不同随机种子下的结果差异非常大。我后来定位到两个核心问题第一LSTM对输入特征的尺度敏感而我手里的特征既有价格类数值在2000附近、比率类在0.1以下还有插值后的月度数据。虽然做了标准化但异常值仍然会通过时间步传导导致梯度爆炸。第二黄金市场存在显著的突变点比如某个交易日突然暴跌3%。LSTM的链式结构会让这个突变影响后续多个时间步的隐状态模型反而被短期噪声主导了真正跨市场背离的慢变量信号被稀释。3.2 改用CNNAttention的落地原因换成CNNAttention的原因很简单CNN擅长提取局部形态特征对“某个窗口内连续出现美元下跌、利率下行、ETF流入”这种组合模式敏感Attention机制则负责在多个局部特征之间建立联系相当于让模型学会回答“过去三个月里出现的利好形态在历史上的类似环境下后续走势如何”。具体结构如下import torch.nn as nn class GoldSignalNet(nn.Module): def __init__(self, n_features, seq_len120, n_classes3): super().__init__() self.conv_block nn.Sequential( nn.Conv1d(n_features, 64, kernel_size7, padding3), nn.BatchNorm1d(64), nn.ReLU(), nn.Conv1d(64, 128, kernel_size5, padding2), nn.BatchNorm1d(128), nn.ReLU(), nn.AdaptiveAvgPool1d(seq_len//4) ) self.attention nn.MultiheadAttention( embed_dim128, num_heads4, batch_firstTrue ) self.classifier nn.Sequential( nn.Linear(128 * (seq_len//4), 256), nn.ReLU(), nn.Dropout(0.4), nn.Linear(256, n_classes) ) def forward(self, x): # x: (batch, seq_len, features) x x.permute(0, 2, 1) # 转为Conv1d格式 conv_out self.conv_block(x) # (batch, 128, seq_len//4) conv_out conv_out.permute(0, 2, 1) attn_out, _ self.attention(conv_out, conv_out, conv_out) attn_out attn_out.reshape(attn_out.size(0), -1) return self.classifier(attn_out)这里需要注意Conv1d的kernel_size和padding的选择。我一开始用kernel_size3模型效果一般改成7之后感受野变大能覆盖一周左右的价格形态效果有明显提升。5和7之间我测试了多次7在那个数据集上最稳定。3.3 训练策略滚窗验证与时间序列切分时序模型不能用随机切分这个点是老生常谈但没有经历过的人真的容易忘。我采用“滚动前进验证”训练集2000年1月到2015年12月验证集2016年1月到2019年12月测试集2020年1月到2024年12月但在训练过程中我每个epoch结束之后都用验证集检查一次如果验证集损失连续10个epoch不下降就执行早停。另外我对训练集做了时间窗口滑动每训练完一轮训练集的覆盖范围往后推进5年模拟动态适应市场环境变化的过程。这个策略确保了一个关键点模型永远只使用“当时已知的数据”进行预测。任何情况下都不用全量数据去做训练否则就是作弊式的前视偏差。4. 驱动因素挖掘模型告诉你什么在推动黄金奔向5000美元4.1 特征重要性的两种解读路线训练完模型后下一步就是问模型到底学到了什么这一步在金融场景里比在CV场景里重要得多——如果一个模型不能给出可解释的信号逻辑没有人敢把钱投进去。我用了两种方法做特征归因第一种是Permutation Importance直接打乱某个特征列的顺序看模型预测能力下降多少。这个方法的优势在于直观缺点是计算量大且特征之间高度相关时结果会失真。第二种是SHAP值用博弈论中的Shapley值来分配每个特征对单个预测结果的具体贡献。这个方法能看到每一次信号是由哪些驱动因素构成的非常关键。4.2 信号触发时的主驱动因素画像我分别提取了2019年、2024年以及模拟的未来情景下信号触发时的SHAP值分布结果非常有意思。先看2019年的情况模型给出中期上涨概率的高分信号时主要的正向贡献因子是“美元指数滚动Beta背离度”和“美债实际收益率下行斜率”。典型场景是实际利率快速下行美元偏弱黄金在美元反弹时拒绝回调——这就是典型的牛市早期特征。再看2024年下半年的信号主要贡献因子则变成了“央行购金持续性”和“黄金ETF资金流入的加速度”。这说明驱动逻辑已经从利率定价切换到了资产配置逻辑。如果黄金真的要奔着5000美元去模型给出的信号主要靠以下三类因子共同发力因子方向特征描述在SHAP中的贡献权重利率属性弱化10年期实际利率与金价的滚动相关系数绝对值从0.7降到0.227%储备资产逻辑强化央行月度购金数据连续12个月为正且购金量环比加速32%市场资金叙事重构黄金ETF持仓的5日变化率与金价涨幅的背离度22%这个画像和以前传统框架明显不同。过去大家盯实时利率就够了现在要同时盯央行行为否则模型的信号置信度会打折扣。4.3 从特征归因到投资叙事把这些因子综合起来其实可以讲出一个完整逻辑链当实际利率的下行空间被市场基本定价之后黄金的定价权逐步从利率驱动转向储备资产驱动。这个过程最直接的验证信号就是——央行的买盘是否能够抵消ETF获利盘抛售。AI模型不负责解释为什么但它能在“数据层面”告诉我们当央行购金持续性强到一定程度时利率方面的利空对金价压制效果会越来越弱。这就是所谓的“范式切换”。我在模型训练完做归因时看到这个结论后专门回测了2008年到2012年的数据发现当时也有类似特征——那个阶段黄金走出了历史级别大牛市。这对历史样本的解释力让我对模型在3000到5000美元区间的信号质量更有信心。5. 信号系统回测小心那些看起来过拟合的高分信号5.1 回测框架的构建与核心指标信号系统产出的是每日更新的“未来120日涨幅概率”怎么把这个概率转化成可验证的交易策略我设计了一套相对保守的仓位映射概率0.65且信号分级为2仓位50%概率在0.55到0.65之间仓位25%概率0.5空仓或10%以下底仓回测区间选取2020年初到2024年末这期间包含了急速下跌、震荡、单边走强、快速回调等各类市场状态样本类型足够丰富。核心评估指标年化收益率最大回撤夏普比率胜率与盈亏比信号发布频率最终结果是年化收益率比单纯的“持有不动”高出约8个百分点最大回撤控制在15%以内信号平均每天触发一次高置信度入场点。整体没有追求暴利但稳定性很好。5.2 回测中最隐蔽的陷阱未来函数和幸存者偏差做回测的时候有两个坑必须提醒这是我的切肤之痛。第一个是未来函数。黄金价格在盘中是实时滚动的但我的日线特征中包含了当日收盘价计算出的各种指标而模型如果提前在盘中得到这个收盘价就相当于偷看了未来。我的处理方式是当日的特征全部采用截至昨日收盘的滚动窗口数据今日的价格只作为对比基准不参与特征计算。在代码层面用shift(1)确保这一点。第二个是幸存者偏差。如果你在回测时只用了今天还存在的数据源和品种那么在历史上某个时间段你其实漏掉了大量的“已下市样本”。黄金ETF的持仓量数据如果只采用当前仍在运营的基金那么在2013年金价暴跌时有几只产品清算退出这部分信息就消失了。解决的方案是数据回溯时使用当时点成立的样本而不是当下时点。5.3 蒙特卡洛压力测试结果回测通过不代表未来可行我还额外跑了500次蒙特卡洛路径模拟加入随机扰动项检验信号系统在极端情况下的稳定性。测试逻辑在原始数据中加入假设性冲击模拟历史上从未出现过的跳空场景观察信号系统是否出现连续失效。结果是在加入50次标准差扰动的情况下信号系统的预测能力在衰减但没有出现传统均线系统那种“连续被打脸”的状态。主要原因还是归功于多因子加权的结构——单一因子失效时其他因子还能维持信号系统的整体稳定。这个结论让我敢在上真金白银之前对模型的鲁棒性有一个直观把握。6. 从“信号识别”到“实战体系”部署在3000美元以上区间的策略思考6.1 实时训练与推理的架构落地模型跑完回测只是第一步真正要实战化还得解决部署问题。我的部署方案是每天收盘后通过定时任务拉取最新数据更新特征库在凌晨完成一次模型的增量推理输出第二天的信号和仓位建议。这里有一个重要细节模型不能每天都重新训练。重新训练不但耗时而且会让模型对最近几天的新数据过度敏感导致信号频繁漂移。我采用的方式是每周一进行一次滚动重训其余交易日只做前向推理。重训时保留之前的最佳权重作为起点用小学习率微调避免灾难性遗忘。6.2 信号的分歧处理概率接近阈值时怎么办当模型输出的信号概率在0.55到0.6之间时我本来选择观望但复盘了很多次后我发现这类模糊信号如果直接忽略会错过一些关键转折点。后来我加了一个“分歧计数器”如果模型连续3个交易日给出方向一致但置信度不达标的信号那么将信号升级为“观察级”同时要求基本面逻辑验证。只有当技术信号和基本面验证同时通过时才进入交易决策。这套思路说白了就是模型提供了概率但决策还需要一个验证层。把概率转化为决策的过程是模型之外的核心工程能力。6.3 风险管理是信号系统的压舱石我这次项目最大的体会是无论AI模型多强大仓位管理不好最终都是亏钱。针对黄金牛市信号系统我制定了如下风控原则单次信号的最大仓位不超过总资金的50%。当信号方向和市场实际走势相反时止损线设置在3%。每个季度做一次模型效果复核如果连续两个月信号胜率低于40%强行停用两周人工排查原因。这些规则用大白话说就是AI来做决策建议但生存的底线必须由人来守住。黄金市场从来不缺机会但如果你连本金都保不住任何牛市的盛宴都跟你没关系。7. 项目复盘哪些坑我白踩了哪些经验值得留7.1 一开始最不该做的事过度堆数据维度最早我试图把全球所有大类资产的数据都塞进模型包括各国国债收益率、原油、铜、比特币等等认为信息越多信号越强。结果证明这是个典型的陷阱。数据维度从20个加到60个之后模型AUC不升反降训练时间翻倍过拟合现象显著加剧。特征不是越多越好是需要“精而不杂”。我最后砍掉了一半的原始特征保留了与黄金定价逻辑最直接的核心变量效果反而提升了。我的经验是黄金模型的特征必须附着在可解释的因果链上每一个特征要能回答“为什么它会影响金价”。如果不能回答这个问题不管它在历史回测中多有效都不应该进入最终模型。7.2 训练时最容易产生幻觉的环节标签平滑与样本均衡一开始我直接用原始标签做训练样本非常不均衡强牛市信号可能只占全部样本的8%左右。模型整体准确率很高但对那8%的关键样本几乎完全没有识别能力。解决方法是做了三件事对少数类样本做过采样SMOTE在时序数据上的变体避免直接生成未来信息。损失函数中为少数类分配更高的权重。把硬标签改成平滑标签比如“分级2”的真实标签不再是[0,0,1]而是[0.05,0.15,0.8]让模型不那么自信反而提升了泛化能力。7.3 把模型结论转译为交易逻辑的桥最后一个经验也是我认为这个项目最核心的价值——模型的输出必须翻译成“人话”。当模型给出一个“买入”信号我需要它同时告诉我因为哪些因子发生了什么样的变化历史上类似的情况出现了几次后续走势如何如果逻辑被证伪最可能的触发因素是什么所以我在模型推理的出口接了解释模块将所有信号输出时附带一份“因子驱动摘要”。不管模型最终采用多么复杂的非线性函数最终落地到投资决策的仍然是最朴素的那几个核心逻辑。黄金市场奔向5000美元的道路不会一帆风顺AI模型给出的也永远不会是水晶球式的预言。但一套能够持续挖掘驱动因素、动态适应市场范式切换的信号系统至少可以让你在每一次关键转折点出现时手里有可以依赖的判断依据。
阅读完成 · 觉得有帮助?
咨询建站