这个美股历史交易数据集堪称量化金融领域的"基础粮仓"。它覆盖了6192只股票在5年时间跨度内的完整交易记录,总计780万条数据点,每条记录包含开盘价、收盘价、最高价、最低价和成交量等核心交易指标。对于金融数据分析师、量化研究员和算法交易开发者而言,这种结构化历史数据就像厨师的顶级食材——质量决定最终成果的上限。
我曾在华尔街某对冲基金负责过数据基础设施搭建,当时为了获取类似质量的历史数据,团队每年要支付六位数的数据订阅费。现在随着数据民主化趋势,这类结构化数据集逐渐开放,使得个人研究者和中小机构也能开展专业级的量化分析。这780万条记录如果按每分钟行情计算,相当于连续5年每天跟踪约1000只活跃股票的全天交易轨迹,足够支撑起一个中等规模量化策略的回测需求。
这个数据集的核心字段构成了一套完整的OHLCV(Open-High-Low-Close-Volume)体系:
在华尔街,我们常用"价格是船长,成交量是燃料"的比喻。例如2020年3月疫情期间,很多股票出现无量下跌,这种价量背离往往预示着后续反弹。数据集里如果包含盘后交易数据(通常以Flag字段标记),价值会更高,因为近40%的财报都在盘后发布。
5年周期(2018-2022)覆盖了多个关键市场阶段:
这种完整周期数据能有效避免"周期偏差"。我见过太多策略在牛市表现优异,却在2022年熊市亏光本金。建议做回测时至少包含一次完整牛熊转换,这个数据集的时间窗口刚好满足要求。
以下Python示例展示如何用该数据集计算MACD指标:
python复制import pandas as pd
import numpy as np
def calculate_macd(data, fast=12, slow=26, signal=9):
"""计算MACD指标"""
data['EMA_fast'] = data['close'].ewm(span=fast).mean()
data['EMA_slow'] = data['close'].ewm(span=slow).mean()
data['MACD'] = data['EMA_fast'] - data['EMA_slow']
data['Signal'] = data['MACD'].ewm(span=signal).mean()
return data
# 示例调用
aapl_data = pd.read_csv('AAPL_2018-2022.csv') # 假设已加载苹果公司数据
aapl_with_macd = calculate_macd(aapl_data)
关键细节:EWMA(指数加权移动平均)比SMA(简单移动平均)对近期价格更敏感,这是MACD优于均线交叉策略的原因之一。
利用多只股票数据可以进行统计套利。以下是寻找配对交易机会的典型流程:
python复制from statsmodels.tsa.stattools import coint
def find_cointegrated_pairs(data_dict):
"""在股票池中寻找协整对"""
keys = list(data_dict.keys())
pairs = []
for i in range(len(keys)):
for j in range(i+1, len(keys)):
stock1 = data_dict[keys[i]]['close']
stock2 = data_dict[keys[j]]['close']
score, pvalue, _ = coint(stock1, stock2)
if pvalue < 0.05: # 显著性水平5%
pairs.append((keys[i], keys[j], pvalue))
return sorted(pairs, key=lambda x: x[2])
金融数据中常见的"胖手指"错误(如价格多输个零)可通过以下规则过滤:
python复制def detect_anomalies(df):
"""标记异常交易记录"""
df['return'] = df['close'].pct_change()
df['volume_ma10'] = df['volume'].rolling(10).mean()
conditions = [
abs(df['return']) > 0.2,
df['volume'] > 5 * df['volume_ma10'],
df['high'] < df['low']
]
df['anomaly'] = np.select(conditions, [1,2,3], default=0)
return df
股票分拆和分红会影响历史价格可比性。以苹果公司为例:
处理方式:
python复制def adjust_price(raw_price, split_ratio, dividend):
"""价格复权计算"""
return (raw_price * split_ratio) - dividend
使用该数据集进行回测时,除了常见的夏普比率,还应关注:
| 指标名称 | 计算公式 | 健康阈值 |
|---|---|---|
| 最大回撤 | 峰值到谷底的最大损失 | <20% |
| 胜率 | 盈利交易数/总交易数 | >55% |
| 盈亏比 | 平均盈利/平均亏损 | >1.5 |
| 换手率 | 交易金额/平均持仓市值 | <10 |
实战经验:很多论文中的"完美策略"在实际交易中失败,往往是因为忽略了滑点和交易成本。建议回测时至少加入0.1%的交易成本假设。
原始OHLCV数据可以扩展出上百个技术指标:
python复制def calculate_atr(df, window=14):
"""计算平均真实波幅"""
df['TR'] = np.maximum(
df['high'] - df['low'],
np.maximum(
abs(df['high'] - df['close'].shift()),
abs(df['low'] - df['close'].shift())
)
)
df['ATR'] = df['TR'].rolling(window).mean()
return df
通过全市场股票数据可以构建:
python复制def calculate_market_breadth(daily_data):
"""计算市场宽度指标"""
advancers = daily_data[daily_data['return'] > 0].groupby('date').size()
decliners = daily_data[daily_data['return'] < 0].groupby('date').size()
breadth = (advancers - decliners) / (advancers + decliners)
return breadth
780万条记录的处理建议:
sql复制-- ClickHouse建表示例
CREATE TABLE stock_data (
date Date,
symbol String,
open Float32,
high Float32,
low Float32,
close Float32,
volume UInt64
) ENGINE = MergeTree()
ORDER BY (symbol, date);
用Pandas处理时容易内存溢出,解决方法:
python复制# 内存优化示例
dtypes = {
'open': 'float32',
'high': 'float32',
'low': 'float32',
'close': 'float32',
'volume': 'uint32'
}
df = pd.read_csv('all_stocks.csv', dtype=dtypes)
金融数据需要特殊处理:
python复制from sklearn.preprocessing import StandardScaler
def preprocess_features(df):
"""金融特征预处理"""
df['log_volume'] = np.log1p(df['volume'])
df['return'] = df['close'].pct_change()
df['hour_sin'] = np.sin(2*np.pi*df['hour']/24)
df['hour_cos'] = np.cos(2*np.pi*df['hour']/24)
scaler = StandardScaler()
scaled = scaler.fit_transform(df[['log_volume', 'return']])
return pd.DataFrame(scaled, columns=['scaled_volume', 'scaled_return'])
金融时间序列要特别注意:
python复制# 正确的时间序列交叉验证
from sklearn.model_selection import TimeSeriesSplit
tscv = TimeSeriesSplit(n_splits=5)
for train_index, test_index in tscv.split(X):
X_train, X_test = X.iloc[train_index], X.iloc[test_index]
y_train, y_test = y.iloc[train_index], y.iloc[test_index]
分析多股票相关性:
python复制import seaborn as sns
corr_matrix = returns.corr()
sns.clustermap(corr_matrix, cmap='coolwarm', figsize=(12,10))
使用Plotly实现时间轴控制:
python复制import plotly.express as px
fig = px.line(data_frame=df, x='date', y='close',
animation_frame='symbol', range_y=[df['close'].min(), df['close'].max()])
fig.update_layout(title='Stock Price Evolution')
fig.show()
当策略准备投入实盘时:
血泪教训:曾经有个年化60%的策略,实盘后因为没考虑大单冲击成本,实际年化只有12%。建议用逐笔数据(tick data)做最后的成本验证。