Lab 2 實作:SMA 與 EMA 平滑均線的 Python 實戰|Quant Theory 第 19 講筆記

第 19 課・共 34 課

⚠️ 本站內容僅作教育用途,不構成投資建議。投資涉及風險,作出任何投資決定前請諮詢持牌專業人士。
目錄

這是 Liu Peng 大學級量化交易課程第二個實作 lab 的筆記,主題是以 Python 實作簡單移動平均線 SMA 與指數移動平均線 EMA。兩條均線的公式推導與平滑原理,第 11 講已有完整講解(詳見移動平均線與雙均線趨勢跟隨策略|第 11 課);本 lab 把理論落地:用 yfinance 下載蘋果公司(AAPL)2022 年起的日線數據,以 pandas 的 rolling 與 ewm 函數分別計算兩種均線,並逐步驗證結果。

學習重點

詳細筆記

數據準備:yfinance 下載與日期索引

講者先用 yfinance 下載蘋果公司的日線數據,範圍由 2022 年 1 月初至 2023 年初,約一年的交易日數據。下載所得是一個 pandas DataFrame,包含開市、最高、最低、收市、調整後收市價 Adjusted Close 與成交量六欄,與一般行情軟件的 OHLCV 結構一致。

下載後有一個容易忽略但十分重要的步驟:把 DataFrame 的索引轉換為 datetime 格式。yfinance 回傳的索引預設未必是標準日期時間型態;講者指出,轉換之後 pandas 才「聰明」到能識別索引是日期,繪圖時自動把時間軸聚合到月份層級,圖表刻度才會顯示為 2022-01、2022-03 等月份標籤,而不是逐日擠滿整條橫軸。這一步不改變任何數據,純粹是讓後續的視覺化與時間序列操作能正確運作。

其後的分析只聚焦調整後收市價一欄——均線一般以收市價為輸入,而調整後收市價已剔除拆股、股息等公司行動造成的跳空,是量化計算的標準選擇。把它繪出來,可見 AAPL 在該年內由約 180 美元水平反覆回落至 130 美元附近,途中多次急升急跌——這正是需要用均線平滑的典型序列:長線方向被大量短期噪音遮蔽,肉眼難以判讀趨勢。

AAPL 調整後收市價日線圖:索引轉為 datetime 後,時間軸自動聚合至月份層級(截圖出自原片(Liu Peng))

SMA 實作:rolling 加 mean

簡單移動平均線的定義,是當期連同過去 $M-1$ 期價格的等權重平均:

$$\mathrm{SMA}_t = \frac{S_{t-(M-1)} + \cdots + S_{t-1} + S_t}{M}$$

程式層面,pandas 的 rolling 方法把窗口沿序列逐期滾動,再套 mean 對每個窗口求平均。講者以窗口 3 為例:先指定 window = 3,再動態拼出新欄名稱 SMA-3——欄名跟着窗口大小走,日後改參數時不用手動改名。新欄每個值是當期連同前兩期收市價的平均:窗口框住該行及之前兩行共三個數據點,取其均值作為該行的均線值。最後把調整後收市價與新均線兩欄抽出,組成新的 DataFrame 展示:

# 摘錄自原片教學
window = 3
SMA1 = "SMA-" + str(window)
df[SMA1] = df['Adj Close'].rolling(window).mean()
colnames = ["Adj Close", SMA1]
df2 = df[colnames]
df2.head()

輸出的表格清楚顯示:首兩行的 SMA-3 是 NaN,因為第一、二期之前沒有足夠歷史數據填滿窗口——窗口要求三個點,期初只有一兩個點可用,平均值在定義上不存在。由第三期起,窗口首次填滿,均線開始有值。

講者即場做驗證:取出調整後收市價的首三個值手動求平均,結果與第三行的 SMA-3 完全一致(約 177.84),證明 rolling 的計算邏輯正確。這種「用函數算出來,再手動驗算首幾個值」的習慣,貫穿整個 lab——函數是黑盒,只有對照過定義,才能確定參數沒有用錯。

SMA-3 的程式碼與輸出表格:首兩行為 NaN,第三期起是三期價格的等權重平均(截圖出自原片(Liu Peng))

min_periods:期初空值的處理

首兩行的 NaN 代表「窗口尚未填滿」,在後續計算中不可用。講者示範,若想在期初「有多少用多少」,可以放寬要求:在 rolling 中加入 min_periods=1,意思是窗口內只要至少有一個數據就計算,不再堅持填滿整個窗口。

效果立竿見影:第一行的窗口只有一個值,平均值等於價格本身;第二行的窗口有兩個值,均線是首兩個價格的平均;第三期起窗口填滿,回復正常的三期平均。這是實作上對初始值的特殊處理,用處是保留期初數據供後續運算——例如序列較短時,丟掉期初十幾行可能損失可觀的樣本。但講者也提示了代價:這些期初值只由一至兩個數據點構成,平均的統計基礎薄弱,平滑效果近乎沒有,解讀時要留意。

窗口大小的平滑效果對比

講者接着比較兩條 SMA,把平滑效果視覺化。先看 SMA-3:紅線疊加在原價格上幾乎形影不離,走勢緊貼價格,仍保留大量短期上落——窗口只有三期,平均效應有限,平滑作用僅止於削去最極端的單日跳動。

把窗口加大到 20,畫面截然不同。SMA-20 每個點都要動用過去 20 期價格取平均,單日的大升大跌被其餘 19 期攤薄,短期震盪大幅消減,曲線明顯圓滑,只餘中期走向。這正正印證第 11 講的推導:平滑程度與反應速度是一對取捨——窗口越長,曲線越平滑,對最新價格變化的反應也越慢;窗口越短,反應越快,但均線與原價格分別不大,失去平滑意義。

EMA 實作:ewm 與 alpha

指數移動平均線的遞推定義是:

$$\mathrm{EMA}_t = \alpha S_t + (1-\alpha)\,\mathrm{EMA}_{t-1}$$

當期值佔權重 $\alpha$,過去的運行均值佔 $(1-\alpha)$——本質是當期觀測與歷史記憶之間的權衡。把遞推逐層展開,可見所有歷史數據點都納入計算,只是權重按幾何級數遞減:

$$\mathrm{EMA}_t = \alpha\left[S_t + (1-\alpha)S_{t-1} + (1-\alpha)^2 S_{t-2} + \cdots\right]$$

講者強調,EMA 沒有明確的窗口設定:越遠的歷史數據權重越小,呈指數式衰減,但理論上永不為零。這與 SMA 的「窗口之內等權、窗口之外歸零」形成鮮明對比。

實作上用 pandas 的 ewm(exponentially weighted moving)函數。這個函數有多個參數可調——例如可以改用窗口長度(span)或半衰期(halflife)取代 $\alpha$ 來定義權重——而為了完全對應第 11 講的遞推公式,講者選擇直接指定 $\alpha$,並設定 adjust=False

# 摘錄自原片教學
alpha = 0.1
df2['EWM_' + str(alpha)] = df2['Adj Close'].ewm(alpha=alpha, adjust=False).mean()

與 SMA 不同,EMA 的輸出由第一期起已有數值——因為它動用全部歷史數據而非固定窗口,期初不存在「窗口未填滿」的問題,第一期的 EMA 就是價格本身。

講者同樣即場驗證:以 $\alpha=0.1$ 手動計算第二期的值,即 $0.1$ 乘第二期收市價加上 \$0.9$ 乘第一期收市價,得出約 180.73,與 ewm 輸出的第二期完全一致。換言之,遞推公式、手算結果與函數輸出三方對照無誤,才算真正完成這一步實作。

EMA 的程式碼、輸出表格與手動驗證:0.1 乘當期價加 0.9 乘前期值,結果與 ewm 輸出一致(截圖出自原片(Liu Peng))

參數對比與策略預告

調整 $\alpha$ 可產生不同的權重方案。講者再算一條 $\alpha=0.5$ 的 EMA:一半權重給當期價格,一半給歷史均值。他用同一個驗證方法核對過新序列的數值,確認無誤才繼續。這條 EWM-0.5 的曲線自然緊貼價格,是圖中與原價格最貼近的一條平滑線;$\alpha=0.1$ 則把九成權重交給歷史均值,平滑得多,滯後也更明顯。

最後把原價格、SMA-3、SMA-20 與兩條 EMA 同圖繪出。五條曲線並排,參數規格與平滑程度的關係一目了然:貼近價格的一端是 SMA-3 與 EWM-0.5,平滑的一端是 SMA-20 與 EWM-0.1。不同參數、不同權重方案,得出的平滑曲線就不同——沒有哪一條「最正確」,只有哪一條最配合分析目的。

五線同圖:原價格、SMA-3、SMA-20、EWM-0.1 與 EWM-0.5 的平滑程度對比(截圖出自原片(Liu Peng))

講者在結尾預告:這些平滑曲線會進入日後的策略構建部分——取兩條平滑曲線,當兩線出現交叉 Crossover 時產生交易訊號,並按訊號執行交易動作。本 lab 計算均線的功夫,正是為那一刻鋪路;屆時快線與慢線的選擇,就是今天比較過的各種參數組合。

🙏 覺得內容有用?本站所有內容免費提供,使用推薦碼開戶就是支持我們繼續營運的最大鼓勵:

ZA Bank 邀請碼 P20923 —— 你享 HKD 2,000 迎新獎賞,本站獲得營運支持。 立即開戶 → (聯盟連結|投資涉及風險,受條款及細則約束,此資料僅可於香港境內分發)

欣利克的看法

名詞解釋

常見問題 FAQ

為什麼 SMA 計算結果的開頭幾行是 NaN?

因為窗口尚未填滿。以窗口 $M$ 計算時,首 $M-1$ 期之前沒有足夠歷史數據,平均值在定義上不存在,pandas 以 NaN 標示。若設 min_periods=1,期初會以不足額的數據先行計算,但那些值的平滑意義有限。

ewm 的 adjust 參數應該怎樣設定?

要重現教科書的遞推公式 $\mathrm{EMA}_t = \alpha S_t + (1-\alpha)\,\mathrm{EMA}_{t-1}$,應設 adjust=False。預設的 adjust=True 會對整條序列做歸一化加權平均,期初數值會與遞推定義不同,兩者不可混用。

EMA 的 α 與 SMA 的窗口大小有沒有對應關係?

坊間常用 $\alpha \approx 2/(M+1)$ 作粗略換算,例如 $\alpha=0.1$ 約對應 19 期 SMA 的「快慢」。但兩者權重結構不同——SMA 窗口外權重為零,EMA 權重指數衰減且無限延伸,這個換算只宜當參考。

均線參數(窗口或 α)應該如何選擇?

沒有標準答案。窗口小或 $\alpha$ 大,曲線貼近價格、訊號多但雜訊也多;窗口大或 $\alpha$ 小,曲線平滑但滯後。參數對策略表現影響極大,須配合回測驗證,並警惕過度擬合歷史數據的風險。

原影片

本文整理自以下影片,版權屬原創作者所有,建議配合原片觀看:

來源:https://www.youtube.com/watch?v=nRNa0eElb50

🏦 ZA Bank 開戶優惠

本站所有內容免費提供。多使用網站的推薦碼,就是對我們繼續製作優質內容的最大鼓勵和支持 🙏

去 ZA Bank 開戶,享價值 HKD 2,000 迎新獎賞,仲有機會享 USD 30 指定美股兌換券!

  • 💛 全線上開戶,無需前往分行
  • 💛 無最低存款要求,零賬戶管理費
  • 💛 24x7 銀行服務

專屬邀請碼:P20923

立即開戶 → (聯盟連結)