第三章 数据获取与清洗:用akshare搭建你的可转债数据库

做量化交易,数据就是你的弹药库。弹药不行,再好的策略也白搭。

我个人习惯每天开盘前先跑一遍数据脚本,把全市场的可转债数据拉下来。今天我就带你走一遍这个流程——从akshare获取数据,到清洗、标准化,最后构建出一个可以直接用于策略分析的DataFrame。

3.1 为什么选akshare?

市面上能拿可转债数据的库不少,但akshare是我用得最顺手的。原因有三:

  • 免费且开源——不用花钱买数据接口,对个人量化玩家非常友好
  • 数据源稳定——底层抓取的是东方财富、新浪财经等主流平台的数据
  • 接口统一——股票、基金、可转债都用同一套调用方式,省心
小提示:akshare需要定期更新。我建议你每周至少执行一次 pip install akshare --upgrade,否则某些接口可能会因为网站改版而失效。

3.2 获取全市场可转债列表

先上代码。这是我最常用的数据获取脚本:

import akshare as ak
import pandas as pd
import datetime

# 获取全市场可转债实时数据
def get_all_convertible_bonds():
    """
    获取全市场可转债行情数据
    返回:DataFrame,包含代码、名称、价格、溢价率等核心字段
    """
    try:
        df = ak.bond_convert_jsl()
        print(f"数据获取成功,共 {len(df)} 只可转债")
        return df
    except Exception as e:
        print(f"数据获取失败:{e}")
        return None

# 执行获取
raw_data = get_all_convertible_bonds()

这里用的是 bond_convert_jsl() 接口,它返回的是集思录风格的数据表。为什么选这个?因为集思录的数据字段最全——价格、溢价率、到期收益率、转股价值、剩余规模……基本上你策略需要的都有了。

注意:akshare的接口名可能会随版本变化。如果你发现 bond_convert_jsl 报错,可以试试 ak.bond_convert_jsl() 或者去akshare官方文档查最新接口名。

3.3 数据清洗——把脏数据变成干净数据

拿到原始数据后,千万别直接拿去跑策略。我踩过这个坑——有一次没做清洗,结果策略里混进了一只已经退市的可转债,回测曲线直接崩了。

数据清洗我一般做这几步:

  1. 删除无效行——比如那些已经退市、或者数据为空的记录
  2. 处理缺失值——有些字段可能为空,需要填充或删除
  3. 数据类型转换——把字符串转成数值,把百分比转成小数
  4. 过滤异常值——比如价格低于50元或者高于500元的,基本是数据错误

来看具体代码:

def clean_bond_data(df):
    """
    清洗可转债数据
    """
    # 1. 删除退市和无效数据
    df = df[df['债券代码'].notna()]
    df = df[df['债券代码'].str.len() == 6]  # 可转债代码都是6位
    
    # 2. 处理缺失值
    df = df.dropna(subset=['现价', '溢价率'])
    
    # 3. 数据类型转换
    # 现价转浮点数
    df['现价'] = pd.to_numeric(df['现价'], errors='coerce')
    # 溢价率转浮点数(原始数据可能是"12.34%"这种格式)
    df['溢价率'] = df['溢价率'].str.replace('%', '').astype(float) / 100
    
    # 4. 过滤异常值
    df = df[(df['现价'] > 50) & (df['现价'] < 500)]
    df = df[df['溢价率'] > -0.5]  # 溢价率不会低于-50%
    
    return df

# 执行清洗
clean_data = clean_bond_data(raw_data)
print(f"清洗后剩余 {len(clean_data)} 只可转债")

嗯,这里要注意一点:errors='coerce' 这个参数很关键。它会把无法转换的值变成NaN,而不是直接报错中断程序。我在生产环境里吃过亏——某天数据源突然改了格式,整个脚本直接崩溃,从那以后我就养成了加这个参数的习惯。

3.4 数据标准化——让数据口径统一

不同数据源、不同接口返回的数据,字段名和单位可能都不一样。标准化就是把这些数据统一成你策略能直接用的格式。

我一般做以下标准化:

  • 字段重命名——把中文名改成英文名,方便后续代码调用
  • 单位统一——比如规模统一用"亿元",价格统一用"元"
  • 计算衍生字段——比如双低值 = 价格 + 溢价率×100
def standardize_bond_data(df):
    """
    标准化可转债数据
    """
    # 字段重命名
    column_mapping = {
        '债券代码': 'bond_code',
        '债券简称': 'bond_name',
        '现价': 'price',
        '溢价率': 'premium_ratio',
        '到期收益率': 'ytm',
        '剩余规模': 'remain_size',
        '转股价值': 'convert_value',
        '正股代码': 'stock_code',
        '正股名称': 'stock_name'
    }
    df = df.rename(columns=column_mapping)
    
    # 计算衍生字段
    df['double_low'] = df['price'] + df['premium_ratio'] * 100
    
    # 排序
    df = df.sort_values('double_low')
    
    return df

# 执行标准化
final_data = standardize_bond_data(clean_data)

双低值这个字段,说白了就是衡量可转债"便宜程度"的一个指标。价格低、溢价率低,双低值就低,说明这只债性价比高。我自己的轮动策略就是基于双低值来排序的。

3.5 构建基础数据DataFrame

最后一步,把清洗和标准化后的数据整理成你策略可以直接用的DataFrame。我习惯保留这些核心字段:

字段名 含义 数据类型 示例
bond_code 债券代码 str 123456
bond_name 债券简称 str XX转债
price 当前价格(元) float 118.50
premium_ratio 溢价率 float 0.1234
ytm 到期收益率 float 0.025
remain_size 剩余规模(亿元) float 3.5
convert_value 转股价值 float 105.20
double_low 双低值 float 130.84
stock_code 正股代码 str 600000
stock_name 正股名称 str XX股份

有了这个DataFrame,你就可以直接用它来做策略回测、排序选债、甚至实盘监控了。

核心要点:数据获取与清洗是整个量化交易流程的基石。花80%的时间把数据搞干净,剩下20%的时间做策略,效果远好于反过来。

3.6 本章知识体系

下面这张图概括了本章的核心流程:

可转债数据获取与清洗流程 步骤1:数据获取 akshare.bond_convert_jsl() 步骤2:数据清洗 删除无效行 处理缺失值 步骤3:标准化 字段重命名 计算衍生字段 步骤4:构建DataFrame 核心字段 + 双低值 输出:标准DataFrame 可直接用于策略分析 数据清洗是量化交易中最耗时但最重要的环节 DataFrame核心字段 • bond_code(债券代码) • price(当前价格) • premium_ratio(溢价率) • ytm(到期收益率) • remain_size(剩余规模) • convert_value(转股价值) • double_low(双低值) • stock_code(正股代码) • stock_name(正股名称)

这张图把整个流程串起来了。你每天跑一遍这个脚本,就能拿到一份干净、标准化的全市场可转债数据。有了这个基础,后面的策略分析和实盘调仓才能站得住脚。

我的习惯:我会把这个脚本设置成每天开盘前自动运行,然后把数据保存到本地CSV文件。这样即使盘中网络出问题,我也有前一天的数据可以应急。

数据获取与清洗这一步,说白了就是磨刀。刀磨好了,砍柴才快。下一章我们会基于这份干净数据,开始构建真正的轮动策略。

蓝海数据掘金营 | 专注资料整理