如何用Python进行数据清洗以提高股票选择的准确性

企业微信

缺失值处理策略

股票数据中经常存在缺失值问题,这可能源于交易日休市、数据采集失败或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')

某些情况下,缺失值比例过高可能意味着该数据质量存在问题,需要考虑剔除相关股票或指标。

异常值检测与处理

股票数据中的异常值会严重影响选股模型的准确性。常见的异常值包括:价格突变、成交量异常放大、涨跌幅超过合理范围等。

如何用Python进行数据清洗以提高股票选择的准确性

可以使用统计学方法检测异常值。标准差法适用于近似正态分布的数据,设定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)

数据清洗是量化交易系统的基石。高质量的清洗数据能够显著提升选股策略的稳定性,避免因数据问题导致的模型失效。在实际应用中,需要根据具体的数据源和策略需求,不断调整和优化清洗流程。

转载请注明出处:https://www.lianghuajiaoyi.top/wenzhang/python-shuju-qingxi-58.html