周二清晨,鹏城南山区的阳光透过百叶窗,在书房的地板上切割出明暗相间的条纹。林晨坐在电脑前,左手边是半杯早已冷却的美式咖啡,右手边的屏幕上闪烁着复杂的代码。
距离t厂hR承诺的“最晚周二中午前出结果”,还有三个小时。
他没有干等。等待的焦虑反而转化成了专注的能量——与其盯着时钟一分一秒地煎熬,不如把这段时间变成技术打磨的宝贵窗口。
投资系统昨晚又完成了一轮交易。林晨打开账户管理后台,最新净值曲线平稳向上,过去一周的累计收益率达到了3.2%。对于一个全自动运行、风险严格控制的多市场量化策略来说,这个数字已经相当可观。
但林晨盯着仓位管理模块的日志,眉头微微皱起。
“问题出在仓位调整上。”他自言自语,手指在键盘上敲击着调出详细交易记录,“系统识别到了黄金期货的趋势突破信号,但加仓速度太保守了。”
日志显示,系统在确认趋势后的六个交易小时内,分三次将仓位从初始的5%提升到15%。而根据林晨手动回测的经验,在那种明确的多头行情中,完全可以在确认信号后的第一个小时就加到12%,第二个小时达到20%上限。
“还是太机械了。”林晨靠在椅背上,望着窗外腾讯大厦的玻璃幕墙,“固定的仓位调整规则,没法适应不同市场、不同波动率环境下的最优策略。”
这个发现让他既兴奋又紧迫。兴奋是因为找到了明确的优化方向,紧迫是因为他知道,如果现在不解决这个问题,等真正入职t厂开始高强度工作后,这个个人项目很可能会被搁置。
他点开手机,给张伟发了条微信:“老张,强化学习在量化仓位管理上有成熟案例吗?”
几分钟后,张伟的电话直接打了过来。
“你小子还真是不闲着啊。”张伟的声音带着晨起的沙哑,“等offer的当口还在折腾系统?”
“总比干等强。”林晨笑了笑,“你了解这块吗?”
“略知一二。华尔街那边几年前就开始用dRL(深度强化学习)做动态仓位管理了,不过大部分是高频策略。你想做的是中低频吧?”
“对,日级别到小时级别的调仓。”
“那可以试试dqN(深度q网络)或者ppo(近端策略优化)。”张伟显然对这个话题很感兴趣,“关键是要设计好状态空间、动作空间和奖励函数。状态得包括市场数据、技术指标、账户信息;动作就是加减仓的幅度;奖励函数嘛……夏普比率?最大回撤控制?”
“我正在想这个。”林晨快速记录着,“如果只用夏普比率,系统可能会过度追求低波动而错失大行情。”
“那就复合指标。夏普比率占60%,年化收益占30%,最大回撤占10%——权重你自己调。对了,训练数据要足够长,至少覆盖两轮牛熊周期。”
挂断电话后,林晨的思路清晰了许多。他重新打开pytorch,新建了一个名为“rl_portfolio_manager”的文件夹。
上午九点半,A股开盘。林晨将系统切换到观察模式,自己则开始搭建强化学习框架。
第一步是定义状态空间。他整合了二十多个维度的数据:标的资产的当前价格、20日移动平均线、布林带宽度、RSI强弱指标、成交量变化率……还包括账户层面的信息,如当前仓位比例、浮动盈亏、可用资金等。
“状态向量长度……87维。”林晨敲下确认键,“够用了。”
动作空间相对简单:从空仓到满仓,按5%的步长划分,共21个离散动作。奖励函数则按照张伟的建议,采用复合指标,但林晨调整了权重——他更看重收益风险比,所以将夏普比率的权重提高到70%。
架构搭好,接下来是训练数据。林晨调取了系统过去两年的历史回测数据,涵盖A股、商品期货、黄金EtF和外汇市场,总计超过五十万条分钟级别的K线记录。
“开始训练。”
他按下回车键,屏幕上的命令行窗口开始滚动数字。GpU占用率瞬间飙升到98%,风扇发出轻微的嗡鸣声。
等待训练结果的时间变得异常缓慢。林晨起身续了杯咖啡,站在窗前俯瞰南山科技园的车流。早高峰已过,深南大道上的车辆依然川流不息,每一辆车里都载着一个正在奔赴各自战场的人。
他想起一个月前,自己还是那车流中的一员,每天赶着地铁去跨境电商公司上班,担心着35岁的职场天花板。而现在,他站在这里,等待着一个可能改变职业生涯的offer,同时亲手搭建着一个可能改变财务命运的系统。
“代码可以骗人,但逻辑不会。”林晨低声重复着自己的口头禅,“人更不能。”
十点整,手机震动。是苏婉发来的消息:“乐乐安全送到幼儿园了。你那边有消息吗?”
“还没有,说中午前。”林晨回复,“我在优化系统,进展不错。”
“那就好。中午想吃什么?我回来时顺便买。”
“简单点就行。你下午还有课吧?”
“嗯,两节作文课。孩子们要写《我的梦想》,挺期待的。”
林晨看着这句话,嘴角不自觉地上扬。苏婉总是这样,在那些看似平凡的教学日常里,找到属于自己的光亮。而他现在要做的,就是守护这份光亮。
他回到电脑前,训练已完成第一轮迭代。初步结果显示,在测试集上,强化学习模型管理的仓位调整策略,比原有固定规则策略的年化收益率提高了1.8个百分点,夏普比率从1.52提升到1.67。
“有戏。”林晨眼睛一亮。
但他没有急于部署到实盘。量化交易最忌讳的就是过度拟合——在历史数据上表现优异,不代表在未来市场也有效。
林晨启动了交叉验证:将数据分成五份,用四份训练,一份测试,轮流五次。同时加入了随机市场噪声和滑点模拟,让模型在更接近真实交易的环境下学习。
时间来到十一点。距离t厂承诺的最后期限,还有一个小时。
林晨强迫自己不去看时钟,专注于手头的工作。他调整了神经网络的层数和节点数,加入了dropout层防止过拟合,还尝试了不同的优化器——Adam、RmSprop、SGd。
十一点半,第五轮交叉验证的结果出炉。
平均年化收益提升:2.1%。 夏普比率提升:从1.52到1.71。 最大回撤改善:从-8.3%降低到-7.1%。
更重要的是,模型在不同市场行情下表现出良好的适应性:在趋势明显的单边市中会快速加仓,在震荡市中会降低仓位并高抛低吸,在行情反转时会及时止损。
“可以实盘试运行了。”林晨做了决定。
他没有全仓切换,而是采用渐进式部署:将新模型作为“建议模块”,与原系统的固定规则并行运行。新模型给出仓位调整建议,如果与原规则偏差不超过10%,则采纳;如果偏差过大,则触发人工审核——目前由林晨自己审核。
部署代码,重启系统。十一点五分。
林晨看着监控面板,新模型开始接收实时市场数据,并输出了第一个仓位建议:在黄金期货上,建议将仓位从当前的12%提升到18%。
原系统的规则建议是15%。
偏差3个百分点,在阈值内。系统自动采纳了新模型的建议。
几乎在同一时刻,黄金价格突破了一个小时级别的阻力位,开始放量上涨。
林晨屏住呼吸,盯着分时图。接下来的十五分钟里,金价上涨了0.8%。按照18%的仓位计算,这波行情带来的浮盈已经超过了原策略的预期。
“漂亮。”他忍不住赞叹。
这不是运气,而是模型从历史数据中学到的规律:当黄金价格在特定技术形态下突破关键位置,且成交量配合放大时,后续延续趋势的概率高达73%。