你是否还在苦恼为什么要学 Python 以及 Matplotlib 吗?今天就以近20年苹果和微软的股票走势数据分析来介绍它们的应用场景,话不多说,直接放码过来:
import yfinance as yf
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 根据不同操作系统设置字体
import platform
system = platform.system()
if system == 'Windows':
# Windows系统
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'SimSun']
elif system == 'Darwin':
# macOS系统
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS', 'PingFang SC', 'Heiti SC']
else:
# Linux系统
plt.rcParams['font.sans-serif'] = ['DejaVu Sans', 'WenQuanYi Zen Hei']
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
# 下载股票数据
data = yf.download(["AAPL", "MSFT"], start="2015-10-01", end="2025-12-30")['Close']
# 提取个股数据
aapl = data.iloc[:, 0]
msft = data.iloc[:, 1]
# 计算日收益率(您的计算方法)
aapl_return = [(new - old) / old for old, new in zip(aapl[:-1], aapl[1:])]
msft_return = [(new - old) / old for old, new in zip(msft[:-1], msft[1:])]
# 创建第一个图表:股价走势对比
fig, axes = plt.subplots(2, 2, figsize=(16, 10))
# 子图1:AAPL和MSFT收盘价走势(对数坐标)
axes[0, 0].plot(aapl.index, aapl, color='blue', alpha=0.7, linewidth=1.5, label='AAPL')
axes[0, 0].plot(msft.index, msft, color='red', alpha=0.7, linewidth=1.5, label='MSFT')
axes[0, 0].set_yscale('log') # 对数坐标更好地显示增长率
axes[0, 0].set_title('AAPL vs MSFT 收盘价走势 (2015-2025)', fontsize=14, fontweight='bold')
axes[0, 0].set_xlabel('日期')
axes[0, 0].set_ylabel('收盘价 (对数坐标)')
axes[0, 0].legend(loc='best')
axes[0, 0].grid(True, alpha=0.3)
axes[0, 0].tick_params(axis='x', rotation=45)
# 子图2:AAPL日收益率
axes[0, 1].plot(aapl.index[1:], aapl_return, color='blue', alpha=0.6, linewidth=1)
axes[0, 1].axhline(y=0, color='gray', linestyle='--', alpha=0.5)
axes[0, 1].fill_between(aapl.index[1:], aapl_return, 0, where=np.array(aapl_return) >= 0,
color='green', alpha=0.3, label='正收益')
axes[0, 1].fill_between(aapl.index[1:], aapl_return, 0, where=np.array(aapl_return) < 0,
color='red', alpha=0.3, label='负收益')
axes[0, 1].set_title('AAPL 日收益率变化', fontsize=14, fontweight='bold')
axes[0, 1].set_xlabel('日期')
axes[0, 1].set_ylabel('日收益率')
axes[0, 1].legend(loc='best')
axes[0, 1].grid(True, alpha=0.3)
axes[0, 1].tick_params(axis='x', rotation=45)
# 子图3:MSFT日收益率
axes[1, 0].plot(msft.index[1:], msft_return, color='red', alpha=0.6, linewidth=1)
axes[1, 0].axhline(y=0, color='gray', linestyle='--', alpha=0.5)
axes[1, 0].fill_between(msft.index[1:], msft_return, 0, where=np.array(msft_return) >= 0,
color='green', alpha=0.3, label='正收益')
axes[1, 0].fill_between(msft.index[1:], msft_return, 0, where=np.array(msft_return) < 0,
color='red', alpha=0.3, label='负收益')
axes[1, 0].set_title('MSFT 日收益率变化', fontsize=14, fontweight='bold')
axes[1, 0].set_xlabel('日期')
axes[1, 0].set_ylabel('日收益率')
axes[1, 0].legend(loc='best')
axes[1, 0].grid(True, alpha=0.3)
axes[1, 0].tick_params(axis='x', rotation=45)
# 子图4:收益率分布直方图
bins = np.linspace(-0.15, 0.15, 50)
axes[1, 1].hist(aapl_return, bins=bins, alpha=0.5, color='blue', label='AAPL', density=True)
axes[1, 1].hist(msft_return, bins=bins, alpha=0.5, color='red', label='MSFT', density=True)
axes[1, 1].axvline(x=0, color='gray', linestyle='--', alpha=0.5)
axes[1, 1].set_title('AAPL vs MSFT 日收益率分布', fontsize=14, fontweight='bold')
axes[1, 1].set_xlabel('日收益率')
axes[1, 1].set_ylabel('频率 (标准化)')
axes[1, 1].legend(loc='best')
axes[1, 1].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# 创建第二个图表:累计收益率
fig2, ax2 = plt.subplots(figsize=(12, 6))
# 计算累计收益率
aapl_cum_return = np.cumprod([1 + r for r in aapl_return])
msft_cum_return = np.cumprod([1 + r for r in msft_return])
ax2.plot(aapl.index[1:], aapl_cum_return, color='blue', linewidth=2, label='AAPL累计收益率')
ax2.plot(msft.index[1:], msft_cum_return, color='red', linewidth=2, label='MSFT累计收益率')
ax2.axhline(y=1, color='gray', linestyle='--', alpha=0.5, label='初始投资')
# 添加关键事件标记(示例)
key_events = {
'2018-12': '贸易摩擦',
'2020-03': '疫情冲击',
'2021-01': '科技股大涨',
'2022-01': '加息周期开始',
'2023-10': 'AI热潮'
}
for date_str, event in key_events.items():
try:
date = pd.to_datetime(date_str)
if date > aapl.index[0] and date < aapl.index[-1]:
ax2.axvline(x=date, color='orange', linestyle=':', alpha=0.5, linewidth=0.8)
# 在合适位置标注事件
ax2.text(date, ax2.get_ylim()[1]*0.9, event, rotation=90,
fontsize=8, alpha=0.7, ha='center', va='top')
except:
pass
ax2.set_title('AAPL vs MSFT 累计收益率对比 (2015-2025)', fontsize=14, fontweight='bold')
ax2.set_xlabel('日期')
ax2.set_ylabel('累计收益率 (倍数)')
ax2.legend(loc='best')
ax2.grid(True, alpha=0.3)
ax2.tick_params(axis='x', rotation=45)
# 添加统计信息文本框
stats_text = f'''
统计信息 (2015-2025):
AAPL:
平均日收益率: {np.mean(aapl_return)*100:.4f}%
日收益率标准差: {np.std(aapl_return)*100:.4f}%
最终累计收益率: {(aapl_cum_return[-1]-1)*100:.2f}%
MSFT:
平均日收益率: {np.mean(msft_return)*100:.4f}%
日收益率标准差: {np.std(msft_return)*100:.4f}%
最终累计收益率: {(msft_cum_return[-1]-1)*100:.2f}%
'''
ax2.text(0.02, 0.98, stats_text, transform=ax2.transAxes, fontsize=9,
verticalalignment='top', bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.8))
plt.tight_layout()
plt.show()
运行以后的效果如何呢?
📊 图表解读
图1:多面板分析图(四个子图)
-
左上角 - 股价走势对比图:
- 使用对数坐标显示AAPL(蓝色)和MSFT(红色)从2015到2025年的收盘价走势
- 对数坐标的特点是:相同百分比的变化在图上表现为相同的垂直距离
- 可以看到两家科技巨头在这10年间都实现了显著增长,MSFT的增长轨迹相对更稳定
-
右上角 - AAPL日收益率变化:
- 显示苹果公司每日收益率的波动情况,绿色区域表示正收益日,红色表示负收益日
- 可以观察到收益率围绕零轴上下波动,有明显的波动聚集现象(大波动后往往跟随大波动)
- 在2020年3月疫情期间出现了极端负收益率,随后迅速反弹
-
左下角 - MSFT日收益率变化:
- 微软的日收益率模式与苹果相似,但整体波动性似乎略低
- 同样在2020年3月出现显著下跌,但恢复速度较快
- 2023年后受AI热潮推动,正收益日明显增多
-
右下角 - 收益率分布直方图:
- 比较两家公司日收益率的分布情况,均进行了标准化处理
- 两家公司的收益率分布都近似正态分布,但尾部比正态分布更厚(极端事件概率更高)
- MSFT的分布中心略向右偏移,表明其平均日收益率可能稍高于AAPL
图2:累计收益率对比图
-
核心趋势分析:
- 两条曲线显示从2015年10月开始的1单位初始投资如何随时间增长
- 总体来看,两家公司都为投资者创造了丰厚回报,累计收益率远超初始投资
- MSFT的累计收益率曲线在某些时期表现更优,特别是在2020年后的云计算和AI转型期
-
关键事件影响:
- 图中标注了几个关键市场事件的时间点
- 2018年贸易摩擦期间,两家公司股价均受影响但恢复迅速
- 2020年3月疫情冲击造成大幅下跌,但随后科技股引领市场反弹
- 2023年开始的AI热潮特别利好MSFT(因其对OpenAI的投资)
-
风险收益特征:
- 从统计信息框可以看出,MSFT在这段时间内的平均日收益率略高于AAPL
- 但AAPL的**波动性(标准差)**也略高,符合高风险高收益的特征
- 最终累计收益率显示两家公司都实现了数倍的投资回报
📈 投资启示
-
长期投资价值:两家科技巨头在10年周期中都证明了强大的创造股东价值能力
-
分散化益处:同时投资两家公司可以平滑单一公司的特定风险
-
波动性管理:日收益率图表显示市场波动是常态,投资者需有相应的风险承受能力
-
事件驱动机会:重大市场事件(如疫情)往往带来短期冲击,但也可能创造买入机会
此分析基于历史数据,使用yfinance库获取美股数据,通过matplotlib进行可视化展示,为量化投资分析提供了基础框架。
再有什么想看的内容欢迎告诉我,也欢迎在评论区留言。