3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在 JoinQuant(聚宽)量化交易平台中,进行投资组合优化时,为了防止策略在实盘交易中因下单量过大而对市场价格造成冲击(即降低冲击成本),我们通常需要对标的进行流动性约束。
聚宽的投资组合优化器 portfolio_optimizer 提供了专门的边界函数 LiquidityBound,用于限制单只标的的购买数量不超过其过去一段时间平均成交量的一定比例。
LiquidityBound 属于优化器的边界函数(bounds),其定义如下:
LiquidityBound(limit, capital, count=1, subset=None)
limit (float):成交量比例限制。例如 0.5 表示购买数量不能超过该标的历史平均成交量的 50%。capital (float):当前可用于该投资组合的资金总额(单位:元)。优化器需要根据此资金和个股价格来换算购买股数,从而进行比例限制。count (int):向前取均值的天数,默认为 1。例如设置为 5,则表示参考过去 5 个交易日的日均成交量。subset (list, 可选):限制特定股票的列表。如果为 None(默认值),则表示股票池中的所有股票都要满足该流动性限制。以下是一个完整的聚宽策略初始化与调仓代码片段,展示了如何在 portfolio_optimizer 中应用 LiquidityBound:
import pandas as pd
from jqdata import *
from jqlib.optimizer import *
def initialize(context):
# 设定沪深300作为基准
set_benchmark('000300.XSHG')
# 开启动态复权模式(真实价格)
set_option('use_real_price', True)
# 股票池:假设为部分上证50成分股
g.buy_list = ['600000.XSHG', '600016.XSHG', '600030.XSHG', '600519.XSHG', '601318.XSHG']
# 每月第一个交易日开盘运行调仓
run_monthly(market_open, monthday=1, time='09:30', reference_security='000300.XSHG')
def market_open(context):
# 获取当前账户总资产作为优化器的可用资金
capital = context.portfolio.total_value
# 设定优化目标:组合风险最小化(最小化组合方差)
target = MinVariance(count=250)
# 设定约束条件:组合总权重在 90% 到 100% 之间
constraints = [WeightConstraint(low=0.9, high=1.0)]
# 设定边界条件:
# 1. 基础权重边界:每只标的权重在 0% 到 30% 之间
# 2. 流动性边界:购买数量不超过过去 5 个交易日平均成交量的 10%
bounds = [
Bound(0.0, 0.3),
LiquidityBound(limit=0.1, capital=capital, count=5)
]
# 运行投资组合优化器
optimized_weight = portfolio_optimizer(
date=context.previous_date,
securities=g.buy_list,
target=target,
constraints=constraints,
bounds=bounds,
default_port_weight_range=[0., 1.0],
ftol=1e-09,
return_none_if_fail=True
)
# 执行调仓
if optimized_weight is not None:
log.info("优化后的权重结果:")
log.info(optimized_weight)
for stock in optimized_weight.keys():
value = capital * optimized_weight[stock]
order_target_value(stock, value)
else:
log.warn("组合优化失败,保持原仓位或执行备用方案。")
capital 的准确性:传入 LiquidityBound 的 capital 必须是真实的可用资金或计划分配给该组合的资金。如果传入的资金过大,换算出的个股购买股数会偏高,导致流动性约束失效或优化失败。portfolio_optimizer 时,date 参数应传入 context.previous_date(前一交易日),确保优化器计算历史成交量时使用的是已知数据,避免引入未来数据。Bound 和 LiquidityBound。当存在多个边界限制时,优化器会自动取交集(即下限取最大值,上限取最小值)来约束个股权重。