Skip to content
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

[解答] 关于回测的一些问题 #1028

Open
yutiansut opened this issue Mar 11, 2019 · 0 comments
Open

[解答] 关于回测的一些问题 #1028

yutiansut opened this issue Mar 11, 2019 · 0 comments

Comments

@yutiansut
Copy link
Owner

yutiansut commented Mar 11, 2019

基于QAMARKET的回测样例解读(学习笔记)

以回测样例的控制台输出信息为线索,解读回测框架的大概流程,以便对于今后回测过程中遇到的各种问题,针对性地到相关文件中查找原因和解释。

**注:**Backtest.after_success()中的代码基本能理解不在此次解读范围之内。

1 开头的活动线程列表

控制台输出的第一条[<_MainThread(MainThread, started 16088)>, <Thread(pymongo_server_monitor_thread, started daemon 20464)>, <Thread(pymongo_kill_cursors_thread, started daemon 2448)>, <Thread(pymongo_kill_cursors_thread, started daemon 10404)>, <QA_ENGINE with ['ORDER'] kernels ident 19088>, <QA_Thread: ORDER id=1962034272968 ident 15468>]是一组正在运行的线程,不知道是谁输出的,但肯定不是在strategy文件的on_bar函数中输出

解答:

该输出在https://github.com/QUANTAXIS/QUANTAXIS/blob/master/QUANTAXIS/QAMarket/QAMarket.py#L132

2 market start 标志

market start是由backtest.start_market()输出的,这里调用的是**QABacktest.run()**函数。

subscribe是在哪里输出的暂时没找到。

解答:

此处的subscribe是ORDERHANDLER 订阅了该账户
https://github.com/QUANTAXIS/QUANTAXIS/blob/master/QUANTAXIS/QAMarket/QAOrderHandler.py#L271

3 start:running和current data/time

start: running、current date、current time都是由backtest.run()输出的。

这里调用的是**QABacktest.run()**函数,其中start running只启动一次,而current data和time则是对回测区间的的每个交易日输出。

4 QABacktest.run()

QABacktest.run()是一个非常重要的函数。对于socket-cn而言,当current data和current time输出完成后,只有当前一个交易日已经过去(_date != date)才会尝试对交易事件进行处理,try to settle就是在这里输出的。

4-1 QAMarket._settle

QABacktest.run()之后会调用以下函数:

self.market._settle(self.broker_name)

函数,在这里实际调用的是**QAMarket._settle()**函数,

“>-----------------------settle-----------------------------> QA_Market._settle”,就是在这里输出的。

4-1-1 QAMarket._trade

在_settle函数中会调用:

self._trade(event=QA_Event(broker_name=broker_name))

在这里会输出“==================================market enging: trade”

接着输出的列表应该是存放成交过程中出现的问题,例如:待成交、未成交、部分成交;如果交易成功,则这里应该是空列表。

然后输出==================================

接下来的self.order_handler._trade()这个函数的功能没太看明白,大概是对队列中的order进行处理

最后输出done。

4-1-2 QAMarket.broker[broker_name].run

这里实际上调用的是QABacktestBroker.run函数,这里首先输出“">>>>-----------------------QABacktestBroker.run----------------------------->"”

紧接着输出的是event.event_type,这一步的event_type取值是broker_settle,即在控制台中输出“">>>>-----------------------QABacktestBroker.run----------------------------->broker_settle"”

event_type的具体取值及意义见QAParameter.py文件。

    例如:
    """交易前置事件
    query_order 查询订单
    query_assets 查询账户资产
    query_account 查询账户
    query_cash 查询账户现金
    query_data 请求数据
    query_deal 查询成交记录
    query_position 查询持仓
    """
        """引擎事件"""
    MARKET_INIT = 'market_init'
    UPCOMING_DATA = 'upcoming_data'
    BAR_SETTLE = 'bar_settle'
    DAILY_SETTLE = 'daily_settle'
    UPDATE = 'update'

4-1-3

遍历QAMarket.session.values(),输出所有的account.history。

4-1-4

print('===== SETTLED {} ====='.format(self.running_time))

输出:===== SETTLED 2018-01-02 00:00:00 =====,如果之前没有待处理的交易,则这里会输出:===== SETTLED None =====

猜测:其中SETTLED后面跟着的是前一个交易日的日期,及前一天产生的order会在这里(也就是相对前一个交易日而言的下一个交易日)进行处理。

至此,QAMarket._settle函数结束。

4-2 QAMarket.next_tradeday()

通过以下语句调用QAMarket.next_tradeday()函数:

self.market.next_tradeday()

这里通过以下代码调用了**QAOrderHandler.run()**函数。

        self.order_handler.run(
            QA_Event(
                event_type=BROKER_EVENT.NEXT_TRADEDAY,
                event_queue=self.trade_engine.kernels_dict['ORDER'].queue
            )
        )

猜测:在这个函数中判断如果进入下一个交易日,则将order添加到任务队列中,可以认为是开始执行交易?

这个环节在控制台没有输出

4-3 QAMarket.upcoming_data()

被下面这条语句调用,生成 UPCOMING_DATA 事件放到 队列中去执行,更新市场数据。

self.market.upcoming_data(self.broker_name, data)

在QAMarket.upcoming_data()中,通过下面的语句调用了QABacktestBroker.run()

account.run(QA_Event(
    event_type=ENGINE_EVENT.UPCOMING_DATA,
    # args 附加的参数
    market_data=data,
    broker_name=broker,
    send_order=self.insert_order,  # 🛠todo insert_order = insert_order
    query_data=self.query_data_no_wait,
    query_order=self.query_order,
    query_assets=self.query_assets,
    query_trade=self.query_trade
))

4-3-1 QABacktestBroker.run()

在这里会首先识别event_type,在控制台输出下面的信息:

>>>>-----------------------QABacktestBroker.run----------------------------->

由于上面的赋值是ENGINE_EVENT.UPCOMING_DATA,所以会到相应的条件下执行,这里主要执行了一些赋值和数据缓存操作?

**猜测:这部分代码中涉及event的事件驱动,strategy中的on_bar也将在此(或此后执行)。**输出活动线程信息:

[<_MainThread(MainThread, started 7988)>, <Thread(pymongo_server_monitor_thread, started daemon 18904)>, <Thread(pymongo_kill_cursors_thread, started daemon 5328)>, <Thread(pymongo_kill_cursors_thread, started daemon 14092)>, <QA_ENGINE with ['ORDER'] kernels ident 7684>, <QA_Thread: ORDER id=2703319234544 ident 20044>]

=============================== 以下为strategy部分======================================

5 strategy中的on_bar()

strategy中on_bar函数的send_order调用的实际是**QAPortfolio.send_order()函数,在QAPortfolio.send_order中又会调用QAAccount.send_order()**函数。

5-1 QAAccount.send_order()

QAAccount.send_order()会对提交的order进行一系列判别和操作,如果提交的order没有问题,会历史委托order状态存储, 保存到 QA_Order 对象中的队列中,然后执行以下三条语句,如果提交的order有问题,则会输出ERROR : CODE {} TIME {} AMOUNT {} TOWARDS {}......类似信息。

self.datetime = time
self.orders.insert_order(_order)
return _order

5-1-1 self.datetime

赋值结果是当前交易日的0点0分。

5-1-2 insert order

self.orders.insert_order(_order)

这条语句会调用QAOrder.insert_order()函数,把order加入到order_list中。

5-1-3 _order

将_order作为返回值,其数据样式如下:

< QA_Order realorder_id Order_c1JDTdhk datetime:2018-01-02 00:00:00 code:000001 amount:100 price:13.35 towards:1 btype:stock_cn order_id:Order_c1JDTdhk account:mastrategy status:queued >

这段输出与控制台中的输出信息基本一致,唯一不同的是上面输出中的时间是00:00而控制台中输出信息的时间是 9:30。

问题:

1.对样例程序的运行机制理解不到位,尤其是字体加粗并标注“猜测”的部分把握不准。

2.从控制台信息输出顺序来看,strategy中输出活动线程的信息之前的部分大概能找到出处。但是接下来程序是如何运行的有些摸不着头脑,特别是以下输出信息找不到出处或者能找到出处但是不知道在哪里调用的。

>-----------------------insert_order-----------------------------> QA_Market.insert_order
>>>>-----------------------QABacktestBroker.run-----------------------------> query_data
100 by_amount 2018-01-02 00:00:00 000001 13.35 MARKET 1 None
< QA_Order realorder_id Order_flko2IS1 datetime:2018-01-02 09:30:00 code:000001 amount:100 price:13.625 towards:1 btype:stock_cn order_id:Order_flko2IS1 account:mastrategy status:queued >
queued
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!receive deal
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant