单体架构的量化我跑了大概一年多。
整体介绍
- 量化架构
1.0.0
- 单体架构
- 量化名称
tomoon
- 服务器
AWS
免费套餐ubuntu18.04
1核1G- 最巅峰使用
12
台服务器跑 - 每台服务器都是独立运行
- 所跑策略
- 低延时策略,如搬砖等
- 量化领域
- 加密货币
- 集中在
MEXC
和BSC
上
- 集中在
- 加密货币
- 编写语言
python3.7
- 代码量
3-4
万行
- 运行时长
- 大概
14
个月
- 大概
- 是否盈利
- 盈利
- 编写人员
1
人
设计架构的思路
首先受制于金钱,我的服务器是 1
核 1 G
的,经过多次迭代后,我的最终整套架构都选择用 python
编写。
而,python
受制于 GIL
,所以,多进程方案肯定排出。
由于整体结构是密集 IO
架构,经过多次迭代形成了下面的图,「多线程 + 协程版本」。
详细请参考
当然,上面的图仅仅只是核心流程图,很多细节并没有展示。
架构模块解释
tomoon 1.0.0
是单体架构,虽然是单体架构,但是为了考虑后期维护,将很多代码抽成了独立的模块。
Engine
- 中心引擎模块,处理各个其他模块间的中转站
MainFngine
、ManagerEnginer
、ProjectEnginer
、StrategyEnginer
、TradeEnginer
- 有的时候我在想,真的需要这么多引擎中间件吗?但是,有的时候确实需要,有的时候又觉得多余
Handler
- 各个交易所、链等,主要是对接非认证的行情信息
logger
- 日志模块
Sender
- 通知模块,钉钉
Transfer
- 各个交易所的对接,主要是认证对接,比如下单、查询账户信息、提现等
Strategy
- 最核心最复杂的模块,所有的代码都在这里实现
- 各种策略实现的代码,包含的内容非常多
虽然在上面图中看到 Strategy
是自成一体,其实,Strategy
和 Transfer
等模块的地位是一样的,只不过,为了展示数据流向才那样画的。
整体架构是面向策略编程。
数据流向
以图中 Strategy
为流向讲解。
DataService
是获取数据模块,首先整个架构只有一个主进程,主进程里面放置了一个数量为 10
的线程池。
主进程维持一个 while 1
的无限循环。每一个线程有一个任务,任务是通过两个协程来获取数据。然后,获取相关的数据后进行比较。如何合适再进行下一步。
用伪代码进行书写。
1 | class Strategy: |
线程池会通过协程得到的数据,进行比较,假设比较通过后,会进入执行策略环节,这里要特别注明的是,执行策略环节是需要加锁的,否则,很容易出现数据紊乱问题。
线程池中,一次性会提交 10
个任务。假设,10
个任务返回的数据中,有 2
个任务的数据能用,但是,只执行第一个到来的数据,剩下的数据会被放弃。当一次执行完毕,会重新开始新一轮的 10
个任务。
这里的任务指的就是单个线程获取数据。
解答疑问
这里主要回答两个疑问
- 为什么单个线程中需要放置两个协程?
- 每个策略都是上面的架构吗?
这两个问题,我加在一起回答。首先,tomoon 1.0.0
跑了 1
年多,真正盈利的就是一个策略,即搬砖。
事实上,tomoon 1.0.0
本质上是一个低延时系统,通过抢单进行盈利操作。比如,mexc
的 token
价值 10
,binance
的价值 11
,这里面就有价差,也就存在了套利空间。
当然,我真正执行的策略是复杂于上述的操作的。我也进行了不通过策略编写,比如趋势啥的,和图中不同的就是,可能只使用一个线程获取数据,没有线程池和协程。我开发了十几个策略,但是,真正盈利的就是搬砖策略,所以,图中也是以搬砖的策略画的流程图。
之所以,里面放置两个协程,我们需要思考一个问题。
对于,搬砖来说,最重要的是什么?
- 数据的实时性
- 数据的连续性
- …
实际上,搬砖作为抢单策略,不需要考虑数据的连续性,只需要考虑实时性就好了。
所以,每个线程里面有两个协程,每个协程去单独的请求一个交易所某一个交易对的数据,整体数据的实效性可以得到保障。
运行情况
tomoon 1.0.0
运行了一年多,运行非常稳定,即便是 1 核 1G
也才用了 6%
的资源。之所以,我弄了十几台服务器,主要是,交易所对服务器的 IP
有限制。
但是,tomoon 1.0.0
自 2022
年 9
月份之后,就没有跑了。原因有二
- 单体架构过于臃肿
- 下面说
- 策略已不能盈利
架构的优缺点
优点
Strategy
里面的每一个策略都是独立的,整个量化框架可以说是面向策略编程。
策略独立包括,每个策略有自己的风控、数据采集、处理模块等。并且,大策略底下还分很多细节策略区分。
比如,Cex2Dex
策略中,又分成Mexc2BSC
、Binance2BSC
。
并且,单体架构在编写初期可以让项目快速迭代。
缺点
当项目过于庞大的时候,单体架构就越来越难维护了。
尤其是涉及到变量传递,编写不好就很容易产生耦合。
由于所有的代码都放置在一个工程中,后期维护越来越难,偶尔有人想要我帮忙谢谢策略,我就又得加入一些冗余代码,后期,看了就头疼。
所以,我想要一个模块独立运行的架构,比如,数据模块就专门用来爬去数据,然后,有其他模块通过中间件比如 MQ
或者 redis
来获取这些数据。
这样就少写很多代码。
后期,应该不会再维护该架构了,而是全面转向 2.0.0
的架构,伪微服务架构,请参考