2、数据准备与预处理:获取转债行情数据、数据清洗与对齐、复权价格处理、缺失值处理

做量化投资,圈里有个共识:数据和策略,七三开。数据占七,策略占三。这话一点不夸张。你策略再牛,数据是脏的,结果就是垃圾进垃圾出。

我个人习惯,拿到一个策略想法,第一件事不是写代码,而是先想清楚:我需要什么数据?数据从哪里来?怎么保证它干净? 这一步想透了,后面能省80%的坑。

今天我们就来聊聊转债轮动策略的数据准备。说白了,就是给策略做一顿好饭——食材得新鲜,洗得干净,切得整齐。

2.1 获取转债行情数据

转债行情数据,主要分两块:日频行情基础信息

  • 日频行情:开盘价、收盘价、最高价、最低价、成交量、成交额、转股价值、溢价率等。
  • 基础信息:转债代码、正股代码、发行规模、剩余规模、到期日、转股价、下修条款等。

数据源怎么选?我建议用聚宽、Tushare、AkShare这些国内平台。它们接口稳定,数据质量也还行。我在项目中遇到过,有些小平台的数据偶尔会断更,尤其是节假日前后,特别坑。

下面是一个获取转债日行情的示例代码(以聚宽为例):

# 获取转债日行情
from jqdatasdk import *
auth('你的账号', '密码')

# 获取所有转债列表
bonds = get_all_securities(['bond_convert'])

# 获取某只转债的日行情
df = get_price('123456.XSHE', 
               start_date='2023-01-01', 
               end_date='2023-12-31',
               frequency='daily',
               fields=['open','close','high','low','volume','money'])
小提示: 获取数据时,建议一次性拉取全量数据,存到本地数据库(比如SQLite或CSV)。每次策略运行都去拉API,既慢又不稳定。我习惯每周更新一次本地数据。

2.2 数据清洗与对齐

数据拿到手,别急着用。先看看有没有脏数据。常见的坑有:

  • 停牌数据:转债停牌期间,价格不变,成交量是0。如果不处理,会干扰策略信号。
  • 异常值:比如某天收盘价突然涨了50%,但成交量没放大。这很可能是数据录入错误。
  • 日期对齐:转债和正股的交易日可能不完全一致。比如正股停牌,转债还在交易。这时候需要做对齐。

我曾经踩过一个坑:某只转债因为正股重组停牌了两个月,但转债还在交易。我没做对齐,直接把正股数据填了前一天的收盘价。结果策略信号完全乱了。后来我学乖了,停牌期间的数据一律标记为NaN,后面再处理。

数据对齐的代码示例:

# 对齐转债和正股数据
import pandas as pd

# 假设df_bond是转债数据,df_stock是正股数据
# 按日期对齐,只保留共同交易日
df_merged = pd.merge(df_bond, df_stock, 
                     on='date', 
                     how='inner', 
                     suffixes=('_bond', '_stock'))
注意: 对齐时用how='inner'还是how='left'?我个人建议用inner,只保留两者都有交易的日期。这样能避免因停牌导致的虚假信号。

2.3 复权价格处理

转债的复权,和股票不太一样。股票复权是为了消除分红送股的影响。转债复权,主要是为了处理转股价调整强赎

转股价调整,通常发生在正股分红、送股、配股时。这时候转债的转股价会下调,转股价值会变化。如果不做复权,历史价格就失去了可比性。

我建议的做法是:用后复权。后复权能保持历史价格的一致性,方便做回测。前复权会改变历史价格,容易让人误解。

复权处理的逻辑:

# 转债后复权处理(简化版)
def adjust_convertible_bond_price(df, adjust_factor):
    """
    df: 原始行情数据
    adjust_factor: 复权因子(通常由数据源提供)
    """
    df['close_adj'] = df['close'] * adjust_factor
    df['open_adj'] = df['open'] * adjust_factor
    df['high_adj'] = df['high'] * adjust_factor
    df['low_adj'] = df['low'] * adjust_factor
    return df
核心要点: 复权因子一般数据源会直接提供。如果没有,可以自己算:复权因子 = 调整前转股价 / 调整后转股价。这个公式我验证过多次,基本靠谱。

2.4 缺失值处理

缺失值,是数据预处理里最烦人的事。常见的处理方法有:

  • 删除法:直接删掉有缺失的行。简单粗暴,但会损失数据。
  • 填充法:用前一天的数值填充(forward fill),或者用均值填充。
  • 插值法:用线性插值或多项式插值。适合连续缺失的情况。

我个人习惯,优先用前向填充。为什么?因为转债市场流动性好,停牌时间一般不长。前一天的收盘价,基本能代表当天的合理价格。如果连续缺失超过3天,我会直接删除。

缺失值处理的代码示例:

# 缺失值处理
# 前向填充,最多填充3天
df.fillna(method='ffill', limit=3, inplace=True)

# 如果还有缺失,直接删除
df.dropna(inplace=True)
避坑指南: 我曾经遇到过一个极端情况:某只转债因为强赎,最后几天成交量极低,价格几乎没变。这时候前向填充没问题。但如果是刚上市的新债,前几天的数据缺失,千万别用前向填充——因为根本没有历史数据。这时候建议用同行业、同评级的转债均值来填充。

2.5 知识体系总览

为了让你更直观地理解整个数据准备流程,我画了一张流程图。嗯,这张图我反复改了好几版,希望能帮你把逻辑理清楚。

转债轮动策略 · 数据准备流程 获取行情数据 数据清洗与对齐 复权价格处理 缺失值处理 ✅ 干净可用的数据 日频行情 基础信息 停牌处理 异常值检测 日期对齐 后复权 转股价调整 前向填充 插值法 删除法

你看,整个流程其实不复杂。但每一步都马虎不得。数据准备阶段花的时间,往往占整个策略开发时间的40%以上。别嫌烦,这是值得的。

好了,数据准备好了。下一章我们聊聊怎么构建轮动策略的核心逻辑。嗯,到时候见。


专注资料整理