🚀 AI 一键生成 joinquant 策略代码
立即体验

聚宽(JoinQuant)量化策略入门:如何协同使用 initialize、context 与 portfolio 核心对象?

joinquant | 发布时间: 2026/8/9
以下内容由 EasyQuant 生成。

问题描述

聚宽量化策略入门:initialize、context 与 portfolio 核心对象如何协同使用?
在聚宽中如何正确编写 initialize 和每日交易函数,并使用 context、context.portfolio 获取现金、持仓和账户状态?

解决方案

聚宽(JoinQuant)核心对象协同工作原理

在聚宽量化交易平台中,编写一个完整的策略主要依赖于初始化函数(initialize、**上下文对象(context以及账户资产对象(portfolio)**的协同配合。它们的关系如下:

  1. initialize(context):策略的起点。在整个回测或模拟盘生命周期中仅执行一次。用于设定基准、开启真实价格模式、初始化全局变量(使用 g 对象)以及注册定时运行任务(如 run_daily)。
  2. context:策略的“大管家”。它是一个只读对象,贯穿策略的整个运行过程,并被自动传入各个执行函数中。它包含了当前的时间戳(context.current_dt)、运行参数以及最重要的子账户与资产信息。
  3. context.portfolio:资金与持仓的“账本”。通过它,策略可以实时查询当前账户的总资产、可用现金、持仓标的及持仓成本,从而做出买入或卖出的决策。

核心 API 与属性介绍

1. 获取账户整体状态 (context.portfolio)

  • context.portfolio.total_value:当前账户总权益(现金 + 持仓市值)。
  • context.portfolio.available_cash:当前可用资金,可用于购买证券。
  • context.portfolio.positions_value:当前持有的所有证券的总市值。
  • context.portfolio.returns:账户自回测开始以来的累计收益率。

2. 获取单只股票的持仓状态 (context.portfolio.positions)

context.portfolio.positions 是一个字典(Dict),键为股票代码,值为 Position 对象:

  • context.portfolio.positions[security].total_amount:总持仓股数。
  • context.portfolio.positions[security].closeable_amount:可卖出的仓位(A股 T+1 规则下,当天买入的不可卖出)。
  • context.portfolio.positions[security].avg_cost:当前持仓的开仓/加仓均价。
  • context.portfolio.positions[security].value:该股票当前的持仓市值。

完整策略源码示例:均线突破策略

以下策略展示了如何在 initialize 中初始化账户,并在每日开盘时通过 context 获取现金和持仓状态,执行买卖操作:

# 导入聚宽函数库
import jqdata

def initialize(context):
    # 1. 定义全局变量,保存要操作的股票(平安银行)
    g.security = '000001.XSHE'
    
    # 2. 设定沪深300作为基准
    set_benchmark('000300.XSHG')
    
    # 3. 强烈建议开启真实价格模式(动态复权)
    set_option('use_real_price', True)
    
    # 4. 设置佣金与印花税:买入万三,卖出万三加千一印花税,最低5元
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
    
    # 5. 注册每日运行函数:每天 09:30 运行 market_open 函数
    run_daily(market_open, time='09:30')

def market_open(context):
    security = g.security
    
    # 1. 使用 context 获取当前逻辑时间
    log.info("当前交易日时间: %s" % context.current_dt)
    
    # 2. 获取历史数据:过去5天的收盘价
    close_data = attribute_history(security, 5, '1d', ['close'])
    MA5 = close_data['close'].mean()
    current_price = close_data['close'][-1]
    
    # 3. 使用 context.portfolio 获取账户状态
    cash = context.portfolio.available_cash  # 获取可用现金
    
    # 获取个股持仓信息
    position = context.portfolio.positions[security]
    current_holdings = position.total_amount  # 当前持仓股数
    sellable_amount = position.closeable_amount  # 可卖出股数
    
    log.info("当前可用现金: %.2f 元, 当前持仓: %d 股, 可卖出: %d 股" % (cash, current_holdings, sellable_amount))
    
    # 4. 交易逻辑判断
    # 如果上一时间点价格高出五天平均价1%,且当前无持仓,则全仓买入
    if current_price > 1.01 * MA5 and current_holdings == 0:
        log.info("价格高于均价1%%,执行买入。")
        order_value(security, cash)  # 用所有可用资金买入
        
    # 如果上一时间点价格低于五天平均价,且持有可卖出的股票,则清仓卖出
    elif current_price < MA5 and sellable_amount > 0:
        log.info("价格低于均价,执行卖出。")
        order_target(security, 0)  # 卖出所有股票,使最终持有量为0
        
    # 5. 记录数据,绘制在回测图表上
    record(stock_price=current_price, ma5=MA5)

编写注意事项

  1. 不要跨日期缓存数据:在开启 use_real_price=True 后,attribute_history 等 API 返回的是基于当天日期的前复权价格。不同日期看到的前复权价格可能不同,因此切勿将获取的价格数据存入全局变量 g 中跨日使用。
  2. 区分 total_amountcloseable_amount:在 A 股市场实行 T+1 交易制度,当天买入的股票在当天不可卖出。因此,在编写卖出逻辑时,应判断 position.closeable_amount > 0,避免因可用仓位不足导致废单。