交易 - 组合优化
jh_quant.trading 集成了 Riskfolio-Lib 进行组合优化与再平衡。
启用组合优化
from jh_quant.trading.config import ( SessionServiceConfigBuilder, RebalanceMode, RebalancePolicySpec,)
config = ( SessionServiceConfigBuilder.defaults() .with_session(session_id="optimized", mode="paper") .with_selection(...) .add_strategy(...) .with_portfolio( enabled=True, objective="MinRisk", # MinRisk / MaxRet / MaxSharpe / MaxUtility risk_measure="MV", # MV / MAD / MSV / CVaR / CDaR 等 model="Classic", # Classic / BL / FM / HRP / HERC / NCO covariance_method="hist", # hist / ewma1 / ewma2 / ledoit / oas 等 min_weight=0.01, max_weight=0.20, lookback=252, rebalance_policy=RebalancePolicySpec( mode=RebalanceMode.DRIFT_THRESHOLD, drift_threshold=0.10, ), ) .build())再平衡模式
DRIFT_THRESHOLD(漂移触发)
实际持仓偏离目标权重超过阈值时触发。
rebalance_policy=RebalancePolicySpec( mode=RebalanceMode.DRIFT_THRESHOLD, drift_threshold=0.10, min_rebalance_interval_seconds=86400,)EVERY_CYCLE(每周期)
每个交易周期都运行优化并再平衡。
INITIAL_ONLY(仅首次建仓)
初始运行一次建仓,之后由策略自主调仓。
SCHEDULE(定时调度)
rebalance_policy=RebalancePolicySpec( mode=RebalanceMode.SCHEDULE, schedule_cron="0 16 * * 5", # 每周五 16:00)再平衡执行流程
策略选股信号 │ ▼Riskfolio-Lib 优化 ── 输入:历史收益率矩阵 + 选股信号 │ 输出:原始目标权重 ▼权重后处理 ── 信号引导的权重微调、上下限截断 │ ▼再平衡计划 ── 对比目标权重 vs 当前持仓 │ T+1 约束、资金约束、取整约束 ▼TradingEngine 执行订单REST API
优化预览
POST /sessions/{session_id}/portfolio/optimize触发再平衡
POST /sessions/{session_id}/portfolio/rebalance查看组合分析
GET /sessions/{session_id}/portfolio/analysis编程接口
from jh_quant.trading.portfolio import ( RiskfolioPortfolioOptimizer, optimize_portfolio_preview, build_rebalance_plan,)from jh_quant.trading.config.portfolio import PortfolioSpec
spec = PortfolioSpec( objective="MinRisk", risk_measure="MV", model="Classic", covariance_method="hist", min_weight=0.01, max_weight=0.20, lookback=252,)
optimizer = RiskfolioPortfolioOptimizer()result = optimizer.optimize( returns=returns_df, portfolio_spec=spec, signals=signal_scores,)print(result.weights) # 目标权重print(result.diagnostics) # 优化诊断
# 生成再平衡订单plan = build_rebalance_plan( target_weights=result.weights, positions=current_positions, latest_prices=prices, portfolio_spec=spec,)