• backtrader日志、日历及resample


    本文摘自https://blog.csdn.net/m0_46603114/article/details/107889583

    日志功能

    可以通过下面的代码在backtrader中添加日志功能:

    cerebro.addwriter(bt.WriterFile, out = 'log.csv', csv = True)
    1
    日志信息将被输出到工作目录下的log.csv文件中,输出内容包括:

    种子数据(Data Feeds)
    策略数据(lines和参数)
    指标和观察者(Observer)数据(lines和参数)
    分析数据(参数和分析结果数据)
    交易日历

    交易日历适用于以下场景:

    由日线数据resample得到周线数据时,使用交易日历可以准确识别每周的最后1根日线。
    在策略的next()方法中打印一下内容

    在输出的每一行中,第一个日期为策略所使用的日期,第二个日期为当前日线的日期,第三个日期为当前月线的日期。
    其中,第3行1月4日为星期五,应该出现第一根周线数据,但是输出结果中却没有周线数据。第8行1月11日为周五,从1月7日至1月11日的5根日线可以合成1根周线,后面的周线数据也应该更新为1月11日,但是输出结果却是1月4日。
    产生以上结果的原因是,backtrader把2019年1月1日当作了交易日,只是没有读入数据。这样1月1日至4日,再加上7日共计5根日线,就在1月7日合成了第一根周线;同样1月8日至11日,再加上14日共计5根日线,在1月14日合成了第二根周线。这显然不是想要的结果。

    解决上述问题的方案是,通过继承bt.TradingCalendar定义新的日历,然后在日历中设定节假日。如以下代码所示,将2019年1月1日添加到holidays列表中,然后在cerebro添加该日历:

    class AStockCalendar(bt.TradingCalendar):
    params = dict(
    holidays=[
    datetime.date(2019, 1, 1),
    ],
    open=datetime.time(9, 30),
    close=datetime.time(15, 0),
    )

    cerebro.addcalendar(AStockCalendar())

    当使用交易日历时可以看到,在1月4日(星期五)合成了第一根周线,在1月11日(星期五)合成了第二根周线,得到了正确的结果。

    同样,可以把2019年的其他节假日都添加到holidays列表中,来实现整年的周线数据的正确合成。

    日内分时数据resample合成日线数据时,使用交易日历处理提前收盘的情况。
    美股在感恩节后的第一天,会在下午1点休市,这样如果不做处理,使用分钟数据合成日线数据时就会出问题,可以通过添加以下日历来解决:
    class CustomCalendar(bt.TradingCalendar):
    params = dict(
    holidays=[
    datetime.date(2016, 1, 1),
    datetime.date(2016, 1, 18),
    datetime.date(2016, 2, 15),
    datetime.date(2016, 3, 25),
    datetime.date(2016, 5, 30),
    datetime.date(2016, 7, 4),
    datetime.date(2016, 9, 5),
    datetime.date(2016, 11, 24),
    datetime.date(2016, 12, 26),
    ],
    earlydays=[
    (datetime.date(2016, 11, 25),
    datetime.time(9, 30), datetime.time(13, ,0))
    ],
    open=datetime.time(9, 30),
    close=datetime.time(16, 0),
    )

    以2016年为例,日历中设定了2016年的节假日,一般每日交易时间为9:30至16:00,11月25日的交易时间为9:30至13:00。

    resample浅析

    借助于日志功能,对resample功能进行简单分析。这里以30分钟数据为数据源,使用resample来合成60分钟数据,同时加载已下载好的60分钟数据用于对比resample结果,部分代码如下:

    data = load_data(stk_code, fromdate, todate, '30')
    cerebro.adddata(data, name = stk_code + '_30m')
    cerebro.resampledata(data, name = stk_code + '_30to60m', timeframe = bt.TimeFrame.Minutes, compression = 60)
    data = load_data(stk_code, fromdate, todate, '60')
    cerebro.adddata(data, name = stk_code + '_60m'

    以加载2020年6月1日至4日平安银行的数据为例,使用日志功能将结果输出至log.csv中,部分结果如下:


    标黄的D、L、T列分别表示加载的30分钟时间标签数据、由30分钟数据合成的60分钟时间标签数据、加载的60分钟时间标签数据。
    对比D列和T列可以发现,在加载的60分钟数据中,6月1日首个时间点(10:00)数据为空,在时间点10:30出现第一个数据。在D列时间标签变为11:00时,T列时间标签仍为10:30。在D列时间标签变为11:30时,T列时间标签才变为11:30。这样就保证了,在同时加载多个周期数据进行回测时,不会发生使用未来数据的情况。
    对比D列和L列发现,resample结果未按预期得到10:30、11:30、14:00、15:00四个时段的60分钟数据,而是得到10:00、11:00、12:00、14:00、15:00五个整点时间段的数据。笔者尝试了调整函数resampledata()的bar2edge、rightedge、adjbartime、boundoff参数,也尝试了使用交易日历功能设置每日交易起止时间,均未能实现预期的resample结果。目前的解决方案是,在合成分钟级数据时,不使用backtrader的resampledata()函数,而是先离线合成所需周期的数据,然后使用cerebro.adddata()加载合成的数据,再进行多周期策略的回测。

  • 相关阅读:
    【20211112】学习,为自己,也为别人
    【20211109】计划会使人拥有魔力
    【20211110】责任是不确性的克星
    【20211113】因材施教
    【20211119】责任能使人变得难以置信
    【20211115】连岳摘抄
    【20211106】连岳摘抄
    c#中用正则过滤所有标点符号
    带农历的JavaScript日期时间
    JQuery常用方法一览
  • 原文地址:https://www.cnblogs.com/xingnie/p/16138509.html
Copyright © 2020-2023  润新知