用 Python 實(shí)現(xiàn)股票指數(shù)移動(dòng)平均線(xiàn)
移動(dòng)平均指標(biāo)用于各種交易策略,以發(fā)現(xiàn)價(jià)格數(shù)據(jù)的長(zhǎng)期趨勢(shì)。簡(jiǎn)單移動(dòng)平均線(xiàn)策略的一個(gè)潛在缺點(diǎn)是它們對(duì)所有價(jià)格的權(quán)重相同,而您可能希望最近的價(jià)格占有更大的比重。指數(shù)移動(dòng)平均線(xiàn) (EMA) 是實(shí)現(xiàn)這一目標(biāo)的一種方法。
下面我們通過(guò)代碼示例詳細(xì)介紹 EMA 的實(shí)現(xiàn),并將其與 SMA (簡(jiǎn)單移動(dòng)平均)進(jìn)行比較。
EMA 通過(guò)加權(quán)乘數(shù)賦予最新價(jià)格更多權(quán)重。這個(gè)乘數(shù)應(yīng)用于最后一個(gè)價(jià)格,因此它比其他數(shù)據(jù)點(diǎn)占移動(dòng)平均線(xiàn)更大的部分。EMA 是通過(guò)采用最近的價(jià)格(我們將其稱(chēng)為“時(shí)間 t 的價(jià)格”) 減去前一個(gè)時(shí)間段 (EMA_{t-1})。此差異由您將 EMA 設(shè)置為 (N) 并加回到 EMA_{t-1}的時(shí)間段數(shù)加權(quán)。在數(shù)學(xué)上,我們可以這樣寫(xiě):
你可能已經(jīng)注意到上面的等式有一個(gè)小問(wèn)題,它是如何開(kāi)始的?它參考了最后一個(gè)時(shí)期的 EMA,所以如果你進(jìn)行第一次計(jì)算,它參考的是什么?這通常可以通過(guò)替換簡(jiǎn)單移動(dòng)平均線(xiàn) (SMA) 來(lái)初始化計(jì)算來(lái)延緩,這樣您就可以在第一次之后的所有時(shí)間段構(gòu)建 EMA。
讓我們通過(guò)導(dǎo)入我們的包,用 Python 中的一個(gè)簡(jiǎn)單示例來(lái)展示它是如何工作的。
- import numpy as np
- import pandas as pd
- import yfinance as yf
- import matplotlib.pyplot as plt
從這里開(kāi)始,我們將構(gòu)建兩個(gè)函數(shù)來(lái)協(xié)同工作并計(jì)算我們的指標(biāo)。第一個(gè)函數(shù)將是我們上面概述的公式的簡(jiǎn)單實(shí)現(xiàn):
- def _calcEMA(P, last_ema, N):
- return (P - last_ema) * (2 / (N + 1)) + last_ema
第二個(gè)函數(shù)將計(jì)算我們所有數(shù)據(jù)的 EMA,首先使用 SMA 對(duì)其進(jìn)行初始化,然后迭代我們的數(shù)據(jù)以使用我們的 SMA 列中的值更新每個(gè)后續(xù)條目,或者調(diào)用我們上面定義的 _calcEMA 函數(shù)來(lái)處理大于 N的值。
- def calcEMA(data, N):
- # Initialize series
- data['SMA_' + str(N)] = data['Close'].rolling(N).mean()
- ema = np.zeros(len(data))
- for i, _row in enumerate(data.iterrows()):
- row = _row[1]
- if i < N:
- ema[i] += row['SMA_' + str(N)]
- else:
- ema[i] += _calcEMA(row['Close'], ema[i-1], N)
- data['EMA_' + str(N)] = ema.copy()
- return data
現(xiàn)在,讓我們獲取一些數(shù)據(jù),看看它是如何工作的。我們將拉出比回測(cè)更短的時(shí)間段,并比較 EMA 和 SMA 的 10、50 和 100 天。
- ticker = 'BABA'
- yfyfObj = yf.Ticker(ticker)
- data = yfObj.history(ticker, start='2018-01-01', end='2020-12-31')
- N = [10, 50, 100]
- _ = [calcEMA(data, n) for n in N]
- colors = plt.rcParams['axes.prop_cycle'].by_key()['color']
- fig, ax = plt.subplots(figsize=(18, 8))
- ax.plot(data['Close'], label='Close')
- for i, n in enumerate(N, 1):
- ax.plot(data[f'EMA_{n}'], label=f'EMA-{n}', color=colors[i])
- ax.plot(data[f'SMA_{n}'], label=f'SMA-{n}', color=colors[i], linestyle=':')
- ax.legend()
- ax.set_title(f'EMA and Closing Price Comparison for {ticker}')
- plt.show()
您可以在上圖中看到,EMA 比 SMA 對(duì)最近的變化更敏感。較短的時(shí)間范圍也比較長(zhǎng)的時(shí)間范圍更具響應(yīng)性,較長(zhǎng)的時(shí)間范圍具有可以追溯到幾個(gè)月或更長(zhǎng)時(shí)間的價(jià)格“記憶”。
所有類(lèi)型的移動(dòng)平均線(xiàn)都是滯后指標(biāo),這意味著它們只能告訴您價(jià)格中已經(jīng)發(fā)生了什么。然而,這并不意味著它們不能用于識(shí)別趨勢(shì)和制定使用一個(gè)或多個(gè)移動(dòng)平均指標(biāo)的策略。如果您有想法,請(qǐng)繼續(xù)進(jìn)行測(cè)試,看看如何結(jié)合 EMA、SMA 和其他值來(lái)開(kāi)發(fā)新的盈利交易策略。



























