股票CSV怎么导入:把行情文件整理成可计算的数据表
股票CSV导入,是把一个具体来源的导出文件转换为有明确约定的行情表。文件能够打开只是第一步,还要识别字段、保留证券标识、按预期解释日期、归一化数值单位,并把不能安全计算的行隔离。最终交付应包括标准文件、拒绝行报告,以及产生两者的字段映射,而不是只有一张看起来整齐的表。
本文使用含中文表头的四行虚构CSV,一行成功,另外三行因不同机制失败。示例通过Python标准库在本地实际解析,不代表CoTrading或Vibe已有任意文件上传入口;这些产品承接仍为规划或待核实。实际使用中,数据源导出格式不同,就应分别建立映射,不能只按“股票CSV”这个名称认定格式相同。
转换前先检查导出约定
保留原始字节,记录来源、导出时间、日期范围、分隔符、编码与价格口径。按声明编码抽读少量行;若文件带字节顺序标记,要采用相应解码方式,避免它混进第一个表头。遇到解码失败应停止并核对,不要默认替换乱码,因为证券标识或字段名可能已经损坏。
使用CSV解析器,不能简单按逗号切行。样例成交量有带引号的"1,200",其中逗号属于字段内容。Python CSV官方文档介绍方言、字典读取以及真实文件的换行处理。解析出字符串以后,仍需自己验证金融含义和类型,CSV模块不会自动确认某一列是股数还是金额。
字段映射为:代码到symbol,日期到date,开盘到open,最高到high,最低到low,收盘到close,成交量到volume。额外的单位列解释成交量口径。证券代码始终按文本处理,保留前导零;真实市场还应加入交易所限定标识,避免不同市场短代码重名。映射文件需有版本,供应商改表头后重新验收。
明确币种、成交单位与复权口径
目标表包含证券、ISO日期、开高低收、成交量、币种和复权标识。本例价格为CNY,口径为原始价,成交量单位为股。这些来自合成输入约定,不是从数值大小猜测。若导出文件以手为单位,要取得适用换算依据;不能跨股票、跨市场统一假设一手固定多少股。
Alpha Vantage官方接口文档区分原始日线开高低收成交量、复权收盘价和公司行动字段。这个来源说明为什么看到“复权”一列,不能直接拿它替换全部原始价格。原始开盘、最高和复权收盘混在一起,并不是口径一致的复权K线。没有明确转换方法时,应保留来源口径并向下游说明。
日期也要有严格约定。本例只接受%Y/%m/%d,输出YYYY-MM-DD,非法日期直接拒绝,而不是让宽松解析器自动挪到下个月。日内数据另需时区、交易时段和夏令时处理;本例日级日期不能用来证明时间戳转换正确。也不要因为某日没有交易,就把无法解析的日期改成邻近交易日。
逐行解析并检查行情关系
成功行是AAA在2026/10/19的行情:开盘10、最高12、最低9、收盘11、成交量1,200股。第二行重复同一证券日期键;第三行写2026/02/30;第四行单位为lots_unknown。这三种错误分别针对身份唯一性、日历有效性和测量单位,不应合并成一条含糊的“格式错误”。
day = datetime.strptime(row["日期"], "%Y/%m/%d").date().isoformat()
key = (row["代码"], day)
if key in seen:
raise ValueError("duplicate_key")
if row["单位"] != "shares":
raise ValueError("unknown_volume_unit")
prices = [D(row[k]) for k in ("开盘", "最高", "最低", "收盘")]
volume = int(row["成交量"].replace(",", ""))
完整样例还检查价格为正、成交量非负,以及最低价不高于开盘和收盘、最高价不低于两者。正式导入还应覆盖非有限数、缺少表头、额外字段等情况;本例围绕四条声明输入检验核心转换,不能把通过样例说成已经兼容所有供应商导出。
行全部通过后才把键加入已接受集合。若先登记键,再发现该行非法,后面一条有效观测可能也被错误挡住。对于冲突重复,本例拒绝后出现的行并交人工核对,不采用无记录的“最后一条覆盖”。其他策略可以使用,但必须说明选择依据,并保留被替换值及来源。
查看实际输出并对账
完整文件位于作者仓库docs/growth/research/round-5/examples/R528.py,用Python执行。实际接受AAA,日期为2026-10-19,价格10、12、9、11,成交量1200,币种CNY,原始价。来源第3行因重复键拒绝,第4行因日期越界拒绝,第5行因成交单位未知拒绝。
下载完整示例。使用Python 3.12+,仅需标准库,全部为合成数据;下载后运行python R528.py。
断言验证四条输入数据等于一条接受加三条拒绝,并验证带引号的千位分隔成交量最终是1200,而非被拆成两个字段或误读为1。只对账行数还不够,数值转换也必须抽查。输入中没有真实证券和账户,不需要凭证或联网。
保存标准文件时固定列顺序和编码,使用CSV写出器;拒绝表保留原始值、原始行号、错误原因和映射版本。本例在内存实际写出标准CSV字符串,再用DictReader读回并断言日期和成交量,将字符串包含在打印JSON中,不生成磁盘文件;真实导入器可以把同样两个结构分别保存。写文件只是交付步骤,不能成为绕开拒绝规则的理由。
按原因修复,再定向重跑
单位未知是本题不同机制反例。去掉逗号、改编码或把字符串转成数字,都不能回答一手究竟代表多少股。应取得单位定义、更新映射版本,再重跑对应拒绝行。在此之前,该行不能进入回测或流动性计算。用一个“通常如此”的倍率补上,会使表面完整的数据包含未经确认的假设。
非法日期应回查原导出;重复键应比较两条内容,判断是重复导出还是数据修订。修复行要连接原拒绝记录和修复依据,未受影响的成功行保持原版本。重复导入同一文件时,也应识别相同输入,避免把修复结果再追加一次造成重复日期。
交给下游前,比较原文件与标准表的首末日期、逐证券行数,以及若干原始价格与成交量。检查代码文本、币种、复权和单位是否随文件一起交付;若这些元数据只写在人的聊天说明里,加载器仍可能按错误默认值解释。导入成功只证明当前数据交接,不证明全市场覆盖、公司行动处理正确或策略盈利。
以后来源表头、编码、导出版本或单位发生变化,都应重新打开映射测试。保留一个固定的小型回归样例,让成功行、重复键、非法日期和未知单位再次走到原来的分支。这样文件格式更新不会悄悄改变研究输入,也能让每次拒绝都有可处理的下一步。
给导入器与拒绝政策一起编号
保留简短导入清单,包括原文件引用、映射版本、编码、分隔符、日期格式、币种、价格口径和成交单位,并分别记录接受与拒绝数量。供应商后来只改了表头拼写,也要更新映射并重放同一四行样例,再接收更大的真实文件。字段名称变化不应通过模糊匹配悄悄绕过人工约定。
重复行优先级或未知单位处理变化,属于政策变更,不能称为纯外观维护。原先被拒绝的一行如今进入标准表,使用者应该能看到放行依据。保留旧拒绝与新决定之间的关系,避免一份旧研究引用的文件与新导入文件虽然同名,实际采用完全不同的数据治理规则。
真实导入器写出标准文件后,还应按声明约定重新打开,比较磁盘内容与内存中已接受记录。这个读回能发现输出编码、列序和引号缺陷,而成功解析输入无法覆盖这些错误。本文样例打印结构,采用它的文件导入器还要完成自己的写出与读回验证,不能把打印成功当作磁盘交付成功。
验收时可以按字段横向检查,也可以按证券纵向检查。横向检查成交量是否统一为股、价格是否同币种;纵向检查AAA按日期排序后有无重复与异常跳变。两种视角发现的问题不同,不能以一条成功记录代替整份文件的身份和单位核对。跳变本身也不该自动删除,先查公司行动或来源修订,必要时加入拒绝或待查表。
导入状态最好明确区分“文件已解析”“有效行已标准化”“下游已读回”。某一步完成后仍可交付部分成果,但不能用同一个成功标签掩盖后续未验收工作。这让使用文件的人知道哪些步骤可以继续,哪些问题仍需数据负责人处理。
常见问题
自动识别分隔符能代替映射吗?
只能辅助判断方言,仍需核对表头、引号字段和数值单位。
重复日期是否都应该删除?
不是。先判断是重复行、修订记录,还是需要更丰富主键的不同观测。