Üstel Ağırlıklı Hareketli Ortalama
Finansal analizde kullanılan standart bir teknik olan ewm(span=) ile üstel yumuşatma uygulayarak güncel değerlere daha fazla ağırlık verin.
Üstel Ağırlıklı Hareketli Ortalama, CoddyKit'te ücretsiz bir Pandas & NumPy Academy dersidir. Bu, 4 dersinin 3. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, Pandas & NumPy Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. Pandas & NumPy Academy kursu toplamda 4 dersten oluşur.
Bu dersin bazı bölümleri henüz çevrilmemiş olup İngilizce olarak gösterilmektedir.
The Problem with Simple Moving Averages
A simple moving average treats all n observations in the window equally — a price from 30 days ago contributes the same as yesterday's price. But for predicting near-term values, recent observations are more informative than old ones. An Exponentially Weighted Moving Average (EWMA) solves this by assigning exponentially decreasing weights to older observations: yesterday counts the most, the day before counts slightly less, and so on back to the beginning of the series.
import pandas as pd
import numpy as np
np.random.seed(42)
prices = pd.Series(
100 + np.cumsum(np.random.normal(0.5, 2, 30)),
index=pd.date_range('2024-01-01', periods=30)
)
df = pd.DataFrame({'price': prices})
df['SMA_7'] = df['price'].rolling(7).mean()
df['EWM_span7'] = df['price'].ewm(span=7).mean()
print(df.tail(5).round(2))How EWMA Weighting Works
EWMA computes each value as a weighted combination of the current observation and the previous EWMA: EWM_t = alpha * x_t + (1 - alpha) * EWM_{t-1}. The alpha (smoothing factor) determines how quickly weights decay — a large alpha (close to 1) responds quickly to recent changes (less smoothing), a small alpha (close to 0) is slow to respond (more smoothing). The weights form a geometric series: the most recent value has weight alpha, the previous has alpha*(1-alpha), and so on.
import numpy as np
# Manually show EWMA weights
alpha = 0.3
n_points = 8
weights = [alpha * (1 - alpha)**i for i in range(n_points)]
print(f'Alpha = {alpha}')
print(f'Weights (most recent first):')
for i, w in enumerate(weights):
print(f' t-{i}: {w:.4f}')
print(f'Sum of shown weights: {sum(weights):.4f} (converges to 1.0)')The ewm() Method and span Parameter
Pandas implements EWMA through Series.ewm(). The most intuitive parameter is span, which is analogous to a simple moving average window: alpha = 2 / (span + 1). A span of 10 approximately corresponds to a 10-period SMA but with exponentially decaying weights instead of equal weights. Use ewm(span=n).mean() to get the EWMA, and ewm(span=n).std() for exponentially weighted volatility.
import pandas as pd
import numpy as np
np.random.seed(0)
data = pd.Series(
np.random.normal(100, 10, 50),
index=pd.date_range('2024-01-01', periods=50)
)
df = pd.DataFrame({'value': data})
df['EWM_3'] = df['value'].ewm(span=3).mean()
df['EWM_10'] = df['value'].ewm(span=10).mean()
df['EWM_20'] = df['value'].ewm(span=20).mean()
print('Alpha values:')
for span in [3, 10, 20]:
alpha = 2 / (span + 1)
print(f' span={span} → alpha={alpha:.3f}')
print(df.tail(5).round(2))The halflife Parameter
The halflife parameter defines how many periods it takes for the weight to decrease by half. If halflife=5, a value from 5 periods ago has half the weight of the current value. The relationship is: alpha = 1 - exp(log(0.5) / halflife). Halflife is often more intuitive than span or alpha because it directly expresses the 'memory' of the average in business terms — for example, 'prices from 2 weeks ago should have half the influence of today's price'.
import pandas as pd
import numpy as np
np.random.seed(5)
prices = pd.Series(
100 + np.cumsum(np.random.normal(0, 2, 30)),
index=pd.date_range('2024-01-01', periods=30)
)
df = pd.DataFrame({'price': prices})
# halflife=5: weight halves every 5 days
df['EWM_hl5'] = df['price'].ewm(halflife=5).mean()
# halflife=14: weight halves every 14 days (longer memory)
df['EWM_hl14'] = df['price'].ewm(halflife=14).mean()
print(df.tail(5).round(2))The alpha Parameter Directly
You can also set the smoothing factor directly with ewm(alpha=). Alpha must be between 0 and 1 (exclusive). A high alpha like 0.8 gives very little smoothing — the EWMA tracks the raw signal closely. A low alpha like 0.1 gives heavy smoothing — the EWMA changes slowly and lags behind sudden shifts. Choosing the right alpha depends on the trade-off between responsiveness (detecting real trend changes quickly) and stability (ignoring random noise).
import pandas as pd
import numpy as np
np.random.seed(3)
data = pd.Series(
[100]*20 + [120]*20, # sudden level shift at row 20
dtype=float
) + np.random.normal(0, 2, 40)
df = pd.DataFrame({'signal': data})
df['alpha_0.1'] = df['signal'].ewm(alpha=0.1).mean() # slow
df['alpha_0.5'] = df['signal'].ewm(alpha=0.5).mean() # medium
df['alpha_0.9'] = df['signal'].ewm(alpha=0.9).mean() # fast
print('After the level shift (rows 20-25):')
print(df.iloc[18:26].round(2))EWMA for Volatility: ewm().std()
ewm(span=).std() computes an exponentially weighted standard deviation. This is the basis of the EWMA volatility model used in financial risk management (also known as the RiskMetrics model with decay factor lambda=0.94). Exponentially weighted volatility responds faster to volatility spikes than a simple rolling std because it assigns more weight to recent high-variance observations.
import pandas as pd
import numpy as np
np.random.seed(42)
# Simulate returns: quiet period then volatile period
returns = pd.Series(
np.concatenate([
np.random.normal(0, 0.01, 60),
np.random.normal(0, 0.04, 60) # 4x more volatile
]),
index=pd.date_range('2024-01-01', periods=120)
)
df = pd.DataFrame({'returns': returns})
df['rolling_vol'] = df['returns'].rolling(20).std()
df['ewm_vol'] = df['returns'].ewm(span=20).std()
print('Volatility comparison (transition at row 60):')
print(df.iloc[58:65].round(5))MACD: Combining Two EWMAs
The MACD (Moving Average Convergence Divergence) is a classic financial indicator built from two EWMAs. It is the difference between a fast (short-span) EWMA and a slow (long-span) EWMA of the price. When the MACD crosses zero from below, it signals potential upward momentum (a buy signal); crossing from above signals downward momentum. MACD is a perfect example of applying two EWMAs to derive a derived indicator.
import pandas as pd
import numpy as np
np.random.seed(7)
prices = pd.Series(
100 + np.cumsum(np.random.normal(0.3, 2, 100)),
index=pd.date_range('2024-01-01', periods=100)
)
df = pd.DataFrame({'price': prices})
df['EMA_12'] = df['price'].ewm(span=12).mean() # fast
df['EMA_26'] = df['price'].ewm(span=26).mean() # slow
df['MACD'] = df['EMA_12'] - df['EMA_26']
df['Signal'] = df['MACD'].ewm(span=9).mean() # signal line
print('MACD values (last 8 rows):')
print(df[['price', 'MACD', 'Signal']].tail(8).round(2))EWMA with Time-Based Halflife
Pandas 1.1+ supports specifying halflife, span, and com as time offsets (e.g. halflife='7D') when working with a DatetimeIndex. This enables proper EWMA on non-uniform time series — for example, if you have hourly data with gaps on weekends, a halflife of '7D' means the weight truly halves every 7 calendar days regardless of the number of rows in that period.
import pandas as pd
import numpy as np
np.random.seed(0)
# Business-day data (no weekends)
biz_dates = pd.bdate_range('2024-01-01', periods=20)
prices = pd.Series(100 + np.cumsum(np.random.randn(20)), index=biz_dates)
# halflife as a time offset (7 calendar days)
ewm_7d = prices.ewm(halflife='7D', times=biz_dates).mean()
# halflife as row count (7 rows)
ewm_7rows = prices.ewm(halflife=7).mean()
df = pd.DataFrame({'price': prices, 'hl_7D': ewm_7d, 'hl_7rows': ewm_7rows})
print(df.round(2))Choosing Between EWMA, Rolling, and Expanding
Summary of when to use each:
- Rolling(n).mean(): all n recent observations equally weighted — good for simple trailing metrics and when all recent periods matter equally.
- ewm(span=n).mean(): exponentially weighted — best when you want smoothing that responds more to recent changes, commonly used in finance and signal processing.
- expanding().mean(): all historical data with equal weight — best for YTD or all-time statistics where forgetting old data is not acceptable.
Visualising EWMA vs SMA
Plotting EWMA and SMA together on a time series chart makes the difference in their responsiveness visible. The EWMA reacts more quickly to sudden level changes because it has not 'forgotten' all previous observations — the short-span EWMA will turn faster than an SMA with the same nominal window. This makes EWMA preferable in forecasting applications where capturing trend direction quickly is more valuable than maximum noise reduction.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
prices = pd.Series(
np.concatenate([
100 + np.cumsum(np.random.normal(0.3, 1.5, 50)),
130 + np.cumsum(np.random.normal(-0.3, 1.5, 50))
]),
index=pd.date_range('2024-01-01', periods=100)
)
df = pd.DataFrame({'price': prices})
df['SMA_10'] = df['price'].rolling(10).mean()
df['EWMA_10'] = df['price'].ewm(span=10).mean()
df.plot(figsize=(12, 5), title='SMA vs EWMA — EWMA reacts faster to trend reversals')
plt.ylabel('Price')
plt.axvline(x=df.index[50], color='red', linestyle='--', label='Trend change')
plt.legend()
plt.show()EWMA in Business Applications
Beyond finance, EWMA is widely used in product analytics and operations: customer lifetime value smoothing (recent behaviour predicts future spend better than old behaviour), server latency monitoring (an exponentially smoothed latency metric sounds false alarms faster than a rolling mean), and inventory demand forecasting (recent sales weeks should outweigh data from six months ago). The universal principle is: wherever recency matters, EWMA outperforms simple averaging.
Quick Check
Test your understanding of exponentially weighted moving averages from this lesson.
Lesson Recap
In this lesson you learned: ewm(span=) applies exponentially decaying weights so recent observations matter more, alpha controls responsiveness (high = fast, low = smooth), and the halflife parameter expresses memory in business-meaningful terms. EWMA outperforms SMA when detecting trend reversals quickly is important. Next up we explore rank and percentile calculations within groups using groupby().rank() and pd.qcut.
Sıkça Sorulan Sorular
“Üstel Ağırlıklı Hareketli Ortalama” dersi ücretsiz mi?
Evet — “Üstel Ağırlıklı Hareketli Ortalama” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve Pandas & NumPy Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. Pandas & NumPy Academy kursu toplamda 4 dersten oluşur.
“Üstel Ağırlıklı Hareketli Ortalama” dersinde ne öğreneceğim?
Finansal analizde kullanılan standart bir teknik olan ewm(span=) ile üstel yumuşatma uygulayarak güncel değerlere daha fazla ağırlık verin. Pandas & NumPy Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
Pandas & NumPy Academy öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te Pandas & NumPy Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 3. dersidir.
“Üstel Ağırlıklı Hareketli Ortalama” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu Pandas & NumPy Academy dersinde kod yazıp çalıştırabilir miyim?
Evet. Her Pandas & NumPy Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- Kayan Pencereler
- Genişleyen Pencereler
- Üstel Ağırlıklı Hareketli Ortalama
- Gruplar İçinde Sıra ve Yüzdelik Dilim