数据采集与清洗:成本数据来源、数据质量检查、缺失值处理、异常值检测

做执行成本分析,最怕什么?

不是模型不够复杂,也不是算法不够高级。我最怕的是——数据本身是脏的。你想想看,如果源头数据就有问题,后面再漂亮的图表、再精准的算法,都是白搭。这就像盖楼,地基没打好,装修再豪华也住不踏实。

所以今天这一章,咱们就聊聊数据采集与清洗。我把它叫做「成本分析的守门人」。

一、成本数据从哪里来?

数据来源这事儿,说起来简单,做起来门道不少。我这些年接触过的项目,成本数据来源大致分三类:

数据来源 典型系统 特点
交易系统 OMS、EMS 实时、高频、量大
清算系统 结算平台、托管行 准确、但有时滞
外部数据源 交易所、数据供应商 标准化、但需付费

我个人习惯,优先用清算系统的数据做基准。为什么?因为它经过了多方对账,准确度最高。交易系统的数据虽然快,但经常有「未确认」的状态,容易误导分析。

小技巧: 我建议你至少保留两个独立数据源。一个做主数据,一个做交叉验证。我在项目中遇到过,单靠一个数据源,结果某天系统出bug,整整一周的成本数据全偏了。还好有备份源,不然报告交上去就尴尬了。

二、数据质量检查——别急着分析

拿到数据后,第一件事不是跑模型,而是做质量检查。我一般会问自己三个问题:

  1. 数据完整吗? 有没有缺失的字段?
  2. 数据一致吗? 同一笔交易在不同系统里对得上吗?
  3. 数据合理吗? 有没有明显超出正常范围的值?

举个例子,我曾经接手一个项目,对方说「数据都整理好了」。结果我一查,交易日期字段里居然有「2023-02-30」这种值。2月哪来的30号?这就是典型的数据质量问题。

我常用的检查脚本长这样:

# 数据质量快速检查
import pandas as pd

df = pd.read_csv('execution_cost.csv')

# 1. 检查缺失值
print("缺失值统计:")
print(df.isnull().sum())

# 2. 检查重复行
print(f"重复行数:{df.duplicated().sum()}")

# 3. 检查数值范围
print("交易金额范围:", df['trade_amount'].min(), "-", df['trade_amount'].max())
注意: 数据质量检查不是一次性工作。我建议每次跑分析前都做一遍,哪怕只是简单的检查。因为数据源可能随时变化,今天没问题的数据,明天可能就出幺蛾子。

三、缺失值处理——别直接删

缺失值怎么处理?很多人第一反应是「删掉」。嗯,这确实是最简单的方法,但未必是最合适的。

我遇到过的情况是这样的:某次分析中,有5%的交易缺少「佣金」字段。如果直接删掉,那这5%的交易就完全被排除在分析之外了。但问题是,这些交易恰好都是大额交易,佣金比例本来就低。删掉它们,整体成本率反而被高估了。

所以我的处理原则是:

  • 缺失率 < 1%:直接删除,影响不大
  • 缺失率 1%-5%:用均值/中位数填充,或者用同类交易的平均值
  • 缺失率 > 5%:必须搞清楚为什么缺失,再决定处理方式

代码实现也不复杂:

# 缺失值处理示例
# 用同类交易的中位数填充佣金缺失值
df['commission'] = df.groupby('asset_class')['commission']\
                     .transform(lambda x: x.fillna(x.median()))
核心原则: 缺失值处理没有标准答案。关键是要理解数据背后的业务逻辑,而不是机械地套公式。

四、异常值检测——别被「异常」骗了

异常值检测,说白了就是找「不对劲」的数据。但什么是「不对劲」?这其实是个主观判断。

我记得有一次,分析某只股票的成交成本,发现有一笔交易的佣金是其他交易的10倍。第一反应是「异常值,删掉」。但仔细一查,那笔交易是紧急大宗交易,走的是人工通道,佣金确实高。这不是异常,这是特殊情况。

所以我的做法是:先检测,再判断,最后处理。

常用的检测方法:

  • Z-score 方法:适合正态分布的数据
  • IQR 方法:适合偏态分布,更稳健
  • 业务规则:比如佣金不能为负,交易量不能超过持仓量

我一般先用IQR方法做个初步筛选:

# IQR异常值检测
Q1 = df['commission_rate'].quantile(0.25)
Q3 = df['commission_rate'].quantile(0.75)
IQR = Q3 - Q1

lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR

outliers = df[(df['commission_rate'] < lower_bound) | 
              (df['commission_rate'] > upper_bound)]
print(f"检测到 {len(outliers)} 个异常值")
避坑指南: 我曾经犯过一个错误——把所有异常值都标记为「无效」。后来发现,有些异常值其实是市场极端波动导致的真实成本。所以现在我的做法是:异常值单独标记,但不自动删除。先人工复核,再决定是保留、修正还是剔除。

五、知识体系总览

说了这么多,咱们用一张图来梳理一下本章的核心逻辑:

数据采集与清洗核心流程 数据来源 交易系统 | 清算系统 | 外部源 数据质量检查 完整性 | 一致性 | 合理性 缺失值处理 删除 | 填充 | 业务判断 异常值检测 Z-score | IQR | 业务规则 人工复核 判断是否真正异常 迭代优化 ✅ 干净、可信的成本数据

这张图其实就说明了一个道理:数据清洗不是线性的,而是循环迭代的过程。你可能会在异常值检测时发现新的数据质量问题,然后回到质量检查环节重新审视。这很正常,别嫌麻烦。

好了,数据采集与清洗这部分就聊到这儿。记住一句话:花在数据清洗上的时间,永远不会浪费。你省掉的每一步,最后都会在分析结果里「还回来」。

专注资料整理