大约 8 分钟
案例1 股票技术画像:K线、成交量与 MACD 综合分析
前言
定义
生活场景
学校投资社团准备做一次“个股观察周报”。
老师希望同学们不要只说“这只股票最近涨了”或“最近跌了”,而是要用图形和指标把行情说清楚。
现在请你以 600300.SH 为研究对象,完成一份简单的技术画像报告,回答下面几个问题:
- 最近 60 个交易日价格整体是上涨、下跌还是震荡?
- 成交量有没有明显放大或缩小?
- MACD 最近是否出现金叉或死叉?
- 如果你要给同学做 1 分钟讲解,你会怎么概括这只股票近期状态?
实验目标
- 复习并掌握
个股 K 线图的绘制方法 - 复习并掌握
成交量柱状图的搭配观察方法 - 复习并掌握
MACD的计算和绘图 - 学会从图形中提取“趋势、量能、信号”三个层面的信息
- 学会把代码结果整理成一段简洁的金融分析结论
实验数据
仍然使用 个股行情.csv,字段与 part12.md 保持一致。
本实验重点会用到下面这些列:
代码日期开盘价(元)最高价(元)最低价(元)收盘价(元)成交量(股)
实验任务
- 读取
600300.SH的历史行情数据 - 截取最近
60个交易日,绘制K 线图 + 成交量图 - 使用全部历史收盘价计算
EMA12、EMA26、DIF、DEA、MACD柱 - 绘制
MACD图 - 找出最近
3次金叉和最近3次死叉 - 用
100~150字写出你的实验结论
完成要求
实验报告至少要包含:
- 一张
K 线 + 成交量图 - 一张
MACD图 - 一张“最近 3 次金叉 / 死叉日期”结果表
- 一段你自己的结论说明
实验过程(代码框架及说明)
先复制
part12.md中“4.2 统一运行准备”的公共准备代码,再补齐下面的实验代码。
# 先复制 part12 中的公共准备代码:
# load_stock_data()、get_stock()、matplotlib/numpy/pandas 导入等
# =========================
# 第 1 步:读取 600300.SH 数据
# =========================
stock = get_stock("600300.SH")[
["日期", "开盘价(元)", "最高价(元)", "最低价(元)", "收盘价(元)", "成交量(股)"]
].dropna().copy()
# =========================
# 第 2 步:绘制最近 60 个交易日 K 线图
# =========================
recent = stock.tail(60).copy()
# TODO:
# 1. 参考 part12,把列名改成 Date / Open / High / Low / Close / Volume
# 2. 使用 mdates.date2num() 处理日期
# 3. 使用 for 循环逐日绘制 K 线实体和影线
# 4. 在下方画成交量柱状图
# 5. 设置标题、坐标轴名称和网格
# =========================
# 第 3 步:计算 MACD
# =========================
stock["EMA12"] = stock["收盘价(元)"].ewm(span=12, adjust=False).mean()
stock["EMA26"] = stock["收盘价(元)"].ewm(span=26, adjust=False).mean()
stock["DIF"] = stock["EMA12"] - stock["EMA26"]
stock["DEA"] = stock["DIF"].ewm(span=9, adjust=False).mean()
stock["MACD柱"] = 2 * (stock["DIF"] - stock["DEA"])
# =========================
# 第 4 步:识别金叉和死叉
# =========================
# 金叉:今天 DIF > DEA,昨天 DIF <= DEA
stock["金叉"] = (stock["DIF"] > stock["DEA"]) & (
stock["DIF"].shift(1) <= stock["DEA"].shift(1)
)
# 死叉:今天 DIF < DEA,昨天 DIF >= DEA
stock["死叉"] = (stock["DIF"] < stock["DEA"]) & (
stock["DIF"].shift(1) >= stock["DEA"].shift(1)
)
golden_cross = stock.loc[stock["金叉"], ["日期", "收盘价(元)", "DIF", "DEA"]].tail(3)
dead_cross = stock.loc[stock["死叉"], ["日期", "收盘价(元)", "DIF", "DEA"]].tail(3)
print("最近 3 次金叉:")
print(golden_cross)
print("\n最近 3 次死叉:")
print(dead_cross)
# =========================
# 第 5 步:绘制 MACD 图
# =========================
# TODO:
# 1. 使用 stock["日期"] 作为横轴
# 2. 画 DIF 折线
# 3. 画 DEA 折线
# 4. 画 MACD 柱状图
# 5. 正柱用红色,负柱用绿色
# =========================
# 第 6 步:写实验结论
# =========================
# 请根据图形与结果,自行写出 100~150 字实验结论思考题
- 如果 K 线图显示上涨,但 MACD 柱在缩短,这说明了什么?
- 为什么只看金叉、死叉还不够,还要结合成交量一起看?
- 如果你把最近 60 个交易日改成最近 20 个交易日,图形解读会发生什么变化?
实验结论
自己写
案例2 市场波动结构与个股异常信号综合分析
前言
定义
生活场景
某位同学准备做一次“市场日报”分享,但老师要求他不能只盯着一只股票,而要同时回答下面 4 个层次的问题:
- 全市场 的涨跌幅分布是什么样的?
- 某只股票在 周一到周五 的上涨概率有没有差别?
- 某只股票历史上是否经常出现 跳空缺口?
- 如果按一段长期区间统计,哪些股票是历史上的 强势股?
现在请你继续使用同一个数据集,完成一份“市场统计 + 个股分析”的综合练习。
实验目标
- 掌握全市场
涨跌幅分布统计 - 掌握个股
星期效应统计 - 掌握个股
跳空缺口识别 - 掌握多股票
累计涨跌幅排名 - 学会把“市场整体特征”和“个股局部特征”结合起来分析
实验数据
仍然使用 个股行情.csv。
本实验重点会用到下面这些列:
代码日期开盘价(元)最高价(元)最低价(元)收盘价(元)涨跌幅(%)
实验任务
- 对全市场绘制
涨跌幅分布图 - 对
600300.SH统计周一到周五的上涨 / 平盘 / 下跌次数与上涨占比 - 对
600339.SH识别全部跳空交易日,并统计:- 向上跳空次数
- 向下跳空次数
- 平均缺口幅度
- 统计
2015-01-01之前的股票累计涨跌幅前 10 名 - 写出一段综合结论,说明“市场整体特征”和“个股特征”之间的差异
完成要求
实验报告至少要包含:
- 一张全市场涨跌幅分布图
- 一张
600300.SH星期统计结果表 - 一张
600339.SH跳空统计结果表 - 一张累计涨跌幅前 10 名表
- 一段
150~200字综合分析结论
实验过程(代码框架及说明)
先复制
part12.md中“4.2 统一运行准备”的公共准备代码,再补齐下面的实验代码。
# 先复制 part12 中的公共准备代码:
# load_stock_data()、get_stock()、matplotlib/numpy/pandas 导入等
# =========================
# 第 1 步:全市场涨跌幅分布统计
# =========================
data = load_stock_data().dropna(subset=["涨跌幅(%)"]).copy()
data["涨跌幅分组"] = data["涨跌幅(%)"].round(1)
dist = data["涨跌幅分组"].value_counts().sort_index()
print("样本均值:", round(data["涨跌幅(%)"].mean(), 3))
print("样本标准差:", round(data["涨跌幅(%)"].std(), 3))
# TODO:
# 1. 画出涨跌幅分布柱状图
# 2. 设置横轴范围,例如 -12 到 12
# 3. 给图添加标题、横轴名、纵轴名
# =========================
# 第 2 步:600300.SH 星期效应统计
# =========================
weekday_map = {0: "周一", 1: "周二", 2: "周三", 3: "周四", 4: "周五"}
weekday_order = ["周一", "周二", "周三", "周四", "周五"]
data["星期"] = data["日期"].dt.weekday.map(weekday_map)
data = data[data["星期"].notna()].copy()
data["涨跌标签"] = np.select(
[data["涨跌幅(%)"] > 0, data["涨跌幅(%)"] < 0],
["上涨", "下跌"],
default="平盘",
)
stat = (
data.groupby(["代码", "星期", "涨跌标签"])
.size()
.reset_index(name="天数")
)
target_code = "600300.SH"
table = (
stat[stat["代码"] == target_code]
.pivot(index="星期", columns="涨跌标签", values="天数")
.reindex(weekday_order)
.fillna(0)
.astype(int)
)
table = table.reindex(columns=["上涨", "平盘", "下跌"], fill_value=0)
table["总天数"] = table.sum(axis=1)
table["上涨占比"] = (table["上涨"] / table["总天数"]).round(3)
print("600300.SH 星期效应统计:")
print(table)
# =========================
# 第 3 步:600339.SH 跳空缺口统计
# =========================
stock_gap = get_stock("600339.SH")[
["日期", "开盘价(元)", "最高价(元)", "最低价(元)"]
].dropna().copy()
stock_gap["昨日最高价"] = stock_gap["最高价(元)"].shift(1)
stock_gap["昨日最低价"] = stock_gap["最低价(元)"].shift(1)
gap_up = stock_gap["开盘价(元)"] > stock_gap["昨日最高价"]
gap_down = stock_gap["开盘价(元)"] < stock_gap["昨日最低价"]
stock_gap["缺口方向"] = np.select(
[gap_up, gap_down],
["向上跳空", "向下跳空"],
default="无",
)
stock_gap["缺口幅度(%)"] = np.select(
[gap_up, gap_down],
[
(stock_gap["开盘价(元)"] / stock_gap["昨日最高价"] - 1) * 100,
(stock_gap["开盘价(元)"] / stock_gap["昨日最低价"] - 1) * 100,
],
default=np.nan,
)
gaps = stock_gap[stock_gap["缺口方向"] != "无"].copy()
gap_summary = gaps.groupby("缺口方向").agg(
跳空次数=("缺口方向", "size"),
平均缺口幅度=("缺口幅度(%)", "mean"),
)
print("600339.SH 跳空统计:")
print(gap_summary.round(3))
# =========================
# 第 4 步:累计涨跌幅前 10 名
# =========================
end_date = pd.Timestamp("2015-01-01")
sample = data[data["日期"] < end_date].copy()
sample["单日净值"] = 1 + sample["涨跌幅(%)"] / 100
sample = sample[sample["单日净值"] > 0].copy()
ranking = (
sample.groupby("代码")
.agg(交易天数=("单日净值", "size"), 区间累计净值=("单日净值", "prod"))
.sort_values("区间累计净值", ascending=False)
)
ranking["区间累计涨跌幅(%)"] = (ranking["区间累计净值"] - 1) * 100
print("累计涨跌幅前 10 名:")
print(ranking[["交易天数", "区间累计涨跌幅(%)"]].head(10).round(2))
# =========================
# 第 5 步:写综合分析结论
# =========================
# 请根据上面 4 部分结果,自行写出 150~200 字综合结论思考题
- 为什么全市场涨跌幅分布往往是“中间高、两边低”?
- 如果
600300.SH的某一天上涨占比最高,能不能直接说明“以后这一天更适合买入”? - 向上跳空和向下跳空,哪个更值得结合 K 线继续观察?为什么?
- 为什么长期累计涨跌幅排名要用“净值连乘”,而不是直接把每天涨跌幅相加?
实验结论
自己写
