python量化回测框架——zipline

python量化框架有很多,zipline是一个比较好的选择(在之后的安装中我后悔了),在github上星也是最多的,国内外很多量化都在用,文档齐全,社区完整,发展成熟(好,不吹了)

安装

文档上有很多种安装,这里主要用anaconda在linux上安装(conda自行下载安装

zipline目前能良好支持 python2.7 python3.5,建议你不要有其他想法,我最先就是用的其他版本,结果爆了一堆奇奇怪怪的错误还无法解决。
# 创建一个3.5的python环境
$ conda create -n env_zipline python=3.5
# 激活环境
$ source activate env_zipline (winddows 使用 activate env_zipline ) 
# 安装zipline
$ conda install -c Quantopian zipline

# -- 其他 --
# 停用环境
$ source deactivate
# 查看conda环境的目录
$ conda env list
# pycharm集成
在pycharm中的File->setting->Project:XXXX->Project Interperter添加刚才查看的目录就行了

数据绑定

我没有下载数据,国内速度感人,请自行想办法,我那该死的1核1g的服务器,根本干不了,进程会被killed,加大了swap虚拟内存也不行,不了了之

    # 默认数据 需要绑定一次
    # 需要 Quandl 的 API key 来获取默认数据 https://docs.quandl.com/docs#section-authentication
    # 可以去网站免费注册一个账号(获取API_KEY),并使用如下命令将数据灌入zipline。
    $ QUANDL_API_KEY=<yourkey> zipline ingest [-b <bundle>]
    # 其中<bundle> 是数据包的名称,默认为 quandl
    $ QUANDL_API_KEY=jYsYCRqJTk1C6GojWZ3- zipline ingest -b quandl
    
    # 从.csv文件中加载数据
    # 导入 csvdir 和 pandas 包 (可以编辑 ~/.zipline/extension.py,也可以直接写在策略中)
    import pandas as pd
    
    from zipline.data.bundles import register
    from zipline.data.bundles.csvdir import csvdir_equities
    # 指定开始和结束时间:
    start_session = pd.Timestamp('2016-1-1', tz='utc')
    end_session = pd.Timestamp('2018-1-1', tz='utc')
    # 然后我们可以传入 .csv 文件路径,用 register() 注册我们的自己编写的 bundle
    register(
        'custom-csvdir-bundle',
        csvdir_equities(
            ['daily'],
            '/path/to/your/csvs',
        ),
        calendar_name='NYSE', # US equities
        start_session=start_session,
        end_session=end_session
    )
    # 运行命令导入自己编写的 bundle 
    $ zipline ingest -b custom-csvdir-bundle
    
    # 我们可以通过命令行传递我们的csvs的位置
    $ CSVDIR=/path/to/your/csvs zipline ingest -b custom-csvdir-bundle
    
    # 默认情况下,数据将被写在 $ZIPLINE_ROOT/data/<bundle> (默认情况下 ZIPLINE_ROOT=~/.zipline )
    # ingest 会将新数据写入$ZIPLINE_ROOT/data/<bundle> 并以当前日期命名,可以按日期查看旧数据,用旧数据进行回测。 使用旧数据进行回测,可以更容易地重现回测结果
    # zipline 默认保存所有绑定的数据 数据目录会非常大,可以使用清理命令
    # clean everything older than <date>
    $ zipline clean [-b <bundle>] --before <date>
    
    # clean everything newer than <date>
    $ zipline clean [-b <bundle>] --after <date>
    
    # keep everything in the range of [before, after] and delete the rest
    $ zipline clean [-b <bundle>] --before <date> --after <after>
    
    # clean all but the last <int> runs
    $ zipline clean [-b <bundle>] --keep-last 0 #数字表示保留最近的n次数据
    
    # 查看zipline 数据
    $ zipline bundles

编写算法策略

每个算法策略包含两个函数

  • initialize(context)
  • handle_data(context, data)

在算法执行前,zipline首先会调用 initialize() 传入context,context是算法执行过程中共用的上下文信息,可以用来存储算法执行不同阶段的需要保存的数据。
初始化后,zipline会根据事件调用 handle_data(),每次调用,都会传入context与data,context是执行过程中唯一的一份,但data则与该次调用的事件相关,通常会包含此刻的开盘,最高、最低及收盘价。
来尝试写一个最简单的算法策略(就是官网的例子~)

from zipline.api import order, record, symbol


def initialize(context):
    pass


def handle_data(context, data):
    order(symbol('AAPL'), 10)
    record(AAPL=data.current(symbol('AAPL'), 'price'

可以看到,首先我们引入一些需要的函数。策略中所有常用的函数可以在 zipline.api 中找到。 这里的 order() 函数接受两个参数:一个股票代码,一个数量(为负则为卖出或做空)。 在例子中,每次迭代我们买入 10 股 APPL 股票。更多 order() 信息,可参阅 Quantopian 文档

record() 函数能在每一次迭代的时候记录一些临时数据。 第一个参数接受 变量名=变量值 的这样参数。回测结束进行分析的时候,能够通过变量名访问到 这些记录的数据(下面会有示例)。您还可以看到如何在 data 事件框架中访问之前记录的 AAPL 股票的价格数据(更多信息请访问 这里

运行算法策略

zipline 提供三种方式

  • 命令行
  • IPython Notebook
  • run_algorithm()函数

命令行

zipline run -f ../../zipline/examples/buyapple.py --start 2016-1-1 --end 2018-1-1 -o buyapple_out.pickle
-f 指定策略算法路径 即文件路径
--start 和 --end 指定回测时间区间
-b 设置使用的数据(默认为 quandl)
-o 指定文件名,回测结果将以 DateFrame 的格式保存到 Python 的 pickle 文件内
-c 指定配置文件的路径,这样就不用每次都指定各种参数了(请参阅文档)

IPython Notebook 不作介绍

run_algorithm()运行

文档上没有说明,这种方式其实是ide中,程序内部中,使用python运行,实际是使用TradingAlgorithm类运行

传参方式

from zipline import TradingAlgorithm
import pandas as pd

def initialize(context):
    pass

def handle_data(context, data):
    pass

algo_obj = TradingAlgorithm(initialize=initialize,
           handle_data=handle_data)

data = pd.read_csv('AAPL.csv')
perf_manual = algo_obj.run(data)

也可以使用继承

rom zipline.algorithm import TradingAlgorithm
import pandas as pd


class Strategy(TradingAlgorithm):

    def initialize(self):
        pass

    def handle_data(self, data):
        pass


if __name__ == '__main__':
    data = pd.read_csv("AAPL.csv")

    simple_algo = Strategy()
    results = simple_algo.run(data)

当然,参数我没传完,还有回测时间 等。
重点是运行后,在实例化的时候报错了
zipline报错JSONDecodeError
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

image.png

谷歌搜了半天也没找到问题,最后在zipline社区论坛github中找到了这个问题
zipline 1.3.0 JSONDecodeError
这个问题是当时一个月前发现的,是因为在benchmarks.py中使用IEX API获取基准数据的api于2019年6月15日删除,使用此API尝试下载任何库存数据都将报错,功能现在转移到新的API IEX Cloud,在请求时需要加上注册后用户的token
解决办法,修改benchmarks.py文件

def get_benchmark_returns(symbol):
    """
    Get a Series of benchmark returns from IEX associated with `symbol`.
    Default is `SPY`.

    Parameters
    ----------
    symbol : str
        Benchmark symbol for which we're getting the returns.

    The data is provided by IEX (https://iextrading.com/), and we can
    get up to 5 years worth of data.
    """
    IEX_TOKEN = 'pk_TOKEN_COMES_HERE'  # 这里新增你在iex注册后拿到的令牌token 
    r = requests.get(
        # 原代码删除
        # 'https://api.iextrading.com/1.0/stock/{}/chart/5y'.format(symbol)
        # 改为新连接
        'https://cloud.iexapis.com/stable/stock/{}/chart/5y?token={}'.format(
            symbol, IEX_TOKEN)
    )
    data = r.json()

    df = pd.DataFrame(data)

    df.index = pd.DatetimeIndex(df['date'])
    df = df['close']

    return df.sort_index().tz_localize('UTC').pct_change(1).iloc[1:]

新增IEX_TOKEN = '你的token '
'https://api.iextrading.com/1.0/stock/{}/chart/5y'.format(symbol)
更改
'https://cloud.iexapis.com/stable/stock/{}/chart/5y?token={}'.format(symbol, IEX_TOKEN)

这是更改基准下载方法以请求其他API的解决办法,还有人提出了通过将所有数据条目设置为零来创建虚拟基准文件,但不建议

没想到最后居然要改源代码,我也很绝望,希望之后Zipline Maintainers尽快修护这个问题

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,108评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,699评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,812评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,236评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,583评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,739评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,957评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,704评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,447评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,643评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,133评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,486评论 3 256
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,151评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,889评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,782评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,681评论 2 272