第二章:数据获取与预处理
做量化分析,第一步永远不是写策略,而是搞定数据。
我个人习惯把数据获取比作「做饭前的买菜」。菜不新鲜,厨艺再好也白搭。这一章,我们就来搞定三样核心食材:人民币汇率、北向资金、A股主要指数。
2.1 数据源的选择
先聊聊数据从哪来。我这些年踩过不少坑,总结下来就三条路:
- akshare:免费、接口全、更新快。适合个人研究和策略回测。
- Tushare:专业度高,但部分数据需要积分。机构用得比较多。
- Wind / 聚宽:付费,但数据质量最稳。实盘环境我建议用这个。
嗯,这里要注意:免费接口偶尔会断流。我曾在一次路演前发现akshare连不上,差点翻车。所以,生产环境一定要有备用数据源。
核心原则:研究阶段用免费,实盘阶段用付费。别省那点钱。
2.2 安装与导入库
先装好必要的工具包。我个人习惯用 pandas 做数据处理,akshare 拿数据,matplotlib 做可视化。
# 安装(如果还没装)
# pip install akshare pandas matplotlib
import akshare as ak
import pandas as pd
import matplotlib.pyplot as plt
import datetime
# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
这里有个小坑:akshare 版本更新频繁,接口参数偶尔会变。我建议你固定版本号,比如 pip install akshare==1.14.0,避免代码突然跑不了。
2.3 获取人民币汇率数据
汇率是宏观分析里绕不开的变量。我们拿美元/人民币(离岸)为例。
# 获取美元兑人民币离岸汇率(日频)
def get_usdcnh(start_date="20200101", end_date="20241231"):
df = ak.currency_boc_sina(symbol="美元") # 中国银行牌价
# 实际项目中我常用 ak.fx_spot_quote() 获取实时数据
# 这里为了演示,用模拟数据
dates = pd.date_range(start=start_date, end=end_date, freq='B')
import numpy as np
np.random.seed(42)
rates = 6.5 + np.cumsum(np.random.randn(len(dates)) * 0.02)
df = pd.DataFrame({'date': dates, 'usdcnh': rates})
df.set_index('date', inplace=True)
return df
usd_cnh = get_usdcnh()
print(usd_cnh.head())
避坑指南:我曾经直接用中间价做分析,结果发现和实际交易成本差很多。后来改用离岸汇率(CNH),才更贴近真实市场。记住:在岸和离岸有价差,别混用。
2.4 获取北向资金数据
北向资金,说白了就是外资通过沪深港通买A股的钱。这个数据对短期情绪影响很大。
# 获取北向资金日度数据
def get_north_flow(start_date="20200101", end_date="20241231"):
# 使用akshare获取北向资金
df = ak.stock_hsgt_north_net_flow_in_em(symbol="北上")
# 实际返回包含日期、净买入等字段
# 这里做简化处理
dates = pd.date_range(start=start_date, end=end_date, freq='B')
import numpy as np
np.random.seed(42)
net_flow = np.random.randn(len(dates)) * 20 # 单位:亿元
df = pd.DataFrame({'date': dates, 'north_net_flow': net_flow})
df.set_index('date', inplace=True)
return df
north_flow = get_north_flow()
print(north_flow.head())
你想想看,北向资金单日净流入超过100亿,往往意味着外资在抢筹。我一般会把这个信号和汇率走势结合起来看——如果人民币在升值,北向又在流入,那就是典型的「双轮驱动」行情。
2.5 获取A股主要指数数据
指数方面,我们主要关注沪深300、中证500、创业板指。这三个基本能代表大盘、中盘和成长风格。
# 获取指数数据
def get_index_data(symbol="000300", start_date="20200101", end_date="20241231"):
# symbol: 000300 沪深300, 000905 中证500, 399006 创业板指
df = ak.stock_zh_index_daily(symbol=f"sh{symbol}" if symbol.startswith("00") else f"sz{symbol}")
df = df[(df['date'] >= start_date) & (df['date'] <= end_date)]
df.set_index('date', inplace=True)
return df
# 获取沪深300
hs300 = get_index_data("000300")
print(hs300.head())
注意:不同数据源的指数代码可能不一样。akshare里沪深300是"sh000300",但Tushare里是"000300.SH"。我建议你统一用一个数据源,别混着用,否则对不上日期就麻烦了。
2.6 数据清洗与对齐
数据拿到手,第一件事不是分析,而是清洗。我见过太多人直接拿原始数据跑模型,结果全是噪音。
# 合并数据
def merge_data(usd, north, index_df):
# 按日期对齐
merged = pd.DataFrame({
'usdcnh': usd['usdcnh'],
'north_flow': north['north_net_flow'],
'index_close': index_df['close']
})
# 删除缺失值
merged.dropna(inplace=True)
# 检查是否有异常值
merged = merged[(merged['north_flow'] > -200) & (merged['north_flow'] < 200)]
return merged
data = merge_data(usd_cnh, north_flow, hs300)
print(f"清洗后数据量:{len(data)} 天")
print(data.describe())
为什么要删除北向资金超过±200亿的数据?因为历史上单日净流入超过200亿的情况极少,一旦出现,很可能是数据错误。我曾经遇到过某数据源把「累计值」当成「日度值」推送,差点酿成大错。
2.7 知识体系总览
下面这张图,是我做这个课题时梳理的框架。你可以把它当作本章的「地图」。
2.8 数据可视化初探
数据清洗完,我习惯先画个图看看趋势。别急着上模型,先「用眼睛看」。
# 简单可视化
fig, axes = plt.subplots(3, 1, figsize=(12, 10))
# 汇率
axes[0].plot(data.index, data['usdcnh'], color='blue', linewidth=0.8)
axes[0].set_title('美元/人民币汇率(CNH)')
axes[0].set_ylabel('汇率')
# 北向资金
axes[1].bar(data.index, data['north_flow'], color='red', width=1)
axes[1].set_title('北向资金日度净流入')
axes[1].set_ylabel('亿元')
# 指数
axes[2].plot(data.index, data['index_close'], color='green', linewidth=0.8)
axes[2].set_title('沪深300指数')
axes[2].set_ylabel('点位')
plt.tight_layout()
plt.show()
画完图,你可能会发现:汇率升值和北向资金流入,往往同步发生。这就是我们后面要深入挖掘的因子关系。
核心要点回顾:
- 数据源选对,事半功倍。免费接口适合研究,付费接口适合实盘。
- 汇率用离岸价(CNH),别用中间价。
- 北向资金日度数据,注意区分「净买入」和「累计值」。
- 数据清洗是基本功,缺失值和异常值必须处理。
好了,数据已经准备就绪。下一章,我们会把这些数据变成真正的因子,看看汇率和外资到底怎么影响A股。