凌晨两点半,林晨的手机震动了一下。
他刚从一段复杂的异步回调地狱里挣扎出来,揉了揉发酸的眼睛,拿起手机。是张伟的回复,距离他睡前发的那条询问“什么事”已经过去了六个小时。
“抱歉刚开完会。电话方便吗”?
林晨看了眼窗外沉寂的夜色,又看了看屏幕上正在运行的量化系统终端——它正安静地按照既定策略分析着夜间的外汇市场数据。他起身走到阳台,拨通了电话。
“喂,伟哥,还没睡”?林晨压低声音,怕吵醒隔壁卧室的苏婉和乐乐。
“刚弄完一个智能合约的审计报告”。张伟的声音带着熬夜后的沙哑,但语气很精神,“你上次不是说在搞量化系统吗?进展怎么样”?
“原型跑起来了,用7万块实盘试了快一个月,收益……还行,大概8%左右”。林晨实话实说,“但架构很糙,就是个脚本集合,调度、监控、风控都是手搓的,得重构”。
电话那头传来张伟敲击键盘的声音,似乎一边聊一边在查什么。“8%一个月?年化快翻倍了,可以啊。不过你说得对,这种‘实验室产品’不上正经架构,迟早出问题。我找你其实是另一件事——t厂AI Lab那边,我有个前同事跳过去了,说他们最近在扩招,尤其是应用算法方向,可能跟你现在搞的东西有重叠”。
林晨心里一动。t厂,那是国内互联网的顶级山头之一,AI Lab更是无数技术人向往的圣殿。但他立刻冷静下来:“我简历……够得着吗?而且我现在的系统,还没到能拿出去说的程度”。
“所以我才问你进展”。张伟很直接,“如果你只是玩票,那就算了。但如果你真把这系统当个正经项目在打磨,甚至有了架构升级的计划,那这就是一个非常好的‘项目经验’。大厂面试,尤其是技术面,最喜欢有完整闭环实践经验的候选人,哪怕项目不大,但深度够、思考够,比空谈算法强得多”。
夜风微凉,吹散了林晨的困意。他握着手机,脑海里快速闪过自己那个杂乱的项目目录。“我正打算重构。后端用FastApI重写,提供标准ApI;前端想用React做个可视化监控面板;然后部署到云服务器上,做成一个可以远程访问、监控的完整服务”。
“FastApI + React + 云部署……”张伟重复了一遍,笑了起来,“思路很正嘛。这就是一个标准的现代web应用架构了。你搞跨境电商后端这么多年,这套东西对你来说应该不难,重点是把你的量化逻辑封装成服务。什么时候能弄出个雏形”?
“快的话,一周。慢的话,两周”。林晨估算了一下学习React和部署的时间。
“那就搞”。张伟果断道,“搞出来之后,如果需要内推,跟我说一声。不过别急,先把东西做扎实。代码可以骗人,但逻辑不会”。
挂掉电话后,林晨站在阳台上,看着远处鹏城湾星星点点的灯火,心中那股因妻子支持而燃起的火苗,被张伟这通电话又添了一把柴。不再是模糊的“试试看”,而是有了更清晰的技术路径和潜在的机会窗口。
他回到电脑前,关掉了那个运行着原始脚本的终端。打开浏览器,新建了三个标签页:FastApI官方文档、React中文教程、一家国内云服务商的价格计算器。
重构,从现在开始。
接下来的一周,林晨进入了某种心流状态。白天,当苏婉去学校、乐乐去幼儿园后,整个家就成了他一个人的实验室。他把原本堆在书房各个角落的金融数据资料、打印的论文、写满公式的草稿纸全部收纳整齐,给三台显示器重新规划了布局:左边显示FastApI开发文档和pycharm编辑器;中间是React学习教程和VS code;右边是量化核心策略的python代码和测试终端。
FastApI的选择是经过深思熟虑的。相比传统的Flask或django,FastApI基于python 3.6+的类型提示,性能接近Node.js和Go,自动生成交互式ApI文档,对于需要高性能、清晰接口定义的量化服务后端来说非常合适。林晨花了三天时间,将原本散落在多个脚本里的数据获取模块、特征工程模块、模型预测模块、交易信号生成模块,逐一拆解、重构,封装成一个个独立的、具有明确输入输出的函数和类。
然后,他用FastApI将这些模块“粘合”起来。创建了 /api/v1/data/ 系列端点,用于获取实时和历史数据;创建了 /api/v1/feature/ 端点,用于计算技术指标和特征;最重要的是 /api/v1/signal/ 端点,它接收市场数据,调用核心AI模型,返回买卖信号和置信度。每一个端点都有详细的pydantic模型进行请求和响应数据的验证与序列化。
“这才像个样子”。林晨看着自动生成的Swagger ApI文档页面(
后端雏形完成,接下来是前端。这对林晨是个新挑战。他以前做后端,前端知识停留在jquery和一点Vue的程度。React是现代前端绝对的主流,其组件化、声明式编程的思想,与他正在做的模块化后端不谋而合。
学习过程比预想的顺利。React的核心概念——组件、JSx、状态(State)、属性(props)、hooks——对于有扎实编程基础的他来说,理解起来并不困难。难的是前端那一套生态系统:webpack(或Vite)、babel、npm包管理、cSS框架……他选择了一条最快捷的路径:使用 create-react-app 脚手架快速搭建项目,UI组件库选用轻量且流行的Ant design,图表库选用Echarts。
他的目标是做一个简洁、实用的监控面板。左侧导航栏,中间主区域显示核心内容。主区域又分为几个卡片组件:实时资产总览(账户余额、浮动盈亏、持仓)、市场状态(主要股指、汇率、大宗商品涨跌)、交易信号列表(最近产生的买卖信号详情)、性能图表(资金曲线、回撤图、胜率统计)。
当第一个Echarts折线图在浏览器里成功绘制出模拟的资金曲线时,林晨忍不住挥了一下拳头。那种从无到有,从杂乱数据到清晰可视化的创造感,令人着迷。他不断调整着图表的颜色、提示框、缩放功能,让它看起来更专业、更直观。
前后端都跑通后,最大的考验来了:部署。
他对比了几家主流云服务商。大厂的云服务稳定但稍贵,创业公司的云性价比高但怕有坑。考虑到目前系统规模小,访问量几乎为零(只有他自己看),他最终选择了一家口碑不错的中型云服务商,买了一个最低配置的云服务器(1核2G,带宽按量付费),月费不到一百块。
按照教程,他在纯净的Linux系统上安装了python环境、Node环境、Nginx、数据库。将后端FastApI代码打包上传,用Uvicorn作为ASGI服务器启动;将前端React项目构建成静态文件,也上传到服务器,通过Nginx配置反向代理和静态文件服务。
最难搞的是让后端服务稳定地在后台运行,并且开机自启。他研究了systemd,写了服务配置文件。又为了更方便管理,引入了pm2来守护Node服务(虽然目前前端是静态的,但他为未来可能的前后端分离ApI预留了可能)。
整整折腾了两天,遭遇了无数次“permission denied”、“端口被占用”、“依赖缺失”的错误。每一次排错,都是对Linux运维知识的恶补。当他在本地电脑的浏览器里,输入那个属于自己的云服务器Ip地址,看到React监控页面成功加载,并且通过页面上的按钮调用后端ApI,实时获取到最新的账户余额和交易信号时,那种跨越重重障碍终于抵达终点的成就感,几乎要满溢出来。
系统,上线了。
现在是下午四点,鹏城的阳光斜照进书房。林晨靠在椅背上,长长地舒了一口气。他拿起手机,给自己点了一份平时舍不得点的、来自南山科技园某家知名烧腊店的豪华双拼饭,多加一份叉烧。
等待外卖的间隙,他用自己的手机4G网络,再次访问了那个监控面板。页面流畅加载,图表清晰展示。这意味着,无论他在家里、在咖啡馆、甚至在未来可能去面试的路上,只要能上网,他就能随时掌握自己那个“AI交易员”的工作状态。
他点开“交易信号”列表,最新一条记录显示,就在十五分钟前,系统基于欧元兑美元汇率的小幅波动,结合AI模型判断,自动执行了一笔微量的买入操作。状态显示“已成交”。
林晨切换到实盘的券商App,核对了一下。成交记录一致。浮动盈亏栏显示着一个绿色的正数:+86.33元。
钱不多,甚至不够付刚才那顿外卖。但意义重大。这证明从数据获取、AI分析、信号生成、到自动下单执行、再到结果反馈至监控面板的整个闭环,在全新的、更健壮的架构上,跑通了。
手机震动,外卖电话。林晨起身去拿外卖,脚步都轻快了几分。
当他吃着香喷喷的叉烧饭,时不时瞥一眼旁边平板电脑上自动刷新的监控面板时,一种久违的、扎实的掌控感,慢慢在心底沉淀下来。失业的阴霾,求职的焦虑,似乎被这一行行亲手敲出的代码,一个个被攻破的技术难点,暂时驱散了。
饭吃到一半,苏婉发来微信:“晚上爸妈那边打电话来,说想过来看看乐乐,顺便……看看我们。我估计周末可能会来。你有个心理准备”。
林晨咀嚼的动作慢了下来。他看着微信,又看了看屏幕上那条+86.33元的盈利记录,以及背后代表的一整套正在悄然运转的系统。
他回复:“好,我知道了。别担心”。
周末,父母要来。他们看到的,将是一个仍在家中、没有“正经工作”的儿子。但林晨知道,有些东西已经不一样了。他放下手机,继续吃饭。代码可以骗人,但逻辑不会。而他自己亲手构建的逻辑世界,正在变得越来越清晰,越来越有力。