用Python和akshare搞定三大交易所期权数据:从深交所、上交所到中金所的完整爬虫实战

张开发
2026/4/18 12:57:23 15 分钟阅读

分享文章

用Python和akshare搞定三大交易所期权数据:从深交所、上交所到中金所的完整爬虫实战
Python实战三大交易所期权数据高效采集与处理指南金融数据是量化交易和投资分析的基石而期权数据因其复杂的结构和丰富的维度对采集和处理提出了更高要求。本文将带你深入探索如何用Python和akshare库构建一个健壮的期权数据采集系统覆盖深交所、上交所和中金所三大市场。1. 环境准备与基础配置在开始采集数据前我们需要搭建一个稳定的Python环境。推荐使用Anaconda创建独立环境避免依赖冲突conda create -n option_data python3.8 conda activate option_data pip install akshare pandas requests lxml openpyxlakshare作为国内金融数据的瑞士军刀其优势在于统一接口封装了各交易所的复杂API内置交易日历等实用工具函数持续维护更新适应交易所接口变化关键配置点设置合理的请求间隔建议≥500ms避免触发反爬准备持久化存储方案本地文件或数据库配置日志系统记录运行状态提示三大交易所的数据更新频率不同深交所和上交所通常是T1中金所部分数据实时更新采集前需了解各品种的具体规则2. 深交所期权数据采集实战深交所采用XLSX格式提供期权数据这种二进制格式需要特殊处理。我们先看核心采集函数def fetch_szse_option(date): base_url http://www.szse.cn/api/report/ShowReport params { SHOWTYPE: xlsx, CATALOGID: option_hyfxzb, TABKEY: tab1, txtSearchDate: date.strftime(%Y-%m-%d) } try: with requests.get(base_url, paramsparams, timeout10) as resp: resp.raise_for_status() # 使用BytesIO避免临时文件 return pd.read_excel(BytesIO(resp.content), engineopenpyxl) except Exception as e: logger.error(f深交所数据获取失败 {date}: {str(e)}) return None常见问题解决方案问题类型现象解决方案乱码问题Excel打开显示乱码强制指定编码为gbk格式变化列名或结构变更添加版本检查逻辑网络超时连接中断实现自动重试机制数据清洗的关键步骤统一日期格式为YYYY-MM-DD处理缺失值特别是价外期权数据标准化合约代码格式转换百分比数据为小数# 数据清洗示例 def clean_szse_data(raw_df): df raw_df.copy() # 统一合约代码格式 df[合约代码] df[合约代码].str.replace( , ) # 转换涨跌幅 df[涨跌幅] df[涨跌幅].str.rstrip(%).astype(float) / 100 # 处理成交量单位 df[成交量] df[成交量] * 10000 # 万手→手 return df3. 上交所CSV流式数据处理上交所采用CSV流式接口这种格式虽然结构简单但需要特别注意编码问题def fetch_sse_option(date): date_str date.strftime(%Y%m%d) url fhttp://query.sse.com.cn/derivative/downloadRisk.do?trade_date{date_str}productType0 headers { Referer: http://www.sse.com.cn/, User-Agent: Mozilla/5.0 } try: resp requests.get(url, headersheaders, streamTrue) resp.raise_for_status() # 流式处理大文件 lines (line.decode(gbk) for line in resp.iter_lines()) reader csv.reader(lines) return pd.DataFrame(list(reader)[1:], columnslist(reader)[0]) except Exception as e: logger.error(f上交所数据获取失败 {date}: {str(e)}) return None性能优化技巧使用streamTrue避免大文件内存溢出生成器表达式逐行处理节省内存并行下载多个日期的数据需控制并发数数据验证环节特别重要def validate_sse_data(df): required_cols [合约编码, 行权价, 到期日, 前结算价] if not all(col in df.columns for col in required_cols): raise ValueError(缺少必要字段可能接口已变更) # 检查异常值 if (df[成交量] 0).any(): raise ValueError(成交量出现负值) return True4. 中金所XML数据解析实战中金所采用XML格式这种结构化数据需要特定的解析方法def fetch_cffex_option(date): date_str date.strftime(%Y%m%d) url fhttp://www.cffex.com.cn/sj/hqsj/rtj/{date_str[:6]}/{date_str[-2:]}/index.xml try: resp requests.get(url) resp.raise_for_status() root etree.fromstring(resp.content) records [] for daily_data in root.xpath(//dailydata): record {} for child in daily_data.getchildren(): record[child.tag] child.text records.append(record) return pd.DataFrame(records) except Exception as e: logger.error(f中金所数据获取失败 {date}: {str(e)}) return NoneXML解析注意事项使用lxml比内置xml模块性能更好XPath语法要适配实际XML结构处理命名空间如果有注意编码声明是否匹配实际内容字段映射表示例XML节点数据库字段类型说明instrumentidcontract_idVARCHAR合约代码tradingdaytrade_dateDATE交易日openpriceopenDECIMAL开盘价volumevolumeBIGINT成交量5. 工程化增强与异常处理生产环境中的数据采集需要更强的鲁棒性重试机制实现from tenacity import retry, stop_after_attempt, wait_exponential retry(stopstop_after_attempt(3), waitwait_exponential(multiplier1, min4, max10)) def fetch_with_retry(url, paramsNone): response requests.get(url, paramsparams, timeout15) response.raise_for_status() return response完整的数据处理流水线获取交易日历过滤节假日分批获取原始数据数据验证和质量检查转换和标准化持久化存储生成采集报告def process_pipeline(start_date, end_date): trade_dates get_trade_dates(start_date, end_date) results [] for date in trade_dates: # 三大交易所并行采集 szse_data fetch_szse_option(date) sse_data fetch_sse_option(date) cffex_data fetch_cffex_option(date) # 数据校验和转换 validated_data validate_and_transform( szse_data, sse_data, cffex_data ) # 存储到数据库 save_to_database(validated_data) results.append(validated_data) generate_report(results) return results6. 数据存储方案选型根据数据量和使用场景可以选择不同的存储方案方案对比存储类型优点缺点适用场景CSV文件简单直观查询效率低小规模临时分析SQLite零配置并发性能差个人研究MySQL成熟稳定需要维护中小团队ClickHouse分析性能强事务支持弱大数据量分析数据库建模示例# 使用SQLAlchemy定义数据模型 from sqlalchemy import Column, Integer, String, Date, Numeric class OptionContract(Base): __tablename__ option_contracts id Column(Integer, primary_keyTrue) exchange Column(String(10)) # SZSE/SSE/CFFEX contract_code Column(String(20)) trade_date Column(Date) open_price Column(Numeric(12,4)) volume Column(Integer) # 其他字段...7. 数据质量监控与分析采集到的数据需要持续监控质量关键监控指标数据完整性是否缺少交易日字段填充率缺失值比例数值合理性价格是否在合理范围跨交易所一致性相同标的的定价关系def quality_check(df): report { date_coverage: check_date_coverage(df), missing_values: calculate_missing_rate(df), price_consistency: check_price_logic(df), volume_abnormal: detect_volume_outliers(df) } return report实际项目中我们会用Jupyter Notebook进行探索性分析# 分析历史波动率 df[daily_return] df[close].pct_change() df[hist_vol] df[daily_return].rolling(20).std() * np.sqrt(252)8. 应用场景扩展获取到的期权数据可以支持多种分析波动率曲面构建按到期日分组计算隐含波动率按行权价标准化二维插值生成平滑曲面可视化分析市场预期套利机会监测平价关系检查Put-Call Parity跨期价差分析跨市场价差监控# 简单的平价关系检查示例 def check_parity(call, put, spot, strike, rate, ttm): theoretical_diff call - put - (spot - strike * np.exp(-rate * ttm)) return theoretical_diff在部署自动化交易系统时这些数据采集模块可以作为独立服务运行通过消息队列将处理好的数据推送给交易引擎。

更多文章