イベント駆動バックテスト Python - Part VII

作者: リン・ハーン優しさ作成日: 2019-03-26 10:52:49, 更新日:

Event-Driven Backtester シリーズの最後の記事では,ExecutionHandler の基本的な階層を考慮した.この記事では,ポートフォリオオブジェクトの以前に構築された株式曲線 DataFrame を使用して,バックテスト後の戦略のパフォーマンスを評価する方法について議論します.

性能指標

シャープ比率は,以下のような方法で計算されます.img

株式曲線のリターンストリームが Ra で,適切な金利や株式指数などのベンチマークが Rb である.

最大引き上げと引き上げ期間は,投資家がしばしばポートフォリオのリスクを評価するために使用する2つの追加指標である.前者数値は,株式曲線のパフォーマンスの最高峰から最低点までの減少であり,後者は,発生する取引期間の数で定義される.

この記事では,Pythonベースのイベント駆動バックテスト用パッケージで使用するためのポートフォリオパフォーマンスの指標として,シャープ比率,最大引き下げおよび引き上げ期間を実装します.

Python の実装

新しいファイルを作成します.performance.py計算を重くするクラスのほとんどと同様に NumPy と pandas をインポートする必要があります.

# performance.py

import numpy as np
import pandas as pd

シャープ比率はリスクと報酬の指標であることに注意してください (実際は多くの指標のうちの1つです).

通常,この値は252に設定され,これは1年あたり米国での取引日数である.しかし,あなたの戦略が1時間以内に取引される場合,それを正しく年化するためにシャープを調整する必要があります.したがって,あなたは2526.5=1638に期間を設定する必要があります.これは1年以内に米国の取引時間の数です.あなたが毎分取引する場合,この因子は2526.560=98280に設定する必要があります.

create_sharpe_ratio関数は,返済と呼ばれるパンダシリーズオブジェクトで動作し,単に,周期パーセント返済の平均値と周期パーセント返済標準偏差の割合を計算します.

# performance.py

def create_sharpe_ratio(returns, periods=252):
    """
    Create the Sharpe ratio for the strategy, based on a 
    benchmark of zero (i.e. no risk-free rate information).

    Parameters:
    returns - A pandas Series representing period percentage returns.
    periods - Daily (252), Hourly (252*6.5), Minutely(252*6.5*60) etc.
    """
    return np.sqrt(periods) * (np.mean(returns)) / np.std(returns)

シャープ比率は,リターン単位ごとにどれだけのリスク (資産経路標準偏差によって定義される) がかかっているのかを特徴づけているが,引き下げは,株式曲線に沿った最大峰から底辺までの減少値として定義される.

create_drawdowns関数は,最大引き上げと最大引き上げ期間の両方を提供します.前者は上記最大のピークから底まで減少であり,後者は,この減少が起こる期間数として定義されます.

引き下げ期間について,いくつかの細かい解釈が必要であり,それは取引期間を数え,したがって"日"などの時間単位に直接変換できないからです.

この関数は,各取引のbarの引き下げと期間を表す2つのパンダシリーズオブジェクトを作成し,その後,株式曲線がすべての以前のピークを超えているかどうかを決定することによって,現在の高水位 (HWM) を確立します.

引き下げは,単に現在のHWMと株式曲線の差である.この値がマイナスである場合,次のHWMに到達するまで発生するすべてのバーで期間が増加する.この関数は,2つのシリーズのそれぞれの最大値を返します:

# performance.py

def create_drawdowns(equity_curve):
    """
    Calculate the largest peak-to-trough drawdown of the PnL curve
    as well as the duration of the drawdown. Requires that the 
    pnl_returns is a pandas Series.

    Parameters:
    pnl - A pandas Series representing period percentage returns.

    Returns:
    drawdown, duration - Highest peak-to-trough drawdown and duration.
    """

    # Calculate the cumulative returns curve 
    # and set up the High Water Mark
    # Then create the drawdown and duration series
    hwm = [0]
    eq_idx = equity_curve.index
    drawdown = pd.Series(index = eq_idx)
    duration = pd.Series(index = eq_idx)

    # Loop over the index range
    for t in range(1, len(eq_idx)):
        cur_hwm = max(hwm[t-1], equity_curve[t])
        hwm.append(cur_hwm)
        drawdown[t]= hwm[t] - equity_curve[t]
        duration[t]= 0 if drawdown[t] == 0 else duration[t-1] + 1
    return drawdown.max(), duration.max()

これらのパフォーマンス指標を利用するには,バックテストが行われ,つまり適切な株式曲線が利用可能になった後に計算する方法が必要です!

また,計算を特定のオブジェクト階層と関連付ける必要があります.パフォーマンスメアはポートフォリオに基づいて計算されるので,この記事で議論したポートフォリオクラス階層上の方法にパフォーマンス計算を結びつけるのが意味があります.

まず最初に オープンにすることportfolio.py前回の記事で議論したように,性能機能をインポートします.

# portfolio.py

..  # Other imports

from performance import create_sharpe_ratio, create_drawdowns

Portfolio は抽象的なベースクラスであるため,その派生クラスの一つにメソッドをアタッチしたい.この場合は NaivePortfolio です.したがって,Sharpe と引き下げ情報を生成するためにポートフォリオの株式曲線に作用するoutput_summary_stats というメソッドを作成します.

この方法は単純です.単に2つのパフォーマンスメーターを利用し,それらを直接株式曲線 DataFrame に適用し,統計を形式に適した方法でタプルリストとして出力します:

# portfolio.py

..
..

class NaivePortfolio(object):

    ..
    ..

    def output_summary_stats(self):
        """
        Creates a list of summary statistics for the portfolio such
        as Sharpe Ratio and drawdown information.
        """
        total_return = self.equity_curve['equity_curve'][-1]
        returns = self.equity_curve['returns']
        pnl = self.equity_curve['equity_curve']

        sharpe_ratio = create_sharpe_ratio(returns)
        max_dd, dd_duration = create_drawdowns(pnl)

        stats = [("Total Return", "%0.2f%%" % ((total_return - 1.0) * 100.0)),
                 ("Sharpe Ratio", "%0.2f" % sharpe_ratio),
                 ("Max Drawdown", "%0.2f%%" % (max_dd * 100.0)),
                 ("Drawdown Duration", "%d" % dd_duration)]
        return stats

明らかにこれはポートフォリオのための非常に単純なパフォーマンス分析です.それは取引レベルの分析や他のリスク/報酬の測定を考慮しません.しかし,より多くの方法を追加して拡張することは簡単です.performance.pyそして必要に応じて output_summary_stat に組み込む.


もっと