@jenniewu 问题找到了,可以按照下面自己修复,也可以重新拉一下代码:
报错是:AttributeError: 'StrategyGlobals' object has no attribute 'sub_account'
出在 make_record 里这行:
g.sub_account[sid]['total_value'] = g.sub_account[sid]['cash'] + holdings_value
含义是:当时的全局对象 g 上根本没有 sub_account 这个属性。正常路径里它是在 set_params(由 initialize 调用)里初始化的(约 90–98 行)。在模拟盘热更新、改代码后继续跑、或状态恢复不完整等场景下,initialize / set_params 可能没再执行一遍,但定时任务 run_daily(make_record, "15:01") 仍会跑,于是访问 g.sub_account 就崩溃。日志里随后出现的「策略已经暂停或失败,不执行策略代码」是崩溃后的结果,不是原因。
要在make record前新增这些代码就可以了:
def _sub_account_structure_ok():
sa = getattr(g, "sub_account", None)
if not isinstance(sa, dict):
return False
for i in range(1, 5):
row = sa.get(i)
if not isinstance(row, dict):
return False
for k in ("initial_capital", "cash", "total_value"):
if k not in row:
return False
return True
def _ensure_make_record_globals(context):
"""
模拟盘热更新 / 恢复会话后,g 可能不完整;补齐 make_record 依赖字段,避免 AttributeError。
不调用完整 set_params,以免清空 stock_strategy、strategy_holdings 等运行时状态。
"""
pv = getattr(g, "portfolio_value_proportion", None)
pv_ok = isinstance(pv, (list, tuple)) and len(pv) >= 4
need = (
not _sub_account_structure_ok()
or getattr(g, "strategy_value_data", None) is None
or not pv_ok
or getattr(g, "strategy_holdings", None) is None
)
if not need:
return
log.warning(
"[make_record] 子账户相关全局缺失或损坏,已按当前参数与总资产重建虚拟子账户(热更新兜底)。"
)
if not pv_ok:
g.portfolio_value_proportion = [0.5, 0, 0.5, 0]
if getattr(g, "starting_cash", None) is None:
g.starting_cash = context.portfolio.total_value
if getattr(g, "strategy_holdings", None) is None:
g.strategy_holdings = {1: [], 2: [], 3: [], 4: []}
if getattr(g, "strategy_value_data", None) is None:
g.strategy_value_data = {1: 0, 2: 0, 3: 0, 4: 0}
g.sub_account = {}
for i in range(1, 5):
initial_capital = float(g.starting_cash) * float(
g.portfolio_value_proportion[i - 1]
)
g.sub_account[i] = {
"initial_capital": initial_capital,
"cash": initial_capital,
"total_value": initial_capital,
}
g.xsz_pnl_realized_cumulative = float(
getattr(g, "xsz_pnl_realized_cumulative", 0.0)
)
# 尾盘记录各个策略的收益
def make_record(context):
_ensure_make_record_globals(context) #make record里要新增这一句
positions = context.portfolio.positions
current_data = get_current_data()
2026-04-28