Python05.04.2026schedule3 min read

Python ile Teknik İndikatör Hesaplama — RSI, MACD, Bollinger, ATR

En yaygın dört teknik indikatörü ta-lib olmadan, sıfırdan Python'da hesaplıyoruz. Her indikatörün BIST'e özgü parametre önerileri ve görselleştirme dahil.

Yıllarca hazır kütüphanelerin ürettiği indikatör değerlerine güvendim. Bir gün aynı hisse için farklı iki platformda RSI değerlerinin örtüşmediğini fark ettim. O günden sonra her indikatörü bir kez sıfırdan yazmayı alışkanlık haline getirdim. Neyi hesapladığını bilmeden kullanmak, kör uçmak gibi.

Python Kod Geliştirme

Neden Sıfırdan?

ta-lib gibi kütüphaneler hızlı ama kurulumu zahmetli, bazı ortamlarda çalışmıyor. Daha önemlisi: kara kutu gibi kullanılıyor. RSI hesaplamasının iki farklı smoothing yöntemi var — Wilder's ve EMA bazlı. Hangisini kullandığınızı bilmeden sonuçları karşılaştıramazsınız.

Adım 1: Veri Hazırlığı

!pip install yfinance --quiet

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

ticker = "GARAN.IS"
df = yf.download(ticker, start="2022-01-01", end="2025-01-01", progress=False)

if isinstance(df.columns, pd.MultiIndex):
    df.columns = df.columns.droplevel(1)

df = df[df["Volume"] > 0].ffill().dropna()
df.index = pd.to_datetime(df.index)

print(f"{ticker} | {len(df)} gün | {df.index[0].date()} → {df.index[-1].date()}")

Adım 2: RSI — Göreceli Güç Endeksi

RSI, belirli bir penceredeki yükseliş ve düşüş güçlerini karşılaştırır.

def hesapla_rsi(close, period=14):
    delta = close.diff()
    kazanc = delta.clip(lower=0)
    kayip = (-delta).clip(lower=0)

    ort_kazanc = kazanc.ewm(alpha=1/period, adjust=False).mean()
    ort_kayip = kayip.ewm(alpha=1/period, adjust=False).mean()

    rs = ort_kazanc / ort_kayip
    rsi = 100 - (100 / (1 + rs))
    return rsi

df["RSI"] = hesapla_rsi(df["Close"], period=14)
print(df[["Close", "RSI"]].tail(5).round(2))

Adım 3: MACD — Hareketli Ortalama Yakınsama/Iraksama

MACD üç bileşenden oluşur: MACD çizgisi, sinyal çizgisi ve histogram.

def hesapla_macd(close, hizli=12, yavas=26, sinyal=9):
    ema_hizli = close.ewm(span=hizli, adjust=False).mean()
    ema_yavas = close.ewm(span=yavas, adjust=False).mean()

    macd_cizgi = ema_hizli - ema_yavas
    sinyal_cizgi = macd_cizgi.ewm(span=sinyal, adjust=False).mean()
    histogram = macd_cizgi - sinyal_cizgi

    return macd_cizgi, sinyal_cizgi, histogram

df["MACD"], df["MACDSinyal"], df["MACDHist"] = hesapla_macd(df["Close"])

Teknik Analiz Grafikleri

Adım 4: Bollinger Bands

Fiyatın standart sapma bazlı bantların dışına çıkmasını ölçer.

def hesapla_bollinger(close, period=20, std_carpan=2):
    orta = close.rolling(period).mean()
    std = close.rolling(period).std()
    ust = orta + std_carpan * std
    alt = orta - std_carpan * std
    b_yuzdesi = (close - alt) / (ust - alt)
    bant_genisligi = (ust - alt) / orta

    return orta, ust, alt, b_yuzdesi, bant_genisligi

df["BB_Orta"], df["BB_Ust"], df["BB_Alt"], df["BB_B"], df["BB_Genislik"] = \
    hesapla_bollinger(df["Close"])

Adım 5: ATR — Ortalama Gerçek Aralık

ATR volatiliteyi ölçer. Süpertrend ve dinamik stop-loss hesaplamalarının temel taşı.

def hesapla_atr(high, low, close, period=14):
    tr1 = high - low
    tr2 = (high - close.shift(1)).abs()
    tr3 = (low - close.shift(1)).abs()
    true_range = pd.concat([tr1, tr2, tr3], axis=1).max(axis=1)
    atr = true_range.ewm(alpha=1/period, adjust=False).mean()
    return atr

df["ATR"] = hesapla_atr(df["High"], df["Low"], df["Close"], period=14)
df["ATR_Pct"] = df["ATR"] / df["Close"] * 100

Adım 6: Dört İndikatörü Tek Grafik

fig = plt.figure(figsize=(14, 14))
gs = gridspec.GridSpec(4, 1, height_ratios=[3, 1, 1, 1], hspace=0.4)

son_300 = df.tail(300)

ax1 = fig.add_subplot(gs[0])
ax1.plot(son_300["Close"], color="black", linewidth=0.9, label="Kapanış")
ax1.plot(son_300["BB_Orta"], color="blue", linewidth=0.8, linestyle="--", label="BB Orta")
ax1.plot(son_300["BB_Ust"], color="gray", linewidth=0.7)
ax1.plot(son_300["BB_Alt"], color="gray", linewidth=0.7)
ax1.fill_between(son_300.index, son_300["BB_Alt"], son_300["BB_Ust"], alpha=0.05, color="blue")
ax1.set_title(f"{ticker} — RSI | MACD | Bollinger | ATR")
ax1.legend(fontsize=8); ax1.grid(alpha=0.3)

ax2 = fig.add_subplot(gs[1])
ax2.plot(son_300["RSI"], color="purple", linewidth=0.9)
ax2.axhline(70, color="red", linestyle="--", alpha=0.6)
ax2.axhline(30, color="green", linestyle="--", alpha=0.6)
ax2.set_ylabel("RSI"); ax2.set_ylim(0, 100); ax2.grid(alpha=0.3)

ax3 = fig.add_subplot(gs[2])
ax3.plot(son_300["MACD"], color="blue", linewidth=0.9, label="MACD")
ax3.plot(son_300["MACDSinyal"], color="orange", linewidth=0.9, label="Sinyal")
renkler = ["green" if v >= 0 else "red" for v in son_300["MACDHist"]]
ax3.bar(son_300.index, son_300["MACDHist"], color=renkler, alpha=0.6)
ax3.set_ylabel("MACD"); ax3.legend(fontsize=7); ax3.grid(alpha=0.3)

ax4 = fig.add_subplot(gs[3])
ax4.plot(son_300["ATR_Pct"], color="darkorange", linewidth=0.9)
ax4.fill_between(son_300.index, 0, son_300["ATR_Pct"], alpha=0.2, color="orange")
ax4.set_ylabel("ATR %"); ax4.grid(alpha=0.3)

plt.tight_layout()
plt.show()

Sonuç

  • RSI, MACD, Bollinger ve ATR'yi sıfırdan yazmak bir kez bile olsa yapılması gereken bir alıştırma.
  • BIST'te parametre seçimi önemli: yüksek volatilite dönemlerinde ATR period'u ve Bollinger std çarpanını artırmak daha sağlıklı sinyal üretiyor.
  • Bu indikatörlerin sınırı şu: hepsi gecikmeli — geçmiş fiyatları kullanarak hesaplanıyor.
  • Bir sonraki adım: bu indikatörleri Plotly ile interaktif grafiklere dönüştürmek.

Bu yazıdaki kodlar eğitim amaçlıdır; yatırım tavsiyesi değildir.