快递是下午到的。一个牛皮纸的包裹,A4大小,用透明胶缠了三圈,胶带上印着顺丰的红色字。包裹不重——拿在手上掂了一下,大概一斤多。寄件人:赵启明。寄件地址:上海浦东陆家嘴环路1088号。
拆开。里面是一叠打印的资料——不是书,是从各种地方打印出来装订的,有的页边还留着网页的页眉和页码,有的纸是A4的,有的纸是B5的,大小不一,摞在一起边角参差不齐。赵启明大概是把自己手边能找到的都打了一份寄过来,没管格式。纸的厚度也不一样——有的薄,透字,有的厚,摸着像卡纸。最上面一张是目录,赵启明用红笔编的号:
1. K线基础
2. 移动平均线
3. 动量指标
4. 均值回归
5. 量化策略入门
红笔的字是他一贯的写法——横平竖直,没有连笔,像印刷体。每个编号后面的冒号都是对齐的,五个冒号排成一条竖线。他在第三条的旁边打了一个括号,括号里写了一个字:"略"。大概是他觉得动量指标不太适合我的算法思路。第二条"移动平均线"旁边打了一个对勾——他大概觉得这是最应该先看的。
夜里。办公室只剩我一个人。他们都走了——合伙人去见人,两个写代码的回租房了。服务器在机房里嗡嗡响,和深圳的夜一样不会停。我把资料摊在桌上——五摞,按他编的顺序排好。台灯的光照在打印纸上,纸面泛白,黑色的图表和文字在白纸上很清晰。旁边的咖啡凉了——速溶的,棕色的液面上浮着一圈没化开的白色粉末。
K线基础。第一页画了一根K线——一根竖着的矩形,矩形的上下各伸出一条细线。矩形是实体,细线是影线。实体上边是收盘价,下边是开盘价——收盘比开盘高就是阳线,画成空的或者红的;收盘比开盘低就是阴线,画成实心的或者绿的。上面的影线尖是最高价,下面的影线尖是最低价。
一根K线。四个价格。开盘、收盘、最高、最低。
我看了很久。把那页纸拿起来凑到台灯下面。纸面上K线的图示被灯光照得很清楚,矩形的边是直线,影线的端点有小横杠标记。旁边还画了一组K线排列的示例,阳线和阴线交替出现,高高低低排成一行。
这四根价格线把一段时间里的市场行为压成了一个形状。矩形的宽窄是涨跌的幅度,影线的长短是波动的范围,阳线阴线的交替是多空力量的拉锯。
状态变成了形状。
我把K线图竖起来看。竖起来之后,K线从左到右排成一排,每一根都是一个时间点,时间点之间连成一条线。
管网→路网→K线。三种图放在一起,先看节点和边,再看权重和方向。
我拿起蓝色钢笔,在打印纸的空白处画了一幅对照图:
管网:节点=管段交点 边=管段 权重=水压/流量 方向=水流
路网:节点=路口 边=道路 权重=距离/时间 方向=车流
K线:节点=价格 边=时间间隔 权重=波动率 方向=资金流
三行字。三套标签。先这样拆开。
我打开电脑。Python环境还在——之前写金融数据脚本的时候装的。打开一个新的编辑器窗口。光标在左上角闪。
第一个策略写什么?赵启明的资料里第四章"均值回归"讲了一个最简单的思路——价格偏离均值太多的时候会回来。但第三章"动量指标"讲的是相反的思路——价格沿趋势走,强者恒强。
两个思路矛盾。可市场本来就不是一种状态。慢的时候会回到均值,快的时候会沿着趋势继续走。问题不是哪个永远正确,而是什么时候该用哪一个。
我先写最简单的:双均线交叉。短周期均线和长周期均线。短均线上穿长均线的时候买入,短均线下穿长均线的时候卖出。简单,甚至有点笨,但能跑起来。
代码从import开始。pandas读数据,numpy算数组。读入日线数据——日期、开盘、收盘、最高、最低、成交量。计算五日均线和二十日均线。五日均线看短期变化,二十日均线看更慢的方向。两条线交叉的时候,程序就记录一次信号。
写代码的时候手指在键盘上跑,和写管网优化程序的时候一样。变量命名沿用了旧习惯:node改成price,pipe改成interval,pressure改成volatility。不是因为它们真的相同,只是这样写,我自己看得懂。
信号生成了。买入信号、卖出信号、持仓状态、累计收益。代码一共一百二十行。从第一行import到最后一行print,一百二十行。比管网优化程序的第一版多了四十行——但管网程序的第一版只有Dijkstra,这一版有信号生成、仓位计算和回测框架,结构更完整。
回测。
历史数据拉了沪深三百指数从2010年到2012年的日线。三年的时间,七百多个交易日。程序跑起来,进度条从0%到100%用了十二秒。十二秒跑完了三年的数据——和管网优化程序跑一千代遗传算法用的时间差不多。
结果出来了。
年化收益率7.2%。最大回撤8.6%。夏普比率0.84。
7.2%。不高。银行理财都有5%了。但7.2%是程序跑出来的——程序不知道贪婪,不知道恐惧,不知道新闻上说了什么,不知道央行加了息还是降了准。它只知道五日均线穿过了二十日均线,然后执行。执行完了等下一个信号。下一个信号什么时候来?它不知道。它只等。
和在百度优化导航一样——程序不关心你为什么要去那个地方,它只找最短的路线。在管网里也一样——程序不关心水龙头为什么打开了,它只算最优的压力分配。算法不问为什么。算法只找最优。
7.2%是一个起点。管网优化程序的第一版也只能算最短路径,后来加了遗传算法才变成多目标优化。这个双均线策略也一样——先跑通,再加东西。仓位管理、风险控制、止损,都还没有真正写进去。框架有了,内容还很薄。
凌晨三点。窗外的深圳还没睡——远处有塔吊的红灯在闪,一闪一闪的,像心跳。楼下的烧烤摊还有人在喝酒,声音隔着窗户传上来,听不清说的什么,只听见笑。笑的声音在夜里传得远——比说话远。
我翻开笔记本。蓝色钢笔。
K线可以拆成点和线。价格是点,时间把点连起来。止损先放在旁边,像一条不能越过去的线。
写完这行停了一下。然后在下面又写了一行:
管网→路网→K线。数据换了,方法也要重新试。
笔尖在"试"字后面没有画句号。没有句号的意思是——这件事还没有结束。数据换了,程序还没写完。一百二十行的双均线策略只是一个雏形。管网优化程序的第一版也很粗,后来加了遗传算法、自适应变异率、精英保留策略,才慢慢能用。
K线策略也需要加东西。加什么?仓位管理,风险控制,止损。旧系统里那些我熟悉的边界,在这里都要重新命名、重新写一遍。
合上笔记本。屏幕上回测结果的数字还在——7.2%、8.6%、0.84。图还在画,远没有画完。