我们做量化交易时可能需要多品种多策略同时运行,就需要用到多线程或异步协程来实现,本文便给出一个实现多线程和异步协程的策略框架。线程和协程的概念可以在网上查阅相关资料,本文就不详述了。
本文代码基于天勤量化平台编写。
我们可能需要跟随一个品种或多个品种的行情、持仓等一个或多个业务数据的变动,来执行一个或多个策略,如果能有一个公共的框架,只要传入相应参数就能实现各种应用场景,会给量化交易带来很大便利,本文便尝试给出了这样一个公共框架,分为多线程和异步协程两种,当然两种也可以嵌套。
一、多线程:
天勤多线程需要保持主线程里的账户实例调用api.wait_update(),在子线程里创建主线程账户实例的副本api.copy(),用实例副本调用wait_update()。线程类定义如下:
#多线程类
class WorkerThread(threading.Thread):
'''1,主要用于依赖某个业务更新动态启动多品种策略的情况,比如随着账户持仓的变化启动各持仓品种的风控2,多品种策略不需要额外依赖自身业务更新时,推荐使用异步协程'''
def __init__(self, api,data=[],func1=[],func2=[],**job):
threading.Thread.__init__(self)
self.api = api #传入天勤实例副本
self.data = data #需要更新的业务数据,如行情、账户,可传入列表
self.func1 = func1 #随着业务更新需要执行的函数列表
self.func2 = func2 #自带业务更新的协程函数列表
self.job = job #func函数需要的参数,不定关键字参数
async def execute(self): #业务更新函数,为了保持线程代码块简洁性和自由性,业务更新采用了注册TqChan方式
async with self.api.register_update_notify(self.data) as update_chan: #业务注册到channel
async for _ in update_chan:#
e = 0
for f in self.func1:
e += f(api=self.api,**self.job) #返回值True保持业务更新,重复调用函数,全部返回值False退出业务更新,全部函数返回值必须一致
#也可以self.func1[index](api=self.api,**self.job)逐一调用
if not e : break
def run(self):
task1 = self.api.create_task(self.execute()) #
task2 = []
for f in self.func2: #线程中创建异步协程
task2.append(self.api.create_task(f(api=self.api,data=self.data,**self.job))) #func2为协程,直接创建协程任务
#也可以self.api.create_task(self.func2[index](api=self.api,data=self.data,**self.job))逐一调用
while True :
if task1.done() and all([t.done() for t in task2]) :break
self.api.wait_update()