實作交易策略:黃金交叉與定期定額

有了技術指標之後,我們可以開始實作交易策略了!這一章我們將實作兩個最經典的策略,並比較它們的績效。

策略一:黃金交叉策略 (Golden Cross)

黃金交叉是技術分析中最經典的趨勢跟隨策略。當短期移動平均線向上突破長期移動平均線時,代表上升趨勢確立,是買進信號。

實作黃金交叉策略

import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 載入資料
df = yf.download("2330.TW", start="2020-01-01", end="2024-12-31")
close = df['Close']

# 計算移動平均線
df['MA10'] = close.rolling(window=10).mean()
df['MA30'] = close.rolling(window=30).mean()

# 產生交易信號
# 當 MA10 > MA30 時持倉 (1),否則空倉 (0)
df['Signal'] = 0
df.loc[df['MA10'] > df['MA30'], 'Signal'] = 1

# 計算每日報酬率
df['Return'] = close.pct_change()

# 策略報酬 = 信號 * 每日報酬(信號會在收盤後產生,所以用 shift 延遲一天)
df['Strategy_Return'] = df['Signal'].shift(1) * df['Return']

# 計算累積報酬
df['Cum_Strategy'] = (1 + df['Strategy_Return']).cumprod() - 1
df['Cum_BuyHold'] = (1 + df['Return']).cumprod() - 1

# 畫圖
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(14, 10), gridspec_kw={'height_ratios': [2, 1]})

# 上圖:價格與買賣點
ax1.plot(df.index, close, label='收盤價', alpha=0.5)
ax1.plot(df.index, df['MA10'], label='MA10', linewidth=1)
ax1.plot(df.index, df['MA30'], label='MA30', linewidth=1)

# 標示買進點
buy_signals = df[df['Signal'] == 1]
ax1.scatter(buy_signals.index, buy_signals['MA10'], 
           marker='^', color='g', s=50, label='買進信號', alpha=0.7)

sell_signals = df[df['Signal'] == 0]
sell_indices = sell_signals.index.difference(buy_signals.index)
ax1.scatter(sell_indices, sell_signals['MA30'].loc[sell_indices],
           marker='v', color='r', s=50, label='賣出信號', alpha=0.7)

ax1.set_title('台積電 - 黃金交叉策略')
ax1.legend()
ax1.grid(True, alpha=0.3)

# 下圖:累積報酬率比較
ax2.plot(df.index, df['Cum_Strategy'] * 100, label='黃金交叉策略', color='green', linewidth=2)
ax2.plot(df.index, df['Cum_BuyHold'] * 100, label='買入持有', color='blue', linewidth=2, linestyle='--')
ax2.axhline(y=0, color='black', linestyle='-', alpha=0.2)
ax2.set_title('累積報酬率比較 (%)')
ax2.legend()
ax2.grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

績效評估

# === 計算績效指標 ===
total_return_strategy = df['Cum_Strategy'].iloc[-1]
total_return_buyhold = df['Cum_BuyHold'].iloc[-1]

# 年化報酬率
trading_days = len(df)
annual_return_strategy = (1 + total_return_strategy) ** (252 / trading_days) - 1
annual_return_buyhold = (1 + total_return_buyhold) ** (252 / trading_days) - 1

# 夏普比率(假設無風險利率為 0)
sharpe_strategy = np.sqrt(252) * df['Strategy_Return'].mean() / df['Strategy_Return'].std()
sharpe_buyhold = np.sqrt(252) * df['Return'].mean() / df['Return'].std()

# 最大回撤
cumulative = (1 + df['Strategy_Return']).cumprod()
rolling_max = cumulative.cummax()
drawdown = (cumulative - rolling_max) / rolling_max
max_drawdown = drawdown.min()

print(f"=== 黃金交叉策略 vs 買入持有 ===")
print(f"\n策略總報酬率: {total_return_strategy*100:.2f}%")
print(f"買入持有總報酬率: {total_return_buyhold*100:.2f}%")
print(f"\n策略年化報酬率: {annual_return_strategy*100:.2f}%")
print(f"買入持有年化報酬率: {annual_return_buyhold*100:.2f}%")
print(f"\n策略夏普比率: {sharpe_strategy:.2f}")
print(f"買入持有夏普比率: {sharpe_buyhold:.2f}")
print(f"\n策略最大回撤: {max_drawdown*100:.2f}%")

策略二:定期定額 (Dollar Cost Averaging)

定期定額是最適合散戶的策略:每個月固定日期買入固定金額的股票,不管價格高低。

# === 定期定額回測 ===
monthly_investment = 10000  # 每個月投入 1 萬元

# 取得每月第一個交易日的索引
monthly_dates = df.resample('ME').first().index

# 模擬定期定額
total_shares = 0
total_invested = 0
portfolio_value = []

for date in df.index:
    # 如果是每月第一個交易日,買入
    if date in monthly_dates:
        shares_bought = monthly_investment / close.loc[date]
        total_shares += shares_bought
        total_invested += monthly_investment
    
    # 計算目前市值
    current_value = total_shares * close.loc[date]
    portfolio_value.append(current_value)

df['DCA_Value'] = portfolio_value
df['DCA_Return'] = (df['DCA_Value'] - total_invested) / total_invested

# 比較
print(f"=== 定期定額績效 ===")
print(f"總投入: {total_invested:,} 元")
print(f"最終市值: {df['DCA_Value'].iloc[-1]:,.0f} 元")
print(f"總報酬率: {df['DCA_Return'].iloc[-1]*100:.2f}%")

三種策略最終比較

plt.figure(figsize=(14, 7))
plt.plot(df.index, df['Cum_Strategy'] * 100, label='黃金交叉策略', linewidth=2)
plt.plot(df.index, df['Cum_BuyHold'] * 100, label='買入持有', linewidth=2, linestyle='--')
plt.plot(df.index, df['DCA_Return'] * 100, label='定期定額', linewidth=2, linestyle=':')
plt.axhline(y=0, color='black', alpha=0.2)
plt.title('三種策略累積報酬率比較 (%)')
plt.xlabel('日期')
plt.ylabel('累積報酬率 (%)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()

使用 Vibe Coding 實作交易策略

🔥 【交易策略詠唱範例】 「請幫我回測「MACD 金叉死叉策略」: 1. 抓取 TSLA 過去 3 年的日資料。 2. 計算 MACD (12, 26, 9)。 3. 當 MACD 線向上突破訊號線時買進,向下突破時賣出。 4. 計算策略的總報酬率、夏普比率與最大回撤。 5. 畫出權益曲線與買賣點。 6. 與買入持有策略比較。」

本日總結

在本章中,你學到了:

  1. 黃金交叉策略:根據移動平均線的交叉產生交易信號
  2. 定期定額策略:固定金額定期買入
  3. 績效比較:總報酬率、年化報酬率、夏普比率、最大回撤
  4. 權益曲線:視覺化策略的盈虧變化
  5. 三種策略比較:了解不同策略的優劣

下一章,我們將使用回測框架來更專業地評估策略!

解鎖完整教學內容

本章為付費內容。加入專案即可解鎖超過 5000 字的深度解析,包含 10 個以上神級 Prompt 與真實 Source Code 範例!