# 量化交易 - 回測(Backtest) > 強大的回測工具:backtesting. py > Package使用方法: [官方文件](https://kernc.github.io/backtesting.py/doc/backtesting/backtesting.html#gsc.tab=0) ## 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](https://hackmd.io/_uploads/ryy54gmgC.png) ## 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](https://hackmd.io/_uploads/r1exBeQgA.png) ![image](https://hackmd.io/_uploads/ry1XBlXx0.png) ![image](https://hackmd.io/_uploads/HyJrBgXgC.png) > 從上面這張圖顯示的是我們累積的損益,若在這段時間內 從低點一直買到高點 - 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% > 可以發現當我們在做投資的時候 可能不是每筆交易都要賺錢,只要少數幾筆交易賺足夠多,那麼資產就能成長