4、Python环境与数据准备:Anaconda安装、Jupyter Notebook配置、债券数据API获取(Wind/Bloomberg模拟)、数据清洗基础
好,咱们正式开始动手了。
前面三章聊了不少理论,什么做市商定价逻辑、报价价差模型、库存管理策略……说实话,光看这些容易犯困。我当年刚入行的时候也是这样,看了两周论文,结果打开电脑发现连Wind接口都调不通,别提多郁闷了。
所以这一章,咱们先把地基打牢。环境搭好了,后面写代码才顺手。
4.1 Anaconda安装:别小看这一步
我个人习惯用Anaconda来管理Python环境。为什么?因为做债券量化,你免不了要装一堆库——pandas、numpy、scipy、statsmodels、matplotlib……一个个手动装,版本冲突能让你怀疑人生。
Anaconda自带conda包管理器,说白了就是帮你把依赖关系理清楚。我建议直接装最新版的Anaconda,去官网下载就行。安装时有个坑:记得勾选“Add Anaconda to my PATH environment variable”。虽然安装界面会提示不推荐,但我曾经因为这个没勾,后面在命令行里死活找不到conda命令,折腾了半小时。
装完之后,打开终端(Windows用Anaconda Prompt),输入:
conda --version
能看到版本号,说明装好了。嗯,这一步很简单,但别跳过。
4.2 Jupyter Notebook配置:你的交互式实验台
做债券做市模型,我很少用PyCharm或者VS Code直接写脚本。为什么?因为做市策略需要反复调试参数、看中间结果。Jupyter Notebook的交互式特性,说白了就是让你边写边看,跟做实验一样。
安装完Anaconda后,Jupyter Notebook已经自带了。启动方式:
jupyter notebook
浏览器会自动打开一个页面。我个人习惯先创建一个专用文件夹,比如叫bond_making,所有代码都放里面。
这里有个小技巧:配置Jupyter Notebook的默认工作目录。不然每次启动都要cd到目标文件夹,挺烦的。
修改方法:
- 在终端输入
jupyter notebook --generate-config - 找到生成的
jupyter_notebook_config.py文件 - 搜索
c.NotebookApp.notebook_dir,改成你的路径,比如'D:/bond_making'
c.NotebookApp.autosave_interval = 30
4.3 债券数据API获取:Wind/Bloomberg模拟
做债券做市,数据是第一关。你想想看,没有实时行情,你怎么报价?
国内用Wind最多,国外用Bloomberg。但这两个API都是收费的,而且接口文档写得……嗯,你懂的。咱们课程里没法直接用真实API,所以我写了一个模拟数据生成器,模拟Wind和Bloomberg的返回格式。
先看Wind风格的模拟代码:
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
def mock_wind_bond_data(bond_code='210205.IB', days=100):
"""
模拟Wind债券行情数据
返回DataFrame,包含日期、净价、全价、到期收益率、久期
"""
np.random.seed(42)
dates = [datetime.now() - timedelta(days=i) for i in range(days)]
dates.sort()
# 模拟净价,围绕100元波动
clean_price = 100 + np.cumsum(np.random.normal(0, 0.1, days))
# 模拟全价(净价+应计利息)
accrued_interest = np.random.uniform(0.5, 1.5, days)
dirty_price = clean_price + accrued_interest
# 模拟到期收益率
ytm = 0.03 + np.random.normal(0, 0.002, days)
# 模拟久期
duration = np.random.uniform(4.5, 5.5, days)
df = pd.DataFrame({
'date': dates,
'clean_price': clean_price.round(4),
'dirty_price': dirty_price.round(4),
'ytm': ytm.round(6),
'duration': duration.round(4)
})
df['bond_code'] = bond_code
return df
# 试试看
df_wind = mock_wind_bond_data()
print(df_wind.head())
Bloomberg的模拟也类似,只是字段名不同。Bloomberg习惯用PX_LAST表示最新价,YLD_CNV表示到期收益率。我在项目中遇到过一个问题:两个系统的字段名不统一,导致策略回测时数据对不上。所以建议一开始就建一个字段映射表。
| 字段含义 | Wind字段 | Bloomberg字段 | 统一字段 |
|---|---|---|---|
| 净价 | clean_price | PX_LAST | clean_price |
| 全价 | dirty_price | PX_DIRTY | dirty_price |
| 到期收益率 | ytm | YLD_CNV | ytm |
| 久期 | duration | DUR_ADJ | duration |
4.4 数据清洗基础:脏数据是量化的大敌
数据拿到了,但别急着用。你想想看,Wind和Bloomberg返回的数据真的干净吗?
我在项目中遇到过:某只债券某天的净价突然变成0,或者到期收益率出现负值(国债偶尔会有,但信用债不应该)。这些异常值如果不处理,模型会直接跑偏。
数据清洗,说白了就是三件事:
- 缺失值处理——是直接删掉,还是用前值填充?
- 异常值检测——价格超出3倍标准差,要不要标记?
- 重复值去重——同一只债券同一天出现两条记录,留哪条?
来看一段清洗代码:
def clean_bond_data(df):
"""
债券数据清洗函数
"""
# 1. 去重:按日期和债券代码去重,保留第一条
df = df.drop_duplicates(subset=['date', 'bond_code'], keep='first')
# 2. 缺失值:净价为空时,用前一天的净价填充
df['clean_price'] = df['clean_price'].fillna(method='ffill')
# 3. 异常值:净价超出[80, 120]范围的,标记为NaN并填充
df.loc[(df['clean_price'] < 80) | (df['clean_price'] > 120), 'clean_price'] = np.nan
df['clean_price'] = df['clean_price'].fillna(method='ffill')
# 4. 收益率合理性检查:国债收益率一般在1%-5%之间
df.loc[(df['ytm'] < 0.01) | (df['ytm'] > 0.05), 'ytm'] = np.nan
df['ytm'] = df['ytm'].fillna(method='ffill')
return df
# 应用清洗
df_clean = clean_bond_data(df_wind)
print(f"清洗前数据量: {len(df_wind)}, 清洗后: {len(df_clean)}")
嗯,数据清洗这块,没有标准答案。不同的策略对数据质量要求不一样。比如高频做市,对Tick级数据的精度要求极高;而做趋势策略的,日频数据稍微有点噪声也能接受。我的建议是:先定策略,再定清洗规则。
4.5 本章知识体系总览
说了这么多,咱们用一张图把这一章的内容串起来。我画了个流程图,帮你理清从环境搭建到数据清洗的完整链路:
这张图把咱们这一章的内容串起来了。从Anaconda安装开始,到Jupyter配置,再到API获取数据,最后落到数据清洗。每一步都环环相扣,缺一不可。
好了,环境搭好了,数据也洗干净了。下一章咱们就可以开始真正的做市报价模型了——不过那是后面的事。先把这一章的代码跑通,有问题随时翻回来看看。
公众号:蓝海数据掘金营,微信deep3321