基础入门
本讲使用 Python 标准库 csv 完成价格记录的最小文件往返:先写出 CSV,再读回并恢复价格类型,帮助新手第一次打通内存数据与本地文件之间的实操闭环。
第 6 讲把前几讲一直在内存里操作的小样本,第一次真正落到文件里。目标很明确:学会用标准库 csv 把价格表写到磁盘,再从磁盘读回来,确认数据结构没有丢。量化练习不可能永远只靠手写列表,迟早要和文件发生关系,所以这一步值得尽早练熟。
学完这一讲后,你可以直接完成下面几件事:
csv.writer 把价格样本写成 CSV 文件。csv.DictReader 把它重新读回来。第 6 讲的重点不是文件系统知识,而是让你第一次打通“内存数据 <-> 本地文件”的最小闭环。
如果只在代码里临时定义列表和字典,你很容易误以为数据处理一直都会这么简单。真实工作里,数据通常来自文件,也经常需要把结果再写回文件。若你在入门阶段不尽早练这一步,后面一碰到“把结果保存下来”,就很容易卡住。
第 6 讲故意只用标准库 csv,原因很简单:
records = [
{'date': '2024-01-01', 'close': 12.34},
{'date': '2024-01-02', 'close': 12.80},
{'date': '2024-01-03', 'close': 12.65},
]
当前只保留 date 和 close 两列,目的是把文件读写动作本身看清楚,不让额外字段把注意力分散掉。
下面四步分别解决文件路径、写出结构、读回内容和类型恢复四个问题,按顺序做最不容易丢字段或读错类型。
import csv
file_path = 'prices_sample.csv'
本讲先用相对路径,这样文件就会直接生成在当前脚本所在目录,最容易找到。
with open(file_path, 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerow(['date', 'close'])
for record in records:
writer.writerow([record['date'], record['close']])
这里有三个细节值得记住:
newline='' 能避免 Windows 下多余空行。encoding='utf-8' 能让后面加中文列名或摘要时更稳。loaded_records = []
with open(file_path, 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
for row in reader:
loaded_records.append(row)
print(loaded_records)
这一步故意使用 DictReader,因为读回来以后,每一行都会直接按列名组织成字典,比“按位置取第 0 列、第 1 列”更直观。
for row in loaded_records:
row['close'] = float(row['close'])
print(loaded_records)
CSV 文件里的数据读回来时通常先是字符串。若你后面还要继续算收益率,这一步转回浮点数很有必要。
验证时重点看三件事:文件有没有真的落盘、读回来的条数对不对、价格能不能恢复成后面还能继续计算的数值类型。
import os
assert os.path.exists(file_path)
assert len(loaded_records) == len(records)
assert loaded_records[0]['date'] == '2024-01-01'
assert isinstance(loaded_records[0]['close'], float)
assert loaded_records[0]['close'] == 12.34
只要这几项通过,就说明你已经把“写出文件”和“读回继续用”这个闭环打通了。
这一节最常见的疑惑都和“CSV 只是文本格式”有关。只要先接受这一点,很多现象都会更容易理解。
因为 CSV 本身只是一种文本格式,不会自动替你保留 Python 里的数值类型。需要你在读回后手动转成 float。
通常是写文件时少了 newline=''。这个参数在 CSV 入门里很常用,最好从一开始就养成习惯。
因为它能直接按列名读取,结构更清楚。对 starter 系列来说,这比按索引读列更适合入门。
当然可以。本讲重点不是文件名,而是你要知道“写哪儿、读哪儿、读回后长什么样”。
date 和 close,不要求把收益率一起写进去。float,也可以,但后面继续分析前一定要补上类型转换。import csv
def save_price_csv(records, file_path):
with open(file_path, 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerow(['date', 'close'])
for record in records:
writer.writerow([record['date'], record['close']])
def load_price_csv(file_path):
loaded = []
with open(file_path, 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
for row in reader:
row['close'] = float(row['close'])
loaded.append(row)
return loaded
这样你下一次换一组样本时,不用再从零重写整段文件操作。
前几讲的价格、收益率和筛选结果都只活在脚本运行当下。第 6 讲的价值,在于让你第一次明确感受到:一份小数据是可以被保存、被重新读取、被重复使用的。对量化入门来说,这一步非常重要,因为后面你几乎一定会处理外部文件。
因此,本讲真正跑通的,不只是 csv 的基本写法,而是“我写出来的数据,下一次还能读回来继续分析”的工作流意识。
如果你现在已经能把一组价格记录写成 CSV,再读回来并恢复成可继续计算的结构,那第 6 讲就算完成。
本讲是《Python量化入门短课》的第 6/8 讲,当前主题是《CSV读写:保存再读回价格表》。
上一讲:第 5 讲《条件判断:筛出上涨交易日》。
下一讲:第 7 讲《异常处理:避开空值和除零》。
后续安排:第 8 讲《生成一份行情摘要》。
风险揭示与免责声明
本页面内容仅用于量化研究与技术交流,旨在展示研究方法与流程,不构成对任何金融产品、证券或衍生品的要约、招揽、推荐或保证。
本文所涉历史数据、回测结果与示例参数不代表未来表现,也不应作为投资决策依据。
市场存在波动、流动性与执行偏差等不确定性,任何策略均可能出现收益波动或阶段性失效。
读者应结合自身风险承受能力进行独立判断,并在必要时咨询持牌专业机构意见。