Product Philosophy

Son Yazılar


Python ile Portföy Optimizasyonu (Modern Portföy Teorisi)

Python ve modern portföy teorisini kullanarak yatırım varlıklarınızın risk düzeylerini optimize edin, etkin sınır analizine dayalı alokasyon önerileri ile finansal modelinizi geliştirin.

Murat Ova Murat Ova

Modern Portföy Teorisine ve Python ile Portföy Optimizasyonuna Giriş

Yüzyıllardır süren borsacılık tarihinde risk ve beklenen getiri kavramı arasındaki ilişkinin matematiksel incelemesi, kavramların ilk çıktığı yılların tarihsel başlangıcını baz aldığımızda hayatımıza epey geç girmiştir.

Akademik mecralardaki gelişmeler ve istatistiğin finans dünyasında bir mihenk taşı hâline gelmesi sonrasında, yatırım ve riskler üzerine yapılan araştırmaların finans dünyasındaki etkisi, sadece yatırım getirisine odaklanan yatırımcıların, risk faktörüne daha fazla önem vermeleri gerektiği şeklinde paradigma değişikliğine neden olmuştur.

Beklenen getiriye odaklanan yatırımcılar ve analistler, zaman içerisinde risk faktörüne öncelik veren stratejiler geliştirmeyi refleks edinmişlerdir.

Geleneksel portföy yönetiminde, yatırım bütçesi toplamının farklı hisse senetleri ve varlıklar üzerinde paylaştırılmasının, yani çeşitlilik yapılmasının risk faktörünü düşüreceği tespit edilmiş ve yatırımcının düşük riskli yüksek beklenen getiriye potansiyeline sahip olan varlıkları seçmesi ile finansal olarak optimal bir portföy tasarlayabileceği düşünülmüştür.

Geleneksel yaklaşım farklı sektörlerden farklı varlıklara yatırım yapmanın iyi bir çeşitlilik olgusu oluşturacağını kabul eder, fakat iktisâdi ilimlerde sıklıkla duyduğumuz “yumurtaları aynı sepete koymamak” ifadesi tam olarak da geleneksel portföy yaklaşımının taşıdığı gerçek dünya risklerini ifade etmektedir.

Farklı varlıklara yatırım yapma düşüncesinin riski düşüreceği hipotezi göreli olarak doğru olsa da, geleneksel portföy yönetimindeki “çeşitlilik” faktörünün bazı dezavantajları vardır.

Örnek vermek gerekirse 10 varlık yerine 20 varlığa yatırım yapmak risk faktörünü sadece sınırlı bir seviyeye kadar koruyabilir, çünkü yatırımlar her zaman sistematik risk faktörü taşımaktadır ve sistematik riskler varlık türlerinin artırılması ile yok edilebilir riskler değillerdir. 

Yatırım yapılan varlık türlerinin sayısında yapılan artışın optimal bir portföy oluşturacağını söylemek mantıksal olarak doğru bir zemin oluşturmayabilir, çünkü sadece varlık türlerinde artışa gidilmesi riski minimize etmek için yeterli değildir ve portföydeki hisse senetlerinin sayısındaki artış takip ve yönetim süreçleri bakımından süreç yönetimi maliyetini artıran faktörlerdir.

İçerikler

Finansal Risk Çeşitlerine Giriş

Risk: beklenen sonuçların ya da değerlerin dışında gelişen pozitif ya da negatif bir yön ile simgelenebilecek olay ya da olaylar bütünüdür.

Finansal risk: yatırım kararları sonrasındaki beklenen getirilerin pozitif ya da negatif gerçekleşme olasılıklarını etkileyen faktör ya da faktörler bütünüdür.

Sistematik Riskler

Ekonomi, politika ve sosyolojik faktörlerden kaynaklanan değişimlerin finansal piyasaları etkilediği durumlarda gerçekleşen risk türüdür. Pazarda yer alan tüm ticari kurumların bu risklerden aynı zamanda ve aynı yönde etkilendiği görülür, varlıklardan (menkul kıymetler) beklenen yatırım getirilerinde dalgalanmalar gözlemlenir.

Portföy yönetimindeki çeşitlilik faktörü sistematik risk ile karşılaşılan durumlarda etkisiz kalmaktadır, çünkü piyasaların bütüncül olarak etkilendiği bir durum söz konusu olduğu için bütün varlıklar bu tür risklerden etkilenmektedir.

Faiz, enflasyon, pazar, piyasa, politika ve satın alım gücü gibi faktörler üzerinde yaşanan riskler, sistematik risk örneklerindedir.

Sistematik Olmayan Riskler

Riskin piyasaların ve pazarın geneline yayılmadığı, spesifik olarak belirli bir sektörde, ticari kurumda veya sektördeki tüm ticari kurumlarda etkisini gösterdiği risk türüdür.

Portföy yönetimindeki çeşitlilik faktörü sistematik olmayan riskler karşısında önlem almak konusunda bir güvenlik kriteri olarak karşımıza çıkmaktadır. Portföydeki varlıkların ağırlıklarının farklı sektörlerdeki varlıklar üzerinden paylaştırılması, sektör bazında çıkan krizlerde portföyün minimum hasar ile varlığını korumasında önemlidir.

Şirketlerin veya sektörlerin; kendi içlerindeki finansal veya yönetimsel problemlerinden kaynaklı olarak yaşadıkları riskler, sistematik olmayan risk örneklerindendir.

Modern Portföy Teorisi

Modern Portföy Teorisi (MPT), Harry Markowitz tarafından geliştirilen ve 1952’de Journal of Finance’da yayınlanan “Portföy Seçimi” başlığıyla yayınlanan bir yatırım teorisidir.

Harry Markowitz, Ekonomist
Harry Markowitz, 1990 yılında Ekonomik Bilimler dalında Nobel Ödülü’nü kazanmuştır.

İyi bir portföy, uzun soluklu risksiz bir hisse senedi veya tahvil listelerinden daha fazlasıdır. Dengeli bir bütündür ve yatırımcıya geniş bir yelpazedeki koşullara ilişkin kararlar ve fırsatlar sunmaktadır.

Harry Markowitz

Modern Portföy Teorisi’ni anlamanıza yardımcı olabilecek birkaç temel kavram vardır. Finansal modellemeye aşina iseniz, “TANSTAAFL”“There Ain’t No Such Thing As A Free Lunch” kısaltmasının ne anlama geldiğini biliyor olabilirsiniz. Bedava Bir Öğle Yemeği Gibi Bir Şey Yok cümlesindeki baş harflerin kısaltmasıdır.

Nosyon olarak risk, getiri ve takas kombinasyonundan oluşan projelerde “her fırsatın bir maliyeti” (opportunity cost) olabileceği düşüncesini öne süren bu kavram, yatırımların beklenen getiri (expected value) faktörünü ele alırken aynı zamanda riskin de (volatility) göz ardı edilmemesi gerektiğini hatırlatır.

Yatırım süreçlerinde genellikle daha yüksek risk, daha yüksek getiri olasılığı ile ilişkiliyken, düşük risk ise düşük yatırım getirisi ile ilişkilidir.

Modern portföy teorisi yatırımcıların risk analizlerini kullanarak riskten olabildiğince muaf olabileceğini varsaymaktadır, yani aynı beklenen getiriyi sunan iki portföy göz önüne alındığında, yatırımcılar daha az riskli olanı tercih edebilirler.

Bu nedenle bir yatırımcı, yalnızca yüksek getiri beklediği durumlarda, riski telafi edebilecek büyüklükte beklenen getiri potansiyeli gördüğü varlıklara yatırım yapabilir.

Beklenen getiri ile ilişki olarak risk faktörünün yanı sıra modern portföy teorisinde karşımıza çıkan bir diğer olgu “çeşitlilik” faktörüdür. Modern Portföy Teorisi, belirli bir hisse senedinin beklenen riskine ve getirisine bakmanın yeterli olmadığını söylüyor. Birden fazla hisse senedine yatırım yapan bir yatırımcı, çeşitliliğin faydalarından faydalanabilir, bu faydalardan bir tanesi portföyün riskini azaltmaktır.

Risk, varlığın ne kadar değişken olduğu ile ilgilidir, eğer portföyünüzde birden fazla hisse senediniz varsa, bu hisse senedi hareketlerinin birbirleriyle nasıl ilişkili olduğunu da hesaba katmamız gerekmektedir. Çeşitlendirmenin faydalarından bir tanesi, hisselerin portföydeki ağırlığını optimize ederek, portföyünüzdeki en riskli varlıkların risklerini daha da düşürmektir.

Modern Portföy Teorisi Modeli

Optimizasyon modelinde iki temel faktör (getiri ve risk) yer almaktadır. Birden fazla varlıktan oluşan portföylerin beklenen getiri ve risk değerlerinin bulunmasında aşağıdaki formül kullanılmaktadır.

$$
\begin{array}{l}{E\left(r_{p}\right)=\sum_{i=1}^{n} E\left(r_{i}\right) x_{i}}\end{array}
$$

$$
\begin{array} \ {\sigma_{p}^{2}=\sum_{i=1}^{n} \sum_{j=1}^{n} \operatorname{cov}\left(r_{i}, r_{j}\right) x_{i} x_{j}}\end{array}
$$

$x_{i}$$i$ varlığın portföydeki ağırlığı
$E(r_{p})$portföyün beklenen getiri toplamı
$\sigma_{p}^{2}$portföyün riski (varyansı)
$E(r_{i})$$i$ varlığının beklenen getirisi
$\operatorname{cov}\left(r_{i}, r_{j}\right)$$i$ ve $j$ varlıklarının getirilerinin kovaryansı
$n$mevcut varlık sayısı

Markowitz, modern portföy teorisi ile gerçekleştirilen portföy optimizasyonunda optimal portföyü oluştururken, beklenen getiriyi en yüksek düzeyde tutmak istemekle birlikte bu getiriye ulaşırken minimum riskli (minimum variance) portföyü oluşturmayı amaçlamaktadır.

Minimum Risk (Minimum Variance) Optimizasyonu Formülü

$$
\min \sum_{i=1}^{n} \sum_{j=1}^{n} x_{i} x_{j} \sigma_{i j}
$$

$n$portföydeki mevcut varlık sayısı
$\mu_{i}$i. varlığın beklenen getirisi
$\sigma_{i}$i. ve j. varlıklar arasındaki kovaryans
$R$beklenen getiri düzeyi hedefi
$X_{i}$i. varlığın portföydeki ağırlığı

Quandl’e Giriş

Quandl finans ve ekonomi verilerini anlık olarak sunabilen bir veri servisidir, Python kütüphanesi de bulunan bu servis, ücretsiz hesaplar için 10 dakikada 2000 adet veri çekme limitasyonu sunmaktadır.

Quandl’e üye olduktan sonra size vermiş olacağı API key’ini Python ile Quandl servislerinden veri çekerken kullanacağız.

Artık Python ile portföy optimizasyonu yapmaya başlayabiliriz, ilk iş olarak import işlemi ile kütüphaneleri çalışma dosyamıza çekeceğiz.

import pandas as pd  
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import quandl
import scipy.optimize as sco

plt.style.use('fivethirtyeight')
np.random.seed(777)

%matplotlib inline
%config InlineBackend.figure_format = 'retina'

Bu yazımız için oluşturacağımız örnek portföyde Apple, Amazon, Google ve Facebook gibi şirketlerin 2016 ve 2017 yılları (2 yıllık) arasındaki hisse senedi değerlerini kullanacağız.

Aşağıdaki kod bloğu bu şirketlerin belirtilen tarih aralıklarındaki hisse senedi değerlerini (Adjusted Close) Quandl servisinden çekme görevini gerçekleştirecektir.

Kod bloğunun ilk satırında yer alan quandl.ApiConfig.api_key değişkeni değer olarak Quandl’e üye olduktan sonra size vermiş olduğu API key değerini almalıdır.

quandl.ApiConfig.api_key = 'your_api_key_here'
stocks = ['AAPL','AMZN','GOOGL','FB']
data = quandl.get_table('WIKI/PRICES', ticker = stocks, qopts = { 'columns': ['date', 'ticker', 'adj_close'] }, date = { 'gte': '2016-1-1', 'lte': '2017-12-31' }, paginate=True)

Quandl’den çektiğimiz veriler data değişkenine değer olarak atandı, artık verilerimizi aşağıdaki kod bloğu ile önizleyebiliriz.

data.head()

data.info()

info() fonksiyonu ile verilerin türlerine baktığımızda date sütununun tarih formatında olduğunu görüyoruz, bu sütunu index olarak işaretledikten sonra çalışmayı kolaylaştırmak adına veri setini şirket isimleri (ticker sütunu) üzerinden pivot tabloya dönüştüreceğiz.

df = data.set_index('date')
table = df.pivot(columns='ticker')
table.columns = [col[1] for col in table.columns]
table.head()

Verilerimiz artık daha okunaklı görünüyor, seçim yaptığımız tarih aralığı üzerinde, veri setimizdeki şirketler ve onların hisse senetlerinin zaman içindeki değişimlerini inceleyeceğiz.

plt.figure(figsize=(14, 7))
for c in table.columns.values:
    plt.plot(table.index, table[c], lw=3, alpha=0.8,label=c)
plt.legend(loc='upper left', fontsize=12)
plt.ylabel('price in $')

zaman serisi, quandl servisi

Amazon ve Google’ın hisse senedi fiyatlarının Facebook ve Apple’a göre daha pahalı olduğunu görmekteyiz. Ancak Facebook ve Apple’a ait veriler alt tarafta ezildiği için, mevcut grafikte bu ikisinin hareketini detaylı görmek zorlaşmaktadır.

Bu problemi çözmenin bir başka yolu da günlük getirileri zaman serisi olarak görselleştirmektir (önceki güne kıyasla yüzdesel değişim). Günlük fiyatlar yerine günlük getirileri (değişimleri) görselleştirerek stokların oynaklığını görebiliriz.

returns = table.pct_change()
plt.figure(figsize=(14, 7))
for c in returns.columns.values:
    plt.plot(returns.index, returns[c], lw=3, alpha=0.8,label=c)
plt.legend(loc='upper right', fontsize=12)
plt.ylabel('daily returns')

zaman serisi, yüzdesel değişimler

Yukarıdaki görseli incelediğimizde Amazon’un iki belirgin spike’ı olduğunu ve birkaç negatif gözlemi olduğunu görmekteyiz.

Hisse senetleri arasında Facebook en yüksek değer değişimine sahip varlık olarak görünürken, Apple’ın da bazı dönemler spike yaptığı görülmektedir.

Yukarıdaki tabloyu özetleyecek olursak Amazon oldukça riskli bir hisse senedi gibi görünürken, Google diğer varlıklara kıyasla en istikrarlı stok gibi görünüyor.

Rastgele Portföy Üretimi

Portföyümüzde 4 hisse senedi bulunmaktadır, portföy oluştururken vermemiz gereken en önemli karar hisse senetlerinin portföyümüz içerisinde ne şekilde dağılacağını belirlemektir.

Toplam yatırım miktarımızın 1 olduğunu düşünürsek, her hisse senedi için 1 rakamı üstünden ağırlıklandırma işlemi yapmalıyız, ağırlıklandırma işlemi sonrasında hisse senedi ağırlıklarının toplamı 1 olacaktır ve her ağırlık değeri hisse senedinin portföyümüzdeki hacmini belirleyecektir.

Örnek: Amazon için ağırlık değeri 0,5 olduğunda bütçemizin 50%’sini Amazon’a tahsis etmiş oluruz.

Şimdi gerçekleştireceğimiz örnekte portföydeki her bir hisse senedine rastgele ağırlıklar atayıp, portföyü simüle etmek için bazı fonksiyonlar tanımlayacağız.

Ardından oluşan rastgele portföyün yıllık toplam getirilerini ve yıllık oynaklığını (volatility) hesaplayalım.

Portföyün getirisini ve oynaklığını hesaplamak için portfolio_annualised_performance fonksiyonunu kullanacağız, yıllık hesap yapmak için bir yıldaki işlem günlerinin sayısı olarak 252 değerini vermekteyiz.

random_portfolios fonksiyonu, her bir hisse senedine rastgele ağırlıklar atayarak çeşitli portföyler üretecektir, fonksiyon içerisindeki num_portfolios parametresini kullanarak kaç adet rastgele portföy oluşturmak istediğimize karar verebiliriz.

def portfolio_annualised_performance(weights, mean_returns, cov_matrix):
    returns = np.sum(mean_returns*weights ) *252
    std = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights))) * np.sqrt(252)
    return std, returns
  
def random_portfolios(num_portfolios, mean_returns, cov_matrix, risk_free_rate):
    results = np.zeros((3,num_portfolios))
    weights_record = []
    for i in xrange(num_portfolios):
        weights = np.random.random(4)
        weights /= np.sum(weights)
        weights_record.append(weights)
        portfolio_std_dev, portfolio_return = portfolio_annualised_performance(weights, mean_returns, cov_matrix)
        results[0,i] = portfolio_std_dev
        results[1,i] = portfolio_return
        results[2,i] = (portfolio_return - risk_free_rate) / portfolio_std_dev
    return results, weights_record

Yukarıdaki kod bloğunda irdelenmesi gereken 2 önemli detay bulunmaktadır.

Portföy Standart Sapması

İrdelenmesi gereken ilk önemli nokta portföyün standart sapmasıdır, portföy oynaklığını hesaplayan portfolio_annualised_performance fonksiyonu portföy volatilitesini aşağıdaki formül üzerinden hesaplamaktadır.

$$
\sigma_{\text {portfolio }}=\sqrt{w_{1}^{2} \sigma_{1}^{2}+w_{2}^{2} \sigma_{2}^{2}+2 w_{1} w_{2} C o v_{1,2}}
$$

Sharpe Ratio (Sharpe Oranı)

Portföy oluştururken irdelenmesi gereken en önemli ikinci nokta Sharpe oranıdır, Sharpe oranını anlamanın en iyi yolu riske göre uyarlanmış getiri kavramını anlamaktan geçmektedir.

Riske göre ayarlanmış getiri, beklenen getiriyi elde etmek için alınacak riski ölçeklendirerek beklenen yatırım getirisini hassaslaştırmaktadır.

Riske göre ayarlanmış getiriyi ifade etmek için birden fazla yöntem kullanılmaktadır, bu yazıda bu yöntemlerden en popüleri olan Sharpe oranını tercih edeceğiz.

Sharpe oranı 1966 yılında Nobel Ekonomi Ödülünü kazanan William Sharpe tarafından geliştirilmiştir.

William Sharpe, Sharpe Ratio
William Sharpe aynı zamanda Capital Asset Pricing Model’in (Sermaye Varlığı Fiyatlandırma Modeli) yaratıcılarından biriydi

$$ Sharpe Ratio = \frac{\overline{\mathrm{r}}{\mathrm{p}}-\mathrm{r}{\mathrm{f}}}{\sigma_{\mathrm{p}}} $$

$$ \overline{\mathrm{r}}_{\mathrm{p}}\ $$beklenen portföy getirisi
$$ \mathrm{r}_{\mathrm{t}}\ $$risksiz faiz oranı
$$ \sigma_{p}=\ $$portföy standart sapması

Artık fonksiyonumuz için gerekli parametre değerlerini tamamlayabiliriz.
Günlük fiyat verilerine dataFrame içerisindeki pct_change‘i çağırarak kolayca erişebiliriz.

Ortalama günlük getiriler ve getiri kovaryans matrisi, portföy getirilerini ve oynaklığı hesaplamak için gerekli parametrelerdir.

Bu örneğimizde 25.000 rastgele portföy oluşturacağız.

Bu örnekteki 1.78%’lik risksiz faiz oranı ABD Hazine Bakanlığı’ndan alınmıştır.

returns = table.pct_change()
mean_returns = returns.mean()
cov_matrix = returns.cov()
num_portfolios = 25000
risk_free_rate = 0.0178
def display_simulated_ef_with_random(mean_returns, cov_matrix, num_portfolios, risk_free_rate):
    results, weights = random_portfolios(num_portfolios,mean_returns, cov_matrix, risk_free_rate)
    
    max_sharpe_idx = np.argmax(results[2])
    sdp, rp = results[0,max_sharpe_idx], results[1,max_sharpe_idx]
    max_sharpe_allocation = pd.DataFrame(weights[max_sharpe_idx],index=table.columns,columns=['allocation'])
    max_sharpe_allocation.allocation = [round(i*100,2)for i in max_sharpe_allocation.allocation]
    max_sharpe_allocation = max_sharpe_allocation.T
    
    min_vol_idx = np.argmin(results[0])
    sdp_min, rp_min = results[0,min_vol_idx], results[1,min_vol_idx]
    min_vol_allocation = pd.DataFrame(weights[min_vol_idx],index=table.columns,columns=['allocation'])
    min_vol_allocation.allocation = [round(i*100,2)for i in min_vol_allocation.allocation]
    min_vol_allocation = min_vol_allocation.T
    
    print "-"*80
    print "Maximum Sharpe Ratio Portfolio Allocation\n"
    print "Annualised Return:", round(rp,2)
    print "Annualised Volatility:", round(sdp,2)
    print "\n"
    print max_sharpe_allocation
    print "-"*80
    print "Minimum Volatility Portfolio Allocation\n"
    print "Annualised Return:", round(rp_min,2)
    print "Annualised Volatility:", round(sdp_min,2)
    print "\n"
    print min_vol_allocation
    
    plt.figure(figsize=(10, 7))
    plt.scatter(results[0,:],results[1,:],c=results[2,:],cmap='YlGnBu', marker='o', s=10, alpha=0.3)
    plt.colorbar()
    plt.scatter(sdp,rp,marker='*',color='r',s=500, label='Maximum Sharpe ratio')
    plt.scatter(sdp_min,rp_min,marker='*',color='g',s=500, label='Minimum volatility')
    plt.title('Simulated Portfolio Optimization based on Efficient Frontier')
    plt.xlabel('annualised volatility')
    plt.ylabel('annualised returns')
    plt.legend(labelspacing=0.8)

Yukarıdaki portföy oluşturma fonksiyonu rastgele olarak portföy üretir ve sonuçlar (portföy getirisi, portföy volatilitesi, portföy sharpe oranı) üzerinden varlıkların portföy içerisindeki ağırlıklandırma (alocation) işlemini yapar.

Ardından en yüksek Sharpe oranına sahip portföyü bularak, maksimum Sharpe oranına sahip portföyü kırmızı yıldız işareti ile işaretler.

Fonksiyonumuz minimum volatiliteye sahip portföyü bulmak için de benzer adımlar uygulanır ve portföyü grafik üzerinde yeşil bir yıldız ile simgeler.

Rastgele üretilen tüm portföyler, Sharpe oranına göre renk haritası üzerinde görüleceklerdir.

Portföy oluşumunu ve alokasyonunu gerçekleştirecek fonksiyonumuzu parametreleriyle birlikte çalıştırıyoruz.

display_simulated_ef_with_random(mean_returns, cov_matrix, num_portfolios, risk_free_rate)

Portföy Alokasyonları (Minimum ve Maksimum Risk Opsiyonları)

modern portföy teorisi, portföy alokasyonu

modern portföy teorisi, portföy optimizasyonu

Minimum risk taşıyan portföyü incelediğimizde bütçemizin yarısından fazlasının Google’a aloke edildiğini görebiliriz.

Daha önceki günlük getiri grafiğine tekrar bakarsak, Google’ın en az değişim gösteren hisse senedi olduğunu görürürüz,
bu nedenle minimum risk portföyünde Google’a büyük bir yüzde ayırmak, Google’ın düşük risk (volatilite) taşımasından dolayı sezgisel bir anlam da taşımaktadır.

Daha yüksek getiri için daha yüksek risk almak istediğimizde, bize en optimal riske göre ayarlanmış getiri sağlayan bir maksimum Sharpe oranına sahip varlıkları tercih etmeliyizdir.

Bu senaryoda günlük getiri konusunda oldukça değişken hisse senetleri olan Amazon ve Facebook’a önemli bir pay ayrıldığını görmekteyiz.

Efficient Frontier (Etkin Sınır)

Rastgele simüle edilmiş portföy grafiğinde, kümelenmiş mavi noktaların sol tarafında bir kemer çizgisi şekli oluştuğunu görmekteyiz.

Bu çizgiye etkin sınır (efficient frontier) ismi verilemektedir. Etkin sınır kavramı getirilerin ve risklerin görselleştirildiği 2 boyutlu uzayda her hedef yatırım getirisi için risk oranı kesişimini de göstermektedir.

Etkin sınırın üst kısımlarına yakın olan noktalar yüksek geri dönüşü ve düşük riski temsil etmektedir. Getiri yüksek olmasına karşın oynaklığın düşük olduğu varlıklar bu sınıra yakın konumlanacaklardır.

Varlıkların beklenen getirilerinin benzer olduğu durumlarda içlerinden daha düşük riskli olanı tercih etmek için grafiği yorumlamak da yeterli olacaktır.

Yukarıdaki örneğimizde 2 optimal portföyü bulma methodumuz, pek çok olası rastgele seçimi simüle ederek, içlerinden minimum risk veya maksimum riske göre ayarlanmış getiri ölçütleri üzerinden en iyisini seçmektir. Bu bölümde bu işlemi Python’da Scipy kütüphanesininin optimize fonksiyonunu kullanarak uygulayacağız.

constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) — 1})

Yukarıdaki yapı, x’in toplamının 1’e eşit olması gerektiğini belirtmektedir.

Bu yapıyı kullanarak tüm ağırlıkların toplamının 1’e eşit olması gerektiğini belirtmiş oluruz ve alokasyon portföy bütçemizin toplamının 100%’ü üzerinden gerçekleşmiş olur.

def neg_sharpe_ratio(weights, mean_returns, cov_matrix, risk_free_rate):
    p_var, p_ret = portfolio_annualised_performance(weights, mean_returns, cov_matrix)
    return -(p_ret - risk_free_rate) / p_var

def max_sharpe_ratio(mean_returns, cov_matrix, risk_free_rate):
    num_assets = len(mean_returns)
    args = (mean_returns, cov_matrix, risk_free_rate)
    constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1})
    bound = (0.0,1.0)
    bounds = tuple(bound for asset in range(num_assets))
    result = sco.minimize(neg_sharpe_ratio, num_assets*[1./num_assets,], args=args,
                        method='SLSQP', bounds=bounds, constraints=constraints)
    return result

Minimum volatilite portföyünü Sharpe Ratio ile hesaplamak için farklı ağırlıklar deneyerek volatilite düzeyini minimum seviyeye çekecek bir optimizasyon fonksiyonu tanımlayacağız.

def portfolio_volatility(weights, mean_returns, cov_matrix):
    return portfolio_annualised_performance(weights, mean_returns, cov_matrix)[0]

def min_variance(mean_returns, cov_matrix):
    num_assets = len(mean_returns)
    args = (mean_returns, cov_matrix)
    constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1})
    bound = (0.0,1.0)
    bounds = tuple(bound for asset in range(num_assets))

    result = sco.minimize(portfolio_volatility, num_assets*[1./num_assets,], args=args,
                        method='SLSQP', bounds=bounds, constraints=constraints)

    return result

Şimdi optimal portföyleri etkin sınır çizgisi üzerinden görselleştirebilmek için etkin sınır fonksiyonunu kullanacağız.

def efficient_return(mean_returns, cov_matrix, target):
    num_assets = len(mean_returns)
    args = (mean_returns, cov_matrix)

    def portfolio_return(weights):
        return portfolio_annualised_performance(weights, mean_returns, cov_matrix)[1]

    constraints = ({'type': 'eq', 'fun': lambda x: portfolio_return(x) - target},
                   {'type': 'eq', 'fun': lambda x: np.sum(x) - 1})
    bounds = tuple((0,1) for asset in range(num_assets))
    result = sco.minimize(portfolio_volatility, num_assets*[1./num_assets,], args=args, method='SLSQP', bounds=bounds, constraints=constraints)
    return result


def efficient_frontier(mean_returns, cov_matrix, returns_range):
    efficients = []
    for ret in returns_range:
        efficients.append(efficient_return(mean_returns, cov_matrix, ret))
    return efficients

Rastgele oluşturduğumuz bu portföy için, portföy opsiyonlarını maksimum Sharpe oranına ve minimum oynaklığa göre görselleştireceğiz.

Fakat bu sefer, rastgele oluşturulan portföylerden en uygun olanlarını görsel olarak yorumlayarak seçmek yerine bu işlemi Scipy kütüphanesininin minimize fonksiyonunu kullanarak yapacağız.

Ve aşağıdaki fonksiyon, yukarıda tanımladığımız efficient_frontier fonksiyonu ile birlikte çalışarak etkin sınırı da görselleştirecektir.

def display_calculated_ef_with_random(mean_returns, cov_matrix, num_portfolios, risk_free_rate):
    results, _ = random_portfolios(num_portfolios,mean_returns, cov_matrix, risk_free_rate)
    
    max_sharpe = max_sharpe_ratio(mean_returns, cov_matrix, risk_free_rate)
    sdp, rp = portfolio_annualised_performance(max_sharpe['x'], mean_returns, cov_matrix)
    max_sharpe_allocation = pd.DataFrame(max_sharpe.x,index=table.columns,columns=['allocation'])
    max_sharpe_allocation.allocation = [round(i*100,2)for i in max_sharpe_allocation.allocation]
    max_sharpe_allocation = max_sharpe_allocation.T

    min_vol = min_variance(mean_returns, cov_matrix)
    sdp_min, rp_min = portfolio_annualised_performance(min_vol['x'], mean_returns, cov_matrix)
    min_vol_allocation = pd.DataFrame(min_vol.x,index=table.columns,columns=['allocation'])
    min_vol_allocation.allocation = [round(i*100,2)for i in min_vol_allocation.allocation]
    min_vol_allocation = min_vol_allocation.T
    
    print "-"*80
    print "Maximum Sharpe Ratio Portfolio Allocation\n"
    print "Annualised Return:", round(rp,2)
    print "Annualised Volatility:", round(sdp,2)
    print "\n"
    print max_sharpe_allocation
    print "-"*80
    print "Minimum Volatility Portfolio Allocation\n"
    print "Annualised Return:", round(rp_min,2)
    print "Annualised Volatility:", round(sdp_min,2)
    print "\n"
    print min_vol_allocation
    
    plt.figure(figsize=(10, 7))
    plt.scatter(results[0,:],results[1,:],c=results[2,:],cmap='YlGnBu', marker='o', s=10, alpha=0.3)
    plt.colorbar()
    plt.scatter(sdp,rp,marker='*',color='r',s=500, label='Maximum Sharpe ratio')
    plt.scatter(sdp_min,rp_min,marker='*',color='g',s=500, label='Minimum volatility')

    target = np.linspace(rp_min, 0.32, 50)
    efficient_portfolios = efficient_frontier(mean_returns, cov_matrix, target)
    plt.plot([p['fun'] for p in efficient_portfolios], target, linestyle='-.', color='black', label='efficient frontier')
    plt.title('Calculated Portfolio Optimization based on Efficient Frontier')
    plt.xlabel('annualised volatility')
    plt.ylabel('annualised returns')
    plt.legend(labelspacing=0.8)

Portföy oluşumunu ve alokasyonunu gerçekleştirecek fonksiyonumuzu parametreleriyle birlikte çalıştırıyoruz.

display_calculated_ef_with_random(mean_returns, cov_matrix, num_portfolios, risk_free_rate)

python, etkin sınır, efficient frontier

python, etkin sınır, efficient frontier analysis

Sonuçların rastgele oluşturulan portföylerden seçerek simüle ettiğimiz sonuçlarla hemen hemen aynı olduğunu görmekteyiz.

Belirgin küçük farklardan birtanesi, Scipy kütüphanesinin optimize fonksiyonunun maksimum Sharpe oranı portföyünde Google için bütçe alokasyonu yapmaması olarak görülmektedir.

Rastgele oluşturduğumuz her portföyü scatter chart üzerinde görselleştirmek yerine, portföydeki her bir hisse senedini, senetlerin yıllık getirisi ve buna karşılık gelen yıllık riski üzerinden görselleştirebiliriz.

Bu şekilde alokasyonu optimize ederek çeşitlendirme faktörünün riski nasıl düşürdüğünü görebilir ve karşılaştırma yapabiliriz.

def display_ef_with_selected(mean_returns, cov_matrix, risk_free_rate):
    max_sharpe = max_sharpe_ratio(mean_returns, cov_matrix, risk_free_rate)
    sdp, rp = portfolio_annualised_performance(max_sharpe['x'], mean_returns, cov_matrix)
    max_sharpe_allocation = pd.DataFrame(max_sharpe.x,index=table.columns,columns=['allocation'])
    max_sharpe_allocation.allocation = [round(i*100,2)for i in max_sharpe_allocation.allocation]
    max_sharpe_allocation = max_sharpe_allocation.T

    min_vol = min_variance(mean_returns, cov_matrix)
    sdp_min, rp_min = portfolio_annualised_performance(min_vol['x'], mean_returns, cov_matrix)
    min_vol_allocation = pd.DataFrame(min_vol.x,index=table.columns,columns=['allocation'])
    min_vol_allocation.allocation = [round(i*100,2)for i in min_vol_allocation.allocation]
    min_vol_allocation = min_vol_allocation.T
    
    an_vol = np.std(returns) * np.sqrt(252)
    an_rt = mean_returns * 252
    
    print "-"*80
    print "Maximum Sharpe Ratio Portfolio Allocation\n"
    print "Annualised Return:", round(rp,2)
    print "Annualised Volatility:", round(sdp,2)
    print "\n"
    print max_sharpe_allocation
    print "-"*80
    print "Minimum Volatility Portfolio Allocation\n"
    print "Annualised Return:", round(rp_min,2)
    print "Annualised Volatility:", round(sdp_min,2)
    print "\n"
    print min_vol_allocation
    print "-"*80
    print "Individual Stock Returns and Volatility\n"
    for i, txt in enumerate(table.columns):
        print txt,":","annuaised return",round(an_rt[i],2),", annualised volatility:",round(an_vol[i],2)
    print "-"*80
    
    fig, ax = plt.subplots(figsize=(10, 7))
    ax.scatter(an_vol,an_rt,marker='o',s=200)

    for i, txt in enumerate(table.columns):
        ax.annotate(txt, (an_vol[i],an_rt[i]), xytext=(10,0), textcoords='offset points')
    ax.scatter(sdp,rp,marker='*',color='r',s=500, label='Maximum Sharpe ratio')
    ax.scatter(sdp_min,rp_min,marker='*',color='g',s=500, label='Minimum volatility')

    target = np.linspace(rp_min, 0.34, 50)
    efficient_portfolios = efficient_frontier(mean_returns, cov_matrix, target)
    ax.plot([p['fun'] for p in efficient_portfolios], target, linestyle='-.', color='black', label='efficient frontier')
    ax.set_title('Portfolio Optimization with Individual Stocks')
    ax.set_xlabel('annualised volatility')
    ax.set_ylabel('annualised returns')
    ax.legend(labelspacing=0.8)

Artık fonksiyonumuzu çalıştırabiliriz.

display_calculated_ef_with_selected(mean_returns, cov_matrix, num_portfolios, risk_free_rate)

Modern Portföy Teorisi

Python ve Etkin Sınır, Finansal Modelleme

Yukarıdaki portföy alokasyonu özetini yorumladığımız zaman, en az risk taşıyan hisse senedinin 0.18 volatilite değeri ile Google olduğunu söyleyebiliriz.

Google’ı risk düzeyi performans ölçütünde sırasıyla Apple, Facebook ve Amazon takip etmektedir. Risk düzeyinden bağımsız olarak getiri performansları incelendiğinde sırasıyla Amazon, Facebook, Apple ve Google gelmektedir.

Analiz: Maksimum Sharpe Oranı Portföyü

Maximum Sharpe oranına göre alokasyon yapılmış olan portföyde ağırlık dağılımları sırasıyla Apple (44.72), Amazon (29.13), Facebook (26.15) ve Google’a (0) aloke edilmiştir.

Portföyün günlük getirisi 0.3 olarak hesaplanmış ve günlük oynaklık 0.18 seviyesindedir.

Analiz: Minimum Volatilite Portföyü

Minimum volatiliteye göre alokasyon yapılmış olan portföyde ağırlık dağılımları sırasıyla Google (58.4), Apple (33.94), Facebook (7.0) ve Amazon’a (0.66) aloke edilmiştir.

Portföyün günlük getirisi 0.22 olarak hesaplanmış ve günlük oynaklık 0.16 seviyesindedir.

Kaynaklar

Kapanış Notları

Artık Python kullanarak Modern Portföy Teorisi, Etkin Sınır ve Sharpe Oranı üzerinden portföy optimizasyonu gerçekleştirebilir ve yatırım varlıklarınız üzerinden finansal model geliştirebilirsiniz.

Modern portföy teorisini aynı zamanda dijital kanallardaki reklam kampanyalarınız için de uyarlayabilirsiniz. Dijital kampanyaların ROI ve volatilite metriklerini bağımsız etkilenmelerden filtreleyerek, securitising yöntemi ile yatırım yapılabilir varlıklar haline getirip performans tabanlı pazarlama portföyleri oluşturabilirsiniz.

Yazı ile ilgili sorularınız veya danışmanlık talepleriniz için LinkedIn üzerinden iletişime geçebilirsiniz.

Sonraki yazıda görüşmek üzere.

12+ yıl deneyimli full stack yazılım mühendisi, kantitatif analist ve dijital pazarlama uzmanı.

Büyük perakendecilerin dijital dünyadaki kompleks büyüme hedefleri için insan doğası ve kar maksimizasyonu odaklı müşteri deneyimi ile yapay zeka tabanlı karar destek sistemleri (Decision Support Systems) geliştirmektedir.

Apple / Tesco / L’oreal / Carrefour / Trendyol / Vestel / Boyner / Doğan Grubu / DeFacto / ETS Tur / Morhipo / Anadolu Sağlık / Pronet / Koçtaş ve daha birçok FMCG/Perakende/Hizmet/E-ticaret markasının, farklı türlerdeki dijital projelerinde full-stack danışman olarak yer almıştır.

Şu anda AnalyticaHouse'ta pazarlama mühendisliği, veri bilimi ve danışmanlık kalitesinden sorumlu direktör olarak çalışmaktadır.

Yorumlar1
  • Cem Gün
    Posted on

    Cem Gün Cem Gün

    CevaplaAuthor

    Uzun zamandır aradığım ve üzerinde uzmanlaşmak istediğim bir çalışma, açıklamalar çok değerli paylaşımınız için çok teşekkürler. ”Yapay zeka ile sermaye piyasalarında analiz” konusu çalışmak, öğrenmek istediğim bir konu başlangıç için bu paylaşım benim için heyecan verici olacak.