AI应用 量化交易MLOps系统架构部署运维
量化交易系统的AI化部署与运维
道
量子道
量子道 · 扫码阅读
微信 · 浏览器扫码
在手机上获得更好的阅读体验
量化交易系统的AI化部署与运维
回测赚钱的策略成千上万,实盘赚钱的系统万里挑一。差距不在策略本身,而在工程化能力。
从Jupyter到生产系统
原型与生产的鸿沟
Jupyter原型 生产系统
─────────────────────────────────────────────────
手动运行 定时自动执行
数据在内存中 数据持久化和缓存
单标的单周期 多标的多周期
无异常处理 全面的错误处理和告警
手动查看结果 自动监控和通知
代码散落各处 模块化、可测试
生产级系统架构
┌─────────────────────────────────────────────┐
│ 调度层 │
│ Airflow / Prefect / Cron │
├─────────────────────────────────────────────┤
│ 数据层 │ 计算层 │ 执行层 │
│ ─────────── │ ─────────── │ ─────────── │
│ 行情数据采集 │ 特征工程 │ 订单管理 │
│ 另类数据采集 │ 模型推理 │ 风控检查 │
│ 数据质量检查 │ 信号生成 │ 执行报告 │
├─────────────────────────────────────────────┤
│ 存储层 │
│ PostgreSQL + Redis + InfluxDB │
├─────────────────────────────────────────────┤
│ 监控层 │
│ Grafana + Prometheus + 飞书/钉钉告警 │
└─────────────────────────────────────────────┘
数据管道的AI化
数据质量自动检测
import pandas as pd
import numpy as np
from dataclasses import dataclass
from typing import List, Dict
@dataclass
class DataQualityReport:
total_rows: int
missing_pct: float
duplicates: int
outliers_count: Dict[str, int]
stale_data: bool
schema_valid: bool
issues: List[str]
class AIDataValidator:
AI辅助的数据质量检查器
def __init__(self, llm_client=None):
self.llm = llm_client
def validate_ohlcv(self, df: pd.DataFrame) -> DataQualityReport:
验证OHLCV数据
issues = []
# 基础检查
required_cols = [Open, High, Low, Close, Volume]
missing_cols = [c for c in required_cols if c not in df.columns]
if missing_cols:
issues.append(f缺少列: {missing_cols})
schema_valid = False
else:
schema_valid = True
# 逻辑检查
if (df[High] < df[Low]).any():
issues.append(High < Low 的异常行存在)
if (df[Close] > df[High]).any():
issues.append(Close > High 的异常行存在)
if (df[Close] < df[Low]).any():
issues.append(Close < Low 的异常行存在)
# 缺失值检查
missing_pct = df[required_cols].isnull().mean().mean()
if missing_pct > 0.01:
issues.append(f缺失率 {missing_pct:.2%} 超过1%阈值)
# 异常值检测(基于滚动统计)
outliers = {}
if Close in df.columns:
returns = df[Close].pct_change()
zscore = (returns - returns.rolling(252).mean()) / returns.rolling(252).std()
outlier_count = (abs(zscore) > 5).sum()
if outlier_count > 0:
outliers[returns] = int(outlier_count)
issues.append(f收益率异常值: {outlier_count}个 (>5σ))
# 数据时效性
stale_data = (pd.Timestamp.now() - df.index.max()).days > 2
if stale_data:
issues.append(f数据滞后 {(pd.Timestamp.now() - df.index.max()).days} 天)
return DataQualityReport(
total_rows=len(df),
missing_pct=missing_pct,
duplicates=int(df.index.duplicated().sum()),
outliers_count=outliers,
stale_data=stale_data,
schema_valid=schema_valid,
issues=issues
)
def ai_diagnose(self, report: DataQualityReport) -> str:
让AI帮助诊断数据问题
if not self.llm or not report.issues:
return
prompt = f
量化交易系统的数据质量检查发现以下问题:
{chr(10).join(f- {i} for i in report.issues)}
请诊断:
1. 这些问题的根本原因可能是什么?
2. 哪些问题会导致策略信号异常?
3. 建议的修复优先级是什么?
return self.llm.generate(prompt)
模型服务的AI化
自动化特征工程
from sklearn.feature_selection import mutual_info_regression
import warnings
class AutoFeatureEngineer:
自动特征工程流水线
def __init__(self, max_features=50):
self.max_features = max_features
self.selected_features = None
self.feature_importance = None
def generate_features(self, df):
自动生成候选特征
features = {}
# 价格特征
for window in [5, 10, 20, 50, 200]:
features[freturn_{window}d] = df[Close].pct_change(window)
features[fvolatility_{window}d] = df[Close].pct_change().rolling(window).std()
features[fvolume_ratio_{window}d] = df[Volume] / df[Volume].rolling(window).mean()
features[fhigh_low_ratio_{window}d] = (
df[High].rolling(window).max() / df[Low].rolling(window).min()
)
# 价格形态(基于滑动窗口的统计)
for window in [20, 50]:
roll = df[Close].rolling(window)
features[fprice_position_{window}d] = (
(df[Close] - roll.min()) / (roll.max() - roll.min())
)
features[fskewness_{window}d] = df[Close].pct_change().rolling(window).skew()
features[fkurtosis_{window}d] = df[Close].pct_change().rolling(window).kurt()
return pd.DataFrame(features, index=df.index).dropna()
def select_features(self, X, y, method=mutual_info):
自动特征选择
if method == mutual_info:
mi_scores = mutual_info_regression(X.fillna(0), y, random_state=42)
self.feature_importance = pd.Series(mi_scores, index=X.columns).sort_values(ascending=False)
self.selected_features = self.feature_importance.head(self.max_features).index.tolist()
print(f选择了 {len(self.selected_features)}/{len(X.columns)} 个特征)
print(fTop 5: {self.selected_features[:5]})
return self.selected_features
模型版本管理与热更新
import mlflow
import mlflow.sklearn
from datetime import datetime
import hashlib
class ModelRegistry:
模型注册和版本管理
def __init__(self, tracking_uri=sqlite:///model_registry.db):
mlflow.set_tracking_uri(tracking_uri)
self.experiment_name = quant_trading
def register_model(self, model, metrics, params, feature_names):
注册模型版本
mlflow.set_experiment(self.experiment_name)
with mlflow.start_run(run_name=ftrain_{datetime.now():%Y%m%d_%H%M}):
# 记录参数
mlflow.log_params(params)
# 记录指标
mlflow.log_metrics({
sharpe_ratio: metrics[sharpe],
max_drawdown: metrics[max_dd],
win_rate: metrics[win_rate],
profit_factor: metrics[profit_factor],
calmar_ratio: metrics[calmar],
})
# 记录特征
feature_hash = hashlib.md5(
,.join(sorted(feature_names)).encode()
).hexdigest()[:8]
mlflow.log_param(feature_hash, feature_hash)
mlflow.log_param(n_features, len(feature_names))
# 保存模型
mlflow.sklearn.log_model(model, model)
run_id = mlflow.active_run().info.run_id
print(f模型已注册: run_id={run_id})
return run_id
def promote_to_production(self, run_id):
将模型提升到生产环境
client = mlflow.tracking.MlflowClient()
model_uri = fruns:/{run_id}/model
# 注册模型
mv = mlflow.register_model(model_uri, trading_model)
# 标记为生产版本
client.transition_model_version_stage(
name=trading_model,
version=mv.version,
stage=Production
)
print(f模型版本 {mv.version} 已提升至生产环境)
def load_production_model(self):
加载生产环境模型
return mlflow.sklearn.load_model(models:/trading_model/Production)
实时推理引擎
高性能特征服务
import redis
import pickle
from concurrent.futures import ThreadPoolExecutor
import time
class RealTimeInferenceEngine:
实时推理引擎
def __init__(self, model, feature_config, redis_url=redis://localhost:6379):
self.model = model
self.feature_config = feature_config
self.cache = redis.from_url(redis_url)
self.executor = ThreadPoolExecutor(max_workers=4)
self.latency_window = [] # 推理延迟记录
def infer(self, symbol: str, current_data: dict) -> dict:
实时推理
start_time = time.perf_counter()
# 1. 从缓存获取历史特征
cached_features = self._get_cached_features(symbol)
if cached_features is None:
return {error: 缓存未命中,请检查数据流水线}
# 2. 合并实时数据 + 历史特征
features = self._compute_features(cached_features, current_data)
# 3. 模型预测
prediction = self.model.predict_proba([features])[0]
# 4. 风控检查
risk_check = self._risk_check(symbol, prediction)
# 5. 生成信号
signal = self._generate_signal(prediction, risk_check)
latency = time.perf_counter() - start_time
self._record_latency(latency)
return {
symbol: symbol,
signal: signal,
confidence: float(prediction[1]),
risk_approved: risk_check[approved],
latency_ms: latency * 1000,
timestamp: datetime.now().isoformat()
}
def _risk_check(self, symbol, prediction):
多层风控
checks = {
max_position: self._check_position_limit(symbol),
max_exposure: self._check_exposure_limit(),
circuit_breaker: self._check_circuit_breaker(),
volatility_filter: self._check_volatility(symbol),
}
return {
approved: all(checks.values()),
details: checks
}
监控与告警
策略健康度监控
class StrategyMonitor:
策略运行监控
def __init__(self, alert_webhook=None):
self.alert_webhook = alert_webhook
self.metrics_history = []
def check_health(self, strategy_state: dict) -> List[str]:
检查策略健康状态
alerts = []
# 1. 信号频率异常
signal_count = strategy_state.get(signals_today, 0)
avg_signals = strategy_state.get(avg_daily_signals, 10)
if signal_count > avg_signals * 3:
alerts.append(f⚠️ 今日信号异常增多: {signal_count} (均值: {avg_signals}))
if signal_count == 0 and datetime.now().hour > 11:
alerts.append(f⚠️ 今日无任何信号产生)
# 2. 数据延迟
data_lag = strategy_state.get(data_lag_minutes, 0)
if data_lag > 5:
alerts.append(f🚨 数据延迟 {data_lag} 分钟,可能影响信号质量)
# 3. 模型漂移
prediction_mean = strategy_state.get(prediction_mean, 0)
if abs(prediction_mean - 0.5) > 0.2:
alerts.append(f⚠️ 模型预测分布偏移: 均值={prediction_mean:.3f})
# 4. 回撤监控
current_drawdown = strategy_state.get(drawdown, 0)
if current_drawdown > strategy_state.get(max_allowed_dd, 0.15):
alerts.append(f🚨 回撤超过限制: {current_drawdown:.2%})
# 5. AI综合诊断
if len(alerts) >= 3 and self.alert_webhook:
diagnosis = self._ai_diagnose(alerts, strategy_state)
alerts.append(f🤖 AI诊断: {diagnosis})
return alerts
def _ai_diagnose(self, alerts, state):
AI辅助诊断异常
prompt = f
量化策略出现以下告警:
{chr(10).join(alerts)}
策略状态:
夏普比率: {state.get(sharpe, N/A)}
最近5日收益: {state.get(returns_5d, N/A)}
持仓: {state.get(positions, N/A)}
请给出最可能的1-2个根因和紧急行动建议。不超过50字。
# 调用LLM
return 模型漂移 + 市场风格切换,建议暂停交易并重新训练
关键检查清单
在将AI量化系统从回测推向实盘前,确认以下事项:
上线前 Checklist
□ 样本外回测至少覆盖一个完整牛熊周期
□ 考虑了真实的交易成本(佣金、滑点、印花税)
□ 没有前视偏差(所有特征在预测时点可用)
□ 模型在多个不相关标的上表现一致
□ 压力测试:极端行情(2015股灾、2020熔断)下的表现
□ 金丝雀测试:小资金实盘运行至少1个月
□ 监控和告警系统就位
□ 紧急停止开关可用
□ 有完整的数据备份和恢复方案
□ 定期模型重训练流程已自动化
从回测到实盘,90%的努力不在策略算法上,而在工程韧性上。一个好的量化系统,即使策略失效,也不会造成灾难性损失——这才是真正的生产级。