在之前的文章中,我已经演示了如何使用例如Python中的pandas_datareader。
在本文中,我将介绍一种算法,您可以使用该算法根据您可能正在考虑的任何一组股票来构建有效的投资组合。该算法将根据您自信承担的风险级别确定投资组合中每只股票的最佳份额。
更准确地说,我将介绍一种可视化包含一组特定股票的投资组合有效前沿的方法。在此示例中,我将使用以下8个库存公司,它们都是货运公司:
- Yamato Holdings (YATRY)
- Knight-Swift Transportation Holdings (KNX)
- BEST (BEST)
- YRC Worldwide (YRCW)
- Schneider National (SNDR)
- Old Dominion Freight Line (ODFL)
- Arc Best (ARCB)
- Werner Enterprises (WERN)
风险以历史收益的标准差计量。收益以平均历史每日股票收益(使用收盘价)衡量。 我首先在Python中导入一些相关模块:
#导入相关模块 import pandas as pd import numpy as np import pandas_datareader.data as web import datetime import matplotlib.pyplot as plt import statistics as stat import random as rnd from matplotlib.ticker import StrMethodFormatter
我想收集过去6个月的历史股价数据。在下面,我指定从以下日期收集数据的相关期间的开始和结束日期:
#指定股价数据收集期间的相关开始和结束日期 start_date = datetime.datetime(2020,4,1) end_date = datetime.datetime(2020,9,30)
接下来,我定义一个辅助函数,该函数将通过pandas_datareader接收从Yahoo Finance收集的股价数据框架,并将其转换为每日收益:
#define函数返回每日收益列表
def returns(df):
prices = df["Close"]
returns = [0 if i == 0 else (prices[i]-prices[i-1])/(prices[i-1]) for i in range(0,len(prices))]
return(returns)
现在,我定义另一个帮助器函数,该函数将列出一个股票报价,并计算它们在特定时期内的平均日收益率和日收益率的标准差。该函数利用pandas_datareader从Yahoo查询股票价格数据:
#define函数可以构造具有标准偏差和平均每日收益的数据框
def analyzeStocks(tickersArr,start_date,end_date):
# create empty data frame template
index = ["ticker","return","stdev"]
muArr = []
sigmaArr = []
# loop through all tickers
for i in range(0,len(tickersArr)):
# add ticker to table
tick = tickersArr[i]
# get stock price data
data = web.DataReader(tickersArr[i],"yahoo",start_date,end_date)
# calculate average daily return
muArr.append(stat.mean(returns(data)))
# calculate standard deviation
sigmaArr.append(stat.stdev(returns(data)))
# return a data frame
return(pd.DataFrame(np.array([tickersArr, muArr, sigmaArr]),index=index,columns=tickersArr))
在这篇文章中,我想分析以下的滴答声:
tickersArr = ["YATRY","KNX","BEST","YRCW","SNDR","ODFL","ARCB","WERN"]
使用以上代码,我执行analyzeStocks提取股票价格数据并计算平均值。日收益率和日收益率标准差:
base_df = analyzeStocks(tickersArr,start_date,end_date) base_df
| YATRY | KNX | BEST | YRCW | SNDR | ODFL | ARCB | WERN | |
|---|---|---|---|---|---|---|---|---|
| ticker | YATRY | KNX | BEST | YRCW | SNDR | ODFL | ARCB | WERN |
| return | 0.004653743523196298 | 0.0023175179239564793 | -0.0034124339485902665 | 0.011159199755783849 | 0.002462051717055063 | 0.003349259316178459 | 0.005861686829084918 | 0.0017903742321965712 |
| stdev | 0.02358463699374274 | 0.02114091659162514 | 0.031397841155750277 | 0.09455276239906354 | 0.019372571935633416 | 0.023305461738410294 | 0.037234069177970675 | 0.02237976138155402 |
使用matplotlib,我可以简单绘制散点图的历史收益与波动率表现:
plt.figure(figsize=(15,8))
muArr = [float(i) for i in base_df.iloc[1,]]
sigmaArr = [float(i) for i in base_df.iloc[2,]]
sharpeArr = [muArr[i]/sigmaArr[i] for i in range(0,len(muArr))]
plt.scatter(sigmaArr,muArr,c=sharpeArr,cmap="plasma")
plt.title("Historical avg. returns vs. standard deviations [single stocks]",size=22)
plt.xlabel("Standard deviation",size=14)
plt.ylabel("Avg. daily return",size=14)
Text(0, 0.5, 'Avg. daily return')

现在,我定义一个投资组合构建函数。该功能将创建定义数量的投资组合,并为每只股票随机分配权重。由此产生的预期收益和每日收益的标准差以Pandas数据框的形式返回:
#函数用于创建定义数量的投资组合
def portfolioBuilder(n,tickersArr,start_date,end_date):
muArr = []
sigmaArr = []
dailyreturnsArr = []
weightedreturnsArr = []
portfoliodailyreturnsArr = []
#填充每日收益
for i in range(0,len(tickersArr)):
data = web.DataReader(tickersArr[i],"yahoo",start_date,end_date)
dailyreturnsArr.append(returns(data))
#创建n个不同的投资组合
for i in range(0,n):
#重置每日投资组合列表
portfoliodailyreturnsArr = []
#创建投资组合权重
weightsArr = [rnd.uniform(0,1) for i in range(0,len(tickersArr))]
nweightsArr = [i/sum(weightsArr) for i in weightsArr]
#权衡每日收益
for j in range(0,len(dailyreturnsArr[0])):
temp = 0
for k in range(0,len(tickersArr)):
temp = temp + float(dailyreturnsArr[k][j])*float(nweightsArr[k])
portfoliodailyreturnsArr.append(temp)
#计算并附加每日平均加权投资组合收益
muArr.append(stat.mean(portfoliodailyreturnsArr))
#计算并附加加权投资组合日收益的标准差
sigmaArr.append(stat.stdev(portfoliodailyreturnsArr))
#返回所创建投资组合的预期收益和标准差
return([sigmaArr,muArr])
我将投资组合构建功能应用于股票行情,并使用matplotlib.pyplot为500000个随机投资组合绘制结果:
portfoliosArr = portfolioBuilder(500000,tickersArr,start_date,end_date)
plt.figure(figsize=(15,8))
muArr = [float(portfoliosArr[1][i]) for i in range(0,len(portfoliosArr[1]))]
sigmaArr = [float(portfoliosArr[0][i]) for i in range(0,len(portfoliosArr[0]))]
sharpeArr = [muArr[i]/sigmaArr[i] for i in range(0,len(muArr))]
plt.scatter(sigmaArr,muArr,c=sharpeArr,cmap="plasma")
plt.title("Historical avg. returns vs. standard deviations [single stocks]",size=22)
plt.colorbar(label="Sharpe ratio")
plt.xlabel("Standard deviation",size=14)
plt.ylabel("Avg. daily returns",size=14)
Text(0, 0.5, 'Avg. daily returns')

该图表使您可以验证所选股票的当前权重选择当前是否有效。有效的投资组合将位于散点图的上方。

专业领域为优化和仿真的工业工程师(R,Python,SQL,VBA)

Leave a Reply