-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RQAlpha 2.0.0 #65
Comments
吓到了-。- ,老司机写了那么长的总结。。。 |
辛苦艾老师,正在拜读。 |
辛苦老司机了。这次重构完毕之后,业务逻辑更加清晰。account管钱,portfolio管组合方面的风险收益计算,strategy是策略本身的逻辑实现。 |
@cedricporter 部分是总结...部分这次的重构的核心内容 |
升级到2.0时会自动卸载原有的numpy+MKL...导致我一票依赖mkl的包scipy numba全废了- - |
@PhantomCSY ?? RQAlpha 2.0.0还没发布啊 你是怎么升级到2.0的...? |
@PhantomCSY 另外 Python的包依赖本来就很烂,所以才有的 pyenv 或者 conda env,你不能因为一个库扰乱了另一个项目的环境而怪在这个库的头上... 正确的做法是通过env 来进行分离他们之间的依赖关系。 |
受教了,刚刚看到upgrade并非是2.0,感谢! |
good job |
期待啊,2.0什么时候发布 |
@wwgoddess RQAlpha 刚刚发布了 2.0.0b0 测试版本。 您可以通过 |
在最开始,RQAlpha是作为股票策略的回测框架来使用的,因此最初设计认为
Postion
是仓位,而Portoflio
作为仓位的组合,这样可以很好的解决计算对应股票策略的收益、风险度等非position
指标数据的业务逻辑,并且在最初也确实可以比较充分的满足业务的需求。但随着加入期货类型的回测,发现已有的
Portfolio
不能满足期货相关策略的需求,因此我们将Portfolio
抽离成了一个BasePortfolio
,而股票和期货分别继承自BasePortfolio
,形成自有的StockPortfolio
和FuturePortfolio
,他们不再完全一样,有自己内在的计算逻辑和事件响应逻辑。这时候
Portfolio
不仅作为一个投资组合,其中还包含了诸如计算手续费, 计算滑点成交价,存储当日订单和成交等数据,我们认为其承担的职责过重,因此引入了一个新的概念 -Account
来承担Portfolio
中事件响应的逻辑,滑点、交易成本计算的逻辑,persist的逻辑,以及订单、成交相关存储和处理的逻辑。我们将Portfolio
抽离成了一个典型的model
,从而整体上以行为和模型分离了业务逻辑。然而当我们继续深入下去,决定做混合策略的时候,发现独立的
StockAccount
和FutureAccount
同时存在,并且具有不同的业务逻辑,而又需要进行整合来作为整体,因为我们构建了MixedAccount
, 而MixedAccount
下面存在构建的MixedPortfolio
, 而MixedPortfolio
下面包含MixedPositions
,从而构建了一个看上去像是一个整体的模块,而实际上是一层层的代理。这种方案下,可以把
MixedPortfolio
看作是一个黑盒的portfolio
, 我们实现了portfolio
接口定义中所有的方法和属性。而且为了支持扩展性(即增加新的可交易品种,比如期权、比特币等),为了保证统一性(即使只交易股票,也存在MixedPortfolio
,并且需要对应的计算逻辑),无论是跑股票策略、期货策略还是混合策略,其实都使用相同的计算逻辑,而MixedPortfolio
为了兼容多种模式,在性能上做出了妥协。用户通过
context.portfolio.positions[some_order_book_id]
拿到的数据实际上是通过一层层的代理获取到的。因此如果用户在handle_bar
中频繁调用上述语句来获取position
,会多次通过代理获取处理。另外我们为了降低用户写策略时处理异常情况的复杂度,当不存在某个
order_book_id
对应的持仓时,仍然会自动初始化一个position
返回给用户,而其中存在非常严重的性能问题,在handle_bar
中查询过多的position
时,会导致python
的垃圾回收不及时,从而出现回测速度变得极慢的情况。虽然目前为止,只有 Ricequant 一家做到了支持股票和全品种期货回测、模拟和实盘,但这不能成为速度变慢和扩展较复杂的借口,因此我们痛定思痛,决定重新梳理所有的内部计算逻辑,因此才有了这次的2.0.0版本。
1. Portfolio到底是什么? Account到底是什么? 和Portfolio到底应该是什么关系?
为了进行
API
的兼容,我们一直没有修改Portfolio
的意义,以及其所承担的作用,但在多品种混合策略中,Portfolio
已经失去了原有的含义。我们认为每个策略实际上只应该有一个Portfolio
来表示整体的投资组合,而其只应该包含账户汇总相关的信息,因此,全新的Portfolio
包含如下内容:而基于这些基础值,可以计算出来如下投资组合对应的属性:
positions
实际上属于Account
下的内容,这里实际上还是做了一层汇总的代理,不过性能上进行了优化,和直接使用account.positions
速度相差无几了。)Account
从字面意义理解,就是账户,就像股票账户、期货账户一样,账户下面会有持仓,会计算这个账户下的总权益、总市值、可用资金、交易成本等,Account
也应该负责监听事件来处理对应的事件逻辑。而Portfolio
实际上是账户上层的一个逻辑概念,其包含了所有账户并进行汇总。为了保证账户的通用性,无论是模拟交易还是实盘交易,无论是股票、期货还是期权,我们需要寻找他们共同的原子数据作为账户初始化的输入,经过讨论最终确定如下数据作为其共同的初始化内容:
只要获取到这三个数据,就可以完成
Account
的初始化,但实际交易过程中,可能还会存在,盘中重启,请求断连等需要同步仓位到最新状态的需求,因此我们定义了fast_forward
函数,每一个账户都需要实现该函数,来保证账户可以进行positions
,frozen_cash
,backward_trade_set
的同步。比如我们在FutureAccount
中进行了如下实现:2. 滑点、手续费等计算是否属于RQAlpha的核心逻辑?
RQAlpha 作为一个通用性的框架,不局限于回测或者模拟,因此计算滑点、手续费等内容实际上都并非是 RQAlpha 的核心组件,换言之应该是
Simulation Mod
的核心组件,因此我们将其进行了抽离,在Simulation Mod
中提供了commission_decider
,slippage_decider
和tax_decider
,并在broker
中完成相应的计算逻辑。我们还在梳理其他的内容,RQAlpha 只提供最核心、最标准、最通用的内容,其他的业务层内容全部放到Mod中实现。
3. 现有的Portfolio和Position计算的内容是否过于复杂,从而计算了很多用户根本不需要的东西?
我们梳理了
Account
和Position
的计算逻辑,进行了重写,新版本的计算逻辑摒弃了很多累加属性的计算,比如total_orders
,total_trades
,buy_trade_value
等,我们认为这些累加属性并不属于 RQAlpha 核心的一部分,也不属于基础需求,如果在某些场景下需要使用,我们可以通过Mod
的方式扩展,但不应该纳入到核心模块中来。同时我们取消了账户级别的盈亏、收益、净值、份额等概念,这些都不应该跟账户耦合,另外我们修改了
Position
和Account
几乎全部属性的计算方式,现在所有的属性都是由初始化时所传入的原子数据计算所得,而且几乎全部使用lazy compute
来实现按需计算,减少回测和实盘中因为计算而产生的延时。具体更改的内容非常多,如果对于细节感兴趣,可以通过对比代码的变化来进行了解。
4. 到底应该在哪里,哪个模块来处理诸如bar/tick这样的事件?或者说有必要每个bar来了计算market_value等内容吗?那又该是哪个模块来处理下单/拒单/成交相关的计算逻辑?
在不同的场景下,实际上
Account
需要监听的事件是不同的。比如新版本实现了
bar
数据和tick
数据的缓存,因此Account
不需要监听bar
和tick
事件来记录last_price
,只需要将last_price
做成lazy property
即可,用到的时候从缓存的数据中取就可以了。因为我们不再规定
Account
具体的事件注册内容,取而代之的是定义了register_event
函数,每个Account
只需要根据自己的需求来订阅事件即可。比如在StockAccount
中注册了如下事件:目前
StockAccount
和FutureAccount
不再监听Bar
和Tick
事件,也不会实时根据最新的价格更新对应的净值,而是采取lazy_compute
的方式,只有使用到相应数据的时候再进行计算,从而极大降低了回测和实盘的计算逻辑延时。5. 是否需要进行实时持久化?持久化真的有意义吗?
新版本的 RQAlpha 提供持久化的功能,但本身不依赖于实时持久化,
Account
的恢复只需要同一个截面的total_cash
,positions
和backward_trade_set
,当恢复以后直接通过读取当日trades
和open_orders
通过fast_forward
函数即可恢复到最新状态。直接连接实盘也可以瞬间完成准确的账户恢复。6. 我们现有的持久化内容是否和对接实盘获取的数据一致,如果不一致就会导致产生完全不同的两套计算和恢复Account/Positions的逻辑,这些问题应该怎么标准化,怎么解决?
原先我们使用两套不同的逻辑来恢复策略在模拟交易和实盘交易中所拥有的账户及持仓信息,但这次重构以后,他们全部按照上面所述的进行恢复。当我们支持更多的实盘,或者更多的交易品种时,也同样以这样的方式进行恢复,未来对接新的实盘或者交易标的,都是一件非常轻松的事。
7. 如果我们增加净值和份额的话,那是否每个Account都有自己的净值和份额?如果有的话,产生出入金的时候MixedAccount的净值和份额又如何计算?
我们认真讨论过关于每个账户提供净值和份额是否可行的问题,最后的结论是不可行,因为
portfolio
层级的净值和份额无法再出入金后直接通过账户的净值份额来算出,而实际上账户级别应该看的是总资产的变化,讨论净值没有意义。因此我们只以Portfolio
层级提供相应的净值和份额计算,出入金会更改portfolio
的份额以及对应账户的cash。8. 回测过程中,我们真的需要撮合引擎吗?其使用场景到底是怎样的?
很多人询问模拟(回测也算是一种模拟)过程中的撮合逻辑的问题,比如说什么是
CurrentBarClose
成交,什么是NextBarOpen
成交,比如说我下单为什么还有部分订单被拒单,比如说limit order
的下单成交是如何模拟的,比如有的用户其实就是把下单当做一个信号,并不想让其拒单。这些问题或者需求都是现实存在的,而目前来说,基于日线/分钟线的撮合逻辑是存在误差且并不准确的。我们提供撮合逻辑的初衷是帮助初学者避免使用未来数据以及帮助不了解
Market Impact
可能会在实际交易中对于下单产生影响的同学进行模拟,但当前的撮合逻辑反而可能会影响到资深量化用户进行精准回测的需求。因此我们决定提供全新的一个回测模式,即信号模式。用户下单只是信号,不会因为当前
Bar
成交量不足而被拒单,RQAlpha 会根据用户的下单指令立即成交并返回成交信息,更新账户状态(但是验证可用资金是否足够,平仓验证可平仓为是否足够,验证价格是否超过涨跌停等等的风控逻辑还是存在的)。在这种模式下,用户可以做到精准回测,不需要考虑订单被撤销、追单等逻辑,回测速度回更快,但需要自行处理未来数据等问题。9. 为什么Release的新版本会是2.0.0?具体的发布时间?
我们主要是宣传目前版本
0.3.14
而在知乎上发布了 米筐开源量化交易框架 RQAlpha 2.0因为相比于半年前的
0.0.72
版本,几乎是完全不同的框架了,因此以 2.0 vs 1.0 的方式来介绍全新的RQAlpha。但有不少同学,询问具体的版本为什么两边是不同步的,因此觉得从这个角度来看,确实现在的状态不太好。
所以正好趁着这次有别于与
0.3.14
的大版本迭代,升级项目至2.0.0
版本,而且这么大改动,确实对得起这个版本号>_<2.0.0
版本会在 2017/3/27 发布beta版本,并同时发布 rqlpha-mod-vnpy 的beta版本。未来会有更多的交易标的(比如期权、比特币,国外市场)的计算逻辑的支持以及对应的实盘接口和实时数据的支持,也希望有兴趣的同学加入到RQAlpha的开发和测试中来。
The text was updated successfully, but these errors were encountered: