第一章:课程导论与数据准备

各位同学,欢迎来到《多因子时序预测模型实战训练营》。我是你们这趟旅程的向导,一个在量化领域摸爬滚打了七八年的老工程师。今天咱们开篇,不讲虚的,直接上手干活。

多因子时序预测,说白了就是:用一堆历史数据,去猜未来。你想想看,股票价格、天气变化、商品销量,本质上都是时间序列。而多因子,就是咱们找来的各种“线索”——成交量、市盈率、新闻情绪、甚至天气数据。把这些线索组合起来,预测未来走势。

我个人习惯,学任何新东西,先把环境搭好,把数据搞到手。这就好比做饭,你得先有厨房和食材。今天这一章,咱们就干这三件事:搭环境、拿数据、洗数据。

本章核心目标:让你能在自己的电脑上,跑通第一个数据获取和清洗的脚本。别小看这一步,我见过太多人卡在环境配置上,一卡就是半天。

第一章:课程导论与数据准备 - 知识体系 多因子时序预测 环境配置 Python / Anaconda / Jupyter 数据获取 Tushare / Yfinance 数据清洗与预处理 缺失值 / 异常值 / 标准化 Anaconda 一键安装 API Token 配置 数据对齐与合并

1.1 多因子时序预测概述

先聊聊概念。时序预测,就是根据过去一段时间的数据,预测未来某个点的值。比如用过去30天的股价,预测明天的收盘价。多因子呢,就是不止看价格本身,还要看成交量、MACD指标、市场情绪等等。

为什么要用多因子?单看价格,就像盲人摸象。我记得2018年做CTA策略时,只用了价格动量,结果遇到震荡行情,回撤大得吓人。后来加入了波动率因子和持仓量因子,效果立马不一样了。说白了,多因子就是给模型装上“多双眼睛”。

常见的因子类型

因子类别 举例 数据来源
价格因子 收盘价、最高价、最低价 Tushare / Yfinance
成交量因子 成交量、成交额、换手率 Tushare / Yfinance
技术指标因子 MACD、RSI、布林带 通过价格计算得到
基本面因子 市盈率、市净率、ROE Tushare 财务数据
另类数据因子 新闻情绪、搜索热度 爬虫 / API

我的经验:刚开始做多因子模型,别贪多。3-5个核心因子就够了。我曾经一口气加了20个因子,结果模型过拟合得一塌糊涂。记住,少即是多。

1.2 环境配置

好,咱们开始动手。环境配置这块,我推荐用 Anaconda。为什么?因为它把 Python、常用库、Jupyter Notebook 都打包好了,省心。

第一步:安装 Anaconda

去 Anaconda 官网下载对应系统的安装包。我建议下载 Python 3.9 或 3.10 版本,太新的版本有些库可能不兼容。安装时一路默认就行,但记得勾选“Add Anaconda to my PATH environment variable”。

注意:Windows 用户安装时,如果遇到“是否添加环境变量”的选项,一定要勾上。不然后面在命令行里找不到 conda 命令,你会很崩溃。我曾经帮一个学员远程调试,就因为这个卡了半小时。

第二步:创建虚拟环境

我个人习惯,每个项目建一个独立的虚拟环境。这样不同项目的依赖不会打架。

# 打开终端(Windows 用 Anaconda Prompt)
conda create -n quant_env python=3.9

# 激活环境
conda activate quant_env

# 安装核心库
pip install pandas numpy matplotlib seaborn scikit-learn

# 安装 Jupyter
conda install jupyter

# 启动 Jupyter
jupyter notebook

看到浏览器弹出 Jupyter 界面,就说明环境搭好了。嗯,这里要注意,如果浏览器没自动弹出,把终端里显示的 URL 复制到浏览器打开就行。

第三步:安装金融数据库

# 安装 Tushare(国内股票数据)
pip install tushare

# 安装 Yfinance(美股数据)
pip install yfinance

小技巧:安装时如果速度慢,可以加国内镜像源:pip install tushare -i https://pypi.tuna.tsinghua.edu.cn/simple

1.3 数据获取

环境搭好了,咱们来拿数据。我主要用两个数据源:Tushare 拿 A 股数据,Yfinance 拿美股数据。

使用 Tushare 获取 A 股数据

Tushare 需要注册获取 token。去 tushare.pro 注册,然后在个人中心找到 token。

import tushare as ts

# 设置 token(换成你自己的)
ts.set_token('你的token_here')

# 初始化接口
pro = ts.pro_api()

# 获取贵州茅台(600519.SH)2023年的日线数据
df = pro.daily(
    ts_code='600519.SH',
    start_date='20230101',
    end_date='20231231'
)

# 查看数据
print(df.head())

跑完这段代码,你会看到类似这样的输出:

   ts_code trade_date  open  high   low  close  pre_close  change  pct_chg  vol  amount
0  600519.SH   20231229  1720  1735  1710  1728       1715    13.0    0.76  2.5  43200
1  600519.SH   20231228  1700  1725  1695  1715       1690    25.0    1.48  3.1  52800
...

关键点:Tushare 返回的数据是按日期降序排列的,最新的在最上面。做时序预测时,记得按日期升序排列:df = df.sort_values('trade_date')

使用 Yfinance 获取美股数据

import yfinance as yf

# 获取苹果(AAPL)2023年的日线数据
aapl = yf.download('AAPL', start='2023-01-01', end='2023-12-31')

# 查看数据
print(aapl.head())

Yfinance 返回的数据是 MultiIndex 列名,包含 Open、High、Low、Close、Volume、Adj Close。我个人习惯只保留 Close 和 Volume。

# 只保留收盘价和成交量
aapl_simple = aapl[['Close', 'Volume']]
aapl_simple.columns = ['close', 'volume']

1.4 数据清洗与预处理

拿到原始数据后,千万别直接扔进模型。真实数据里全是坑——缺失值、异常值、不同频率的数据怎么对齐?这些都是大问题。

我在项目中遇到过最典型的情况:某只股票因为停牌,中间缺了10天的数据。如果不处理,模型会以为这10天价格没变,预测结果直接崩掉。

处理缺失值

# 检查缺失值
print(df.isnull().sum())

# 方法1:向前填充(适合金融数据)
df.fillna(method='ffill', inplace=True)

# 方法2:线性插值
df.interpolate(method='linear', inplace=True)

# 方法3:删除缺失行(慎用,会破坏时间连续性)
df.dropna(inplace=True)

避坑指南:我曾经直接用 dropna 删除了缺失行,结果导致时间序列不连续,模型训练时出现了奇怪的跳跃。后来我改用向前填充,效果就好多了。金融数据里,缺失值用前一个交易日的数据填充,是最合理的做法。

处理异常值

异常值怎么判断?我常用 3-sigma 法则或 IQR 方法。

# 3-sigma 法则
mean = df['close'].mean()
std = df['close'].std()
df['close_zscore'] = (df['close'] - mean) / std

# 标记异常值(|z-score| > 3)
df['is_outlier'] = df['close_zscore'].abs() > 3

# 用中位数替换异常值
median = df['close'].median()
df.loc[df['is_outlier'], 'close'] = median

数据标准化

不同因子的量纲不一样,比如价格是几百块,成交量是几千万股。直接扔进模型,价格会主导训练过程。所以要做标准化。

from sklearn.preprocessing import StandardScaler

# 初始化标准化器
scaler = StandardScaler()

# 对收盘价和成交量做标准化
df[['close_scaled', 'volume_scaled']] = scaler.fit_transform(df[['close', 'volume']])

多因子数据对齐

如果你有多个数据源,比如价格数据来自 Tushare,基本面数据来自另一个接口,它们的日期可能不一致。这时候要对齐。

# 假设 price_df 和 fundamental_df 都有 date 列
# 以价格数据的日期为基准,左连接基本面数据
merged_df = price_df.merge(
    fundamental_df,
    on='date',
    how='left'
)

# 对齐后,基本面数据缺失的日期用前向填充
merged_df.fillna(method='ffill', inplace=True)

我的习惯:数据对齐后,我会检查一下对齐后的数据长度。如果发现数据量少了很多,说明两个数据源的日期覆盖范围差异太大,需要重新考虑数据源的选择。

本章小结

好了,第一章的内容就到这里。咱们做了三件事:搭好了 Python 环境,学会了用 Tushare 和 Yfinance 拿数据,还掌握了数据清洗的基本方法。这些看起来基础,但基础不牢,地动山摇。

你想想看,如果数据都是脏的,模型再厉害也白搭。我见过太多人花90%的时间调模型,却只花10%的时间处理数据。结果模型上线后,因为数据质量问题,回测曲线漂亮得不行,实盘却亏得一塌糊涂。

下一章,咱们会深入特征工程,教你怎么从原始数据里挖出真正有用的因子。但今天,先把这些基础打扎实。去跑一遍代码,有问题随时在群里问我。


专注资料整理