------從零開始學(xué)量化------
簡書:量化目錄傳送門
知乎:量化目錄傳送門
0. 前言
在1.4中夺颤,我們實(shí)現(xiàn)了一個(gè)簡單的量化擇時(shí)策略,那么該策略到底效果如何呢凿渊?我們該使用什么開源框架秤标,使用歷史數(shù)據(jù)回測策略呢揪阶?我們又該用那些指標(biāo)評價(jià)一個(gè)策略遣总?
本篇的內(nèi)容就是回答以上的問題的睬罗,下面給一個(gè)簡要的答案:
回測的開源框架:zipline
策略的評價(jià)指標(biāo):
- 累計(jì)收益
- 年化收益
- 最大回撤
- 夏普比率
為什么選擇zipline轨功?主要由以下幾點(diǎn)原因:
- 在quant的框架中star數(shù)最多,版本更新和維護(hù)比較快容达。
- 社區(qū)生態(tài)比較好古涧,出現(xiàn)問題,google容易找到解決方案花盐。
- 該框架在國外已經(jīng)比較成熟羡滑,坑少。
1. 策略的回測結(jié)果
1.1 策略的回測指標(biāo)
年化收益率 = 8.34%
累計(jì)收益率 = 17.37%
最大回撤 = -16.14%
夏普比率 = 0.62
1.2 策略的收益圖
1.3 回測的環(huán)境
量化框架:zipline(version = 1.3.0)
1.4 策略追蹤的股票和benchmark
追蹤的股票:個(gè)股選擇了蘋果(AAPL)
benchmark:美國標(biāo)普500(SPX)的指數(shù)
策略時(shí)間: 2015-01-01 ~ 2017-01-01
1.5 擇時(shí)策略描述
買入: 當(dāng)cci >= 50
賣出:當(dāng)cci < 50
2. zipline回測前的準(zhǔn)備
在開始回測之前算芯,zipline首先需要下載數(shù)據(jù)包(data bundle)柒昏。由于在1.2篇——環(huán)境安裝中已經(jīng)說明了zipline的安裝方式,如果還有問題可以查看zipline github installation。下面假設(shè)大家已經(jīng)使用anaconda安裝好了zipline(我的zipline的版本是1.3.0)也祠。
zipline安裝完畢后昙楚,可以打開命令行近速,輸入命令查詢zipline目前支持的數(shù)據(jù)包诈嘿,具體可以參考Zipline Data Bundles,輸入的命令如下:
# 命令行中輸入查詢數(shù)據(jù)包的命令
zipline bundles
# 返回的結(jié)果
csvdir <no ingestions>
quandl <no ingestions>
quantopian-quandl <no ingestions>
從命令行中可以看到削葱,zipline中沒有載入任何數(shù)據(jù)包奖亚。然后我們開始下載數(shù)據(jù)包,具體可以參考Zipline 的安裝配置析砸。下載數(shù)據(jù)包主要分為兩步:
第一步:登錄quandl官網(wǎng)昔字,進(jìn)行注冊,獲得api key首繁。
第二部:設(shè)置api key作郭,并下載數(shù)據(jù)包,具體命令如下:
# 設(shè)置quandl的api key
set QUANDL_API_KEY=your_key
# 下載數(shù)據(jù)包
zipline ingest -b quandl
# 查詢數(shù)據(jù)包
zipline bundles
# 返回
csvdir <no ingestions>
quandl 2018-07-23 09:34:37.144466
quandl 2018-07-23 09:28:37.817531
quantopian-quandl <no ingestions>
當(dāng)zipline bundles 返回的quandl中出現(xiàn)上面的返回弦疮,說明數(shù)據(jù)下載成功夹攒。
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')
# 定義是否買入股票的標(biāo)記
context.invested = False
# 設(shè)置交易的手續(xù)費(fèi)胁塞,股票成交時(shí)咏尝,手續(xù)費(fèi)按成交金額一定比例收取
# 設(shè)置手續(xù)費(fèi)率和最低費(fèi)用
context.set_commission(commission.PerShare(cost=.0075, min_trade_cost=1.0))
# 設(shè)置模擬真實(shí)交易的滑價(jià),當(dāng)實(shí)際下單交易時(shí)啸罢,下單訂單將影響市場编检。買單驅(qū)使價(jià)格上漲,賣單驅(qū)使價(jià)格下滑;
# 這通常被稱為交易的“價(jià)格影響”扰才。價(jià)格影響的大小取決于訂單與當(dāng)前交易量相比有多大允懂。
context.set_slippage(slippage.VolumeShareSlippage(volume_limit=0.025, price_impact=0.1))
def handle_data(context, data):
# 獲取歷史股票數(shù)據(jù)
# context.asset表示股票列表
# fields – 歷史數(shù)據(jù)項(xiàng)或集合,項(xiàng)可以為’close’, ‘open’, ‘high’, ‘low’, ‘price’
# bar_count – 獲取多少單位時(shí)間
# frequency – 可以取值‘1m’ 或 ‘1d’衩匣。 ‘1m’表示分鐘單位, ‘1d’表示日單位, 現(xiàn)在只支持日單位
trailing_window = data.history(context.asset, ['high', 'low', 'close', 'open'], 40, '1d')
# 數(shù)據(jù)為空則返回
if trailing_window.isnull().values.any():
return
# 計(jì)算cci指標(biāo)
cci = ta.CCI(trailing_window['high'].values, trailing_window['low'].values, trailing_window['close'].values,
timeperiod=14)
# 定義買入和賣出的標(biāo)志位
buy = False
sell = False
if (cci[-1] >= 50) and not context.invested:
# 買賣股票蕾总,按股票數(shù)量生成訂單酣倾,amount為負(fù),表示做空谤专。
# 參數(shù):
# asset – 股票
# amount – 交易數(shù)量, 正數(shù)表示買入, 負(fù)數(shù)表示賣出
# style –(可選參數(shù))指定下單類型躁锡,默認(rèn)為市價(jià)單,可用的下單類型如下:
# style=MarketOrder()置侍,下市價(jià)單
# style=StopOrder(stop_price)映之,下止損單,通常用來止損或者鎖定利潤
# style=LimitOrder(limit_price)蜡坊,下限價(jià)單杠输,限定一個(gè)價(jià)格買入或賣出
# style=StopLimitOrder(limit_price=price1, stop_price=price2),指定限價(jià)和止損價(jià)格
order(context.asset, 100)
# 設(shè)置買入
context.invested = True
buy = True
elif (cci[-1] < 50) and context.invested:
order(context.asset, -100)
context.invested = False
sell = True
# 記錄函數(shù)秕衙,在交易執(zhí)行時(shí)記錄用戶自定義數(shù)據(jù)蠢甲,該數(shù)據(jù)存放在回測輸出結(jié)果中
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)
# 定義分析回測效果的函數(shù)
def analyze(context=None, results=None):
pass
def draw_return_rate_line(result):
sns.set_style('darkgrid')
sns.set_context('notebook')
ax = plt.axes()
# 設(shè)置時(shí)間顯示格式
years_fmt = DateFormatter('%Y-%m-%d')
ax.xaxis.set_major_formatter(years_fmt)
# 讓x軸坐標(biāo)旋轉(zhuǎn)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)
# 運(yùn)行算法
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']
# 計(jì)算年化收益率
ann_return = annual_return(return_list)
# 計(jì)算累計(jì)收益率
cum_return_list = cum_returns(return_list)
# 計(jì)算sharp ratio
sharp = sharpe_ratio(return_list)
# 最大回撤
max_drawdown_ratio = max_drawdown(return_list)
print("年化收益率 = {:.2%}, 累計(jì)收益率 = {:.2%}, 最大回撤 = {:.2%}, 夏普比率 = {:.2f} ".format
(ann_return, cum_return_list[-1], max_drawdown_ratio, sharp))
如果你對我的文章有興趣,可以關(guān)注一下我的簡書和知乎据忘,后期會(huì)在簡書和知乎上定期更新鹦牛,傳送門在下方:
簡書:瀟瀟夜雨歸何處
知乎:瀟瀟夜雨
我相信,有趣的靈魂總會(huì)相遇S碌酢B贰!
你的關(guān)注汉规,是我前進(jìn)的動(dòng)力@袷狻!针史!