1.5 量化技术篇—使用zipline回测

------从零开始学量化------
:量化目录传送门
知乎:量化目录传送门


0. 前言

在1.4中,我们实现了一个简单的量化择时策略,那么该策略到底效果如何呢?我们该使用什么开源框架,使用历史数据回测策略呢?我们又该用那些指标评价一个策略?

本篇的内容就是回答以上的问题的,下面给一个简要的答案:

回测的开源框架zipline

策略的评价指标

  • 累计收益
  • 年化收益
  • 最大回撤
  • 夏普比率

为什么选择zipline?主要由以下几点原因:

  • 在quant的框架中star数最多,版本更新和维护比较快。
  • 社区生态比较好,出现问题,google容易找到解决方案。
  • 该框架在国外已经比较成熟,坑少。

1. 策略的回测结果

1.1 策略的回测指标

年化收益率 = 8.34%
累计收益率 = 17.37%
最大回撤 = -16.14%
夏普比率 = 0.62

1.2 策略的收益图

1.5 量化技术篇—使用zipline回测_第1张图片
策略收益图

1.3 回测的环境

量化框架:zipline(version = 1.3.0)

1.4 策略追踪的股票和benchmark

追踪的股票:个股选择了苹果(AAPL)
benchmark:美国标普500(SPX)的指数
策略时间: 2015-01-01 ~ 2017-01-01

1.5 择时策略描述

买入: 当cci >= 50
卖出:当cci < 50

2. zipline回测前的准备

在开始回测之前,zipline首先需要下载数据包(data bundle)。由于在1.2篇——环境安装中已经说明了zipline的安装方式,如果还有问题可以查看zipline github installation。下面假设大家已经使用anaconda安装好了zipline(我的zipline的版本是1.3.0)。

zipline安装完毕后,可以打开命令行,输入命令查询zipline目前支持的数据包,具体可以参考Zipline Data Bundles,输入的命令如下:

# 命令行中输入查询数据包的命令
zipline bundles

# 返回的结果
csvdir 
quandl 
quantopian-quandl 

从命令行中可以看到,zipline中没有载入任何数据包。然后我们开始下载数据包,具体可以参考Zipline 的安装配置。下载数据包主要分为两步:

第一步:登录quandl官网,进行注册,获得api key。

第二部:设置api key,并下载数据包,具体命令如下:

# 设置quandl的api key
set QUANDL_API_KEY=your_key

# 下载数据包
zipline ingest -b quandl

# 查询数据包
 zipline bundles
# 返回
csvdir 
quandl 2018-07-23 09:34:37.144466
quandl 2018-07-23 09:28:37.817531
quantopian-quandl 

当zipline bundles 返回的quandl中出现上面的返回,说明数据下载成功。

3. 策略代码

from datetime import datetime

import matplotlib.pyplot as plt
import pytz
import seaborn as sns
import talib as ta
from empyrical import cum_returns, annual_return, sharpe_ratio, max_drawdown
from matplotlib.dates import DateFormatter
from zipline import run_algorithm
from zipline.api import symbol, order, record
from zipline.finance import commission, slippage


def initialize(context):
    # 记录股票代码,通过股票代码获取股票对象
    context.asset = symbol('AAPL')

    # 定义是否买入股票的标记
    context.invested = False

    # 设置交易的手续费,股票成交时,手续费按成交金额一定比例收取
    # 设置手续费率和最低费用
    context.set_commission(commission.PerShare(cost=.0075, min_trade_cost=1.0))

    # 设置模拟真实交易的滑价,当实际下单交易时,下单订单将影响市场。买单驱使价格上涨,卖单驱使价格下滑;
    # 这通常被称为交易的“价格影响”。价格影响的大小取决于订单与当前交易量相比有多大。
    context.set_slippage(slippage.VolumeShareSlippage(volume_limit=0.025, price_impact=0.1))


def handle_data(context, data):
    # 获取历史股票数据
    # context.asset表示股票列表
    # fields – 历史数据项或集合,项可以为’close’, ‘open’, ‘high’, ‘low’, ‘price’
    # bar_count – 获取多少单位时间
    # frequency – 可以取值‘1m’ 或 ‘1d’。 ‘1m’表示分钟单位, ‘1d’表示日单位, 现在只支持日单位
    trailing_window = data.history(context.asset, ['high', 'low', 'close', 'open'], 40, '1d')

    # 数据为空则返回
    if trailing_window.isnull().values.any():
    return

    # 计算cci指标
    cci = ta.CCI(trailing_window['high'].values, trailing_window['low'].values, trailing_window['close'].values,
    timeperiod=14)

    # 定义买入和卖出的标志位
    buy = False
    sell = False

    if (cci[-1] >= 50) and not context.invested:
    # 买卖股票,按股票数量生成订单,amount为负,表示做空。
    # 参数:
    # asset – 股票
    # amount – 交易数量, 正数表示买入, 负数表示卖出
    # style –(可选参数)指定下单类型,默认为市价单,可用的下单类型如下:
    #   style=MarketOrder(),下市价单
    #   style=StopOrder(stop_price),下止损单,通常用来止损或者锁定利润
    #   style=LimitOrder(limit_price),下限价单,限定一个价格买入或卖出
    #   style=StopLimitOrder(limit_price=price1, stop_price=price2),指定限价和止损价格
    order(context.asset, 100)
    # 设置买入
    context.invested = True
    buy = True
    elif (cci[-1] < 50) and context.invested:
    order(context.asset, -100)
    context.invested = False
    sell = True

    # 记录函数,在交易执行时记录用户自定义数据,该数据存放在回测输出结果中
    record(open=data.current(context.asset, "open"),
        high=data.current(context.asset, "high"),
        low=data.current(context.asset, "low"),
        close=data.current(context.asset, "close"),
        cci=cci[-1],
        buy=buy,
        sell=sell)


# 定义分析回测效果的函数
def analyze(context=None, results=None):
    pass


def draw_return_rate_line(result):
    sns.set_style('darkgrid')
    sns.set_context('notebook')
    ax = plt.axes()
    # 设置时间显示格式
    years_fmt = DateFormatter('%Y-%m-%d')
    ax.xaxis.set_major_formatter(years_fmt)
    # 让x轴坐标旋转45度
    labels = ax.get_xticklabels()
    plt.setp(labels, rotation=35, horizontalalignment='right')
    # 画出收益率曲线
    sns.lineplot(x='period_close',
    y='algorithm_period_return',
    data=result,
    label="AAPL")
    sns.lineplot(x='period_close',
        y='benchmark_period_return',
        data=result, label="SPX")

    plt.legend(loc='upper left')
    plt.title("return rate of AAPL and SPX")
    plt.xlabel('time')
    plt.ylabel('return rate')
    plt.show()


if __name__ == '__main__':
    capital_base = 10000
    start = datetime(2015, 1, 1, 0, 0, 0, 0, pytz.utc)
    end = datetime(2017, 1, 1, 0, 0, 0, 0, pytz.utc)

    # 运行算法
    result = run_algorithm(start=start, end=end, initialize=initialize,
        capital_base=capital_base, handle_data=handle_data,
        bundle='quandl', analyze=analyze)

    # 画出收益曲线图
    draw_return_rate_line(result)

    return_list = result['returns']

    # 计算年化收益率
    ann_return = annual_return(return_list)

    # 计算累计收益率
    cum_return_list = cum_returns(return_list)

    # 计算sharp ratio
    sharp = sharpe_ratio(return_list)

    # 最大回撤
    max_drawdown_ratio = max_drawdown(return_list)

    print("年化收益率 = {:.2%}, 累计收益率 = {:.2%}, 最大回撤 = {:.2%}, 夏普比率 = {:.2f} ".format
        (ann_return, cum_return_list[-1], max_drawdown_ratio, sharp))

如果你对我的文章有兴趣,可以关注一下我的和知乎,后期会在和知乎上定期更新,传送门在下方:
:潇潇夜雨归何处
知乎:潇潇夜雨
我相信,有趣的灵魂总会相遇!!!
你的关注,是我前进的动力!!!

你可能感兴趣的:(1.5 量化技术篇—使用zipline回测)