TQuant Lab 量能回測實戰

TQuant Lab 量能回測實戰
Photo by Hans Eiskonen on Unsplash

本文重點概要

  • 文章難度:★★☆☆☆
  • 以成交量增長為篩選指標
  • 閱讀建議:本文以成交量增長作為買賣指標,以視覺化的方式觀察交易訊號以及買賣點,接著再利用函數計算出報酬率,所有策略所需之程式碼皆使用 TQuant Lab 進行回測。
  • 本文改編自 量能回測

前言

近幾年動能交易很常出現在股票策略的討論當中,我們在股票市場通常很常聽到談論價量關係,價是量的先行指標等等,而本文想進而探討當成交量放大時以做為進場策略之回測效應,本方法並沒有像其他技術指標一樣有一定之準則,於是在設計上比較較為彈性,在程式設計上能使讀者們自行更改,詳細參數設定上會在後面程式碼中提及如何修改。而本文採用以下策略進行回測:

  1. 進場成交量是前”4”日平均的2.5倍做為進入準則
  2. 出場設在成交量低於”5”日平均的0.75倍

編輯環境及模組需求

本文使用 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

資料導入

分別設定以下環境變數:

  1. TEJAPI_BASE: API 聯結網域。
  2. TEJAPI_KEY: API。
  3. mdate: 所欲抓取資料時間區間。
  4. ticker: 股票標的,分別為大盤報酬指數 (IR0001)、2330 (台積電)、3443 (創意)、2337 (旺宏)。

並且使用 !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 函式

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])
    )

建立 initialize 函式

inintialize 函式用於定義交易開始前的每日交易環境,與此例中我們設置:

  • 流動性滑價
  • 交易手續費
  • 大盤報酬作為基準
  • 將 Pipeline 導入交易流程中
def initialize(context):
    set_slippage(slippage.VolumeShareSlippage())
    set_commission(commission.PerShare(cost=0.00285))
    set_benchmark(symbol('IR0001'))
    attach_pipeline(make_pipeline(), 'mystrategy')

建立 handle_date 函式

handle_data 函式用於處理每天的交易策略或行動,其中:

  • condition1: 當日成交量大於四日簡單移動平均之 2.5 倍且現金部位大於 0 ,產生買入訊號。
  • condition2: 當日成交量小於五日簡單移動平均之 0.75 倍,產生賣出訊號。
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

建立 analyze 函式

多半用於繪製績效圖表,於本次案例將使用 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
results
results

視覺化與績效評估

生成 pyfolio 所需資料表

之後我們使用 pyfolio 進行績效視覺化與評估,首先使用 extract_rets_pos_txn_from_zipline 先將上述的 results 資料表細分成以下部分:

  • return: 投組每日報酬
  • positions: 持有部位資料表
  • transactions: 交易明細資料表
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 連結。

投組成分表
投組成分表

繪製基準 (benchmark) 與投組累計報酬率

使用 plot_rolling_returns() 繪製,本案例的基準為大盤報酬率,詳細程式碼請見下方 Github 連結。

投組累計報酬圖
投組累計報酬圖

繪製六個月的滾動波動度

使用 plot_rolling_volatility() 繪製,詳細程式碼請見下方 Github 連結。

滾動波動度
滾動波動度

繪製六個月的滾動夏普值

使用 plot_rolling_sharpe() 繪製,詳細程式碼請見下方 Github 連結。

滾動夏普值
滾動夏普值

完整程式碼

延伸閱讀

相關連結

返回總覽頁
Procesing