3. 核心字段详解(一)

逐笔成交数据里,字段数量往往有十几个甚至几十个,但真正决定“这一笔成交是什么”的,是四个基础字段:证券代码、交易时间、成交价格、成交数量。它们共同构成一条成交记录的“身份四元组”——缺一个,记录就不完整;错一个,后续所有统计都会失真。本节不讨论逐笔委托与逐笔成交的差异,而是把这四个字段逐一拆开,讲清它们的语义边界、精度约定,以及在读取时最容易踩的坑。

证券代码:不是字符串,而是带市场语义的标识

证券代码看似最简单,实则最容易在跨市场拼接时出错。A股市场中,同一串数字在不同交易所可能指向不同证券,因此代码字段通常需要与“市场标识”联合使用。常见做法是采用“市场前缀+代码”的形式,例如 SH600519、SZ000001,其中 SH 表示上海证券交易所,SZ 表示深圳证券交易所。若数据源只给出纯数字代码,读取时必须结合数据文件的市场属性或交易所字段还原,不能默认所有六位数字都属于同一市场。

另一个细节是前导零。证券代码在文件中若以数值类型存储,000001 会被读成 1,导致代码匹配失败。因此读取时应统一按字符串处理,并固定长度(A股一般为6位)。对于北交所、科创板、创业板等不同板块,代码段本身带有板块信息,但不要依赖代码段去推断交易规则,规则判断应交给独立的证券信息表。实践中建议在读取后立即做一次代码规范化:去空格、补前导零、拼接市场前缀,形成唯一主键,再进入后续处理。

交易时间:精度决定能否做时序对齐

交易时间字段的语义是“该笔成交在交易所撮合系统中发生的时间”,而不是数据落地时间或接收时间。逐笔成交的时间精度在不同数据源中差异很大:有的精确到秒(HH:MM:SS),有的精确到毫秒甚至微秒。精度直接决定了你能否做同一时刻多笔成交的排序、能否与逐笔委托做时序对齐、能否计算撮合延迟。

读取时间字段时,第一件事是确认它的时间基准:是交易所本地时间还是UTC,是否包含日期。很多逐笔文件只给“日内时间”,日期需要从文件名或交易日字段补全。第二件事是确认精度与格式:09:30:00.500 与 093000500 是两种常见写法,前者带分隔符,后者是紧凑数字串,解析方式完全不同。第三件事是注意集合竞价时段:开盘集合竞价(如 09:15–09:25)和收盘集合竞价产生的成交,时间戳可能集中在某一秒,不能简单按时间排序就认为是最优撮合顺序,必要时应结合成交编号字段辅助排序。

建议在读取阶段就把时间统一转换为“交易日+日内毫秒数”的整数形式存储,既避免字符串比较的性能问题,也避免跨日拼接时的歧义。展示时再格式化回可读时间。

成交价格:定点小数,禁用浮点累加

成交价格是逐笔成交的核心数值字段,语义为“该笔成交的每股成交价”。A股价格通常以“元”为单位,保留两位小数,但部分品种(如基金、债券、科创板部分标的)可能有三位小数。价格字段的精度必须从数据字典中确认,不能凭经验假设两位小数。

工程上最重要的一条原则是:价格不要用二进制浮点数做累加和比较。例如 0.1 + 0.2 在浮点下不等于 0.3,当你要计算成交金额、均价或做价格相等判断时,误差会累积。推荐做法是将价格按最小价格单位转换为整数存储,例如两位小数乘以100、三位小数乘以1000,用整数做运算,展示时再除以对应倍数。成交金额 = 整数价格 × 整数数量 ÷ 精度倍数,全程保持整数运算,最后一步才转小数。

此外要注意价格的有效范围与异常值。读取后应做基本校验:价格是否大于0、是否落在当日涨跌停范围内、是否与昨收价存在数量级偏差。逐笔数据中偶发的0价格或极大值,往往是字段错位或解析错误,而不是真实成交,必须在入库前拦截。

成交数量:单位是股还是手,必须确认

成交数量字段的语义是“该笔成交的股数”。但不同数据源的单位并不统一:有的以“股”为单位,有的以“手”为单位(1手=100股)。若把“手”当“股”使用,成交量会整体缩小100倍,量价分析全部失真。读取时必须从数据字典确认单位,并在字段命名上体现,例如 volume_shares 与 volume_lots 分开命名,避免混用。

数量字段通常是整数,但也要注意是否存在零成交或负值。正常逐笔成交数量应为正整数,且一般为100股的整数倍(部分市场允许零股成交,如卖出零股)。若出现非整数或负值,应视为异常记录单独隔离。数量与价格联合校验也很有效:成交金额 = 价格 × 数量,若某笔记录的金额明显偏离同价位其他成交,往往说明价格或数量字段解析有误。

逐笔成交基础字段:语义 · 精度 · 读取校验 证券代码 市场前缀 + 6位代码 SH600519 / SZ000001 按字符串读取,补前导零 禁止数值化丢零 交易时间 撮合发生时刻 秒 / 毫秒 / 微秒 确认时区与日期补全 统一转整数毫秒 成交价格 每股成交价(元) 2位或3位小数 转整数最小单位运算 禁用浮点累加比较 成交数量 股 或 手(1手=100股) 正整数为主 字段名标明单位 拦截零值与负值 联合校验:成交金额 = 价格 × 数量 金额偏离同价位成交 → 回查价格/数量字段解析 价格越界、数量非正 → 隔离异常记录 规范化记录:唯一主键 + 整数时间 + 整数价格 进入后续统计与逐笔分析 四个字段共同构成一条成交记录的身份四元组,任一字段精度或单位错误都会传导至全部下游计算

读取时的规范化顺序与示例

把四个字段放在一起看,读取流程应当有固定顺序:先规范化代码形成主键,再解析时间并统一为整数,然后按精度把价格转成整数,最后确认数量单位并做正整数校验。下面是一段示意性的处理逻辑,参数为教学示例,实际精度倍数需以数据字典为准:

# 示例:单条逐笔成交记录的字段规范化(参数为教学假设)
raw = {"code": "600519", "market": "SH",
       "time": "09:30:00.500", "price": "1680.50", "volume": 300}

# 1) 代码:补零 + 市场前缀
code = raw["market"] + raw["code"].zfill(6)        # "SH600519"

# 2) 时间:交易日 + 日内毫秒
h, m, s = raw["time"].split(":")
sec, ms = s.split(".")
t_int = ((int(h)*60 + int(m))*60 + int(sec))*1000 + int(ms)   # 34200500

# 3) 价格:两位小数 → 整数分
price_int = int(round(float(raw["price"]) * 100))  # 168050

# 4) 数量:确认单位为股
vol_int = int(raw["volume"])                        # 300

# 5) 金额:整数运算,最后一步转小数
amount = price_int * vol_int / 100                  # 504150.0 元

这段逻辑的关键不在代码本身,而在每一步都保留了“精度来源”的可追溯性:价格乘的是100还是1000,取决于该证券的最小价格单位;数量是股还是手,取决于数据源说明。把这些约定写进读取层的配置,而不是散落在各处硬编码,才能在更换数据源时快速定位问题。

常见错误与判断依据

实际读取中,四类错误最高频:代码被数值化导致前导零丢失,表现为部分股票代码匹配不上;时间只保留到秒,表现为同一秒内多笔成交无法排序;价格用浮点累加,表现为成交金额与交易所公布值存在分位差异;数量单位误判,表现为成交量整体差100倍。判断依据也很直接:用当日总成交量与行情软件或交易所汇总值比对,用成交金额与价格×数量的关系抽查若干笔,用代码清单做全量匹配。只要这三项校验通过,四个基础字段的读取基本可信。

需要强调的是,这四个字段的精度约定一旦确定,就应在整个数据管道中保持一致,包括存储类型、计算方式和展示格式。中途混用不同精度,比一开始就选错更难排查。把语义写进字段名、把精度写进配置、把校验放在入库前,是这一节最值得带走的工程习惯。