基础入门
本讲把前面几讲拿到并整理好的行情表真正交给 pandas,完成第一列 5 日均线的计算、解释和手工核验。目标是让入门者第一次完整走通“获取数据、整理表格、保存样本、排查问题、算出第一列指标”的闭环。
本讲是 AkShare 入门短课的收束课,目标非常具体:把前面已经拿到并整理好的行情表交给 pandas,计算一列 5 日均线,并确认这个结果能被肉眼检查、能被继续保存,也能作为后续更复杂分析的起点。这一讲的重点不在于发明新指标,而在于第一次把“数据获取”和“数据计算”真正接起来。
学完这一讲后,先把下面三件事做扎实:
这一步之所以重要,是因为它意味着你已经从“会拿数据”正式走到“会在数据上做第一步计算”。
5 日均线不是最复杂的指标,但它非常适合作为入门收尾,因为它同时满足几个条件:
换句话说,第 8 讲重点不在于教你一个“厉害的策略指标”,更在于让你第一次完整体验:拿表、看列、转型、滚动计算、解释结果。这个闭环走通了,后面换成 10 日均线、收益率、波动率,方法都会类似。
这一讲最适合直接复用第 5 讲或第 6 讲的结果。例如:
import pandas as pd
ma_df = preview_df.copy()
如果你是从 CSV 读回来的,也可以:
ma_df = pd.read_csv("sample_stock_daily.csv")
但无论是哪种方式,开始计算前都建议先确保:
ma_df["日期"] = pd.to_datetime(ma_df["日期"], errors="coerce")
ma_df["收盘"] = pd.to_numeric(ma_df["收盘"], errors="coerce")
因为均线计算能不能稳,核心前提不是接口,而是这两列是否已经进入可计算状态。
这四步分别对应排序、计算、对照和理解空值来源。只要顺序不乱,第一列均线通常都能很快走通。
滚动计算最怕顺序乱。所以真正开始算均线前,先把表按日期排好:
ma_df = ma_df.sort_values("日期").reset_index(drop=True)
如果你省掉这一步,即使代码能运行,结果也可能在顺序上不可信。入门阶段一定要先把“顺序正确”这件事看得比“代码跑通”更重要。
ma_df["ma_5"] = ma_df["收盘"].rolling(window=5).mean()
这就是本讲最核心的一行。它的含义非常朴素:从第 5 个样本开始,每一行都用当前行及之前 4 行的收盘价求平均。
print(ma_df[["日期", "收盘", "ma_5"]].head(10))
不要只看 ma_5 一列。把原始收盘价和均线放在一起看,才能真正理解这列新结果是从哪里来的。
滚动窗口为 5 时,前 4 行没有足够历史值,所以会是空值:
print(ma_df["ma_5"].head(6))
这不是失败,反而是你理解滚动计算逻辑的第一道关。很多新手第一次看到前几行是空的,会误以为计算错了。第 8 讲就是要把这个误会提前消掉。
均线算对没算对,最直观的检查就是看列是否生成、窗口空值是否符合预期,以及后面是否开始出现有效数值。
assert "ma_5" in ma_df.columns
assert ma_df["ma_5"].head(4).isna().all()
assert pd.notna(ma_df.loc[4, "ma_5"])
assert ma_df["ma_5"].notna().sum() > 0
print(ma_df[["日期", "收盘", "ma_5"]].head(10))
如果你已经能肉眼看出“均线比原始价格更平滑”,本讲就不仅是把代码跑出来,而是真的开始理解结果。
第一次做滚动计算时,很多“不对劲”其实不是算法错,而是输入列或顺序没有先理顺。
这是滚动窗口的正常结果,不是 bug。窗口长度为 5,就意味着前 4 行凑不够一组完整平均值。
这通常说明收盘列内容并不是纯数值,或者你拿错了列。先回到第 5 讲的结构检查,再决定是不是字段名没对上。
先检查排序是否正确,再检查是不是把非收盘列拿来做了滚动平均。很多“均线不对”其实是数据顺序不对,而不是 rolling 算法错了。
这通常是因为读回后的“日期”“收盘”还是字符串。只要在计算前先 to_datetime() 和 to_numeric(),大多数问题都能消掉。
ma_5,只要语义清楚就行。import pandas as pd
def add_ma5(df: pd.DataFrame, price_col: str = "收盘") -> pd.DataFrame:
out = df.copy()
out[price_col] = pd.to_numeric(out[price_col], errors="coerce")
out["ma_5"] = out[price_col].rolling(window=5).mean()
return out
ma_df = add_ma5(ma_df)
print(ma_df[["日期", "收盘", "ma_5"]].head(10))
这段函数很短,但已经足够支撑你把“拿到表”和“算出第一列指标”连接起来。它是整套 AkShare 入门短课最自然的收束动作。
建议用 10 分钟做一个收尾练习:
ma_5。ma_5 三列的前 10 行。做到这一步,你就已经完整体验了“从接口拿数据到第一次指标计算”的闭环。
如果你现在能说出这句话,AkShare 入门短课的收尾就算完成:
“我已经能用 AkShare 拿到行情数据,用 pandas 整理结构、保存 CSV、排查常见问题,并计算出第一列 5 日均线。”
这句话听起来朴素,但它正好把这 8 讲真正该交给新手的东西都串起来了。
如果你想把第 8 讲练得更扎实,最推荐的动作不是马上加更多指标,而是手工核一次第 5 个均线值。因为第 5 行正好是第一行拥有完整 5 个样本窗口的位置,非常适合做最小验证。
你可以这样做:
check_rows = ma_df.loc[0:4, ['日期', '收盘']]
print(check_rows)
print('手工平均值 =', check_rows['收盘'].mean())
print('程序给出的 ma_5 =', ma_df.loc[4, 'ma_5'])
当你看到这两个值一致时,你会对 rolling 结果建立非常直接的信任。对新手来说,这种“手工核一条”的体验比抽象记住 rolling(window=5).mean() 更有帮助,因为它让你真正明白程序输出不是黑盒子,而是你能解释清楚的计算结果。
第 8 讲虽然是收束课,但它仍然刻意停在“先把第一列指标算清楚”。原因很简单:很多人学量化时会太急,拿到表后马上就想做买点卖点、收益曲线、回测绩效,结果前面的输入和指标本身都还没验证。这样后面一旦结果不对,就很难知道是哪里出了偏差。
而第 8 讲选择先把 5 日均线单独拿稳,有两个明显好处:
当这一步稳了,你以后换成 10 日均线、20 日均线,甚至更复杂指标,也是在同一条路径上扩展,而不是重新开始。
本讲除了看代码运行,还很适合训练最基本的结果解读习惯。建议你重点观察三件事:
ma_5 相比 收盘 更平滑,这是滚动平均最直观的表现。你甚至可以加一小段打印,把最近几行单独拉出来看:
print(ma_df[['日期', '收盘', 'ma_5']].tail(8))
这样你会更容易看到均线在尾部如何跟随价格变化。这种“对结果有肉眼解释”的能力,对后面做信号和回测非常重要。
第 8 讲虽然只算了 5 日均线,但它已经给你留出了很自然的扩展路径。最直接的两个方向是:
window=5 改成 10,比较短均线和长均线的平滑程度差异。ma_5 的基础上,再加一列简单收益率或涨跌幅,看看指标和价格变化之间的关系。比如:
ma_df['ma_10'] = ma_df['收盘'].rolling(window=10).mean()
print(ma_df[['日期', '收盘', 'ma_5', 'ma_10']].tail(10))
注意,第 8 讲并不要求你现在就把这些扩展全部做完。这里更重要的是让你看见:从 AkShare 拿到的一张表,已经可以非常自然地继续衍生出更多分析列。
如果你回头看,会发现这一讲其实把整套短课都串起来了:
也正因为如此,第 8 讲虽然表面上只是一列均线,但它其实是整套入门短课真正形成闭环的地方。
本讲是《AkShare数据获取入门短课》的第 8/8 讲,当前主题是《联动pandas算5日均线》。
上一讲:第 7 讲《排查空数据和字段报错》。
这是本系列的收束课,目标是把“拿到数据”推进到“做出第一列可解释的指标”,为后续更复杂的数据清洗和研究动作打下基础。
风险揭示与免责声明
本页面内容仅用于量化研究与技术交流,旨在展示研究方法与流程,不构成对任何金融产品、证券或衍生品的要约、招揽、推荐或保证。
本文所涉历史数据、回测结果与示例参数不代表未来表现,也不应作为投资决策依据。
市场存在波动、流动性与执行偏差等不确定性,任何策略均可能出现收益波动或阶段性失效。
读者应结合自身风险承受能力进行独立判断,并在必要时咨询持牌专业机构意见。