Try   HackMD

量化交易 - 回測(Backtest)

強大的回測工具:backtesting. py
Package使用方法: 官方文件

Step0: 建議用Colab跑,安裝比較簡單

Step1: 安裝所需套件

!pip install openai
!pip install yfinance
!pip install backtesting
!pip install bokeh==2.4.3 # 繪圖套件
from  openai import OpenAI, OpenAIError # 串接 OpenAI API
import yfinance as yf
import pandas as pd # 資料處理套件
import datetime as dt # 時間套件

from backtesting import Backtest, Strategy # 回測套件
from backtesting.lib import crossover

Step2: 安裝talib

url = 'https://anaconda.org/conda-forge/libta-lib/0.4.0/download/linux-64/libta-lib-0.4.0-h166bdaf_1.tar.bz2'
!curl -L $url | tar xj -C /usr/lib/x86_64-linux-gnu/ lib --strip-components=1
url = 'https://anaconda.org/conda-forge/ta-lib/0.4.19/download/linux-64/ta-lib-0.4.19-py310hde88566_4.tar.bz2'
!curl -L $url | tar xj -C /usr/local/lib/python3.10/dist-packages/ lib/python3.10/site-packages/talib --strip-components=3

Step3: 取得該投資標的資料

import talib
# 輸入股票代號
stock_id = "2376.tw" # 以技嘉為例
# 抓取 5 年資料
df = yf.download(stock_id, period="5y") # 設定回測期間
# 計算指標
df['ma1'] = df['Close'].rolling(window=5).mean()  # rolling(): 代表要滾動幾天的資料
df['ma2'] = df['Close'].rolling(window=10).mean()
df.tail()

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Step4: 定義回測策略

class Three_way_strategy(Strategy):
  def init(self):
    price = self.data.Close

    # 初始化
    self.ma5 = self.I(SMA,price,5)
    self.ma20 = self.I(SMA,price,20)

    # 初始化 KD
    self.slow_k, self.slow_d = self.I(talib.STOCH, self.data.High, self.data.Low,self.data.Close,
                                      fastk_period=9, slowk_period=3, slowd_period=3)
    # 初始化RSI
    self.RSI = self.I(talib.RSI, price, timeperiod = 14)

  def next(self):
    if crossover(self.ma5, self.ma20) and crossover(self.slow_k, self.slow_d) or self.RSI[-1] < 20: 
      self.buy()
    elif crossover(self.ma20, self.ma5) and crossover(self.slow_d, self.slow_k) or self.RSI[-1] > 80:
      if len(self.trades) > 0: 
        self.trades[0].close() 

bt = Backtest(df, Three_way_strategy,cash = 150000, commission=0.004, exclusive_orders = True)
stats = bt.run() 

Step5: 回測結果

圖:

bt.plot() 

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

從上面這張圖顯示的是我們累積的損益,若在這段時間內 從低點一直買到高點

  • Peak: 我們最多賺了385%
  • Final: 到目前是賺了383%
  • Max Drawdown(最大回撤:回徹期間內的最大損失): 期間內的最大損失為-38.5%
  • Max Dd Dur(Maximum Drawdown Duration): 可能會有 179 天都是賠錢的

詳細數據

print(stats)
Start                     2019-04-09 00:00:00  開始日期
End                       2024-04-09 00:00:00  結束日期
Duration                   1827 days 00:00:00  回測總天數
Exposure Time [%]                   34.675431  曝險期間,代表持有的部位佔總天數的百分比
Equity Final [$]                 575027.93386  最終資產
Equity Peak [$]                  577327.81586  最高資產
Return [%]                         283.351956  總報酬率
Buy & Hold Return [%]              541.491405  買入並長期持有的總報酬率
Return (Ann.) [%]                   32.081978  年化報酬率
Volatility (Ann.) [%]               39.073208  年化波動度
Sharpe Ratio                         0.821074  夏普比率: 代表多承擔一單位風險的超額報酬
Sortino Ratio                        1.792689  類似夏普比率,但只考慮下方風險(也就是股票下跌時的標準差)
Calmar Ratio                         0.832427  年化報酬率/最大跌幅:用於衡量資產面臨最大風險時的表現
Max. Drawdown [%]                  -38.540274  最大損失:代表總資產在策略期間的最大下跌幅度
Avg. Drawdown [%]                   -6.480727  平均損失: 所有損失交易的平均數
Max. Drawdown Duration      182 days 00:00:00  最大損失的持續時間
Avg. Drawdown Duration       23 days 00:00:00  平均損失的持續時間
# Trades                                    7  交易次數
Win Rate [%]                        71.428571  交易勝率,若以7次交易來說,超過半數以上的交易都是賺錢的
Best Trade [%]                     108.773007  單一次交易的最佳報酬率
Worst Trade [%]                     -9.663671  單一次交易的最差報酬率
Avg. Trade [%]                      21.165614  每筆交易的平均報酬率
Max. Trade Duration         264 days 00:00:00  單一筆交易的最常持有時間
Avg. Trade Duration          90 days 00:00:00  每筆交易平均持有時間
Profit Factor                       19.358017  總獲利/總損失
Expectancy [%]                      26.388541  用勝率來計算每筆交易的期望獲利
SQN                                  1.854045  衡量期望獲利、風險與交易次數的指標,通常>3就是不錯的策略

在stats中可以發現,win rate只是36%
可以發現當我們在做投資的時候 可能不是每筆交易都要賺錢,只要少數幾筆交易賺足夠多,那麼資產就能成長