在金融領域,回測通過測試交易策略,並根據歷史資料的表現來核查其可行性。換句話說,它使用過去的資料來檢視策略的執行情況。如果回測顯示出良好的結果,則交易者或投資者可以繼續進行並將該策略應用於實際環境。
但是,如果通過回測得到了較滿意的結果,又意味著什麼呢?使用回測工具是為了分析特定策略的風險和潛在獲利能力。可以基於統計反饋來優化和增強投資策略,以最大程度地提高潛在收益。通過完備的回測還可以確保實際交易環境中實施該策略的可行性。
回測平臺或工具在評估策略是否在某些時間段不可行或存在較大風險方面也能夠有所幫助。如果對回測的結果不滿意,則應適當放棄或修改交易思路。同樣,評估回測的市場條件也十分重要。當市場條件發生變化時,相同的回測可能會帶來相反的結果。
From 什麼是回測?
目前Python主流庫基本上就兩種,backtrader與backtesting.py,
zipline過於老舊不考慮,
FinMind雖然有內建回測但穩定度與相容性不佳。
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
如果快線超過慢線,表示股票進入上漲的趨勢,此時進行買空操作,分析圖表以表示。
如果快線跌過慢線,表示股票進入下跌的趨勢,此時進行賣空操作,分析圖表以表示。
顏色代表上一次操作的獲利情形,綠色表示獲利,綠色表示賠錢。
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()
self.trades[0].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)
分析結果欄位說明
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 | 使用策略名稱 |