第二章:数据基础——产业链数据来源、清洗与存储
做量化分析,最怕什么?不是模型不灵,而是数据本身就有问题。我见过太多人花三个月搭模型,最后发现是原始数据里有个字段对不齐。嗯,这一章我们就聊聊数据基础——说白了,就是你的分析地基。
2.1 产业链数据从哪里来?
能源化工产业链的数据源,我把它分成三类:公开数据、行业数据库、爬虫。每一类都有它的脾气。
2.1.1 公开数据
公开数据是最容易拿到的,但也是最需要小心的。比如国家统计局、发改委、海关总署这些官网,会发布原油产量、炼厂开工率、进出口量等数据。我个人习惯是优先用这些官方数据,因为权威性高。
但有个坑——更新频率不统一。有的按月,有的按季度,甚至有的按年。你想想看,做日频模型的人拿到月频数据,怎么对齐?
2.1.2 行业数据库
行业数据库是主力。像隆众资讯、卓创资讯、百川盈孚这些,覆盖了从原油到化工品的全链条数据。价格、库存、开工率、利润……基本都有。
这类数据质量相对稳定,但价格不便宜。我记得有一次客户预算有限,只买了三个品种的数据,结果分析时发现缺少上下游联动数据,模型效果大打折扣。
| 数据库名称 | 覆盖品种 | 更新频率 | 价格水平 |
|---|---|---|---|
| 隆众资讯 | 原油、成品油、化工品 | 日/周/月 | 中等 |
| 卓创资讯 | 能源、化工、塑料 | 日/周 | 中等偏高 |
| 百川盈孚 | 煤化工、化肥、氯碱 | 周/月 | 中等 |
2.1.3 爬虫获取数据
有些数据公开数据库没有,或者更新太慢,那就得自己动手爬。比如一些现货交易平台的实时报价、港口库存的公告信息。
我曾经爬过一个化工品交易平台的报价数据,每天定时跑一次。但要注意——爬虫有法律风险,而且网站反爬措施越来越严。我的建议是:能买到的数据尽量买,爬虫只用来补充非核心数据。
2.2 数据清洗与预处理
数据拿到手,第一件事不是建模,而是清洗。我常说一句话:垃圾进,垃圾出。再好的模型也救不了脏数据。
2.2.1 常见的数据问题
- 缺失值:某个品种的库存数据突然少了一周,怎么办?
- 异常值:价格突然跳涨10倍,是数据错误还是市场异动?
- 重复值:同一时间点出现两条相同记录。
- 格式不一致:有的日期是"2024-01-01",有的是"2024/1/1"。
为什么会这样?很多时候是数据源本身的问题。比如行业数据库的录入员手误,或者爬虫程序在某个时间点重复抓取。
2.2.2 清洗流程
我一般按这个顺序处理:
- 去重:检查并删除完全重复的行
- 格式统一:日期、数值、单位全部标准化
- 缺失值处理:根据业务逻辑选择填充或删除
- 异常值检测:用3σ或IQR方法识别
- 对齐时间戳:不同频率的数据统一到同一时间轴
核心原则:清洗逻辑必须可复现。不要手动改数据,要用代码记录每一步操作。这样出了问题还能回溯。
2.2.3 代码示例
下面是我常用的清洗函数,用pandas实现:
import pandas as pd
import numpy as np
def clean_energy_data(df):
# 1. 去重
df = df.drop_duplicates()
# 2. 日期统一
df['date'] = pd.to_datetime(df['date'])
# 3. 缺失值处理(向前填充,最多填充3天)
df = df.fillna(method='ffill', limit=3)
# 4. 异常值检测(3σ法)
for col in ['price', 'inventory']:
mean = df[col].mean()
std = df[col].std()
df[col] = df[col].clip(mean - 3*std, mean + 3*std)
return df
这段代码看起来简单,但我在实际项目中踩过坑。比如向前填充——如果连续缺失超过3天,说明数据源可能出了问题,这时候填充反而会掩盖问题。
2.3 数据存储:SQLite还是CSV?
数据清洗完了,得找个地方存起来。我常用的两种方式:SQLite和CSV。各有各的适用场景。
2.3.1 CSV:简单直接
CSV的好处是轻量、通用、任何人都能打开。适合小规模数据(几万行以内)或者临时分析。
但缺点也很明显:没有索引,查询慢;不支持并发写入;容易损坏。我曾经用CSV存了半年的日频数据,结果有一次程序崩溃,文件写到一半就坏了,损失了两周的数据。
2.3.2 SQLite:轻量级数据库
SQLite是我个人最推荐的方式。它不需要安装服务器,一个文件就是一个数据库,支持SQL查询,性能也够用。
对于能源化工产业链的数据,我一般这样设计表结构:
-- 品种信息表
CREATE TABLE products (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
category TEXT,
unit TEXT
);
-- 价格数据表
CREATE TABLE prices (
product_id INTEGER,
date TEXT,
price REAL,
source TEXT,
FOREIGN KEY (product_id) REFERENCES products(id)
);
-- 库存数据表
CREATE TABLE inventory (
product_id INTEGER,
date TEXT,
inventory REAL,
location TEXT,
FOREIGN KEY (product_id) REFERENCES products(id)
);
这样设计的好处是:品种信息只存一次,价格和库存分开存储,查询时用JOIN关联。效率比CSV高得多。
2.3.3 如何选择?
| 场景 | 推荐方式 | 原因 |
|---|---|---|
| 单次分析、数据量小 | CSV | 简单快速,无需额外工具 |
| 长期存储、频繁查询 | SQLite | 支持SQL,数据完整性强 |
| 团队协作、多用户访问 | PostgreSQL | 支持并发,但超出本章范围 |
2.4 知识体系框架
下面这张图,是我对本章知识结构的总结。你可以把它当作一个思维导图来看:
这张图把数据基础分成了三条线:来源、清洗、存储。三者缺一不可。我见过太多人只关注模型算法,却忽略了数据本身。记住一句话:数据质量决定模型上限。
避坑指南:我曾经在一个项目中,花了两个月搭建LSTM模型,结果预测效果一直不好。最后排查发现,原始数据里有一个品种的单位是"吨",另一个是"千克",但字段名完全一样。这种低级错误,往往是最致命的。
好了,数据基础就聊到这里。下一章我们会进入量化模型的核心——特征工程。但在此之前,先把数据基础打牢。你想想看,地基不稳,楼盖得再高也是白搭。