问题描述
#
context.portfolio.long_positions["600585.XSHG"].amount = 100;
->说没这个Key("600585.XSHG")
context.portfolio.long_positions["600585.XSHG"]=[];
->TypeError: 'UserPositionsDict' object does not support item assignment
->说不能操作
context.portfolio.long_positions.setdefault("600585.XSHG");
->没setdefault函数
我只是想设个底仓,
感情positions不能强制设置?
解决方案
在 JoinQuant (聚宽) 平台中,context.portfolio.positions(以及 long_positions、short_positions 等)是只读对象。根据官方 API 文档的规定,尝试直接修改 Context、Portfolio、Position 等对象都会报错(如 TypeError: 'UserPositionsDict' object does not support item assignment)或者无效。
因此,你不能通过直接给字典赋值的方式来强制设置底仓。
如果你需要在回测或模拟交易中设置底仓,可以通过以下两种标准方法来实现:
方法一:在策略运行初期通过下单函数建仓(推荐用于常规回测)
最常用的方法是在策略开始运行的第一天,通过代码自动买入你需要的底仓数量。你可以设置一个全局标志位,确保只在第一天执行一次建仓操作。
def initialize(context):
# 设置全局标志位,记录是否已经建立底仓
g.has_built_initial_positions = False
# 运行函数
run_daily(market_open, time='09:30')
def market_open(context):
# 如果还没有建立底仓,则进行建仓
if not g.has_built_initial_positions:
# 强制买入 100 股 600585.XSHG
order_target('600585.XSHG', 100)
log.info("底仓建立完成")
# 更新标志位,以后不再重复建仓
g.has_built_initial_positions = True
return
# 下面写你正常的交易逻辑
# ...
方法二:使用 create_backtest API 的 initial_positions 参数(适用于研究环境)
如果你是在研究环境中通过代码调用 create_backtest 函数来创建回测,你可以直接使用 initial_positions 参数来传入初始持仓。持仓会根据价格换算成现金加到初始资金中。
# 在研究环境中运行
from jqdata import *
# 定义初始持仓
initial_positions = [
{
'security': '600585.XSHG',
'amount': '100',
'avg_cost': '10.0' # 可选,如果不填则默认获取最近的价格
}
]
params = {
"algorithm_id": "你的策略ID",
"start_date": "2023-01-01",
"end_date": "2023-12-31",
"frequency": "day",
"initial_cash": "100000",
"initial_positions": initial_positions, # 传入底仓
}
# 创建回测
created_bt_id = create_backtest(**params)
print("回测创建成功,ID:", created_bt_id)
总结
- 不要直接修改
context.portfolio.positions,它是系统维护的只读状态。 - 常规回测:在
handle_data或定时运行函数中,利用标志位在第一天调用order_target买入底仓。 - API 批量回测:利用
create_backtest的initial_positions参数直接注入底仓注入。