
缺失值处理策略
股票数据中经常存在缺失值问题,这可能源于交易日休市、数据采集失败或API接口不稳定等原因。处理缺失值是数据清洗的第一步。
对于时间序列型的股票数据,可以使用前向填充或后向填充方法。前向填充用前一个有效值替代缺失数据,适合于连续交易日的场景;后向填充则用后一个有效值替代,适用于历史数据补充。在实际应用中,需要根据数据的特性选择合适的方法。
import pandas as pd
import numpy as np
# 读取股票数据
stock_data = pd.read_csv('stock_data.csv', parse_dates=['date'], index_col='date')
# 前向填充处理缺失值
stock_data_filled = stock_data.fillna(method='ffill')
# 对于开市首日使用后向填充
stock_data_filled = stock_data_filled.fillna(method='bfill')
# 线性插值处理数值型列
numeric_columns = ['open', 'high', 'low', 'close', 'volume']
for col in numeric_columns:
stock_data_filled[col] = stock_data_filled[col].interpolate(method='linear')
某些情况下,缺失值比例过高可能意味着该数据质量存在问题,需要考虑剔除相关股票或指标。
异常值检测与处理
股票数据中的异常值会严重影响选股模型的准确性。常见的异常值包括:价格突变、成交量异常放大、涨跌幅超过合理范围等。

可以使用统计学方法检测异常值。标准差法适用于近似正态分布的数据,设定3个标准差以外的数值为异常值。四分位距法(IQR)对非正态分布数据更加稳健,通过计算Q1和Q3的差值,设定1.5倍IQR以外的数值为异常。
def detect_outliers_iqr(df, column, threshold=1.5):
"""使用IQR方法检测异常值"""
Q1 = df[column].quantile(0.25)
Q3 = df[column].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - threshold * IQR
upper_bound = Q3 + threshold * IQR
outliers = df[(df[column] < lower_bound) | (df[column] > upper_bound)]
return outliers, lower_bound, upper_bound
# 检测收盘价异常值
outliers, lower, upper = detect_outliers_iqr(stock_data_filled, 'close')
# 用边界值替代异常值
stock_data_filled['close'] = stock_data_filled['close'].clip(lower=lower, upper=upper)
还可以结合涨跌幅限制进行异常值筛选。A股市场个股单日涨跌幅限制为10%,ST股票为5%,超过这个范围的 数据显然存在异常。
数据重复处理
股票数据重复主要表现为:同一交易日的多条记录、代码更新导致的历史数据重复等。重复数据会导致选股策略过度拟合,降低泛化能力。
# 检查是否存在完全重复的行
duplicates = stock_data_filled.duplicated()
print(f"重复记录数: {duplicates.sum()}")
# 去除完全重复的行
stock_data_cleaned = stock_data_filled.drop_duplicates()
# 对于按日期和股票代码建档的数据,检查特定列组合的重复
if 'code' in stock_data_cleaned.columns:
duplicates_subset = stock_data_cleaned.duplicated(subset=['date', 'code'])
stock_data_cleaned = stock_data_cleaned.drop_duplicates(subset=['date', 'code'])
数据类型标准化
不同数据源的数据类型可能不一致,这会导致后续计算的错误。股票代码需要统一格式,比如将"600000"和"sh600000"统一为标准格式。日期格式需要统一为datetime类型,数值型数据需要确保没有字符串混入。
# 统一股票代码格式
def standardize_code(code):
code = str(code).strip()
if code.isdigit():
return code.zfill(6)
return code
stock_data_cleaned['code'] = stock_data_cleaned['code'].apply(standardize_code)
# 确保数值型列为正确类型
numeric_cols = ['open', 'high', 'low', 'close', 'volume', 'amount']
for col in numeric_cols:
stock_data_cleaned[col] = pd.to_numeric(stock_data_cleaned[col], errors='coerce')
特征数据标准化
在进行多因子选股时,不同因子的量纲和数值范围差异巨大。净利润可能是亿级别,而净资产收益率则是百分比级别,直接使用会导致某些因子主导模型结果。
from sklearn.preprocessing import StandardScaler, MinMaxScaler
# Z-Score标准化:均值为0,标准差为1
scaler = StandardScaler()
factors_normalized = scaler.fit_transform(stock_data_cleaned[['pe_ratio', 'pb_ratio', 'roe', 'gross_margin']])
# 归一化到0-1区间
minmax_scaler = MinMaxScaler()
factors_minmax = minmax_scaler.fit_transform(stock_data_cleaned[['pe_ratio', 'pb_ratio', 'roe', 'gross_margin']])
实战:构建完整的清洗流程
将以上各个环节整合为一个完整的股票数据清洗函数,可以重复使用。
def clean_stock_data(df):
"""完整的股票数据清洗流程"""
df = df.copy()
# 1. 统一索引
if 'date' in df.columns:
df['date'] = pd.to_datetime(df['date'])
df = df.set_index('date').sort_index()
# 2. 处理缺失值
numeric_cols = df.select_dtypes(include=[np.number]).columns
df[numeric_cols] = df[numeric_cols].fillna(method='ffill').fillna(method='bfill')
df[numeric_cols] = df[numeric_cols].interpolate(method='linear')
# 3. 去除重复
df = df.drop_duplicates()
# 4. 异常值处理
for col in numeric_cols:
Q1, Q3 = df[col].quantile(0.25), df[col].quantile(0.75)
IQR = Q3 - Q1
df[col] = df[col].clip(Q1 - 1.5 * IQR, Q3 + 1.5 * IQR)
# 5. 数据类型转换
if 'code' in df.columns:
df['code'] = df['code'].apply(lambda x: str(x).zfill(6) if str(x).isdigit() else x)
return df
数据清洗后的验证
清洗完成后需要进行验证,确保数据质量符合要求。可以检查数据的完整性、分布的合理性以及与原始数据的差异。
def validate_data(df_original, df_cleaned):
"""验证清洗后的数据质量"""
print("="*50)
print("数据清洗验证报告")
print("="*50)
print(f"原始数据行数: {len(df_original)}")
print(f"清洗后数据行数: {len(df_cleaned)}")
print(f"数据损失比例: {(1 - len(df_cleaned)/len(df_original))*100:.2f}%")
# 检查缺失值
missing = df_cleaned.isnull().sum()
print(f"\n剩余缺失值:\n{missing[missing > 0]}")
# 数值列统计
print(f"\n数值列统计描述:\n{df_cleaned.describe()}")
validate_data(stock_data, stock_data_cleaned)
数据清洗是量化交易系统的基石。高质量的清洗数据能够显著提升选股策略的稳定性,避免因数据问题导致的模型失效。在实际应用中,需要根据具体的数据源和策略需求,不断调整和优化清洗流程。