Kripto için Markowitz Portföy Teorisi: Sıfırdan Zirveye

Python ile optimal kripto portföyleri oluşturma - çünkü YOLO bir strateji değildir. Nobel Ödüllü portföy teorisini pratik Python kod örnekleriyle kripto yatırımlarına nasıl uygulayacağınızı öğrenin.

Python ile optimal kripto portföyleri oluşturma - çünkü YOLO bir strateji değildir

Markowitz Portföy Teorisi Markowitz Portföy Teorisi: Belirli bir risk düzeyi için getirileri maksimize etmek amacıyla dijital varlıklara uygulanan matematiksel optimizasyon.


Giriş: Kripto Portföyünüz Neden Matematiğe İhtiyaç Duyar (Sezgiye Değil)

Hey kripto tutkunları! 👋

Elon tweet attığı için tüm birikimini DOGE'a yatırdığın o anı hatırlıyor musun? Ya da son çöküşte paniğe kapılıp her şeyi sattığın zamanı? Evet, hepimiz orada bulunduk. Bugün portföyünü (ve aklını) kurtarabilecek bir şeyden bahsedeceğiz: Markowitz Portföy Teorisi.

Harry Markowitz bu konu için 1990 yılında gerçekten Nobel Ödülü kazandı. Temel fikir? Herhangi bir risk düzeyi için mümkün olan en iyi getirileri elde etmek amacıyla portföyünü matematiksel olarak optimize edebilirsin. Yatırımların için gözleri kapalı sürmek yerine GPS kullanmak gibi.

Temel Kavram: Risk ve Getiri (Sonsuz Dans)

Koda dalmadan önce ne ile uğraştığımızı anlayalım:

  • Beklenen Getiri: Ne kadar para kazanmayı beklediğin
  • Risk (Oynaklık): Portföy değerinin ne kadar dalgalandığı
  • Korelasyon: Farklı varlıkların birlikte nasıl hareket ettiği

Sihir, tam olarak eş zamanlı hareket etmeyen varlıkları birleştirdiğinde ortaya çıkar. Bitcoin çöktüğünde, bazı DeFi tokenleri daha iyi dayanıklılık gösterebilir. İşte bu sizin için çalışan çeşitlendirmedir.

Risk ve Getiri Risk ve Getiri: Optimal geometrik ortalama getiriyi elde etmek için oynak yüksek verimli varlıkları istikrarlı bir temel ile dengeleme.

Python Ortamını Kurma

Her şeyden önce - araçlarımızı hazırlayalım:

# Kripto portföy optimizasyonumuz için temel kütüphaneler
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.optimize import minimize
import yfinance as yf
import warnings
warnings.filterwarnings('ignore')

# Grafik stilini ayarla
plt.style.use('dark_background')
sns.set_palette("husl")

Seviye 1: Küçük Adımlar - Basit Portföy Matematiği

Temel bilgilerle başlayalım. Basit 2 varlıklı bir portföy için getiri ve riski hesaplayacağız.

def get_crypto_data(symbols, period="1y"):
    """
    Yahoo Finance'den kripto verisi çek
    symbols: kripto sembollerinin listesi (örn. ['BTC-USD', 'ETH-USD'])
    period: veri için zaman dilimi
    """
    data = yf.download(symbols, period=period)['Adj Close']
    return data

# Bitcoin ve Ethereum verilerini al
crypto_symbols = ['BTC-USD', 'ETH-USD']
prices = get_crypto_data(crypto_symbols)

# Günlük getirileri hesapla
returns = prices.pct_change().dropna()
print("Günlük Getiri Önizlemesi:")
print(returns.head())

Şimdi bazı temel portföy metriklerini hesaplayalım:

def portfolio_performance(weights, returns):
    """
    Portföy getirisi ve oynaklığını hesapla
    weights: portföy ağırlıklarının dizisi
    returns: varlık getirilerinin veri çerçevesi
    """
    # Portföy getirisi (yıllıklandırılmış)
    portfolio_return = np.sum(returns.mean() * weights) * 252

    # Portföy oynaklığı (yıllıklandırılmış)
    portfolio_vol = np.sqrt(np.dot(weights.T, np.dot(returns.cov() * 252, weights)))

    return portfolio_return, portfolio_vol

# Örnek: %50 BTC, %50 ETH
weights_5050 = np.array([0.5, 0.5])
ret_5050, vol_5050 = portfolio_performance(weights_5050, returns)

print(f"50/50 Portföy:")
print(f"Beklenen Yıllık Getiri: {ret_5050:.2%}")
print(f"Yıllık Oynaklık: {vol_5050:.2%}")
print(f"Sharpe Oranı: {ret_5050/vol_5050:.3f}")

Seviye 2: Ciddiye Alma - Etkin Sınır

Artık pişiriyoruz! Etkin sınır, mümkün olan tüm optimal portföyleri gösterir. Her nokta, belirli bir risk düzeyi için mümkün olan en iyi getiriyi temsil eder.

def generate_random_portfolios(returns, num_portfolios=10000):
    """
    Rastgele portföy kombinasyonları oluştur
    """
    num_assets = len(returns.columns)
    results = np.zeros((4, num_portfolios))

    for i in range(num_portfolios):
        # Rastgele ağırlıklar oluştur
        weights = np.random.random(num_assets)
        weights /= np.sum(weights)  # Toplamı 1'e normalize et

        # Portföy metriklerini hesapla
        portfolio_return, portfolio_vol = portfolio_performance(weights, returns)
        sharpe_ratio = portfolio_return / portfolio_vol

        # Sonuçları sakla
        results[0,i] = portfolio_return
        results[1,i] = portfolio_vol
        results[2,i] = sharpe_ratio
        results[3,i:] = weights

    return results

# 10.000 rastgele portföy oluştur
results = generate_random_portfolios(returns)

# Daha kolay işleme için bir veri çerçevesi oluştur
portfolio_results = pd.DataFrame({
    'Returns': results[0],
    'Volatility': results[1],
    'Sharpe_Ratio': results[2]
})

# Etkin sınırı çiz
plt.figure(figsize=(12, 8))
scatter = plt.scatter(portfolio_results['Volatility'],
                     portfolio_results['Returns'],
                     c=portfolio_results['Sharpe_Ratio'],
                     cmap='viridis', alpha=0.6)
plt.colorbar(scatter, label='Sharpe Oranı')
plt.xlabel('Oynaklık (Risk)')
plt.ylabel('Beklenen Getiri')
plt.title('Etkin Sınır - Rastgele Portföyler')
plt.show()

Etkin Sınır Etkin Sınır: Belirli bir risk düzeyi için mümkün olan maksimum beklenen getiriyi temsil eden eğri.

Seviye 3: Optimizasyon Ustası - Mükemmel Portföyü Bulmak

Rastgele örnekleme eğlenceli, ancak matematiksel olarak optimal çözümü istiyoruz. Büyük silahları çıkarma zamanı - scipy optimizasyonu!

def negative_sharpe_ratio(weights, returns, risk_free_rate=0.02):
    """
    Negatif Sharpe oranını hesapla (bunu minimize ediyoruz)
    """
    portfolio_return, portfolio_vol = portfolio_performance(weights, returns)
    sharpe = (portfolio_return - risk_free_rate) / portfolio_vol
    return -sharpe

def minimize_volatility(weights, returns):
    """
    Portföy oynaklığını hesapla (bunu minimize ediyoruz)
    """
    _, portfolio_vol = portfolio_performance(weights, returns)
    return portfolio_vol

def portfolio_return_objective(weights, returns):
    """
    Portföy getirisini hesapla (bunu maksimize ediyoruz)
    """
    portfolio_return, _ = portfolio_performance(weights, returns)
    return -portfolio_return  # Minimize ettiğimiz için negatif

def optimize_portfolio(returns, objective='sharpe', target_return=None):
    """
    Farklı hedeflere göre portföyü optimize et
    """
    num_assets = len(returns.columns)

    # Kısıtlamalar ve sınırlar
    constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1})  # Ağırlıklar 1'e toplar
    bounds = tuple((0, 1) for _ in range(num_assets))  # Açığa satış yok

    # Başlangıç tahmini
    initial_guess = num_assets * [1. / num_assets]

    if objective == 'sharpe':
        # Sharpe oranını maksimize et
        result = minimize(negative_sharpe_ratio, initial_guess,
                         args=(returns,), method='SLSQP',
                         bounds=bounds, constraints=constraints)

    elif objective == 'min_vol':
        # Oynaklığı minimize et
        result = minimize(minimize_volatility, initial_guess,
                         args=(returns,), method='SLSQP',
                         bounds=bounds, constraints=constraints)

    elif objective == 'target_return':
        # Hedef getiri için oynaklığı minimize et
        constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1},
                      {'type': 'eq', 'fun': lambda x: portfolio_performance(x, returns)[0] - target_return})

        result = minimize(minimize_volatility, initial_guess,
                         args=(returns,), method='SLSQP',
                         bounds=bounds, constraints=constraints)

    return result

# Optimal portföyleri bul
max_sharpe = optimize_portfolio(returns, 'sharpe')
min_vol = optimize_portfolio(returns, 'min_vol')

print("🎯 Maksimum Sharpe Oranlı Portföy:")
for i, symbol in enumerate(crypto_symbols):
    print(f"{symbol}: {max_sharpe.x[i]:.3f}")

ret_sharpe, vol_sharpe = portfolio_performance(max_sharpe.x, returns)
print(f"Getiri: {ret_sharpe:.2%}, Oynaklık: {vol_sharpe:.2%}")
print(f"Sharpe Oranı: {ret_sharpe/vol_sharpe:.3f}\n")

print("🛡️ Minimum Oynaklık Portföyü:")
for i, symbol in enumerate(crypto_symbols):
    print(f"{symbol}: {min_vol.x[i]:.3f}")

ret_minvol, vol_minvol = portfolio_performance(min_vol.x, returns)
print(f"Getiri: {ret_minvol:.2%}, Oynaklık: {vol_minvol:.2%}")

Seviye 4: Çok Varlıklı Çılgınlık - Gerçek Kripto Portföyü

Bunu birden fazla varlıklı gerçek bir kripto portföyüne ölçekleyelim:

# Daha fazla kripto para birimine genişlet
crypto_portfolio = ['BTC-USD', 'ETH-USD', 'BNB-USD', 'ADA-USD', 'SOL-USD', 'DOT-USD']
prices_multi = get_crypto_data(crypto_portfolio, period="2y")
returns_multi = prices_multi.pct_change().dropna()

# Korelasyonları kontrol et
correlation_matrix = returns_multi.corr()

plt.figure(figsize=(10, 8))
sns.heatmap(correlation_matrix, annot=True, cmap='RdYlBu_r', center=0)
plt.title('Kripto Varlık Korelasyon Matrisi')
plt.show()

def efficient_frontier(returns, num_portfolios=50):
    """
    Etkin sınırı hesapla
    """
    # Hedef getirilerin aralığını hesapla
    ret_range = np.linspace(returns.mean().min()*252, returns.mean().max()*252, num_portfolios)

    efficient_portfolios = []

    for target_ret in ret_range:
        try:
            result = optimize_portfolio(returns, 'target_return', target_ret)
            if result.success:
                ret, vol = portfolio_performance(result.x, returns)
                efficient_portfolios.append([ret, vol, result.x])
        except:
            continue

    return np.array(efficient_portfolios)

# Etkin sınırı hesapla
efficient_port = efficient_frontier(returns_multi)

# Her şeyi birlikte çiz
plt.figure(figsize=(14, 10))

# Rastgele portföyler
random_results = generate_random_portfolios(returns_multi, 5000)
plt.scatter(random_results[1], random_results[0],
           c=random_results[2], cmap='viridis', alpha=0.3, s=10)

# Etkin sınır
if len(efficient_port) > 0:
    plt.plot(efficient_port[:,1], efficient_port[:,0], 'r-', linewidth=3, label='Etkin Sınır')

# Optimal portföyler
max_sharpe_multi = optimize_portfolio(returns_multi, 'sharpe')
min_vol_multi = optimize_portfolio(returns_multi, 'min_vol')

ret_sharpe_multi, vol_sharpe_multi = portfolio_performance(max_sharpe_multi.x, returns_multi)
ret_minvol_multi, vol_minvol_multi = portfolio_performance(min_vol_multi.x, returns_multi)

plt.scatter(vol_sharpe_multi, ret_sharpe_multi, marker='*', color='gold', s=500, label='Maks. Sharpe')
plt.scatter(vol_minvol_multi, ret_minvol_multi, marker='*', color='red', s=500, label='Min. Oynaklık')

plt.colorbar(label='Sharpe Oranı')
plt.xlabel('Oynaklık (Risk)')
plt.ylabel('Beklenen Getiri')
plt.title('Çok Varlıklı Kripto Portföy Optimizasyonu')
plt.legend()
plt.show()

# Optimal dağılımları göster
print("🚀 Optimal Çok Varlıklı Dağılımlar:")
print("\nMaksimum Sharpe Oranlı Portföy:")
sharpe_weights = pd.Series(max_sharpe_multi.x, index=crypto_portfolio).sort_values(ascending=False)
for asset, weight in sharpe_weights.items():
    if weight > 0.01:  # Yalnızca önemli tahsisleri göster
        print(f"{asset}: {weight:.1%}")

print(f"\nPortföy Metrikleri:")
print(f"Beklenen Getiri: {ret_sharpe_multi:.1%}")
print(f"Oynaklık: {vol_sharpe_multi:.1%}")
print(f"Sharpe Oranı: {ret_sharpe_multi/vol_sharpe_multi:.2f}")

Çok Varlıklı Portföy Optimizasyonu Çok Varlıklı Çeşitlendirme: Korelasyonsuz kripto varlıkları stabil bir geometrik yapıda birleştirerek güçlü bir portföy oluşturma.

Seviye 5: Gelişmiş Teknikler - Black-Litterman ve Risk Paritesi

Gerçek portföy optimizasyon ninja'ları için bazı gelişmiş teknikler uygulayalım:

def risk_parity_portfolio(returns):
    """
    Risk Paritesi Portföyü - her varlık portföy riskine eşit katkıda bulunur
    """
    def risk_contribution(weights, cov_matrix):
        portfolio_vol = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))
        marginal_contrib = np.dot(cov_matrix, weights) / portfolio_vol
        contrib = weights * marginal_contrib
        return contrib

    def risk_parity_objective(weights, cov_matrix):
        contrib = risk_contribution(weights, cov_matrix)
        target_contrib = np.ones(len(weights)) / len(weights)
        return np.sum((contrib - target_contrib)**2)

    num_assets = len(returns.columns)
    cov_matrix = returns.cov() * 252

    constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1})
    bounds = tuple((0.001, 1) for _ in range(num_assets))
    initial_guess = num_assets * [1. / num_assets]

    result = minimize(risk_parity_objective, initial_guess,
                     args=(cov_matrix,), method='SLSQP',
                     bounds=bounds, constraints=constraints)

    return result

# Risk Paritesi portföyünü hesapla
risk_parity_result = risk_parity_portfolio(returns_multi)

print("⚖️ Risk Paritesi Portföyü:")
rp_weights = pd.Series(risk_parity_result.x, index=crypto_portfolio).sort_values(ascending=False)
for asset, weight in rp_weights.items():
    print(f"{asset}: {weight:.1%}")

ret_rp, vol_rp = portfolio_performance(risk_parity_result.x, returns_multi)
print(f"\nRisk Paritesi Metrikleri:")
print(f"Beklenen Getiri: {ret_rp:.1%}")
print(f"Oynaklık: {vol_rp:.1%}")
print(f"Sharpe Oranı: {ret_rp/vol_rp:.2f}")

def backtest_portfolio(weights, prices):
    """
    Portföy performansının basit geriye dönük testi
    """
    returns = prices.pct_change().dropna()
    portfolio_returns = (returns * weights).sum(axis=1)

    # Kümülatif getirileri hesapla
    cumulative_returns = (1 + portfolio_returns).cumprod()

    # Performans metrikleri
    total_return = cumulative_returns.iloc[-1] - 1
    annualized_return = (1 + total_return) ** (252 / len(portfolio_returns)) - 1
    annualized_vol = portfolio_returns.std() * np.sqrt(252)
    sharpe_ratio = annualized_return / annualized_vol

    max_dd = (cumulative_returns / cumulative_returns.expanding().max() - 1).min()

    return {
        'total_return': total_return,
        'annualized_return': annualized_return,
        'annualized_volatility': annualized_vol,
        'sharpe_ratio': sharpe_ratio,
        'max_drawdown': max_dd,
        'cumulative_returns': cumulative_returns
    }

# Stratejilerimizi geriye dönük test et
strategies = {
    'Maks. Sharpe': max_sharpe_multi.x,
    'Min. Oynaklık': min_vol_multi.x,
    'Risk Paritesi': risk_parity_result.x,
    'Eşit Ağırlık': np.ones(len(crypto_portfolio)) / len(crypto_portfolio)
}

plt.figure(figsize=(14, 8))

for name, weights in strategies.items():
    backtest_results = backtest_portfolio(weights, prices_multi)
    plt.plot(backtest_results['cumulative_returns'], label=f"{name} (Sharpe: {backtest_results['sharpe_ratio']:.2f})")

plt.title('Portföy Stratejisi Geriye Dönük Testleri')
plt.xlabel('Tarih')
plt.ylabel('Kümülatif Getiriler')
plt.legend()
plt.yscale('log')
plt.grid(True, alpha=0.3)
plt.show()

![Portföy Stratejisi Geriye Dönük Testleri](/images/blog/markowitz-backtest.webp)
*Algoritmik Geriye Dönük Test: Teorik optimizasyon modellerini doğrulamak için tarihsel performansı simüle etme.*


# Performans özet tablosu
performance_summary = pd.DataFrame()
for name, weights in strategies.items():
    results = backtest_portfolio(weights, prices_multi)
    performance_summary[name] = [
        f"{results['annualized_return']:.1%}",
        f"{results['annualized_volatility']:.1%}",
        f"{results['sharpe_ratio']:.2f}",
        f"{results['max_drawdown']:.1%}"
    ]

performance_summary.index = ['Yıllık Getiri', 'Yıllık Oynaklık', 'Sharpe Oranı', 'Maksimum Düşüş']
print("\n📊 Strateji Performans Özeti:")
print(performance_summary)

Gerçeklik Kontrolü: Markowitz'in Sana Söylemediği Şeyler

Matematiksel optimizasyona tamamen dalmadan önce, kripto hakkında bazı acı gerçekler:

1. Geçmiş Performans ≠ Gelecekteki Sonuçlar Kripto piyasası genç ve kaotik. Hesapladığın korelasyonlar mı? Düzenlemeler değiştiğinde ya da bir sonraki büyük hack gerçekleştiğinde bir gecede tersine dönebilirler.

2. İşlem Maliyetleri Önemlidir Portföyünü yeniden dengelemek para harcar. DeFi'de gas ücretleri seni mahvedebilir. Bunu stratejine dahil et.

3. Likidite Sorunları Tüm kriptolar eşit derecede likit değildir. O düşük piyasa değerli altcoin optimizasyonunda harika görünebilir, ancak bir çöküş sırasında satmayı dene.

4. Rejim Değişiklikleri Kripto piyasalarının farklı "rejimleri" vardır - boğa piyasaları, ayı piyasaları, yatay piyasalar. Birinde işe yarayan diğerinde çalışmayabilir.

Pratik Uygulama İpuçları

def practical_portfolio_rebalancing(target_weights, current_weights, threshold=0.05):
    """
    Yalnızca ağırlıklar eşiği aştığında yeniden dengele
    """
    weight_diff = np.abs(target_weights - current_weights)
    needs_rebalancing = np.any(weight_diff > threshold)

    if needs_rebalancing:
        print("🔄 Yeniden dengeleme gerekiyor!")
        for i, (target, current) in enumerate(zip(target_weights, current_weights)):
            if abs(target - current) > threshold:
                print(f"Varlık {i}: {current:.1%} → {target:.1%}")
    else:
        print("✅ Portföy tolerans dahilinde, yeniden dengeleme gerekmiyor")

    return needs_rebalancing

# Örnek kullanım
current_allocation = np.array([0.35, 0.25, 0.15, 0.10, 0.10, 0.05])
target_allocation = max_sharpe_multi.x

practical_portfolio_rebalancing(target_allocation, current_allocation)

Sonuç: Portföy Optimizasyon Araç Setiniz

Artık kripto portföy optimizasyonu için eksiksiz bir araç setiniz var:

  1. Temel hesaplamalar risk ve getiri için
  2. Etkin sınır görselleştirmesi
  3. Matematiksel optimizasyon farklı hedefler için
  4. Gelişmiş stratejiler risk paritesi gibi
  5. Geriye dönük test çerçevesi stratejilerinizi doğrulamak için
  6. Pratik değerlendirmeler gerçek dünya uygulaması için

Temel Çıkarımlar

  • Çeşitlendirme bedava öğle yemeğidir - yatırımda tek bedava öğle yemeği
  • Risk toleransına göre optimize et - maksimum Sharpe her zaman senin için en iyisi değildir
  • Sistematik olarak yeniden dengele ama aşırı işlem yapma
  • Alçakgönüllü kal - modeller araçtır, kristal küre değil
  • Basit başla ve öğrendikçe karmaşıklık ekle

Unutma: Kriptoda, en iyi matematiksel modeller bile Elon'un ne zaman Dogecoin hakkında tweet atacağını ya da bir sonraki borsanın ne zaman hacklenebileceğini tahmin edemez. Portföy teorisini temel olarak kullan, ancak her zaman biraz nakit yedekte tut ve asla kaybetmeyi göze alamayacağından fazlasını yatırma.

Artık sorumlu bir şekilde optimize et! 🚀

Daha Fazla Okuma

Kod Deposu

Bu eğitimdeki tüm kodlar GitHub'da mevcuttur: https://github.com/suenot/markowitz

İyi optimizasyonlar! 📈