การหากลุ่มหลักทรัพย์ที่เส้นประสิทธิภาพ Efficient Frontier ด้วย Python

การทำ portfolio optimization ด้วย google colab IX

NUTHDANAI WANGPRATHAM
3 min readMay 9, 2020

warren buffett กล่าวว่าเราไม่ควรนำไข่ใส่ไว้ในตะกร้าเดียวกัน เป็นคำพูดที่แสดงให้เห็นถึงความสำคัญของการกระจยความเสี่ยงได้ดี แต่ผมขอถามเพื่อน ๆ เพื่อน ๆ คิดว่าการกระจายความเสี่ยงที่ดีเป็นอย่างไร ใช่การกระจายเงินลงทุนในสินทรัพย์ที่หลากหลายให้มากที่สุดหรือไม่

คำตอบคือไม่จริงเสมอไป พอร์ตการลงทุนที่ดีคือพอร์ตการลงทุนที่เหมาะสมที่สุดสำหรับข้อจำกัดและความต้องการของผู้ลงทุน เป็นที่มาของชื่อซีรีย์ portfolio optimization ของเรานั้นเอง

เปิด colab กันเลย

เริ่มเหมือนเคยคือ load packeges

# load packagesimport pandas as pdimport numpy as np
import pandas_datareader as pdr
import seaborn as sns
from matplotlib import pyplot as plt
import pandas_datareader as web
import datetime
# not needed, only to prettify the plots.
import matplotlib
from IPython.display import set_matplotlib_formats

ดึงข้อมูลเราใช้ผลตอบแทนรายเดือนแยกตามอุตสาหกรรมของสหรัฐดึงได้จากลิงค์นี้เลยนะครับ https://raw.githubusercontent.com/nutdnuy/Portfolio_optimization_with_Python/master/data/ind30_m_vw_rets.csv

ind = pd.read_csv("https://raw.githubusercontent.com/nutdnuy/Portfolio_optimization_with_Python/master/data/ind30_m_vw_rets.csv", header=0, index_col=0)/100ind.index = pd.to_datetime(ind.index, format="%Y%m").to_period('M')

เราจะใช้ Scipy ในการจำลองผลตอบแทนและความเสี่ยงซึ่งจำเป็นต้องใช้ผลตอบแทนและความแปรปรวนร่วมเราจึงต้องสร้างฟังชันผลตอบแทนขึ้นมาก่อน

def annualize_rets(r, periods_per_year):compounded_growth = (1+r).prod()n_periods = r.shape[0]return compounded_growth**(periods_per_year/n_periods)-1

ประกาศตัวแปลผลตอบแทนและความแปรปรวมร่วม

er = annualize_rets(ind["1996":"2000"], 12)cov = ind["1996":"2000"].cov()

2-Asset Class

เริ่มจาก2-Asset Class ก่อน

n_points = 20weights = [np.array([w, 1-w]) for w in np.linspace(0, 1, n_points)]

n_points คือจุดที่เราจะให้มีบนเส้น หลังจากนั้นเราต้องสร้างฟังชั่นแปลผลตอบแทนของพอร์ตซึ่งผลตอบแทนที่คาดหวังของพอร์ตการลงทุนเท่ากับค่าเฉลี่ยถั่วนั้าหนักของผลตอบแทนหลักทรัพย์แต่ละชนิด

def portfolio_return(weights, returns):return weights.T @ returns

อีกฟังก์ชั่นของความผันผวนของพอร์ตให้แยกประกาศฟัชชั่นเพื่อคนอ่านจะได้เข้าใจง่าย

def portfolio_vol(weights, covmat):return (weights.T @ covmat @ weights)**0.5vols = [portfolio_vol(w, cov.loc[l,l]) for w in weights]ef = pd.DataFrame({"R": rets, "V": vols})

เรียกใช้ Scipy เพื่อหาค่า minimize

from scipy.optimize import minimizedef minimize_vol(target_return, er, cov):n = er.shape[0]init_guess = np.repeat(1/n, n)bounds = ((0.0, 1.0),) * n # an N-tuple of 2-tuples!# construct the constraintsweights_sum_to_1 = {'type': 'eq','fun': lambda weights: np.sum(weights) - 1}return_is_target = {'type': 'eq','args': (er,),'fun': lambda weights, er: target_return -portfolio_return(weights,er)}weights = minimize(portfolio_vol, init_guess,args=(cov,), method='SLSQP',options={'disp': False},constraints=(weights_sum_to_1,return_is_target),bounds=bounds)return weights.x

เราจะได้กราฟออกมา

ef.plot.scatter(x="V", y="R");

ต่อมาเราอยากให้ลากเส้นผ่านแต่ละจุดสร้างฟังชันดังนี้

def plot_ef2(n_points, er, cov):if er.shape[0] != 2 or er.shape[0] != 2:raise ValueError("plot_ef2 can only plot 2-asset frontiers")weights = [np.array([w, 1-w]) for w in np.linspace(0, 1, n_points)]rets = [portfolio_return(w, er) for w in weights]vols = [portfolio_vol(w, cov) for w in weights]ef = pd.DataFrame({"Returns": rets,"Volatility": vols})return ef.plot.line(x="Volatility", y="Returns", style=".-")

plot ก็จะได้กราฟที่เราอยากได้

plot_ef2(25, er[l].values, cov.loc[l,l])

Note book;

https://colab.research.google.com/drive/1kvhKYKZkf-WoYdY7hOypyLqrqcE7k2LZ?usp=sharing

https://colab.research.google.com/drive/1moEcfQzXoiiVKwahfpME8otiQY1EcvXa?usp=sharing

อ้างอิง;

อ่านตอนอื่นๆได้ที่

  1. การคำนวณผลตอบแทนการลงทุนด้วย Python
  2. การหาความผันผวนของพอร์ตการลงทุนด้วย Python
  3. การหา Max Drawdown ด้วย Python
  4. การวัด การเบี่ยงเบนของผลตอบแทนด้วย Python
  5. การวัด SemiDeviation ด้วย Python
  6. การวัด VaR. และ CVaR. ด้วย Python
  7. รีวิวการใช้ ffn. ใน Python
  8. การหา Top Drawdown ด้วย Python
  9. การหาค่า Sharpe ratio ด้วย Python
  10. การหากลุ่มหลักรัพย์ที่เส้นประสิทธิภาพ Efficient Frontier ด้วย Python
  11. การหา shape ratio สูงสุดและเส้น CML ด้วย Python
  12. การสร้างมูลค่าตลาดแบบถ่วงน้ำหนักด้วย PYTHON
  13. ข้อจำกัดของการกระจายความเสี่ยงและการทำประกันพอร์ตการลงทุน
  14. การจำลอง ผลตอบแทนด้วย RANDOM WALK Generation และ Montecarlo simulation
  15. Sharpe Style Analysis
  16. Factor Investing ด้วย Python
  17. วิเคราะห์ ประเภทกองทุนรวมด้วย Python
  18. การทำ Portfolio optimization
  19. สร้างแนวรับแนวต้านวิเคราะห์หุ้นด้วย Python

--

--

NUTHDANAI WANGPRATHAM
NUTHDANAI WANGPRATHAM

Written by NUTHDANAI WANGPRATHAM

I am a learner and have a multipotential life. You can contact me at nutdnuy@gmail.com

No responses yet