问题描述
在 def before_trading_start(context):里
.....
orderlist = list(bb.index)
weights = list(bb['w'])
.....
在def before_trading_start(context):里也可以print出来
后面在:
def handle_data(context, data):
# 每个调仓日截面上,进行数据提取和计算
if g.if_trade == True:
order_stock_sell(context,orderlist)
order_stock_buy(context,orderlist)
g.if_trade = False
执行卖出
def order_stock_sell(context,order_list):
# 对于不需要持仓的股票,全仓卖出
for stock in context.portfolio.positions:
# 除去buy_list内的股票,其他都卖出
if stock not in order_list:
order_target_value(stock, 0)
执行买入(自己修改了)
def order_stock_buy(context,order_list):
# 对于需要持仓的股票,按分配到的份额买入
for stock in order_list:
ww = weights[order_list.index(stock)]
order_target_value(stock, 50000000*ww)
运行时就会报错:
File "/tmp/strategy/user_code.py", line 6609, in handle_data
order_stock_sell(context,orderlist)
NameError: name 'orderlist' is not defined
难道是ef before_trading_start(context):里定义的变量在
def handle_data(context, data):不能用吗?
解决方案
是的,您遇到的问题正是因为 Python 的变量作用域(Scope)规则 导致的。
在 def before_trading_start(context): 里面定义的 orderlist 和 weights 是局部变量。它们只在这个函数内部有效,一旦函数执行完毕,这些变量就会被销毁。因此,当系统接着运行 def handle_data(context, data): 时,它找不到名为 orderlist 的变量,从而抛出 NameError: name 'orderlist' is not defined 的错误。
解决方法:使用 JoinQuant 的全局变量对象 g
在 JoinQuant 平台中,为了在不同的函数(如 initialize、before_trading_start、handle_data 等)之间共享数据,官方提供了一个专门的全局变量对象 g。您只需要把需要跨函数使用的变量绑定到 g 对象上即可。
修改后的代码示例:
1. 在 before_trading_start 中绑定到 g 对象:
def before_trading_start(context):
# ... 前面的代码 ...
# 将变量绑定到全局对象 g 上
g.orderlist = list(bb.index)
g.weights = list(bb['w'])
# ... 后面的代码 ...
2. 在 handle_data 中通过 g 对象调用:
def handle_data(context, data):
# 每个调仓日截面上,进行数据提取和计算
if g.if_trade == True:
# 注意这里传入的是 g.orderlist
order_stock_sell(context, g.orderlist)
order_stock_buy(context, g.orderlist)
g.if_trade = False
3. 修改买入函数(因为里面用到了 weights):
def order_stock_buy(context, order_list):
# 对于需要持仓的股票,按分配到的份额买入
for stock in order_list:
# 注意这里调用的是 g.weights
ww = g.weights[order_list.index(stock)]
order_target_value(stock, 50000000 * ww)
总结
在聚宽写策略时,只要是需要在多个 def 函数之间传递和共享的变量(比如股票池、权重、标志位等),都请加上 g. 前缀,将其定义为全局变量。这样就能完美解决 NameError 的问题了!