iT邦幫忙

2021 iThome 鐵人賽

DAY 14
1

什麼是回測?

在金融領域,回測通過測試交易策略,並根據歷史資料的表現來核查其可行性。換句話說,它使用過去的資料來檢視策略的執行情況。如果回測顯示出良好的結果,則交易者或投資者可以繼續進行並將該策略應用於實際環境。

但是,如果通過回測得到了較滿意的結果,又意味著什麼呢?使用回測工具是為了分析特定策略的風險和潛在獲利能力。可以基於統計反饋來優化和增強投資策略,以最大程度地提高潛在收益。通過完備的回測還可以確保實際交易環境中實施該策略的可行性。

回測平臺或工具在評估策略是否在某些時間段不可行或存在較大風險方面也能夠有所幫助。如果對回測的結果不滿意,則應適當放棄或修改交易思路。同樣,評估回測的市場條件也十分重要。當市場條件發生變化時,相同的回測可能會帶來相反的結果。
From 什麼是回測?

backtrader vs backtesting.py

目前Python主流庫基本上就兩種,backtrader與backtesting.py,
zipline過於老舊不考慮,
FinMind雖然有內建回測但穩定度與相容性不佳。

backtrader

  • 優點
    • 直覺、簡潔。
    • 有很多內容可以學習更多關於算法交易的知識。
    • 有一個活躍的社群在修復錯誤。
    • 非常好的文檔。
  • 缺點
    • 學習曲線高。

backtesting.py

  • 優點
    • 輕量、簡潔。
    • 內建回測會用到的所有功能。
    • 可互動的分析介面
  • 缺點
    • 學習曲線高。
    • 相對小的社群。
    • 簡單到不能更簡單的文檔。

實例

引入函式庫

import datetime
import warnings

import pandas as pd 
import requests
from backtesting import Backtest, Strategy
from backtesting.lib import crossover
from backtesting.test import SMA
from pandas.core.common import SettingWithCopyWarning

warnings.simplefilter(action="ignore", category=SettingWithCopyWarning)
pd.set_option("display.max_columns", None)

取得資料

backtesting強制要求欄位名稱格式,
所以需要先轉換欄位名稱

stock_index = 2340
url = "https://api.finmindtrade.com/api/v4/data"
parameter = {
    "dataset": "TaiwanStockPrice",
    "start_date": datetime.datetime(2012, 1, 1, 0, 0).strftime("%Y-%m-%d"),
    "end_date": datetime.datetime(2018, 1, 1, 0, 0).strftime("%Y-%m-%d"),
    "data_id": stock_index,
}

data = requests.get(url, params=parameter)
data = data.json()

df = pd.DataFrame(data["data"])

df.index = pd.to_datetime(df["date"])
df.rename(
    columns={
        "Trading_Volume": "Volume",
        "open": "Open",
        "max": "High",
        "min": "Low",
        "close": "Close",
    },
    inplace=True,
)

df.drop(
    columns=["stock_id", "date", "Trading_money", "spread", "Trading_turnover"],
    inplace=True,
)

df

回測策略

如果快線超過慢線,表示股票進入上漲的趨勢,此時進行買空操作,分析圖表以https://ithelp.ithome.com.tw/upload/images/20210919/20141586vhDmTPQp9Z.png表示。
如果快線跌過慢線,表示股票進入下跌的趨勢,此時進行賣空操作,分析圖表以https://ithelp.ithome.com.tw/upload/images/20210919/20141586Y98Ntg07AE.png表示。
顏色代表上一次操作的獲利情形,綠色表示獲利,綠色表示賠錢。

class SmaCross(Strategy):
    def init(self):
        self.fast_line = self.I(SMA, self.data.Close, 5)
        self.slow_line = self.I(SMA, self.data.Close, 15)

    def next(self):
        if crossover(self.fast_line, self.slow_line):
            print(
                f"{self.data.index[-1]} Buy: Price: {self.data.Close[-1]}, Slow: {self.slow_line[-5:]}, Fast: {self.fast_line[-5:]}"
            )
            self.buy()
        elif crossover(self.slow_line, self.fast_line):
            print(
                f"{self.data.index[-1]} Sell: Price: {self.data.Close[-1]}, Slow: {self.slow_line[-5:]}, Fast: {self.fast_line[-5:]}"
            )

            self.sell()

執行策略

  • cash:本金。
  • commission:交易費用。
  • hedging:進行反向操作會以FIFO形式進行抵銷。
    • Sell(1100)、Buy(1000) -> 賣空100
    • Sell(1000)、Buy(1100) -> 買空100
  • exclusive_orders:每次操作前自動關閉(close)上次操作。
    • self.trades[0].close()
  • trade_on_close:於收盤時交易,否則預設於開盤交易。
test = Backtest(
    df,
    SmaCross,
    cash=1000000,
    commission=0.004,
    exclusive_orders=True,
    trade_on_close=True,
)
result = test.run()

分析結果

將分析結果儲存,並利用預設瀏覽器開啟,
result為詳細的分析結果。

test.plot(filename=f"./backtest_result/{stock_index}.html")
print(result)

https://ithelp.ithome.com.tw/upload/images/20210919/20141586nTsggfN69g.png

分析結果欄位說明
From https://hackmd.io/@s02260441/SkA7IWVJv

欄位 說明
Start 起始時間
End 結束時間
Duration 經過天數
Exposure [%] 投資比率
Equity Final [$] 最終資產
Equity Peak [$] 最高資產
Return [%] 報酬率
Buy & Hold Return [%] 買入持有報酬率
Max. Drawdown [%] 最大交易回落
Avg. Drawdown [%] 平均交易回落
Max. Drawdown Duration 最長交易回落期間
Avg. Drawdown Duration 平均交易回落期間
Win Rate [%] 勝率
Best Trade [%] 最好交易報酬率
Worst Trade [%] 最差交易報酬率
Avg. Trade [%] 平均交易報酬率
Max. Trade Duration 最長交易間隔
Avg. Trade Duration 平均交易間隔
Expectancy [%] 期望值
SQN 系統品質指標
Sharpe Ratio 夏普比率
Sortino Ratio 索丁諾比率
Calmar Ratio 卡瑪比率
_strategy 使用策略名稱

參考


上一篇
[Day 13]
下一篇
[Day 15] backtesting 使用說明
系列文
從零開始的套牢生活 - AI股票預測系統30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言