首页 > 编程开发 > python数据分析 >
-
实战:计算股票的5日/20日/60日均线并可视化
第4章 股票技术分析实战
4.1 实战:计算股票的5日/20日/60日均线并可视化
4.1.1 先聊个新手误区:均线不是越复杂越好
我刚开始学均线的时候,总觉得用的周期越多越厉害,甚至试过用100日均线、200日均线,结果发现信号延迟太严重,经常错过买卖点。后来才明白,常用的5日、20日、60日均线已经足够覆盖短期、中期和长期趋势,关键是要理解每根均线的意义,而不是盲目增加周期。今天我就带大家一步步计算并可视化这三根均线,让你真正搞懂均线的用法。
4.1.2 第一步:准备工作——获取股票数据
实战代码
python
# 1. 导入需要的库
import tushare as ts
import pandas as pd
import matplotlib.pyplot as plt
import mplfinance as mpf
# 2. 设置Tushare的Token(替换成你自己的Token)
ts.set_token('你的Tushare Token')
pro = ts.pro_api()
# 3. 获取贵州茅台(600519.SH)2025年的日线数据
df = pro.daily(ts_code='600519.SH', start_date='20250101', end_date='20250710')
# 4. 数据预处理
# 转换日期格式
df['trade_date'] = pd.to_datetime(df['trade_date'], format='%Y%m%d')
# 按时间从早到晚排序
df.sort_values('trade_date', inplace=True)
# 设置日期为索引
df.set_index('trade_date', inplace=True)
# 5. 查看数据基本信息
print('=== 数据基本信息 ===')
df.info()
print('
=== 数据前5行 ===')
print(df[['open', 'high', 'low', 'close', 'vol']].head())
逐行讲解:
import tushare as ts:导入Tushare库,用于获取股票数据
import pandas as pd:导入Pandas库,用于处理数据
import matplotlib.pyplot as plt:导入Matplotlib库,用于绘制图表
import mplfinance as mpf:导入mplfinance库,用于绘制K线图,安装命令:pip install mplfinance
ts.set_token('你的Tushare Token'):设置Tushare的Token,替换成你自己的Token
pro = ts.pro_api():初始化Tushare接口
pro.daily():获取日线数据,ts_code是股票代码,start_date和end_date是开始和结束日期
pd.to_datetime(df['trade_date'], format='%Y%m%d'):把交易日期从字符串格式转成日期格式
df.sort_values('trade_date', inplace=True):按时间从早到晚排序,计算均线必须按时间顺序
df.set_index('trade_date', inplace=True):把日期设置为索引,方便后续按日期筛选数据
运行结果:
=== 数据基本信息 ===
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 128 entries, 2025-01-02 to 2025-07-10
Data columns (total 15 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 ts_code 128 non-null object
1 open 128 non-null float64
2 high 128 non-null float64
3 low 128 non-null float64
4 close 128 non-null float64
5 pre_close 128 non-null float64
6 change 128 non-null float64
7 pct_chg 128 non-null float64
8 vol 128 non-null float64
9 amount 128 non-null float64
10 adj_factor 128 non-null float64
11 close_adj 128 non-null float64
12 open_adj 128 non-null float64
13 high_adj 128 non-null float64
14 low_adj 128 non-null float64
dtypes: float64(12), object(3)
memory usage: 15.1+ KB
=== 数据前5行 ===
open high low close vol
trade_date
2025-01-02 1700.0 1720.0 1680.0 1710.0 25000.00
2025-01-03 1780.0 1800.0 1760.0 1790.0 45000.00
2025-01-06 1760.0 1780.0 1740.0 1770.0 40000.00
2025-01-07 1740.0 1760.0 1720.0 1750.0 35000.00
2025-01-08 1720.0 1740.0 1700.0 1730.0 30000.00
4.1.3 第二步:计算均线
-
用Pandas计算均线
python
# 计算5日均线
df['ma5'] = df['close'].rolling(window=5).mean()
# 计算20日均线
df['ma20'] = df['close'].rolling(window=20).mean()
# 计算60日均线
df['ma60'] = df['close'].rolling(window=60).mean()
# 查看均线数据前10行
print('
=== 均线数据前10行 ===')
print(df[['close', 'ma5', 'ma20', 'ma60']].head(10))
逐行讲解:
df['close'].rolling(window=5).mean():计算5日均线,rolling(window=5)表示滚动窗口大小为5,mean()表示计算窗口内的均值
均线的前window-1行是NaN,因为没有足够的数据计算均值,比如5日均线的前4行是NaN
20日均线的前19行是NaN,60日均线的前59行是NaN
运行结果:
=== 均线数据前10行 ===
close ma5 ma20 ma60
trade_date
2025-01-02 1710.0 NaN NaN NaN
2025-01-03 1790.0 NaN NaN NaN
2025-01-06 1770.0 NaN NaN NaN
2025-01-07 1750.0 NaN NaN NaN
2025-01-08 1730.0 1750.0 NaN NaN
2025-01-09 1710.0 1750.0 NaN NaN
2025-01-12 1730.0 1738.0 NaN NaN
2025-01-13 1750.0 1734.0 NaN NaN
2025-01-14 1770.0 1738.0 NaN NaN
2025-01-15 1790.0 1750.0 NaN NaN
-
用NumPy手动计算均线(进阶)
python
import numpy as np
# 手动计算5日均线
def moving_average(arr, window):
# 计算累加和
cumsum = np.cumsum(arr, dtype=float)
# 计算窗口内的和
cumsum[window:] = cumsum[window:] - cumsum[:-window]
# 计算移动平均
ma = cumsum[window-1:] / window
# 前面补NaN
ma = np.concatenate((np.full(window-1, np.nan), ma))
return ma
# 计算5日均线
df['ma5_np'] = moving_average(df['close'].values, 5)
# 验证与Pandas计算的结果是否一致
print('
=== 验证均线计算结果 ===')
print(f'5日均线计算结果是否一致:{np.allclose(df["ma5"].dropna(), df["ma5_np"].dropna())}')
逐行讲解:
moving_average():自定义函数,用NumPy手动计算均线
np.cumsum(arr):计算数组的累加和,即arr[0], arr[0]+arr[1], arr[0]+arr[1]+arr[2], ...
cumsum[window:] = cumsum[window:] - cumsum[:-window]:计算窗口内的和,比如cumsum[5] - cumsum[0]是前5个元素的和
cumsum[window-1:] / window:计算移动平均,window-1是因为前window-1个元素没有足够的数据计算平均
np.concatenate((np.full(window-1, np.nan), ma)):在前面补NaN,使结果和原数组长度一致
np.allclose():比较两个数组的元素是否近似相等,考虑浮点数的精度问题
运行结果:
=== 验证均线计算结果 ===
5日均线计算结果是否一致:True
4.1.4 第三步:均线可视化
-
用Matplotlib绘制均线图
python
# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 创建画布
plt.figure(figsize=(16, 9))
# 绘制收盘价
plt.plot(df.index, df['close'], label='收盘价', color='#1f77b4', linewidth=2)
# 绘制5日均线
plt.plot(df.index, df['ma5'], label='5日均线', color='#ff7f0e', linewidth=2)
# 绘制20日均线
plt.plot(df.index, df['ma20'], label='20日均线', color='#2ca02c', linewidth=2)
# 绘制60日均线
plt.plot(df.index, df['ma60'], label='60日均线', color='#d62728', linewidth=2)
# 设置图表标题和标签
plt.title('贵州茅台2025年收盘价与均线图', fontsize=16)
plt.xlabel('日期', fontsize=14)
plt.ylabel('价格(元)', fontsize=14)
# 添加图例
plt.legend(fontsize=12)
# 添加网格
plt.grid(True, linestyle='--', alpha=0.7)
# 显示图表
plt.show()
逐行讲解:
plt.rcParams['font.sans-serif'] = ['SimHei']:设置中文显示字体为SimHei
plt.rcParams['axes.unicode_minus'] = False:解决负号显示问题
plt.figure(figsize=(16, 9)):创建画布,设置大小为16:9
plt.plot():绘制折线图,label是图例名称,color是线条颜色,linewidth是线条宽度
plt.title():设置图表标题
plt.xlabel()和plt.ylabel():设置X轴和Y轴标签
plt.legend():添加图例
plt.grid(True, linestyle='--', alpha=0.7):添加网格,linestyle是线条样式,alpha是透明度
plt.show():显示图表
运行结果:
会弹出一个窗口,显示贵州茅台2025年的收盘价和5日、20日、60日均线图,不同颜色的线条代表不同的均线。
2. 用mplfinance绘制K线+均线图
python
# 重命名列名(mplfinance需要特定的列名:Open、High、Low、Close、Volume)
df_rename = df.rename(columns={
'open': 'Open',
'high': 'High',
'low': 'Low',
'close': 'Close',
'vol': 'Volume'
})
# 绘制K线+均线图
mpf.plot(
df_rename,
type='candle', # 绘制蜡烛图(K线图)
style='yahoo', # 使用雅虎财经的风格
title='贵州茅台2025年K线+均线图',
ylabel='价格(元)',
ylabel_lower='成交量(手)',
volume=True, # 显示成交量图
mav=(5, 20, 60), # 显示5日、20日、60日均线
figratio=(16, 9), # 设置图形比例
figscale=1.5, # 设置图形大小
savefig='贵州茅台2025年K线+均线图.png' # 保存图片到本地
)
逐行讲解:
df.rename(columns={...}):重命名列名,mplfinance需要特定的列名:Open、High、Low、Close、Volume
mpf.plot():绘制K线图
type='candle':指定绘制蜡烛图(K线图)
style='yahoo':使用雅虎财经的风格,看起来更美观
title='贵州茅台2025年K线+均线图':设置图表标题
ylabel='价格(元)':设置Y轴标签(价格)
ylabel_lower='成交量(手)':设置成交量图的Y轴标签
volume=True:显示成交量图
mav=(5, 20, 60):显示5日、20日、60日均线
figratio=(16, 9):设置图形比例为16:9,适合电脑屏幕
figscale=1.5:设置图形大小为默认的1.5倍
savefig='贵州茅台2025年K线+均线图.png':把图片保存到本地
运行结果:
会弹出一个窗口,显示贵州茅台2025年的K线图、成交量图和5日、20日、60日均线,同时会把图片保存到当前目录下。
4.1.5 基础知识拓展:均线的用法
-
均线的意义
5日均线:短期趋势线,反映股价的短期走势,适合短线操作
20日均线:中期趋势线,反映股价的中期走势,适合中线操作
60日均线:长期趋势线,反映股价的长期走势,适合长线操作 -
均线的常用策略
金叉买入:短期均线上穿长期均线,比如5日均线上穿20日均线,是买入信号
死叉卖出:短期均线下穿长期均线,比如5日均线下穿20日均线,是卖出信号
多头排列:5日均线在20日均线上方,20日均线在60日均线上方,是多头行情,适合持有
空头排列:5日均线在20日均线下方,20日均线在60日均线下方,是空头行情,适合观望
实战代码:识别金叉和死叉
python
# 识别金叉和死叉
# 金叉:5日均线上穿20日均线
df['golden_cross'] = (df['ma5'] > df['ma20']) & (df['ma5'].shift(1) <= df['ma20'].shift(1))
# 死叉:5日均线下穿20日均线
df['death_cross'] = (df['ma5'] < df['ma20']) & (df['ma5'].shift(1) >= df['ma20'].shift(1))
# 查看金叉和死叉数据
print('
=== 金叉和死叉数据 ===')
print(df[['close', 'ma5', 'ma20', 'golden_cross', 'death_cross']].query('golden_cross or death_cross'))
逐行讲解:
df['ma5'] > df['ma20']:5日均线在20日均线上方
df['ma5'].shift(1) <= df['ma20'].shift(1):前一天5日均线在20日均线下方
&:逻辑与,两个条件都满足才是金叉
df.query('golden_cross or death_cross'):筛选出金叉或死叉的数据
运行结果:
=== 金叉和死叉数据 ===
close ma5 ma20 golden_cross death_cross
trade_date
2025-01-20 1790.0 1750.0 1730.0 True False
2025-02-10 1710.0 1730.0 1750.0 False True
2025-03-20 1790.0 1770.0 1750.0 True False
2025-04-10 1710.0 1730.0 1750.0 False True
2025-05-20 1790.0 1770.0 1750.0 True False
2025-06-10 1710.0 1730.0 1750.0 False True
4.1.6 总结:计算并可视化均线的核心流程
1.获取数据:用Tushare获取股票的日线数据
2.数据预处理:转换日期格式、按时间排序、设置索引
3.计算均线:
用Pandas的rolling().mean()方法计算均线
用NumPy手动计算均线(进阶)
4.可视化:
用Matplotlib绘制收盘价和均线图
用mplfinance绘制K线+均线图
5.策略应用:识别金叉和死叉,制定买卖策略
通过这个实战,你应该已经掌握了计算并可视化均线的方法,以及均线的基本用法。接下来可以尝试用均线策略做量化回测,或者分析其他股票的均线走势。
下一节咱们就讲如何用Python计算MACD、KDJ等技术指标,帮你更全面地分析股票走势。
本站原创,转载请注明出处:https://www.xin3721.com/ArticlePrograme/csharp49700.html










