Table of Contents
近幾年動能交易很常出現在股票策略的討論當中,我們在股票市場通常很常聽到談論價量關係,價是量的先行指標等等,而本文想進而探討當成交量放大時以做為進場策略之回測效應,本方法並沒有像其他技術指標一樣有一定之準則,於是在設計上比較較為彈性,在程式設計上能使讀者們自行更改,詳細參數設定上會在後面程式碼中提及如何修改。而本文採用以下策略進行回測:
本文使用 Windows 11 與 Jupyter notebook 作為編輯器。
import pandas as pd
import numpy as np
import tejapi
import os
import pyfolio as pf
from zipline.api import set_slippage, set_commission, set_benchmark, attach_pipeline, order, order_target, symbol, pipeline_output
from zipline.finance import commission, slippage
from zipline.data import bundles
from zipline import run_algorithm
from zipline.pipeline import Pipeline
from zipline.pipeline.filters import StaticAssets
from zipline.pipeline.factors import SimpleMovingAverage
from zipline.pipeline.data import EquityPricing
分別設定以下環境變數:
並且使用 !zipline ingest -b tquant
抓取。
os.environ['TEJAPI_BASE'] = 'https://api.tej.com.tw'
os.environ['TEJAPI_KEY'] = 'yourkey'
os.environ['mdate'] = '20120702 20220702'
os.environ['ticker'] = 'IR0001 2330 3443 2337'
!zipline ingest -b tquant
Pipeline()
提供使用者同時處理不同標的相關的量化指標與價量資料的功能,於本次案例我們用以處理:
此外搭配 screen
與 StaticAssets
讓我們在每日計算上述指標時,過濾掉大盤資料 (IR0001)。讓之後在計算每個股票的成交量的四日簡單移動平均、成交量的五日簡單移動平均與當日成交量時,能跳過計算大盤指數。
bundle = bundles.load('tquant')
ir0001_asset = bundle.asset_finder.lookup_symbol('IR0001',as_of_date = None)
def make_pipeline():
sma_vol_win_4 = SimpleMovingAverage(inputs=[EquityPricing.volume], window_length=4)
sma_vol_win_5 = SimpleMovingAverage(inputs=[EquityPricing.volume], window_length=5)
curr_vol = EquityPricing.volume.latest
return Pipeline(
columns = {
'sma_4':sma_vol_win_4,
'sma_5':sma_vol_win_5,
'curr_vol':curr_vol
},
screen = ~StaticAssets([ir0001_asset])
)
inintialize
函式用於定義交易開始前的每日交易環境,與此例中我們設置:
def initialize(context):
set_slippage(slippage.VolumeShareSlippage())
set_commission(commission.PerShare(cost=0.00285))
set_benchmark(symbol('IR0001'))
attach_pipeline(make_pipeline(), 'mystrategy')
handle_data
函式用於處理每天的交易策略或行動,其中:
def handle_data(context, data):
out_dir = pipeline_output('mystrategy')
for i in out_dir.index: # 遍歷過每檔股票
sma_vol_4 = out_dir.loc[i, 'sma_4']
sma_vol_5 = out_dir.loc[i, 'sma_5']
curr_vol = out_dir.loc[i, 'curr_vol']
condition1 = (curr_vol > 2.5 * sma_vol_4) and (context.portfolio.cash > 0)
condition2 = (curr_vol < 0.75 * sma_vol_5)
if condition1:
order(i, 10)
elif condition2:
order_target(i, 0)
else:
pass
多半用於繪製績效圖表,於本次案例將使用 pyfolio 繪製,故直接略過
def analyze(context, perf):
pass
使用 run_algorithm
執行上述所編撰的交易策略,設置交易期間為 2012-07-02 到 2022-07-02,所使用資料集為 tquant,初始資金為 10,000 元。其中輸出的 results 就是每日績效與交易的明細表。
results = run_algorithm(
start = pd.Timestamp('2012-07-02', tz='UTC'),
end = pd.Timestamp('2022-07-02', tz ='UTC'),
initialize=initialize,
bundle='tquant',
analyze=analyze,
capital_base=1e4,
handle_data = handle_data
)
results
之後我們使用 pyfolio 進行績效視覺化與評估,首先使用 extract_rets_pos_txn_from_zipline
先將上述的 results 資料表細分成以下部分:
from pyfolio.utils import extract_rets_pos_txn_from_zipline
returns, positions, transactions = extract_rets_pos_txn_from_zipline(results)
使用 show_perf_stats()
製作績效表,可以快速計算投資常用績效與風險指標,詳細程式碼請見下方 Github 連結。
使用 show_and_plot_top_positions()
與 get_percent_alloc()
製作且繪製各股於交易期間的成分佔比,詳細程式碼請見下方 Github 連結。
使用 plot_rolling_returns()
繪製,本案例的基準為大盤報酬率,詳細程式碼請見下方 Github 連結。
使用 plot_rolling_volatility()
繪製,詳細程式碼請見下方 Github 連結。
使用 plot_rolling_sharpe()
繪製,詳細程式碼請見下方 Github 連結。
電子報訂閱