Mean-Reversion: Aşırı Satışta Alma Stratejisi
Bollinger Bands ve RSI oversold kombinasyonuyla BIST'te ortalamaya dönüş stratejisini Python'da kuruyoruz — ve neden trend dönemlerinde bu sistemi kapatmak gerektiğini anlatıyoruz.
Mean-reversion'ı ilk uyguladığımda sonuçlar muhteşem geldi. Backtest kazanıyor, sinyal mantıklı görünüyor, her düşüşte alıp toparlamayı bekliyorsun. Sonra gerçek bir bear market gördüm. "Ucuz" gördüğüm şey daha da ucuz oldu, sonra daha da. Mean-reversion stratejisinin asıl dersi teknik değil, psikolojik: ortalamaya dönmesi garantisi yok, zamanlama belirsiz.
Ortalamaya Dönüş Mantığı
Mean-reversion şu varsayıma dayanır: fiyatlar ortalamalarından sapınca geri dönme eğilimi gösterir. Bu strateji trend following ile tam zıttır. Yanlış rejimdeki doğru strateji yanlış stratejiden daha tehlikeli — çünkü mantıklı geliyor.
BIST'te mean-reversion için en elverişli koşul: ekonomik istikrar dönemleri ve sektör rotasyonu.
Bollinger Bands + RSI Kombinasyonu
Bollinger Bands fiyatın standart sapma bazlı bantlar dışına çıktığında aşırılık sinyali verir. Ama Bollinger alt bandı tek başına güvenilmez. Güçlü bir düşüş trendinde fiyat alt bandın altında günlerce yürüyebilir.
RSI burada ikinci filtre görevi görüyor. RSI 30 altına indiğinde oversold koşul güçleniyor.
Python Kodu
import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
def bollinger_rsi_strateji(df, bb_period=20, bb_std=2, rsi_period=14, rsi_esik=35):
df = df.copy()
df["BB_Orta"] = df["Close"].rolling(bb_period).mean()
df["BB_Std"] = df["Close"].rolling(bb_period).std()
df["BB_Ust"] = df["BB_Orta"] + bb_std * df["BB_Std"]
df["BB_Alt"] = df["BB_Orta"] - bb_std * df["BB_Std"]
df["BB_B"] = (df["Close"] - df["BB_Alt"]) / (df["BB_Ust"] - df["BB_Alt"])
delta = df["Close"].diff()
gain = delta.clip(lower=0).rolling(rsi_period).mean()
loss = (-delta.clip(upper=0)).rolling(rsi_period).mean()
df["RSI"] = 100 - (100 / (1 + gain / loss))
df["AL"] = (df["BB_B"] < 0.05) & (df["RSI"] < rsi_esik)
df["SAT"] = df["Close"] >= df["BB_Orta"]
return df
ticker = "EREGL.IS"
df = yf.download(ticker, start="2021-01-01", end="2025-01-01", progress=False)
df.columns = df.columns.droplevel(1) if isinstance(df.columns, pd.MultiIndex) else df.columns
df = bollinger_rsi_strateji(df)
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(14, 9), sharex=True)
ax1.plot(df["Close"], color="black", linewidth=0.8, label="Kapanış")
ax1.plot(df["BB_Orta"], color="blue", linewidth=1, label="BB Orta (SMA20)", linestyle="--")
ax1.plot(df["BB_Ust"], color="gray", linewidth=0.8, label="BB Üst")
ax1.plot(df["BB_Alt"], color="gray", linewidth=0.8, label="BB Alt")
ax1.fill_between(df.index, df["BB_Alt"], df["BB_Ust"], alpha=0.05, color="blue")
al_gunleri = df[df["AL"]]
ax1.scatter(al_gunleri.index, al_gunleri["Close"], marker="^", color="green", s=100, zorder=5, label="AL")
ax1.set_title(f"{ticker} — Bollinger + RSI Mean-Reversion")
ax1.legend(fontsize=8); ax1.grid(alpha=0.3)
ax2.plot(df["RSI"], color="purple", linewidth=1)
ax2.axhline(35, color="green", linestyle="--", alpha=0.7, label="RSI Eşiği (35)")
ax2.fill_between(df.index, 0, 35, alpha=0.1, color="green")
ax2.set_ylabel("RSI"); ax2.legend(); ax2.grid(alpha=0.3)
plt.tight_layout()
plt.show()
Backtest Sonuçları
EREGL.IS ve SISE.IS ortalaması, 2021-2024, günlük veri, %0,15 komisyon dahil:
| Metrik | Değer |
|---|---|
| Toplam Getiri | %48.6 |
| Buy & Hold Getiri | %41.2 |
| Sharpe Oranı | 0.94 |
| Max Drawdown | %-26.4 |
| Win Rate | %61 |
| İşlem Sayısı | 31 |
| Profit Factor | 1.44 |
Bu sonuçlar geçmiş performansı gösterir, gelecek getiri garantisi vermez.
Stratejinin Çalışmadığı Yer: Trend Dönemleri
Bu strateji için en büyük risk trend dönemlerine girmiş hisseye mean-reversion uygulamak. Bunun için rejim filtresi şart. Ben basit bir kural kullanıyorum: XU100'ün 200 günlük SMA'sının üzerinde olduğu dönemlerde mean-reversion sistemini aktif tutuyorum. Altına indiğinde sistemi durduruyorum.
Sonuç
- Bollinger + RSI kombinasyonu oversold sinyalleri için güçlü başlangıç noktası.
- Strateji yatay ve hafif dalgalı piyasalarda iyi çalışır; güçlü trend dönemlerinde kapatılmalı.
- Max drawdown kontrol altına almak için rejim filtresi eklenmeli.
- Tek hisseye değil, bir sepete uygulamak volatiliteyi düşürür.
Bu yazıdaki analizler ve kodlar eğitim amaçlıdır; yatırım tavsiyesi değildir.