Portföy Volatilitesini Ölçmek: ATR ve Beta
ATR ile bireysel hisse riskini, beta ile piyasa duyarlılığını Python'da hesaplıyoruz. BIST'te volatilite rejimlerini tanıma ve portföy risk skorlaması dahil.
Risk yönetimini ciddiye almaya başlamadan önce şöyle düşünürdüm: "iyi hisse alırsan zaten risk az." Yanlış. İyi hisse bile yanlış volatilite rejiminde, yanlış büyüklükte tutulursa portföyü mahvedebilir. ATR ve beta bu dersi öğrettikten sonra her yeni pozisyon açmadan önce mutlaka baktığım iki gösterge oldu.
Neden İki Farklı Ölçüt?
ATR (Average True Range) mutlak volatiliteyi ölçer — hissenin kaç TL oynadığını. Pozisyon büyüklüğü hesaplarken ve stop-loss yerleştirirken kullanılır.
Beta ise göreli volatiliteyi ölçer — hissenin piyasaya (XU100) göre ne kadar oynadığını. Beta 1.5 olan hisse, endeks %10 düştüğünde ortalamada %15 düşer.
İkisi farklı soruları yanıtlıyor: ATR "bu hisse ne kadar oynar?" derken beta "piyasa düşünce bu hisse ne kadar acıtır?" diyor.
Adım 1: Veri Hazırlığı
!pip install yfinance --quiet
import yfinance as yf
import pandas as pd
import numpy as np
import plotly.graph_objects as go
semboller = ["THYAO.IS", "GARAN.IS", "ASELS.IS", "EREGL.IS", "SISE.IS"]
benchmark = "XU100.IS"
ham = yf.download(semboller + [benchmark],
start="2022-01-01", end="2025-01-01", progress=False)
kapanis = ham["Close"].copy()
kapanis.columns = [c.replace(".IS", "") for c in kapanis.columns]
high = ham["High"].copy()
low = ham["Low"].copy()
high.columns = [c.replace(".IS", "") for c in high.columns]
low.columns = [c.replace(".IS", "") for c in low.columns]
kapanis = kapanis[kapanis > 0].ffill().dropna()
high = high[high > 0].ffill().dropna()
low = low[low > 0].ffill().dropna()
print(f"Veri hazır: {len(kapanis)} gün, {len(semboller)} hisse + benchmark")
Adım 2: ATR Hesaplama ve Normalize Etme
def atr_hesapla(yuksek, dusuk, kapanis, period=14):
tr1 = yuksek - dusuk
tr2 = (yuksek - kapanis.shift(1)).abs()
tr3 = (dusuk - kapanis.shift(1)).abs()
true_range = pd.concat(
[tr1.stack(), tr2.stack(), tr3.stack()], axis=1
).max(axis=1).unstack()
atr = true_range.ewm(alpha=1/period, adjust=False).mean()
atr_pct = atr / kapanis * 100
return atr, atr_pct
hisse_adlari = [s.replace(".IS", "") for s in semboller]
atr, atr_pct = atr_hesapla(high[hisse_adlari], low[hisse_adlari], kapanis[hisse_adlari])
print("\nGüncel ATR Değerleri:")
for hisse in hisse_adlari:
son_atr_pct = atr_pct[hisse].iloc[-1]
seviye = "Yüksek" if son_atr_pct > 2.5 else ("Orta" if son_atr_pct > 1.5 else "Düşük")
print(f" {hisse:<10} ATR%: {son_atr_pct:.2f}% ({seviye})")
Adım 3: Beta Hesaplama
def beta_hesapla(hisse_getiri, piyasa_getiri, pencere=60):
kovaryans = hisse_getiri.rolling(pencere).cov(piyasa_getiri)
varyans = piyasa_getiri.rolling(pencere).var()
beta = kovaryans / varyans
return beta
getiriler = kapanis[hisse_adlari].pct_change().dropna()
bm_getiri = kapanis["XU100"].pct_change().dropna()
beta_df = pd.DataFrame(index=getiriler.index)
for hisse in hisse_adlari:
beta_df[hisse] = beta_hesapla(getiriler[hisse], bm_getiri)
print("\nGüncel Beta Değerleri (son 60 gün):")
for hisse in hisse_adlari:
son_beta = beta_df[hisse].iloc[-1]
if son_beta > 1.3:
yorum = "Agresif"
elif son_beta > 0.8:
yorum = "Normal"
else:
yorum = "Savunmacı"
print(f" {hisse:<10} Beta: {son_beta:.2f} ({yorum})")
Adım 4: Portföy Risk Skoru ve Görselleştirme
risk_skoru = atr_pct[hisse_adlari].iloc[-20:].mean() * beta_df[hisse_adlari].iloc[-20:].mean()
risk_skoru = risk_skoru.sort_values(ascending=False)
fig = go.Figure()
for hisse in hisse_adlari:
son_atr_pct = atr_pct[hisse].iloc[-1]
son_beta = beta_df[hisse].iloc[-1]
boyut = risk_skoru[hisse] * 20
fig.add_trace(go.Scatter(
x=[son_beta], y=[son_atr_pct],
mode="markers+text",
name=hisse, text=[hisse], textposition="top center",
marker=dict(size=max(boyut, 15), opacity=0.7)
))
fig.add_vline(x=1.0, line_dash="dash", line_color="gray", line_width=1)
fig.add_hline(y=2.0, line_dash="dash", line_color="gray", line_width=1)
fig.update_layout(
title="Portföy Risk Haritası: ATR% vs Beta",
xaxis_title="Beta (Piyasa Duyarlılığı)",
yaxis_title="ATR% (Mutlak Volatilite)",
plot_bgcolor="#fff", paper_bgcolor="#f8f9fa",
showlegend=False, height=450
)
fig.show()
Sonuç
- ATR ve beta farklı risk boyutlarını ölçüyor; ikisini birlikte kullanmak çok daha bütünlüklü bir tablo veriyor.
- BIST'te volatilite çok değişken — 2021 kur krizi döneminde ATR% iki-üç katına çıkmıştı.
- Bu analizin sınırı: korelasyon ihmal edildi. İki yüksek beta hisse portföyde aynı anda düşerse risk toplamak değil, katlamak demektir.
Bu yazıdaki kodlar eğitim amaçlıdır; yatırım tavsiyesi değildir.