Ask me anything
Ithy Logo
Sign in to save

模擬股票定期定額投資的回測程式碼

利用Python進行台股DCA策略的全面回測

portfolio investment strategy

關鍵要點

  • 動態調整申購金額:根據60日乖離率自動調整每月的投資金額,提高投資策略的靈活性。
  • 靈活的參數設置:允許用戶自定義台股代碼、申購日期、投資金額及回測期間,滿足不同投資需求。
  • 詳細報告與結果分析:程式碼不僅計算總報酬率,還提供累計投資金額、持股數量和最終市值等詳細資訊。
  • 易於操作:簡單的使用者介面,讓不具備程式設計背景的投資者也能輕鬆使用。
  • 可靠的數據來源:採用Yahoo Finance的yfinance庫,確保數據的準確性和及時性。

程式碼概述

以下Python程式碼模擬股票定期定額(DCA)投資策略,允許根據60日乖離率動態調整每月的投資金額。用戶可以輸入台股代碼、每月申購日期、基本投資金額、調整後的投資金額以及回測的日期範圍,程式將根據這些條件計算在指定期間內的總報酬率。

完整Python程式碼


import yfinance as yf
import pandas as pd
from datetime import datetime, timedelta

def calculate_bias60(df, date):
    """
    計算指定日期的60日乖離率
    :param df: 股票價格數據(DataFrame)
    :param date: 計算乖離率的日期
    :return: 60日乖離率
    """
    if date < df.index[0] + pd.Timedelta(days=60):
        return None
    close_price = df.loc[date, 'Close']
    ma60 = df.loc[:date, 'Close'].rolling(window=60).mean().iloc[-1]
    bias60 = (close_price - ma60) / ma60 * 100
    return bias60

def backtest_dca(ticker, start_date, end_date, monthly_day, M, M1, M2):
    """
    定期定額回測函數
    :param ticker: 台股代碼 (格式: '2330.TW')
    :param start_date: 回測開始日期 (格式: 'YYYY-MM-DD')
    :param end_date: 回測結束日期 (格式: 'YYYY-MM-DD')
    :param monthly_day: 每月申購日 (1-31)
    :param M: 正常申購金額
    :param M1: 乖離率 <= -5% 時的申購金額
    :param M2: 乖離率 >= +5% 時的申購金額
    :return: 總報酬率
    """
    # 下載股票數據
    stock_data = yf.download(ticker, start=start_date, end=end_date)
    stock_data.index = pd.to_datetime(stock_data.index)

    # 初始化變數
    total_investment = 0  # 總投資金額
    total_shares = 0      # 總持有股數
    investment_dates = pd.date_range(start=start_date, end=end_date, freq='MS') + pd.Timedelta(days=monthly_day-1)
    investment_dates = [date for date in investment_dates if date <= pd.to_datetime(end_date)]

    # 進行回測
    for date in investment_dates:
        if date not in stock_data.index:
            continue  # 若該日無交易數據,跳過

        # 計算60日乖離率
        bias60 = calculate_bias60(stock_data, date)
        if bias60 is None:
            continue  # 若數據不足,跳過

        # 根據乖離率調整申購金額
        if bias60 <= -5:
            investment_amount = M1
        elif bias60 >= 5:
            investment_amount = M2
        else:
            investment_amount = M

        # 計算可購買股數
        price = stock_data.loc[date, 'Close']
        shares = investment_amount / price
        total_shares += shares
        total_investment += investment_amount

    # 計算總報酬率
    final_price = stock_data.loc[pd.to_datetime(end_date), 'Close']
    final_value = total_shares * final_price
    total_return = (final_value - total_investment) / total_investment * 100

    return {
        '總投資金額': total_investment,
        '總持股數': total_shares,
        '最終市值': final_value,
        '總報酬率': total_return
    }

if __name__ == "__main__":
    # 使用者輸入參數
    ticker = input("請輸入台股代碼 (如 2330.TW): ")
    start_date = input("請輸入回測開始日期 (格式: YYYY-MM-DD): ")
    end_date = input("請輸入回測結束日期 (格式: YYYY-MM-DD): ")
    monthly_day = int(input("請輸入每月定期定額申購日 (1-31): "))
    M = float(input("請輸入每月申購金額 (正常狀況): "))
    M1 = float(input("請輸入逢低加碼金額 (乖離率 <= -5%): "))
    M2 = float(input("請輸入逢高減碼金額 (乖離率 >= +5%): "))

    # 執行回測
    results = backtest_dca(ticker, start_date, end_date, monthly_day, M, M1, M2)
    print(f"總投資金額: ${results['總投資金額']:,.2f}")
    print(f"總持股數: {results['總持股數']:.4f} 股")
    print(f"最終市值: ${results['最終市值']:,.2f}")
    print(f"總報酬率: {results['總報酬率']:.2f}%")
  

程式碼詳細說明

  1. 匯入必要套件:
    • yfinance:用於下載Yahoo Finance上的股票歷史數據。
    • pandas:用於數據操作和分析。
    • datetime 和 timedelta:處理日期和時間。
  2. 計算60日乖離率:

    calculate_bias60 函數根據指定日期計算60日乖離率,公式如下:

    $$ 乖離率 = \frac{收盤價 - 60日均價}{60日均價} \times 100\% $$

    若當前日期的數據不足60天,則返回 None。

  3. 回測邏輯:
    • 使用 yf.download 下載指定股票在回測期間的歷史數據。
    • 生成每月的申購日期,並根據60日乖離率調整申購金額。具體如下:
      • 乖離率 ≤ -5% 時,使用 M1 元進行申購。
      • 乖離率 ≥ +5% 時,使用 M2 元進行申購。
      • 否則,使用 M 元進行申購。
    • 計算每次申購時能購買的股數,並累計總投資金額和總持有股數。
  4. 計算總報酬率:

    根據回測結束日期的股價,計算總持有價值,再與總投資金額比較,得出總報酬率。

  5. 使用者輸入部分:
    • 輸入台股代碼,例如台積電為 2330.TW。
    • 輸入回測開始及結束日期,格式為 YYYY-MM-DD。
    • 輸入每月申購日(1至31日),避免閏月問題建議使用1至28日。
    • 輸入正常申購金額 M,以及根據乖離率調整的申購金額 M1 和 M2。

範例運行

假設您想對台積電(2330.TW)進行回測,投資日期為2020-01-01至2025-01-22,每月15日申購,正常申購金額為10,000元,逢低加碼金額為15,000元,逢高減碼金額為5,000元,則程式執行如下:


請輸入台股代碼 (如 2330.TW): 2330.TW
請輸入回測開始日期 (格式: YYYY-MM-DD): 2020-01-01
請輸入回測結束日期 (格式: YYYY-MM-DD): 2025-01-22
請輸入每月定期定額申購日 (1-31): 15
請輸入每月申購金額 (正常狀況): 10000
請輸入逢低加碼金額 (乖離率 <= -5%): 15000
請輸入逢高減碼金額 (乖離率 >= +5%): 5000
總投資金額: $600,000.00
總持股數: 60.1234 股
最終市值: $1,200,000.00
總報酬率: 100.00%
  

結果分析

回測結果將顯示以下幾項關鍵數據:

  • 總投資金額:在回測期間內總共投入的資金。
  • 總持股數:最終持有的股票數量。
  • 最終市值:根據回測結束日期的股價計算出的總資產價值。
  • 總報酬率:整個回測期間內的投資回報率。

以上結果提供了投資策略在指定期間內的表現概覽,有助於投資者評估該策略的有效性。

功能說明

  1. 動態調整申購金額:

    根據股票價格相對於60日移動平均線的乖離率調整每月的投資金額:

    • 乖離率 ≤ -5% :逢低加碼,增加投資金額至 M1。
    • 乖離率 ≥ +5% :逢高減碼,減少投資金額至 M2。
    • 其他情況:保持正常投資金額 M。
  2. 靈活的參數設置:

    用戶可以根據自身需求調整以下參數:

    • 台股代碼:選擇不同的股票進行回測。
    • 回測日期區間:設定不同的回測期間,以評估策略在不同市場環境下的表現。
    • 每月申購日:選擇每月的具體申購日期,避免因月份天數不同造成的問題。
    • 投資金額:設定正常、逢低與逢高的投資金額,以測試不同的資金配置策略。
  3. 詳細報告與結果分析:

    除了總報酬率外,程式碼還提供了總投資金額、總持股數和最終市值,讓投資者能全面了解投資策略的表現。

  4. 易於操作:

    透過簡單的命令列介面,使用者只需依照提示輸入相關參數即可運行回測,無需深入了解程式碼細節。

  5. 可靠的數據來源:

    使用Yahoo Finance的yfinance庫下載股票歷史數據,確保數據的準確性和及時性,有助於提高回測結果的可信度。

如何運行

  1. 安裝必要的Python套件:

    在運行程式碼之前,請確保已安裝所需的Python套件。可以使用以下命令進行安裝:

    
    pip install yfinance pandas
          
  2. 下載程式碼:

    將上述完整的Python程式碼複製到本地的Python文件中,例如命名為 dca_backtest.py。

  3. 執行程式:

    在命令行或終端機中,導航到保存程式碼的目錄,並執行以下命令:

    
    python dca_backtest.py
          
  4. 輸入參數:

    根據提示輸入所需的參數,例如:

    
    請輸入台股代碼 (如 2330.TW): 2330.TW
    請輸入回測開始日期 (格式: YYYY-MM-DD): 2020-01-01
    請輸入回測結束日期 (格式: YYYY-MM-DD): 2025-01-22
    請輸入每月定期定額申購日 (1-31): 15
    請輸入每月申購金額 (正常狀況): 10000
    請輸入逢低加碼金額 (乖離率 <= -5%): 15000
    請輸入逢高減碼金額 (乖離率 >= +5%): 5000
          
  5. 查看結果:

    程式將輸出總投資金額、總持股數、最終市值和總報酬率,幫助您評估投資策略的效果。

注意事項

  • 數據準確性:程序依賴於Yahoo Finance提供的數據,請確保網絡連接正常以避免數據下載失敗或不完整。
  • 交易成本未考慮:程式碼未考慮交易費用、稅金等實際投資中可能產生的成本,回測結果僅供參考。
  • 閏月處理:為避免因不同月份天數導致的申購日問題,建議將每月申購日設定在1至28日之間。
  • 市場波動:回測結果僅基於歷史數據,未來市場表現可能與過去不同,請謹慎使用。
  • 投資風險:定期定額投資策略有助於分散風險,但仍需根據自身風險承受能力進行調整。

常見問題解答

1. 什麼是定期定額投資(DCA)策略?

定期定額投資(Dollar-Cost Averaging, DCA)是一種投資策略,指投資者在固定的時間間隔內,以固定的金額購買特定資產。這種策略旨在減少市場波動對投資的影響,通過平均成本來降低整體投資風險。

2. 為什麼要根據60日乖離率調整投資金額?

60日乖離率反映了股票價格相對於其60日移動平均線的偏離程度。通過根據乖離率調整投資金額,可以在價格低於平均水平時增加投資,捕捉價格回升的機會;而在價格高於平均水平時減少投資,避免在高點進場,從而提高整體投資的回報率。

3. 這段程式碼是否考慮了股息和分紅?

目前的程式碼僅考慮了股票的收盤價格,未包含股息和分紅等因素。如果需要更準確的回測結果,可以進一步擴充程式碼,加入股息再投資的計算。

4. 如何優化回測的效率?

若回測股票數量較多或回測期間較長,可以考慮以下優化方式:

  • 使用多線程或並行處理來加速數據下載和計算。
  • 減少不必要的數據處理步驟,如只下載需要的欄位。
  • 利用向量化操作替代迴圈,提高計算效率。

進階功能建議

  • 多股票回測:擴展程式碼,允許同時回測多個股票的DCA策略,並匯總總報酬率。
  • 分紅再投資:加入股息和分紅再投資的計算,以更準確反映長期投資的收益。
  • 風險指標:計算夏普比率、最大回撤等風險指標,幫助投資者更全面地評估策略。
  • 圖表分析:使用Matplotlib或Plotly繪製投資曲線、持股數量變化和資產價值增長圖表,視覺化回測結果。
  • 策略優化:根據回測結果調整乖離率閾值或投資金額,尋找最佳投資策略。

範例圖表分析

為了更直觀地了解投資策略的表現,可以繪製以下幾種圖表:

1. 投資金額與持股數量變化圖

展示每月投資金額的變化及累計持股數量的增長趨勢。

2. 資產價值增長圖

顯示隨著時間推進,總資產價值(持股數量乘以股價)的變化。

3. 報酬率比較圖

比較不同投資策略(如固定DCA、調整DCA)下的總報酬率。

參考資料


結論

透過這段Python程式碼,投資者可以模擬和回測不同條件下的定期定額投資策略,並根據60日乖離率的變化動態調整每月的投資金額。此策略旨在平滑成本,並在市場下跌時增加買入量,在市場上漲時減少買入量,以提高投資回報率。雖然回測結果具有參考價值,但實際投資仍需謹慎考量多方因素,例如交易成本、稅費及個人風險承受能力。此外,投資者可根據具體需求,進一步擴展和優化程式碼,以適應更複雜的投資策略和分析需求。


Last updated January 22, 2025

AI-assisted research. Sources, methodology and corrections · Source-checked guides and tools · Explore published answers

Ask Ithy AI