V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
thinkingmind
V2EX  ›  推广

Ricequant 开源量化交易回测框架 RQalpha,提供免费日线行情和分红数据

  •  1
     
  •   thinkingmind · 2016-07-29 16:35:40 +08:00 · 4990 次点击
    这是一个创建于 3021 天前的主题,其中的信息可能已经有所发展或是发生改变。

    rqalpha

    RQAlpha

    项目地址: https://github.com/ricequant/rqalpha

    简介

    RQAlpha 是一个开源的 Python 算法交易和回测引擎,适合 A 股市场,是事件驱动的设计。自带日线数据, 目前暂时仅支持日线回测。

    RQAlpha 的逻辑也将会在Ricequant的一些回测部分使用,Ricequant - 是一个开放的量化算法交易社区,有免费的服务器资源给大家测试、实盘模拟您的交易算法,并且可以将交易信号通过微信和邮件实时推送给大家, 如果您想要更好的回测报告体验和实盘模拟交易功能可以把本地写好的策略复制黏贴到我们的网站上运行。

    如果您想参与和贡献进来这个项目,可以发邮件给 [email protected] 联系,如果您有功能需求或者 bug 报告的话,都可以开一个 issue : https://github.com/ricequant/rqalpha/issues

    特色

    • 容易使用: RQAlpha 可以让你集中精力在策略的开发上。可以参考./examples 下的范例
    • 需要传入历史数据,计算的结果是 pandas 的 DataFrame, 和 PyData 的生态系统很好的结合在一起
    • 可以使用 Python 的统计、机器学习等科学计算库如 matplotlib, scipy, statsmodels 和 sklearn 等
    • 免费提供了 Ricequant 的日级别数据,可以通过互联网自己更新 data bundle

    安装

    # 为了避免一些安装问题,请先升级您的 pip 和 setuptools
    pip install -U pip setuptools
    
    # 安装 rqalpha
    pip install rqalpha
    
    # 升级 rqalpha
    pip install -U rqalpha
    
    # 国内的用户们可以使用镜像
    pip install -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com -U rqalpha
    

    For Windows 用户

    如果出现缺失cl.exe,请访问https://wiki.python.org/moin/WindowsCompilers下载 VC 并且安装。

    如果在安装bcloz出现编译困难,可以从http://www.lfd.uci.edu/~gohlke/pythonlibs/#bcolz下载bcolz安装,安装bcloz后,再安装rqalpha

    安装依赖

    安装 TA-Lib

    你可以通过 PyPI 安装:

    $ pip install TA-Lib
    

    如果发现无法通过 pip 安装,请访问 https://mrjbq7.github.io/ta-lib/install.html 解决。

    对于 Windows 用户,如果编译困难,可以根据您本地的 Python 版本下载指定版本的 whl 包,然后pip install TA_Lib-0.4.9-cp27-none-win_amd64.whl

    Usage

    Usage: rqalpha [OPTIONS] COMMAND [ARGS]...
    
    Options:
      -v, --verbose
      --help         Show this message and exit.
    
    Commands:
      examples       generate example strategies to target folder
      plot           draw result DataFrame
      run            run strategy from file
      update_bundle  update data bundle, download if not found
    

    下载回测需要的数据 bundle

    运行以下命令,将会从 Ricequant 的服务器下载最新的日级别数据,为回测提供数据支持。

    rqalpha update_bundle
    

    生成样例策略

    运行以下命令,将会在指定目录生成一个 examples 文件夹,其中包含几个有趣的样例策略。

    rqalpha examples -d ./
    

    运行回测

    回测脚本参数如下:

    Usage: rqalpha run [OPTIONS]
    
      run strategy from file
    
    Options:
      -f, --strategy-file PATH     [required]
      -s, --start-date DATE        [required]
      -e, --end-date DATE          [required]
      -o, --output-file PATH
      -i, --init-cash INTEGER
      --plot / --no-plot           plot result
      --progress / --no-progress   show progress bar
      -d, --data-bundle-path PATH
      --help                       Show this message and exit.
    

    运行以下命令,将开始回测

    rqalpha run -f examples/multi_rsi.py -s 2014-01-01 -e 2016-01-01 -o result.pkl --plot
    

    等待回测结束后,将显示您的收益率和 Risk 。

    backtest

    绘制回测结果

    如果运行完回测后,还需要再次绘制回测结果,可以运行以下命令:

    rqalpha plot result.pkl
    

    分析结果

    RQAlpha 可以输出一个 DataFrame ,其中包含了每天的 Portfolio 信息、 Risk 信息、 Trades 和 Positions 。

    其 Index 是交易日, columns 包括alpha, annualized_returns, benchmark_annualized_returns, benchmark_daily_returns, benchmark_total_returns, beta, cash, daily_returns, downside_risk, information_rate, market_value, max_drawdown, pnl, portfolio_value, positions, sharpe, sortino, total_commission, total_returns, total_tax, tracking_error, trades, volatility

    其中positions是当日的持仓信息,trades是当日的交易信息。

    import pandas as pd
    df = pd.read_pickle("result.pkl")
    print(df.iloc[-1])
    
    '''
    alpha                                                                   0.0180666
    annualized_returns                                                      0.0559331
    benchmark_annualized_returns                                            0.0454542
    benchmark_daily_returns                                               8.87784e-05
    benchmark_total_returns                                                  0.525913
    beta                                                                     0.518371
    cash                                                                      4971.44
    daily_returns                                                          0.00250376
    downside_risk                                                            0.246409
    information_rate                                                        0.0380054
    market_value                                                               162796
    max_drawdown                                                            -0.602535
    pnl                                                                           419
    portfolio_value                                                            167767
    positions                       {'000068.XSHE': Position({{'value_percent': 0....
    sharpe                                                                    2.35011
    sortino                                                                   2.62967
    total_commission                                                          2585.89
    total_returns                                                            0.677674
    total_tax                                                                 1172.01
    tracking_error                                                           0.269138
    trades                                                                         []
    volatility                                                               0.275721
    Name: 2016-07-01 00:00:00, dtype: object
    '''
    

    架构图

    Architecture

    FAQ

    在 Windows 运行报 Error on import matplotlib.pyplot

    请访问 Error on import matplotlib.pyplot (on Anaconda3 for Windows 10 Home 64-bit PC) 解决。

    Python SDK 简介

    Python 策略 Hello World

    以下的策略是最简单的一个买入并持有平安银行( buy and hold )的展示,非常简单:

    # 可以自己 import 我们平台支持的第三方 python 模块,比如 pandas 、 numpy 等。
    
    # 在这个方法中编写任何的初始化逻辑。 context 对象将会在你的算法策略的任何方法之间做传递。
    def init(context):
        context.s1 = "000001.XSHE"
        # order 是否被发送出去
        context.fired = False
    
    # 你选择的证券的数据更新将会触发此段逻辑,例如日或分钟历史数据切片或者是实时数据切片更新
    def handle_bar(context, bar_dict):
        # 开始编写你的主要的算法逻辑
    
        # bar_dict[order_book_id] 可以拿到某个证券的 bar 信息
        # context.portfolio 可以拿到现在的投资组合状态信息
    
        # 使用 order_shares(id_or_ins, amount)方法进行落单
    
        # TODO: 开始编写你的算法吧!
        if not context.fired:
    	    # order_percent 并且传入 1 代表买入该股票并且使其占有投资组合的 100%
            order_percent(context.s1, 1)
            context.fired = True
    

    需要实现的方法

    你的算法策略目前必须实现至少两个方法:inithandle_bar,而before_trading是可选择实现的方法。

    init

    init(context)
    

    初始化方法 - 在回测和实时模拟交易只会在启动的时候触发一次。你的算法会使用这个方法来设置你需要的各种初始化配置。 context 对象将会在你的算法的所有其他的方法之间进行传递以方便你可以拿取到。

    | 参数 | 类型 | 注释 | | --- | --- | --- | | context | python 简单对象 | 将会在整个算法中当做一个全局变量来使用。属性通过点标记(".")来取到。 |

    返回 None

    范例:

    def init(context):
    	# cash_limit 的属性是根据用户需求自己定义的,你可以定义无限多种自己随后需要的属性, ricequant 的系统默认只是会占用 context.portfolio 的关键字来调用策略的投资组合信息
    	context.cash_limit = 5000
    

    handle_bar

    handle_bar(context, bar_dict)
    

    切片数据的更新会自动触发调用这个方法,如果是日回测则是每日的切片数据( OHLC )会触发调用,分钟回测则会是每分钟的切片数据会调用,那么在实时模拟交易中则是实时每分钟会调用一次。对于切片数据对象你可以看关于Bar 对象的更详细的信息。

    | 参数 | 类型 | 注释 | | --- | --- | --- | | context | 和 init 方法中的 context 对象一样 | 存储所有策略的自己定义的变量状态或是初始设置。| | bar_dict | bar dictionary - 存储了关注的证券的 bar 的一个 dict , order_book_id 作为 key | 所有已‘关注’的股票的切片数据信息都会更新在这个 dict 里面。 |

    返回 None

    范例

    def handle_bar(context, bar_dict):
    	# put all your algorithm main logic here.
    	# ...
    	order_shares('000001.XSHE', 500)
    	# ...
    

    before_trading

    非强制,可选择实现的函数。每天在市场开始前会被调用。不可以在这个函数中发送订单(即不可以调用order_xxxx函数)。

    before_trading(context, bar_dict)
    

    | 参数 | 类型 | 注释 | | --- | --- | --- | | context | 和 init 方法中的 context 对象一样 | 存储所有策略的自己定义的变量状态或是初始设置,也保存了portfolio的信息。 |

    返回 None

    范例

    def before_trading(context, bar_dict):
        context.stock_list = ["000001.XSHE", "000099.XSHE"]
    
        # 手动更新股票池
        update_universe(context.stock_list)
    

    Order 方法

    你可以在策略中使用下面的几种丰富的落单方法,他们不同的用法可以让你落单的操作十分便捷。我们在交易系统内部提供好了仓位计算,因此你可以非常便利使用一些基于仓位管理上的落单方法,比如order_percent 可以让你基于目前的仓位价值进行落单。

    order_shares

    落指定股数的买 /卖单,最常见的落单方式之一。如有需要落单类型当做一个参量传入,如果忽略掉落单类型,那么默认是市价单( market order )。

    order_shares(id_or_ins, amount, style=MarketOrder())
    

    | 参数 | 类型 | 注释 | | --- | --- | --- | | id_or_ins | str 或 instrument 对象-required | order_book_id 或 symbol 或 instrument 对象 | | amount | float-required | 需要落单的股数。正数代表买入,负数代表卖出。将会根据一手 xx 股来向下调整到一手的倍数,比如中国 A 股就是调整成 100 股的倍数。 | | style | OrderType-optional | 订单类型,默认是市价单。目前支持的订单类型有:

    • style=MarketOrder()
    • style=LimitOrder(limit_price)
    |

    返回 int ,唯一的 order id

    范例

    • 购买 Buy 2000 股的平安银行股票,并以市价单发送
    order_shares('000001.XSHE', 2000)
    
    • 卖出 2000 股的平安银行股票,并以市价单发送:
    order_shares('000001.XSHE', -2000)
    
    • 购买 1000 股的平安银行股票,并以限价单发送,价格为¥ 10 :
    order_shares('000001.XSHG', 1000, style=LimitOrder(10))
    

    order_lots

    指定手数发送买 /卖单。如有需要落单类型当做一个参量传入,如果忽略掉落单类型,那么默认是市价单( market order )。

    order_lots(id_or_ins, amount, style=OrderType)
    

    | 参数 | 类型 | 注释 | | --- | --- | --- | | id_or_ins | str 或 instrument 对象-required | order_book_id 或 symbol 或 instrument 对象 | | amount | float-required | 多少手的数目。正数表示买入,负数表示卖出 | | style | OrderType-optional | 订单类型,默认是市价单。目前支持的订单类型有:

    • style=MarketOrder
    • style=LimitOrder(limit_price)
    |

    返回 int ,唯一的 order id

    范例

    • 买入 20 手的平安银行股票,并且发送市价单:
    order_lots('000001.XSHE', 20)
    
    • 买入 10 手平安银行股票,并且发送限价单,价格为¥ 10 :
    order_lots('000001.XSHE', 10, style=LimitOrder(10))
    

    order_value

    使用想要花费的金钱买入 /卖出股票,而不是买入 /卖出想要的股数,正数代表买入,负数代表卖出。股票的股数总是会被调整成对应的 100 的倍数(在 A 中国 A 股市场 1 手是 100 股)。当您提交一个卖单时,该方法代表的意义是您希望通过卖出该股票套现的金额。如果金额超出了您所持有股票的价值,那么您将卖出所有股票。

    order_value(id_or_ins, cash_amount, style=OrderType)
    

    | 参数 | 类型 | 注释 | | --- | --- | --- | | id_or_ins | str 或 instrument 对象-required | order_book_id 或 symbol 或 instrument 对象 | | cash_amount | float-required | 需要花费现金购买 /卖出证券的数目。正数代表买入,负数代表卖出。 | | style | OrderType-optional | 订单类型,默认是市价单。目前支持的订单类型有:

    • style=MarketOrder()
    • style=LimitOrder(limit_price)
    |

    返回 int ,唯一的 order id

    范例

    • 买入价值¥ 10000 的平安银行股票,并以市价单发送。如果现在平安银行股票的价格是¥ 7.5 ,那么下面的代码会买入 1300 股的平安银行,因为少于 100 股的数目将会被自动删除掉。
    order_value('000001.XSHE', 10000)
    
    • 卖出价值¥ 10000 的现在持有的平安银行:
    order_value('000001.XSHE', -10000)
    

    order_percent

    发送一个等于目前投资组合价值(市场价值和目前现金的总和)一定百分比的买 /卖单,正数代表买,负数代表卖。股票的股数总是会被调整成对应的一手的股票数的倍数( 1 手是 100 股)。百分比是一个小数,并且小于或等于 1 (<=100%), 0.5 表示的是 50%

    order_percent(id_or_ins, percent, style=OrderType)
    

    | 参数 | 类型 | 注释 | | --- | --- | --- | | id_or_ins | str 或 instrument 对象 -required | order_book_id 或 symbol 或 instrument object. | | percent | float-required | 占有现有的投资组合价值的百分比。正数表示买入,负数表示卖出。| | style | OrderType-optional | 订单类型,默认是市价单。目前支持的订单类型有:

    • style=MarketOrder()
    • style=LimitOrder(limit_price)
    |

    返回 int ,唯一的 order id

    范例

    • 买入等于现有投资组合 50%价值的平安银行股票。如果现在平安银行的股价是¥ 10/股并且现在的投资组合总价值是¥ 2000 ,那么将会买入 200 股的平安银行股票。(不包含交易成本和滑点的损失)
    order_percent('000001.XSHG', 0.5)
    

    order_target_value

    买入 /卖出并且自动调整该证券的仓位到一个目标价值。如果还没有任何该证券的仓位,那么会买入全部目标价值的证券。如果已经有了该证券的仓位,则会买入 /卖出调整该证券的现在仓位和目标仓位的价值差值的数目的证券。

    order_target_value(id_or_ins, cash_amount, style=OrderType)
    

    | 参数 | 类型 | 注释 | | --- | --- | --- | | id_or_ins | str 或 instrument 对象-required | order_book_id 或 symbol 或 instrument 对象. | | cash_amount | float-required | 最终的该证券的仓位目标价值 | | style | OrderType-optional | 订单类型,默认是市价单。目前支持的订单类型有:

    • style=MarketOrder()
    • style=LimitOrder(limit_price)
    |

    返回 int ,唯一的 order id

    范例

    • 如果现在的投资组合中持有价值¥ 3000 的平安银行股票的仓位并且设置其目标价值为¥ 10000 ,以下代码范例会发送价值¥ 7000 的平安银行的买单到市场。(向下调整到最接近每手股数即 100 的倍数的股数)
    order_target_value('000001.XSHE', 10000)
    

    order_target_percent

    买入 /卖出证券以自动调整该证券的仓位到占有一个指定的投资组合的目标百分比。

    • 如果投资组合中没有任何该证券的仓位,那么会买入等于现在投资组合总价值的目标百分比的数目的证券。
    • 如果投资组合中已经拥有该证券的仓位,那么会买入 /卖出目标百分比和现有百分比的差额数目的证券,最终调整该证券的仓位占据投资组合的比例至目标百分比。

    其实我们需要计算一个 position_to_adjust (即应该调整的仓位)

    position_to_adjust = target_position - current_position
    

    投资组合价值等于所有已有仓位的价值和剩余现金的总和。买 /卖单会被下舍入一手股数( A 股是 100 的倍数)的倍数。目标百分比应该是一个小数,并且最大值应该<=1 ,比如 0.5 表示 50%。

    如果position_to_adjust 计算之后是正的,那么会买入该证券,否则会卖出该证券。

    order_target_percent(id_or_ins, percent, style=OrderType)
    

    | 参数 | 类型 | 注释 | | --- | --- | --- | | id_or_ins | str 或 instrument 对象-required | order_book_id 或 symbol 或 instrument 对象。 | | percent | float-required | 仓位最终所占投资组合总价值的目标百分比。 | | style | OrderType-optional | 订单类型,默认是市价单。目前支持的订单类型有:

    • style=MarketOrder()
    • style=LimitOrder(limit_price)
    |

    返回 int ,唯一的 order id

    范例

    • 如果投资组合中已经有了平安银行股票的仓位,并且占据目前投资组合的 10%的价值,那么以下代码会买入平安银行股票最终使其占据投资组合价值的 15%:
    order_target_percent('平安银行', 0.15)
    

    cancel_order

    取消由 order_id 代表的限价单。

    cancel_order(order_id)
    

    get_order

    通过唯一的 order_id 拿到对应的订单信息,不过这个订单信息会在handle_bar结尾处丢弃掉。

    get_order(order_id)
    

    | 参数 | 类型 | 注释 | | --- | --- | --- | | order_id | int-required | 订单的唯一标示符 |

    返回 order 对象,如:

    <Order: filled_shares=100.0 quantity=100.0 instrument=<Instrument: order_book_id='000001.XSHE' symbol='平安银行' abbrev_symbol='PAYH' round_lot=100.0 sector_code='Financials' sector_name='金融'>>
    

    get_open_orders

    获取一个由 order_id 到 order 对象映射的 dict ,凡在此 dict 中的 order 都未被完全成交或取消。


    更改 context 中的预设值


    更改默认基准

    可以在init函数中使用:

    def init(context):
    	context.benchmark = "000001.XSHE"
    

    上面的代码片段把你的策略的对比参考基准从默认的csi300修改成了平安银行。


    开启允许卖空

    默认卖空是不允许的,不过我们提供了 API 可以开启卖空,不会让您的卖空单被我们的系统拒掉,可以在init函数中使用:

    def init(context):
    	context.short_selling_allowed = True
    

    如果您在测试一些诸如统计套利( pair trading )需要允许卖空机制的策略的时候可以开启这一项,不过注意到在中国 A 股市场卖空股票是一件非常难的事情。


    更改滑点

    可以在init函数中使用:

    def init(context):
    	context.slippage = 0.5
    

    注意 : 其中的数值应为 x%中的 x , 例子中的 0.5=0.5%。

    上面的代码片段把你的策略的滑点更改为了 0.5%。


    更改交易费

    可以在init函数中使用:

    def init(context):
    	context.commission = 0.02
    

    注意 : 其中的数值应为 x%中的 x , 例子中的 0.02=0.02%,即万分之 2.

    上面的代码片段把你的策略使用的交易费更改为了 0.02%。


    更多内容请查看文档: https://github.com/ricequant/rqalpha

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3753 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 10:29 · PVG 18:29 · LAX 02:29 · JFK 05:29
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.