如何產生 Pyfolio 績效報表¶
Info
本頁提供如何從 Zipline 回測結果生成 Pyfolio 績效報表的詳細指南,包括數據準備、時區標準化和 create_full_tear_sheet() 的使用方法。
Pyfolio 是一個強大的 Python 庫,專為量化投資策略的績效與風險分析而設計。它與 Zipline 回測庫完美兼容,能夠將 Zipline run_algorithm() 產生的複雜回測結果,轉換為一套標準化且視覺化的績效報告 (稱為 "tearsheet"),讓您可以全面評估策略的優劣。
本指南將說明如何將 Zipline 的回測結果導入 Pyfolio 並生成完整的績效報表。
1. 準備回測數據¶
首先,您需要從 Zipline run_algorithm() 函數返回的 results DataFrame 中,提取 Pyfolio 所需的核心數據格式。pyfolio.utils.extract_rets_pos_txn_from_zipline() 函數能有效地完成這項任務。
核心數據類型:¶
returns(策略報酬率):pd.Series,包含每個交易日的策略報酬率。positions(持有部位):pd.DataFrame,包含每個交易日各證券與現金的持有部位。transactions(交易紀錄):pd.DataFrame,包含所有交易的詳細資訊。benchmark_rets(基準報酬率):pd.Series,包含每個交易日的 Benchmark 報酬率。這可以從results.benchmark_return直接取得。
數據提取與時區標準化¶
Pyfolio 要求輸入的數據索引必須是 UTC 時區。因此,在提取數據後,通常需要進行時區標準化。
import pandas as pd
import pyfolio
from pyfolio.utils import extract_rets_pos_txn_from_zipline
# 假設 results 是 zipline.run_algorithm() 執行後的結果 DataFrame
# results = run_algorithm(...)
# 提取策略數據
returns, positions, transactions = extract_rets_pos_txn_from_zipline(results)
# 提取 Benchmark 報酬率
benchmark_rets = results.benchmark_return
# 時區標準化 (確保 Pyfolio 兼容性)
returns.index = returns.index.tz_localize(None).tz_localize('UTC')
positions.index = positions.index.tz_localize(None).tz_localize('UTC')
transactions.index = transactions.index.tz_localize(None).tz_localize('UTC')
benchmark_rets.index = benchmark_rets.index.tz_localize(None).tz_localize('UTC')
2. 生成完整績效報表 (create_full_tear_sheet())¶
當您準備好上述數據後,就可以呼叫 pyfolio.tears.create_full_tear_sheet() 函數來生成包含各項圖表和統計數據的完整績效報表。
主要參數:¶
returns: (必要) 策略的每日報酬率 (pd.Series)。positions: (可選) 策略的每日持有部位 (pd.DataFrame)。transactions: (可選) 策略的交易紀錄 (pd.DataFrame)。benchmark_rets: (可選) Benchmark 的每日報酬率 (pd.Series)。若不傳入,則某些與 Benchmark 比較的圖表將不會生成。
import pyfolio
# ... (上述數據提取與時區標準化的程式碼)
pyfolio.tears.create_full_tear_sheet(
returns=returns,
positions=positions,
transactions=transactions,
benchmark_rets=benchmark_rets # 傳入 Benchmark 報酬率以供比較
)
執行後,您會看到一系列的績效圖表和統計數據,包括報酬曲線、回撤、風險指標、各資產的持有比重分析、交易分析等。
3. 完整範例¶
以下將結合一個簡單的「買入並持有台積電」策略的回測結果,演示如何生成 Pyfolio 績效報表。
Tip
在執行此範例前,請確保您已經使用 zipline ingest -b tquant 匯入了價量資料,並且資料範圍涵蓋了回測期間。詳見:匯入價量資料指南
import pandas as pd
from zipline import run_algorithm
from zipline.api import (
set_benchmark,
symbol,
order_target_percent,
record
)
import pyfolio
from pyfolio.utils import extract_rets_pos_txn_from_zipline
import matplotlib.pyplot as plt
# --- Zipline 回測部分 ---
def initialize(context):
context.asset = symbol('2330')
set_benchmark(symbol('IR0001'))
context.has_ordered = False
def handle_data(context, data):
if not context.has_ordered:
order_target_percent(context.asset, 1.0)
context.has_ordered = True
record(price=data.current(context.asset, 'price'))
def analyze(context, results):
pass # Pyfolio 將會處理分析和視覺化
results = run_algorithm(
start=pd.Timestamp('2022-01-01', tz='UTC'),
end=pd.Timestamp('2023-01-01', tz='UTC'),
initialize=initialize,
handle_data=handle_data,
analyze=analyze,
capital_base=1_000_000,
bundle='tquant'
)
# --- Pyfolio 分析部分 ---
# 1. 提取 Zipline 回測結果
returns, positions, transactions = extract_rets_pos_txn_from_zipline(results)
benchmark_rets = results.benchmark_return
# 2. 時區標準化
returns.index = returns.index.tz_localize(None).tz_localize('UTC')
positions.index = positions.index.tz_localize(None).tz_localize('UTC')
transactions.index = transactions.index.tz_localize(None).tz_localize('UTC')
benchmark_rets.index = benchmark_rets.index.tz_localize(None).tz_localize('UTC')
# 3. 生成完整的 Pyfolio 績效報表
pyfolio.tears.create_full_tear_sheet(
returns=returns,
positions=positions,
transactions=transactions,
benchmark_rets=benchmark_rets
)
# 由於 create_full_tear_sheet 內部會調用 plt.show(),
# 如果在非互動環境運行,可能需要手動儲存圖表或確保繪圖環境是互動的。
# plt.show() # 如果 tearsheet 沒有自動顯示,可以嘗試手動呼叫