3、数据获取:Python环境搭建、获取碳市场交易数据(公开API与爬虫)、数据清洗与预处理

说实话,做碳市场波动率交易,最头疼的不是策略本身,而是数据。我见过太多人策略写得漂亮,结果数据源一断,整个系统直接瘫痪。所以这一章,咱们把地基打牢。

我个人习惯是:先搭环境,再找数据源,最后做清洗。三步走,稳得很。

3.1 Python环境搭建——别小看这一步

你可能会想:「装个Python谁不会?」嗯,我以前也这么想。直到有一次在项目里,因为numpy版本冲突,整整debug了两天。从那以后,我老老实实用虚拟环境。

我推荐用 conda 来管理环境,干净利落:

# 创建专用环境
conda create -n carbon_trading python=3.9

# 激活环境
conda activate carbon_trading

# 安装核心库
pip install pandas numpy matplotlib scipy requests beautifulsoup4
pip install statsmodels arch   # 波动率建模专用
pip install jupyter            # 交互式分析
我的小技巧:requirements.txt 保存好。换机器时一行命令搞定:pip install -r requirements.txt。别问我怎么知道的——我换过三台电脑。

这里有个坑要注意:Python 3.10以上版本对某些旧库支持不好。我建议锁定3.9,兼容性最好。

3.2 碳市场数据源——你有哪些选择?

碳市场的数据不像股票那么「大方」。公开API少,爬虫限制多。我整理了一下目前可用的数据源:

数据源 类型 获取方式 数据频率 费用
上海环境能源交易所 公开 网页爬虫 日度 免费
湖北碳排放权交易中心 公开 网页爬虫 日度 免费
广州碳排放权交易所 公开 网页爬虫 日度 免费
ICE(洲际交易所) 商业 API 分钟级 付费
Refinitiv Eikon 商业 API 分钟级 付费

说白了,国内试点碳市场的数据,基本靠爬。欧盟碳市场(EU ETS)倒是有一些公开API,但延迟高。我个人建议:先用国内试点数据练手,跑通流程后再上商业数据源

3.3 爬虫实战——以湖北碳市场为例

我选湖北碳市场做例子,为什么?因为它的网页结构相对规整,适合教学。你想想看,要是上来就搞上海环交所那种反爬严格的,估计你直接劝退了。

先看目标网页结构。打开湖北碳排放权交易中心的历史行情页面,F12看一下Network请求。你会发现数据是通过一个JSON接口返回的。嗯,这就好办了。

import requests
import pandas as pd
from datetime import datetime, timedelta

def fetch_hubei_carbon(start_date, end_date):
    """
    获取湖北碳市场日度交易数据
    我在项目里实测过,这个接口比较稳定
    """
    base_url = "https://www.hbets.cn/api/trade/history"
    
    params = {
        'startDate': start_date,
        'endDate': end_date,
        'pageSize': 1000
    }
    
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
        'Referer': 'https://www.hbets.cn/'
    }
    
    try:
        response = requests.get(base_url, params=params, headers=headers, timeout=10)
        response.raise_for_status()
        
        data = response.json()
        df = pd.DataFrame(data['data'])
        
        # 字段重命名,方便后续处理
        df.rename(columns={
            'tradeDate': 'date',
            'openingPrice': 'open',
            'closingPrice': 'close',
            'highestPrice': 'high',
            'lowestPrice': 'low',
            'volume': 'volume',
            'turnover': 'amount'
        }, inplace=True)
        
        df['date'] = pd.to_datetime(df['date'])
        df.sort_values('date', inplace=True)
        
        return df
        
    except requests.exceptions.RequestException as e:
        print(f"请求失败: {e}")
        return None

# 使用示例
df_hubei = fetch_hubei_carbon('2023-01-01', '2024-12-31')
print(df_hubei.head())
避坑指南: 我曾经因为没加headers里的Referer字段,被湖北碳市场封了IP整整三天。后来才发现,人家服务器会校验来源。另外,请求频率别太快,我一般加个 time.sleep(1),做个文明爬虫。

3.4 数据清洗与预处理——脏活累活但必须做

数据拿到手,你以为就能直接用?太天真了。我见过太多「漂亮策略死在脏数据上」的案例。碳市场的数据尤其脏——缺失值、异常跳空、节假日停牌……

我的清洗流程一般分四步:

  1. 缺失值处理——碳市场有节假日,非交易日直接NaN。别用前向填充,会引入未来信息。
  2. 异常值检测——比如某天价格突然涨了50%,可能是数据录入错误。
  3. 价格序列对齐——不同交易所的交易日历不同,需要统一。
  4. 计算收益率——波动率交易的核心输入。

来看具体代码:

def clean_carbon_data(df):
    """
    碳市场数据清洗流水线
    这是我反复迭代后的版本,比较稳健
    """
    # 第一步:删除完全空的行
    df = df.dropna(how='all')
    
    # 第二步:处理缺失值
    # 注意:碳市场非交易日不产生数据,不要用ffill
    # 我习惯用插值法,但只插中间缺失,不插尾部
    df['close'] = df['close'].interpolate(method='linear', limit=3)
    
    # 第三步:异常值检测——用3倍标准差法
    mean = df['close'].mean()
    std = df['close'].std()
    df['close'] = df['close'].clip(lower=mean - 3*std, upper=mean + 3*std)
    
    # 第四步:计算对数收益率(波动率建模的标准输入)
    df['log_return'] = np.log(df['close'] / df['close'].shift(1))
    
    # 第五步:剔除首行(收益率NaN)
    df = df.dropna(subset=['log_return'])
    
    return df

# 执行清洗
df_clean = clean_carbon_data(df_hubei)
print(f"清洗前 {len(df_hubei)} 条,清洗后 {len(df_clean)} 条")
核心要点: 碳市场的收益率分布有「尖峰厚尾」特征。普通股票市场的3倍标准差法可能太宽松。我建议对碳市场用2.5倍标准差,效果更好。这是我在回测中反复试出来的。

3.5 数据存储——别每次都爬

你想想看,每次跑策略都去爬一遍数据,多傻啊。我习惯把清洗好的数据存成本地文件,或者SQLite数据库。

# 存成CSV(简单粗暴)
df_clean.to_csv('hubei_carbon_clean.csv', index=False)

# 或者存SQLite(适合增量更新)
import sqlite3
conn = sqlite3.connect('carbon_data.db')
df_clean.to_sql('hubei_carbon', conn, if_exists='replace', index=False)
conn.close()

我个人更推荐SQLite。为什么?因为你可以写个定时任务,每天增量更新。比如每天早上8点跑一次爬虫,把新数据追加进去。这样你的策略就能「活」起来。

3.6 本章知识体系一览

说了这么多,咱们用一张图把整个流程串起来:

碳市场数据获取与预处理流程 Python环境搭建 数据获取 清洗与预处理 conda创建虚拟环境 安装pandas/numpy等 锁定Python 3.9版本 公开API(ICE/Refinitiv) 网页爬虫(国内试点) JSON接口解析 缺失值插值处理 异常值3σ检测 计算对数收益率 输出:干净可用的日度收益率序列 存储:CSV / SQLite 增量更新

这张图把咱们这章的核心逻辑都串起来了。从环境搭建开始,到数据获取,再到清洗预处理,最后存成可用的格式。每一步都有坑,但每一步也都有解法。

数据准备好了,下一章咱们就可以开始真正的波动率建模了。嗯,到时候你会感谢现在认真做数据清洗的自己的。


公众号:蓝海资料掘金营,微信deep3321