问题描述
需要一个能按固定比例调仓,每周期卖出不在股票名单内的股票,买入在股票名单内而未持有的股票。
谢谢!
解决方案
在 JoinQuant(聚宽)平台上编写多因子策略的换仓函数,核心逻辑通常分为两步:第一步是卖出(平仓当前持有但不在新目标名单中的股票),第二步是买入/调仓(将目标名单中的股票调整至目标权重)。
以下是一个完整且通用的换仓函数实现,采用**等权重(固定比例)**的方式进行调仓:
完整策略代码示例
# 导入聚宽函数库
import jqdata
def initialize(context):
# 设定沪深300作为基准
set_benchmark('000300.XSHG')
# 开启动态复权模式(真实价格)
set_option('use_real_price', True)
# 设置手续费
set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
# 每月第一个交易日 09:30 运行调仓函数
run_monthly(rebalance, monthday=1, time='09:30')
def get_target_stocks(context):
# 这里是你的多因子选股逻辑,返回一个股票代码列表
# 示例:简单选取几只股票作为目标名单
return ['000001.XSHE', '000002.XSHE', '600000.XSHG', '600036.XSHG']
def rebalance(context):
# 1. 获取本周期的目标股票名单
target_list = get_target_stocks(context)
# 2. 获取当前账户持仓的股票
current_positions = list(context.portfolio.positions.keys())
# 3. 卖出逻辑:如果持仓中的股票不在目标名单内,则全部卖出
for stock in current_positions:
if stock not in target_list:
order_target_value(stock, 0)
log.info("卖出不在目标名单内的股票: %s" % stock)
# 4. 买入/调仓逻辑:按固定比例(等权重)买入目标股票
if len(target_list) > 0:
# 计算每只股票应分配的目标价值(总资产 / 目标股票数量)
# 注意:这里使用 context.portfolio.total_value 获取账户总权益
target_value = context.portfolio.total_value / len(target_list)
for stock in target_list:
# order_target_value 会自动计算差额进行买入或卖出,使其达到目标价值
order_target_value(stock, target_value)
log.info("调仓股票: %s, 目标价值: %.2f" % (stock, target_value))
核心函数解析
context.portfolio.positions:这是一个字典,包含了当前账户所有持仓的股票信息。通过.keys()可以获取当前持有的所有股票代码。order_target_value(security, value):这是聚宽非常强大的一个下单 API。它的作用是将指定标的(security)的仓位调整到目标价值(value)。- 如果
value = 0,相当于全部清仓卖出。 - 如果当前未持有该股票,它会用相应的现金买入该股票直到达到
value的市值。 - 如果当前已持有该股票但市值不足
value,它会补仓;如果市值超过value,它会减仓。
- 如果
context.portfolio.total_value:获取账户的总资产(包含可用现金和当前持仓市值)。用它除以目标股票数量,即可实现“等权重/固定比例”调仓。
进阶优化建议
在实际的实盘或高精度回测中,你可能还需要考虑停牌股票和涨跌停股票的处理。例如,在卖出时如果股票停牌是无法卖出的,这会占用资金,导致后续买入其他股票时资金不足。可以通过 get_current_data()[stock].paused 来判断股票是否停牌,从而优化资金分配逻辑。