4. 数据获取与处理:Python环境搭建、数据接口与清洗对齐
做碳配额价差交易,说白了就是跟数据打交道。我见过不少新手,策略模型写得花里胡哨,结果一跑实盘就崩——十有八九是数据源没处理好。今天咱们就把这第一步踩实了。
4.1 Python环境搭建:别小看这一步
我个人习惯用Anaconda来管理Python环境。为什么?因为碳金融涉及的数据包、回测框架、机器学习库,依赖关系复杂得很。你想想看,一个numpy版本不对,整个项目可能就炸了。
推荐环境配置:
- Python 3.8+(3.9或3.10更稳,我踩过3.11的坑)
- Anaconda 或 Miniconda
- IDE:VS Code + Jupyter Notebook 混用
搭建步骤其实就三条命令的事:
# 创建独立环境,别污染base
conda create -n carbon_trading python=3.9
# 激活环境
conda activate carbon_trading
# 安装核心库
pip install pandas numpy matplotlib seaborn scipy statsmodels
我的小习惯:每次新项目都新建一个环境。曾经有一次,我为了省事在base环境里装了各种包,结果某天更新一个库,把整个交易系统的依赖搞崩了。嗯,从那以后我再也不敢偷懒了。
4.2 数据接口:Wind vs 聚宽
做碳配额价差,数据源是命根子。国内主流就两个:Wind(万得)和聚宽(JoinQuant)。我两个都用过,说说我的感受。
4.2.1 Wind接口
Wind是机构标配,数据全、更新快。但有个问题——你得有Wind终端账号,而且得装他们的客户端。个人玩家基本没戏。
# Wind Python接口示例
from WindPy import w
w.start()
# 获取碳配额现货数据
# 代码:广州碳排放权交易所(GDEA)
data = w.wsd("GDEA.SHE", "close", "2023-01-01", "2023-12-31", "")
print(data)
注意:Wind的Python接口叫WindPy,不是所有环境都能直接装。我曾经在Linux服务器上折腾了一整天,最后发现Wind官方只支持Windows。所以,如果你用Mac或Linux,建议用聚宽或者直接爬取交易所公开数据。
4.2.2 聚宽接口
聚宽对个人用户友好得多。注册个账号,就能用他们的数据API。虽然碳配额数据没有Wind那么全,但做策略回测足够了。
# 聚宽数据获取示例
from jqdatasdk import *
auth('your_account', 'your_password')
# 获取碳配额期货数据
# 注意:聚宽的数据代码格式与Wind不同
df = get_price('GDEA.XSHE', start_date='2023-01-01', end_date='2023-12-31', frequency='daily')
print(df.head())
避坑指南:我曾经在聚宽上发现某天的碳配额数据突然跳空,后来一查是交易所休市但聚宽没更新。所以,拿到数据后一定要做完整性检查——这个咱们下一节细说。
4.3 数据清洗与对齐:这才是真功夫
数据拿到手,别急着跑策略。我见过太多人,数据里一堆空值、异常值,直接扔进模型,结果回测曲线漂亮得不行,实盘一塌糊涂。为什么?因为数据没对齐。
4.3.1 缺失值处理
碳配额市场有个特点:不是每天都有交易。尤其是现货市场,有时候一周才成交几笔。这就导致数据里大量缺失值。
import pandas as pd
import numpy as np
# 假设这是从接口拿到的原始数据
df = pd.read_csv('carbon_data.csv', index_col='date', parse_dates=True)
# 检查缺失值
print(df.isnull().sum())
# 处理方式:前向填充(我常用的方法)
# 因为碳配额价格有粘性,用前一天的价格填充比较合理
df.fillna(method='ffill', inplace=True)
# 如果连续缺失超过5天,我建议直接删除
df = df[df.isnull().sum(axis=1) == 0]
关键点:现货和期货的交易日历不一样。现货可能周一到周五都交易,但期货只有工作日。如果你直接把两个序列拼在一起,日期对不上,价差计算就是错的。
4.3.2 数据对齐
对齐的核心就一句话:找到两个序列的共同交易日,然后对齐。
# 假设spot_df是现货数据,futures_df是期货数据
# 找到共同日期
common_dates = spot_df.index.intersection(futures_df.index)
# 对齐
spot_aligned = spot_df.loc[common_dates]
futures_aligned = futures_df.loc[common_dates]
# 计算价差
spread = futures_aligned['close'] - spot_aligned['close']
我曾经踩过的坑:有一次我用merge函数直接合并两个DataFrame,没注意索引顺序。结果价差序列里混进了不少错位数据,回测出来的夏普比率高达3.5。还好实盘前我做了个可视化检查,发现价差曲线在某个时间段突然跳变——原来是数据没对齐。从那以后,我每次对齐完都会画个图看一眼。
4.3.3 异常值检测
碳配额市场偶尔会出现极端价格,比如某天突然暴涨10%。这种异常值,你得判断是市场真实波动还是数据错误。
# 简单异常值检测:用3倍标准差
mean = spread.mean()
std = spread.std()
outliers = spread[(spread > mean + 3*std) | (spread < mean - 3*std)]
print(f"发现 {len(outliers)} 个异常值")
print(outliers)
# 我的处理方式:先标记,再人工判断
# 不要自动删除,万一那是真实的套利机会呢?
个人经验:2022年7月,广东碳配额现货突然暴跌,我一开始以为是数据错误,后来一查是政策调整。所以,异常值先别急着删,去查查新闻。数据清洗不是机械操作,得结合市场背景。
4.4 知识体系总览
说了这么多,咱们用一张图把数据获取与处理的逻辑串起来。你想想看,整个流程其实就三步:拿数据、洗数据、对齐数据。
这张图把咱们今天讲的内容串起来了。你想想看,从数据获取到最终能用的价差序列,中间每一步都不能省。我刚开始做的时候,总觉得清洗数据浪费时间,后来发现——数据质量决定了策略的天花板。
总结一下:
- 环境搭建用conda,别偷懒
- 数据接口选适合自己的,Wind全但贵,聚宽方便但数据有限
- 清洗对齐是核心,缺失值用前向填充,异常值要人工判断
- 对齐后一定要可视化检查,别信数字
好了,数据这块咱们就聊到这儿。下一节咱们开始真正搭建价差策略模型——到时候你会感谢今天认真清洗数据的自己。