在期货量化交易中,数据清洗和预处理是策略开发的基础环节。以下是常用的**期货数据清洗与预处理方法**,结合理论与实践(引用自知识库相关内容):
---
### **一、数据清洗方法**
#### 1. **处理缺失值**
- **原因**:数据源中断、传输错误或市场休市可能导致缺失值。
- **方法**:
- **删除缺失行**:适用于缺失比例极低的情况(如某日数据完全缺失)(#ref_7)。
- **插值填充**:使用前后值填充(`ffill`/`bfill`)或线性插值(适合时间序列数据)。
- **模型预测填充**:对高价值数据,可使用简单模型(如ARIMA)预测缺失值。
- **代码示例**(来自`get_index_bar`函数):
```python
# 删除包含缺失值的行
df.dropna(subset=[open, high, low, close, volume], inplace=True)
```
#### 2. **去除重复数据**
- **原因**:交易所或数据库重复推送导致同一时间戳多条记录。
- **方法**:
- 按时间戳去重(保留最新记录)(#ref_7)。
- **代码示例**:
```python
# 去除重复日期
df = df.drop_duplicates(subset=trade_date, keep=last)
```
#### 3. **异常值检测与修正**
- **原因**:极端行情(如闪崩)或数据采集错误导致价格/成交量异常。
- **方法**:
- **统计阈值法**:剔除超出3倍标准差的数据点。
- **IQR法**:基于四分位距识别异常值(Q1-1.5IQR ~ Q3+1.5IQR)(#ref_3)。
- **可视化检查**:通过箱线图或散点图定位异常(如Volume突增)。
- **代码示例**(基于ATR动态调整止损逻辑):
```python
# 计算ATR(平均真实波动幅度),用于识别异常波动
def calculate_atr(self, data):
high_low = data[high] - data[low]
high_close = np.abs(data[high] - data[close].shift())
low_close = np.abs(data[low] - data[close].shift())
tr = pd.concat([high_low, high_close, low_close], axis=1).max(axis=1)
atr = tr.rolling(self.atr_period).mean()
return atr
```
#### 4. **数据格式标准化**
- **原因**:不同交易所或API返回的数据格式不统一(如日期格式、小数位数)。
- **方法**:
- 统一时间戳格式(如`YYYY-MM-DD`)。
- 强制转换数值列为浮点型(避免字符串参与计算)(#ref_7)。
- **代码示例**:
```python
# 转换日期格式并设置索引
df[trade_date] = pd.to_datetime(df[trade_date])
df.set_index(trade_date, inplace=True)
# 确保数值列正确
for col in [open, high, low, close, volume]:
df[col] = pd.to_numeric(df[col], errors=coerce)
```
---
### **二、数据预处理方法**
#### 1. **特征工程**
- **技术指标构建**:基于原始数据生成策略所需信号。
- **趋势类**:移动平均线(MA)、指数平滑(EMA)。
- **动量类**:RSI、MACD。
- **波动率类**:ATR、布林带。
- **代码示例**(来自`
calculate_breakouts_and_ma`函数):```python
# 计算突破水平(S1/S2系统)
data[f{self.entry_period_s1}_high] = data[high].rolling(self.entry_period_s1).max()
data[f{self.exit_period_s1}_low] = data[low].rolling(self.exit_period_s1).min()
# 计算KAMA自适应均线
data[kama] = ta.KAMA(data[close].values.astype(np.float64), timeperiod=60)
```
#### 2. **时间序列归一化**
- **目的**:消除量纲差异,便于模型比较。
- **方法**:
- **Min-Max缩放**:将数据映射到[0,1]区间。
- **Z-Score标准化**:均值为0,标准差为1。
- **适用场景**:机器学习模型输入前的处理(#ref_5)。
#### 3. **数据窗口化与滑动窗口**
- **目的**:将连续时间序列分割为固定长度的样本(如训练LSTM模型)。
- **方法**:
- 使用滑动窗口函数(如`rolling`)计算动态指标(如滚动均值)。
- **代码示例**:
```python
# 计算20日ATR
data[atr] = data[tr].rolling(20).mean()
```
#### 4. **标签生成(用于监督学习)**
- **目的**:为策略回测或机器学习模型标注目标变量。
- **方法**:
- **方向标签**:未来N日涨跌(1/-1)。
- **收益标签**:未来N日收益率。
- **代码示例**:
```python
# 生成未来5日收益率标签
df[future_return] = df[close].pct_change(5).shift(-5)
```
---
### **三、特殊数据处理**
#### 1. **K线合并(Resample)**
- **场景**:将高频数据(如1分钟K线)合并为低频数据(如日K线)。
- **代码示例**:
```python
# 1分钟数据转为日K线
daily_df = min_df.resample(D).agg({
open: first,
high: max,
low: min,
close: last,
volume: sum
})
```
#### 2. **主力合约切换处理**
- **问题**:期货合约到期后需切换至次主力合约,避免断档。
- **方法**:
- **展期处理**:通过历史持仓量/成交量筛选主力合约。
- **价差调整**:消除不同合约间的基差影响。
- **代码示例**(来自`CONTRACT_SIZE_CODE_MAP`):
```python
# 合约代码映射表
CONTRACT_SIZE_CODE_MAP = {
"AU": 1000, "IM": 200, "RB": 10, ...
}
```
#### 3. **滑点与手续费建模**
- **目的**:模拟真实交易成本对策略的影响。
- **代码示例**:
```python
def _apply_slippage(self, price, direction):
if direction == 1: # 买入
return price + self.slippage_per_unit
elif direction == -1: # 卖出
return price - self.slippage_per_unit
def _calculate_commission(self, units):
return units * self.commission_per_unit * 2 # 往返佣金
```
---
### **四、工具推荐**
| 工具 | 功能 |
|------|------|
| **Pandas** | 数据清洗、转换、时间序列处理(核心工具) (#ref_1) |
| **NumPy** | 高效数值计算(如ATR计算) (#ref_3) |
| **TA-Lib** | 技术指标计算(如KAMA、MACD) [[代码中ta模块]] |
| **Scikit-learn** | 标准化、异常值检测 (#ref_5) |
| **Plotly/Matplotlib** | 可视化验证数据质量 [[代码中绘图函数]] |
---
### **五、总结**
期货数据清洗与预处理的核心目标是**提升数据质量与可用性**。具体方法需根据数据来源(如交易所API、第三方供应商)和策略需求(如高频交易需处理Tick数据)灵活选择。以下为推荐流程:
1. **基础清洗**:缺失值→重复数据→异常值。
2. **格式标准化**:时间戳→数值类型→单位统一。
3. **特征工程**:技术指标→标签生成。
4. **场景适配**:主力合约切换→滑点手续费建模。
最终,清洗后的数据需通过可视化(如K线图叠加信号点)和统计检验(如分布直方图)验证有效性,才能投入策略回测或模型训练。