深圳融克迪特科技有限公司 Logo,金融科技,量化交易,软件开发

深圳融克迪特科技有限公司

RONG CREDIT TECHNOLOGY CO., LTD.

基础入门

【AkShare 系列 第6讲】保存行情到CSV

本讲围绕“把整理好的行情表稳定落盘并读回验证”这一最小闭环展开,覆盖 CSV 保存参数、编码选择、回读检查、文件命名和可复用保存函数。目标是让前几讲得到的数据不再只停留在当前会话里,而是变成后续均线计算和排错都能复用的本地样本。

2026-04-23 智铨研究 阅读时长 9 分钟

目录

  1. 本节目标
  2. 为什么“保存 CSV”值得单独一讲
  3. 先选一张已经整理过的预览表
  4. 四步把表安全保存成 CSV
  5. 先确定输出路径
  6. 执行保存
  7. 立刻读回文件
  8. 比较保存前后最关键的几个特征
  9. 怎样判断这次保存是真的成功
  10. 文件已经生成
  11. 读回后仍然是 DataFrame
  12. 读回后行数与原表一致
  13. 核心列没有丢
  14. 读回后前几行还能正常查看
  15. 为什么 CSV 保存后看起来“怪怪的”
  16. 打开后多出一列无名索引
  17. 中文列名乱码
  18. 读回后日期列变成普通字符串
  19. 保存路径找不到
  20. 哪些情况仍然算本讲完成
  21. 把保存和回读动作写成一个小函数
  22. 做出一份后面真的会继续用的 CSV
  23. 怎样判断第 6 讲已经过关
  24. 为什么入门阶段要先固定一份本地样本
  25. 保存前最好再做一次轻量整理
  26. 文件命名也值得养成一点习惯
  27. 读回验证时到底该看什么
  28. 第 6 讲在整套短课中的真正位置
  29. 系列衔接
  30. 风险揭示与免责声明

1. 本节目标

本讲的目标很具体:把前面已经整理过的行情预览表稳定地保存成 CSV 文件,再读取回来确认内容没有在落盘过程中被搞乱。它看起来像最朴素的数据操作,但对入门短课来说非常关键,因为从这一讲开始,你拿到的数据就不再只存在于当前 Python 会话里,而是开始变成能复用、能分享、能二次处理的本地文件。

本讲完成后,你至少应该掌握三件事:

  1. 知道什么时候该把表从内存写到文件。
  2. 会用最小参数把表保存成一份可读的 CSV。
  3. 会在写完以后立即读回并做一次结构核对,确认这不是“文件生成了,但已经不可继续使用”的假成功。

2. 为什么“保存 CSV”值得单独一讲

很多入门者会觉得保存 CSV 不就是一行 to_csv() 吗,没必要单独拿出来。但一旦真的开始用数据,你很快会遇到几个现实问题:

  1. 当前会话关掉后,前面拿到的表就没了。
  2. 你想把一份样本表交给别的脚本继续处理。
  3. 你想在算均线前先固定一份原始输入,避免每次都重新调用接口。

这时“会不会保存文件”就不再是杂事,而是把前面几讲从一次性练习推进到可复用工作流的关键动作。

3. 先选一张已经整理过的预览表

本讲不要求重新抓新数据。最稳的做法,是直接拿第 5 讲已经整理过的 preview_df 继续往下用:

import pandas as pd

csv_df = preview_df.copy()

如果你手上还没有现成的 preview_df,也可以从个股日线表里重新抽一次核心列:

csv_df = daily_df[["日期", "开盘", "收盘", "成交量"]].copy()

关键是:这一讲保存的,最好是一张你已经看清结构的工作表,而不是还没预览过的原始大表。

4. 四步把表安全保存成 CSV

保存 CSV 最稳的做法不是写出文件就结束,而是连同读回检查一起做成闭环。下面四步就是按这个顺序展开的。

5. 先确定输出路径

不要把保存路径写得含糊不清。入门阶段建议就在项目目录下给它一个清楚的名字:

output_path = "sample_stock_daily.csv"

如果你愿意更规范一点,也可以把它放到专门的数据目录里。但第 6 讲的核心不是目录管理,而是先把“一张表可稳定落盘”这件事做完整。

6. 执行保存

最简版本建议这样写:

csv_df.to_csv(output_path, index=False, encoding="utf-8-sig")

这里有两个关键点:

  1. index=False,避免把 DataFrame 的索引也写成一列脏字段。
  2. encoding="utf-8-sig",在很多 Windows 环境和表格工具里更容易直接正确显示中文列名。

7. 立刻读回文件

很多人保存完看到目录里有文件就结束了,但真正稳的做法是立刻读回来:

loaded_df = pd.read_csv(output_path)
print(loaded_df.head())

这一步能帮你确认三件事:

  1. 文件路径没写错。
  2. 编码没把中文列名弄坏。
  3. 列结构大体和保存前一致。

8. 比较保存前后最关键的几个特征

不要做复杂比对,先看几个最小指标:

print(csv_df.shape, loaded_df.shape)
print(csv_df.columns.tolist())
print(loaded_df.columns.tolist())

如果行列数没明显变化、核心列还都在,这份 CSV 对入门练习就已经够用了。

9. 怎样判断这次保存是真的成功

验证的重点只有三件事:文件确实写出去了、能正常读回来、核心结构没有明显走样。

10. 文件已经生成

from pathlib import Path
assert Path(output_path).exists()

11. 读回后仍然是 DataFrame

assert isinstance(loaded_df, pd.DataFrame)

12. 读回后行数与原表一致

assert len(csv_df) == len(loaded_df)

13. 核心列没有丢

assert set(csv_df.columns).issubset(set(loaded_df.columns))

14. 读回后前几行还能正常查看

print(loaded_df.head())

对第 6 讲来说,这已经足够说明你把一张内存里的表,变成了一份可重复打开的本地文件。

15. 为什么 CSV 保存后看起来“怪怪的”

CSV 看起来简单,但第一次落盘时最容易栽在索引、编码和路径这三个点上。下面这些现象基本都可以顺着这三类原因去排。

16. 打开后多出一列无名索引

这通常是保存时忘了 index=False。DataFrame 索引如果跟着落盘,很多时候只会让表更乱,不会让它更有用。

17. 中文列名乱码

这往往和编码有关。对当前 Windows 场景来说,utf-8-sig 比直接用 utf-8 更稳一些,特别是你可能还会用 Excel 或别的工具临时打开文件时。

18. 读回后日期列变成普通字符串

这是常见现象,不算失败。CSV 本来就不会自动替你保留所有类型语义。你后面若要继续按日期处理,只需要在读取后再显式 pd.to_datetime() 一次。

19. 保存路径找不到

这通常不是 CSV 的问题,而是你对当前工作目录没有概念。第 6 讲的一个隐含收获,就是让你养成“保存前先想清楚文件会落在哪里”的习惯。

20. 哪些情况仍然算本讲完成

  1. 读回后的数据类型不完全等于保存前,不算本讲失败。CSV 的核心目标是保存结构化表,不是完整保存 pandas 内部类型语义。
  2. 你保存的是股票表、指数表还是财经日历预览表,都可以。第 6 讲训练的是“落盘和回读闭环”,不是某个特定接口。
  3. 文件名不一定非要统一成某个模板,只要你自己能一眼看懂它是什么数据就行。
  4. 你可以先保存一份很小的样本文件,不要求一开始就处理很大的全量数据。

21. 把保存和回读动作写成一个小函数

from pathlib import Path
import pandas as pd

def save_and_reload_csv(df: pd.DataFrame, path: str) -> pd.DataFrame:
    df.to_csv(path, index=False, encoding="utf-8-sig")
    if not Path(path).exists():
        raise FileNotFoundError(f"未生成文件: {path}")
    return pd.read_csv(path)

loaded_df = save_and_reload_csv(csv_df, "sample_stock_daily.csv")
print(loaded_df.head())

有了这个函数,你后面每次都可以把“落盘”和“回读验证”绑在一起做,而不是保存完就靠猜。

22. 做出一份后面真的会继续用的 CSV

建议你做一个最小但真实的练习:

  1. 选一张前面已经整理好的预览表。
  2. 保存成一个名称清楚的 CSV。
  3. 立即读回并打印前 5 行。
  4. 在注释里写一句:这份 CSV 后面准备做什么。

例如:

loaded_df = save_and_reload_csv(csv_df, "stock_daily_for_ma.csv")
print(loaded_df.head())
# 后续用于第8讲计算5日均线

这样第 6 讲就不只是“我会用 to_csv”,而是已经给后续课程准备好了明确的输入文件。

23. 怎样判断第 6 讲已经过关

如果你现在能说出这句话,第 6 讲就算真的完成:

“我已经能把一张整理过的 AkShare 数据表保存成 CSV,并读回确认核心列和样本行数没有丢。”

这条标准很务实,也足够支撑后面的继续练习。

24. 为什么入门阶段要先固定一份本地样本

很多人刚开始会觉得,既然 AkShare 能随时重新拉数据,那就没必要额外保存本地文件。这个想法在练习初期很常见,但会带来两个隐性问题。第一,你每次调试都重新请求接口,输入数据会随着时间、日期区间或参数细节变化而波动;第二,一旦你开始排查均线、信号、字段问题,就很难分清“问题来自计算逻辑”还是“问题来自这次重新拉回来的样本”。

所以第 6 讲把 CSV 单独拿出来,重点不在于让你学会一个孤立函数,更在于帮你固定一份后续练习都能复用的样本输入。这样做以后,你在第 7 讲排错时,就能明确地说:我现在排的是字段和类型,不是接口波动;你在第 8 讲算均线时,也能明确地说:我现在改的是指标计算,不是原始取数逻辑。

25. 保存前最好再做一次轻量整理

虽然第 6 讲强调的是落盘,但真正稳妥的做法,是保存前再做一次最小整理。比如:

csv_df = csv_df.copy()
csv_df = csv_df.drop_duplicates()
csv_df = csv_df.sort_values('日期').reset_index(drop=True)
print(csv_df.head())

这样做的意义不是追求完美清洗,而是避免把明显重复、顺序混乱的数据直接写进文件。因为一旦这份 CSV 被你后面几讲继续引用,它就会从“练习中间结果”变成“后续输入基底”。基底越清楚,后面越省事。

26. 文件命名也值得养成一点习惯

新手常见的一个小问题,是文件名写得过于随意,比如 a.csvtest.csvnew1.csv。短期看没什么,但当你开始同时保存不同标的、不同周期、不同阶段的数据时,这种命名会让你很快失去上下文。第 6 讲很适合顺手养成最小命名习惯:

output_path = '000001_daily_preview.csv'

或者:

output_path = 'stock_daily_for_ma5.csv'

只要文件名能回答“它是谁”和“它准备干什么”,你后面再回来看时就不会费劲。

27. 读回验证时到底该看什么

第 6 讲里“读回验证”不是形式动作,而是一个很真实的质量门槛。建议你固定检查下面这几项:

  1. 列名有没有变化。
  2. 行数是不是和原表一致。
  3. head() 看起来是不是还是同一批样本。
  4. 日期列是否还存在,后面是否需要重新转型。

比如可以写成:

print('原表列名:', csv_df.columns.tolist())
print('回读列名:', loaded_df.columns.tolist())
print('原表行数:', len(csv_df))
print('回读行数:', len(loaded_df))
print(loaded_df.head())

这套检查看似简单,但足够帮你防住很多入门阶段最常见的文件落盘问题。

28. 第 6 讲在整套短课中的真正位置

如果只看代码,第 6 讲确实只有几行。但从整套 AkShare 入门短课的结构看,它其实起的是“把前面几讲的表格练习固化下来”的作用。第 1 到第 5 讲更多是在学如何拿到并看清一张表;从第 6 讲开始,你已经在学如何把中间产物稳定留住,并为后续计算复用。正因为它处在这个承上启下的位置,所以一定不要把它当成“只是保存一下文件”的琐碎动作。

29. 系列衔接

本讲是《AkShare数据获取入门短课》的第 6/8 讲,当前主题是《保存行情到CSV》。

上一讲:第 5 讲《转成DataFrame并预览》。

下一讲:第 7 讲《排查空数据和字段报错》。

后续安排:第 8 讲《联动pandas算5日均线》。

30. 风险揭示与免责声明

风险揭示与免责声明

本页面内容仅用于量化研究与技术交流,旨在展示研究方法与流程,不构成对任何金融产品、证券或衍生品的要约、招揽、推荐或保证。

本文所涉历史数据、回测结果与示例参数不代表未来表现,也不应作为投资决策依据。

市场存在波动、流动性与执行偏差等不确定性,任何策略均可能出现收益波动或阶段性失效。

读者应结合自身风险承受能力进行独立判断,并在必要时咨询持牌专业机构意见。