策略模块
策略模块
我将在此章向你介绍如何在ctpbee中使用策略模块,分为下面三个章节为你讲述
- 架构
- 使用方式
- 需要注意的点
架构
ctpbee将策略设计为一个Level
,而在这个Level
里面可以容纳多个策略,他们都是基于行情驱动的
使用方式
为了你的使用习惯,我们开发了两种模式供你使用ctpbee
的策略模块
- 装饰器模式
- 基于类继承的模式
装饰器大法
首先介绍一下基于装饰器的模式,如果你们有使用过米筐这种的在线平台,那么你应该很熟悉这种使用模式
首先来让我们让创建一个策略实例
from ctpbee import CtpbeeApi
data_recorder = CtpbeeApi("data_recorder")
呐,我们创建一个策略实例,实例的名字的是data_recorder
, 同时我们传入了一个策略的名字叫data_recorder
,而这个id是被app所承认的。 那我们现在创建了核心策略对象,那我们怎么来编写策略呐 ,看以下代码的注释
@data_recorder.route(handler="tick")
def handler_tick(self, tick):
print(tick)
@data_recorder.route(handler="bar")
def handler_bar(self, bar):
print(bar)
# 然后把他载入到app中
app.add_extension(data_recorder)
那么当行情tick到来的时候会自动触发handler_tick
里面的代码,bar/k线也是同样的道理 但是只有这两种API吗,不, 远不如此,route
里面的handler
还可以接受更多的参数,不过他们是非必须,按照你们的意见进行编写即可, 包括以下:
contract
合约position
持仓trade
成交order
报单init
初始化shared
分时图 / todo: 后面进行移除timer
定时器,一秒触发一次
但是随之而来又产生了另外一个问题,我只能写这个几个事件的处理代码吗, 我就不能自己实现一些好用的功能吗?
答案当然是可以的,我们提供了register
装饰器来让你自定义功能函数,并可以在事件处理代码中进行调用,但是你需要注意的是你的函数必须是一个Method
的编写方式而不是一个普通function
的编写方式。
示例:
@data_recorder.register()
def get_position_by_ld(self, local_symbol, direction)
""" 根据local_symbol和direction获取持仓 """
pass
上述我们通过策略data_recorder
的注册函数实现了一个get_position_by_ld
示例方法,注意他传入的参数第一个是self,也就是示例本身,然后传入 local_symbol
和direction
,他是一个Method
,所以我们在调用他们的时候只需要传入local_symbol
和direction
。
通过这个很小巧的API,你可以自定义很多很多的功能,尽情享用他吧
完整代码
from ctpbee import CtpBee, CtpbeeApi
data_recorder = CtpbeeApi("data_recorder")
@data_recorder.route(handler="tick")
def handler_tick(self, tick):
print(tick)
@data_recorder.route(handler="bar")
def handler_bar(self, bar):
# 调用注册的事件
self.get_position_by_ld(bar.local_symbol, bar.direction)
print(bar)
@data_recorder.register()
def get_position_by_ld(self, local_symbol, direction):
""" 根据local_symbol和direction获取持仓 """
print("I AM A METHOD")
if __name__ == '__main__':
app = CtpBee("demo", __name__)
info = {}
app.config.from_mapping(info)
app.add_extension(data_recorder)
app.start()
基于类继承的模式
不同于装饰器模式的先创建示例,再进行编写代码的模式,基于类的方式需要你先写代码,再创建实例
示例
from ctpbee import CtpbeeApi
class DataRecorder(CtpbeeApi):
def __init__(self, name, app):
super().__init__(name, app)
def on_bar(self, bar):
self.get_position_by_ld(bar.local_symbol, bar.direction)
pass
def on_tick(self, tick):
pass
def get_position_by_ld(self, local_symbol, direction):
print("I AM A METHOD")
聪明细心的你肯定发现了上述代码其实和装饰器非常相似,不同的是函数名字换成on_bar这样的模式。
没错,基于继承的方式需要你重写函数,同样的on_bar和on_tick必须要被重写,其余按照你的需要进行重写就好,同样的这里面有一份函数名单需要你去了解
- on_realtime 实时策略检查 , 一秒运行一次
函数签名
def on_realtime(self)
- on_order 报单
函数签名
def on_order(self, order)
- on_trade 成交
函数签名
def on_trade(self, trade)
- on_position 持仓
函数签名
def on_position(self, position)
- on_init 交易接口初始化信号
函数签名 def on_init(self, init)
- on_contract 合约
函数签名 def on_contract(self, contract)
然后我们创建实例并载入到app中去
示例
if __name__ == '__main__':
from ctpbee import CtpBee
app = CtpBee("demo", __name__)
info = {}
app.config.from_mapping(info)
data_reocorder = DataRecorder("data_recorder", app)
app.start()
到这里你应该就能正常运行代码,但是等等, 这里有个小问题,为啥我们没有用add_extension
方法?
我来解释下, 策略肯定要能够拥有app
这个属性,所以我们肯定需要将app
传入进去 有四种可能:
- [ ] app创建的时候传入 // app作为核心,创建的时候传入明显不合适
- [x] app创建后传入 可以,通过
add_extension
传入策略 - [x] 策略创建的时候传入 可以,策略角色属于运行方。
data_recorder = DataRecorder("data_recorder", app)
,但是这不一定是必要的,作为可选方案 - [x] 策略创建后传入
data_recorder.init_app(app=app)
所以基于这三种方式,你可以很灵活的进行工程化~~
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论