前言
Q200已经达到了我既定的目标,在最近的3个月,我需要进一步完善,达到可以试产的程度。
在这个过程当中,许多知识和体会一直在变。
qtv200到目前,虽然通过习惯(每晚运行离线策略和比对)方式维持了注意力的集中,但是仍然有一种睡一觉就容易忘掉的感觉。而今天在思考队列作用时,突然意识到,etl的流应该通过kafka来执行,只有通用的核心能力才需要做微服务。
类似这样的灵感,然我觉得有必要在下一步实施之前重新约定整体的架构。
在谈架构之前先看看业务上的要求和设计。
1 利润目标:每月3%
3月算是q200开始实测的第一个月,因为行情原因,借了东风,感觉大概率达到了。最大的意义是在于还清了历史问题,进入重置状态了。而q200本身的基准策略,只剩下小金额测试,效果比较理想,但没法进行更好的测算。
例如在测试盘中,2月份30单,目前平均浮盈4.6%。但是问题是,目标追求的是整体,而我们很难保证每一分钱都恰好投进去了,所以这里要打折扣;另外,每个测试单未必能精准跟踪,所以这里又有差距。
当然,最重要的单子如果是打开状态的,那么不能够保证,都是敞口。
所以假设这个已经作为一种产品可被生产和销售的话,我们肯定需要考虑其稳定性,也要评估期望。就像生产芯片那样。
现在先不谈具体的数值,但是很显然,有一个问题是需要考虑的:如何计算当前的进展?
假如说,目标是3%,然后目前还在open的订单计算是floating profit ,浮动的;而已经close的订单则是fixed profit固定的。应该有类似的公式:
y' = a * x + b
其中a是折扣率,因为浮动的风险很高;而b是已经完结的部分,是固定的。所以在确保目标完成时,应该有一个策略是要控制a。
技术上,需要能够客观的统计这个,然后预测、跟踪这部分的变化,同时作出反馈。这将影响到全局的仓位控制。
2 行动辅助
因为是手动下单,所以一定会存在跟踪误差。
所以系统应该从事前、事中和事后给到辅助。
- 1 事前。由于信号具有滞后性,所以应当允许事先的,或者whatif 类型的分析,自动的将“可能发生”告诉用户。
- 2 事中。当信号已经确定,这时会需要根据实时数据帮助用户跟踪信号,甚至根据历史经验预测是否有更好的买点在短期会出现。
- 3 事后。当信号确定结束,此时需要清盘。是立即清盘,还是允许等一等,需要系统告知用户。当然,大多数时候应当立即清盘。
技术上,需要有实时的数据获取和消息通知(如邮件、app等);每个事件都具有完全的生命周期,整个过程应该比基准策略的时间范围更宽一些。
3 策略框架
基准策略之所以为基准策略,就是因为不完善,所以一定需要开发衍生策略框架。
如果完全按照基准策略,那么很难达到利润目标,而且有可能因为长时间的负利润而失去信心。
虽然总体上已经是明显盈利了,但是如果 要承受若干个月的损失,我估计大部分人都会放弃:基准策略是无法直接使用的。
那么怎么进行进一步增强?直观上削平波峰,然后摊到后面若干月上。
按照类似游戏的方式,可以做出一些有趣的设计,此处不展开,然后会有一些离散的行为出现:
- 1 试探性买入
- 2 保守的止盈
- 3 激进的止盈
- 4 伺机抄底
- 5 反复收割
对于这些衍生擦略,应当有一个可执行框架,初期仅考虑严格按照规则执行,未来将由算法自行探索。
技术上,需要对每一个主题有专门的存储,统计,来记录在各组参数下的效果,以及总体情况。
以上三部分,构成q200第一阶段业务上的基本要求。
接下来,分析技术上的要素
技术要素
一些离散的功能点:
- 1 要获取分钟级别的行情数据和舆情数据。 这个基础的功能性验证ok,明天我就可以开始获取分钟级别的舆情数据,虽然不多,但应该够了。
- 2 要存储数据。这个也没问题吗,这次特地准备了时间序列数据库。
- 3 要计算信号。最近一直在离线计算校验,明白了调整点,之后可以确保在线计算与离线计算一致。
- 4 要通知。短信不靠谱,app的通知已经准备好,邮件的通路没问题,但是展示方式我想用css稍微加强一下。
- 5 要能辅助分析。这个还没想好,想象中应该把这些要素可以抽取在一起,然后在页面上展示。数据抽取没问题,要怎么展示,特别是如何进行超链跳转可能要想想。
- 6 能够方便的吞吐对象缓存。这个没问题,我甚至用mongo做了这事。redis我怕掉了,懒得同步。
- 7 回测计算。这个已经做了一版,虽然慢了点。后续可能需要使用numba来加速,格式要改改。
- 8 表格计算和统计。这个可以用clickhouse,不怕大量数据,可以实时统计。
为什么要谈架构?
这些离散的功能点随便写写已经很多了,如果要全部落实细节会更多。然后到最后肯定又是失去控制,然后就没法维护和迭代了。我不想这样稀里糊涂的搞,然后做q300。
要考虑到,有些单点功能是非常复杂的,然后当你全力解决玩一个问题,又发现全局结构是模糊的… 效率会很低。
这次我想,至少能做到个部分功能是有组织,适度耦合的。
celery 执行, kafka流转
- 1 任务执行。一部分是IO任务,这个将交给apscheduler_celery框架。一部分是计算任务,暂时用传统方法,6月之后我会用类似rlib这种。
- apscheduler_celery的所有任务均为微服务任务,区别只有参数
- apscheduler_celery的异步任务结果都类似callback,会写入kafka
- 任务的执行都是固定的,按1秒,31秒两个时间点执行
- 队列按照主体,如数据获取的命名为 xxx_market_minute, xxx_market_daily, xxx_news_minute, xxx_news_daily
- 如果是处理,可以称为 xxx_etl_minute…
- 效果:我可以随时加上一个新的code,然后就会自动被分配执行。
line protocal 协议,mongo 存储
2 时间序列。最终所有的可决策数据都将存储时间序列数据库。如果说数据的获取是起点,那么事件就是终点
- 1 新闻事件
- 2 行情事件
- 3 策略事件
- 4 目标事件
3 前端可视。暂时还是采取比较保守的做法,flask + bootstrap + js。
- 1 总体交易数据
- 2 订单详情数据
- 3 辅助决策数据
mongo + clickhouse
- 4 数据存储。mongo存储原始数据,clickhouse存储分析的表数据。
几个核心的元数据:
- 1 celery在每个心跳执行的任务。会有一张表格,记录哪些任务是需要周期执行的,可以增、删、改。这个是一切的源头。
- 2 监控数据。包括了各队列的长度,在时序数据库中对数据的条数统计。这个可以推到kafka,然后送到clickhouse。
- 3 KPI数据。包括运行中的策略,结束的策略,整体的目标效果,波动等。这个应该会在clickhouse.(不需要kafka)
特别重要的对象:
1 通知对象。这个对象会挂在每个策略下面,按照规则进行事前、事中和事后的全跟踪。其行为通过kafka发送,日志持久化在mongo中,主数据也在mongo中。
5 微服务。将一些重要且复杂的处理步骤封装为微服务。
- 1 获取数据封装为微服务。我需要的数据不多,频次也很低,但最好还是通过微服务请求。
- 2 回测作为微服务。这部分容易丢掉,且要长期维护,所以发布为微服务。
- 3 基准策略的信号生成。同上。
这样,可以想象,如果我一次性做好之后,又去忙了很多别的东西,当我要迅速切入进行维护时:
- 1 我会找到celery的任务元数据,我知道我对那些标的执行了后续的计算
- 2 我会看到一个队列清单,知道他们在连接那些处理,有没有超时
- 3 我会看到监控分析,知道数据是否都按时,无遗漏的拿到了
- 4 我会看策略整体效果,确保策略是与目标一致的
- 5 我可以看策略之间的差异,进行分析
当我有新的想法时,我应该采用一个新的命名,按照类似的步骤做好前期的获取和处理,然后,我应该在时间序列中找到这个事件。这样就形成了一个以时间为轴的通用管理方式:我新的任务只是在时间维度上不断拓宽。当然,对应地,事件背后的数据无论是数值、文本还是向量,可以在对应的元数据中展示。所以在需要的时候,可以在一个时刻把所有的的特征数据全部对齐,产生聚集效应。
Next: 把异步任务框架和kafka连接搞好。并开始产生事件。