我们根据你获得的hs300数据,来查看下沪深300的年化收益。
import arrow
import numpy as np
end = arrow.get("2024-09-03")
year_ago = end.shift(years = -1)
year_ago = hs300[hs300.index >= np.datetime64(year_ago)].index[0]
print(year_ago)
# 计算买入并持有的收益(最近一年)
buy_price = hs300[hs300.index == year_ago].iloc[0]["close"]
buy_and_hold = hs300["close"][-1]/buy_price - 1
print(f"买入并持收益:{buy_and_hold:.2%}")
# 通过均值推算年化收益
market_returns = hs300["close"].pct_change().dropna()
market_annual = (1 + market_returns[market_returns.index >= year_ago].mean()) ** 242 - 1
print(f"年化收益: {market_annual:.2%}")
2023-09-04 00:00:00
买入并持收益:-14.95%
年化收益: -12.87%
C:\Users\Administrator\AppData\Local\Temp\ipykernel_5664\1405670539.py:7: UserWarning: no explicit representation of timezones available for np.datetime64
year_ago = hs300[hs300.index >= np.datetime64(year_ago)].index[0]
C:\Users\Administrator\AppData\Local\Temp\ipykernel_5664\1405670539.py:12: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`
buy_and_hold = hs300["close"][-1]/buy_price - 1
通过两种方法进行推算得到,过去一年沪深300的收益大约在-15%左右。
接下来,我们获取沪深300成份股,以便从中抽取个股进行检验。请使用变量名 index_stock_cons_df 来保存你获取的成份股数据。
# 在此写下你的代码
import akshare as ak
index_stock_cons_df = ak.index_stock_cons(symbol="399300")
# 打印结果
print(index_stock_cons_df)
最终,我们应该得到类似输出:
品种代码 品种名称 纳入日期
0 001965 招商公路 2024-06-17
1 000807 云铝股份 2024-06-17
2 300442 润泽科技 2024-06-17
3 600415 小商品城 2024-06-17
4 603296 华勤技术 2024-06-17
.. ... ... ...
295 600660 福耀玻璃 2005-04-08
296 600690 青岛海尔 2005-04-08
297 600741 巴士股份 2005-04-08
298 600795 国电电力 2005-04-08
299 600900 长江电力 2005-04-08
接下来,我们随机取10支股票,获取行情,并计算每日收益率:
# 随机抽取10支股票,获取行情并计算每日收益
# 请在此写下你的代码
np.random.seed(78)
stocks = random.sample(index_stock_cons_df['品种代码'].to_list(), 10)
frames = {}
now = arrow.now()
start = now.shift(years = -1)
end = now.format("YYYYMMDD")
start = start.format("YYYYMMDD")
print(end)
print(start)
# 获取 10 支股票的行情数据
for code in stocks:
bars = ak.stock_zh_a_hist(symbol=code, period="daily", start_date=start, end_date=end, adjust="qfq")
bars.index = pd.to_datetime(bars["日期"])
frames[code] = bars["收盘"]
# 与指数行情数据合并
start = np.datetime64(now.shift(years = -1))
frames["399300"] = hs300[hs300.index >= start]["close"]
df = pd.DataFrame(frames)
# 计算每日收益
returns = df.pct_change()
# 如果存在 NAN,则后面的回归法将无法聚合
returns.dropna(how='any', inplace=True)
returns.head().style.format('{:,.2%}')
为了后面的代码能够运行,请将行情数据保存在df变量中,每日收益保存在returns中。最终,returns应该是类似下面的结果:
688396 600941 600346 002410 000776 601916 300896 600332 601601 601788 399300
2023-09-05 00:00:00 -1.29% -1.06% 0.55% -0.62% -1.13% -1.22% -0.69% -0.43% -1.26% -1.41% -0.74%
2023-09-06 00:00:00 -1.46% -1.02% 1.17% 1.05% -0.34% 0.00% -0.22% -0.13% 1.59% 0.12% -0.22%
2023-09-07 00:00:00 -1.92% 0.28% -0.95% -1.16% -1.01% -0.41% -2.59% -1.73% -0.48% 0.42% -1.40%
2023-09-08 00:00:00 -0.59% 1.48% -0.76% -1.17% 0.34% -0.41% -1.63% -0.34% -0.27% 0.59% -0.49%
2023-09-11 00:00:00 0.07% 0.85% 0.07% 2.30% 1.29% 0.42% 3.18% 2.10% -1.37% 0.94% 0.74%
提示,你可能需要使用这些方法:
- random.sample
- stock_zh_a_hist
- pd.to_datetime
- np.datetime64
- df.pct_change
- df.dropna
- df.style.format
接下来,我们就可以实施CAPM模型。这里我们仅用多项式拟合法。
cols = df.columns
betas = {}
for name in cols:
beta, alpha = np.polyfit(returns[name], returns["399300"], deg=1)
print(name, f"{beta:.2%} {alpha:.2%}")
betas[name] = beta
688396 24.96% -0.02%
600941 1.46% -0.06%
600346 30.01% -0.06%
002410 18.09% 0.00%
000776 58.21% -0.02%
601916 33.28% -0.07%
300896 15.09% -0.02%
600332 36.72% -0.05%
601601 23.79% -0.07%
601788 33.63% -0.05%
399300 100.00% 0.00%
最好的一支是002410。我们就看看,如果买入这一支,它的alpha和beta是多少:
code = "002410"
beta = betas[code]
# 回归法得到的预期收益
expected_return = rf + beta * (market_annual - rf)
print(f"code beta: {beta:.2f}, Er: {expected_return:.2%}")
code beta: 0.18, Er: -0.80%