问题描述
比如我加仓信号出来后可能会持续几天,我可能在第一天就加仓了,但是不希望第二天或第三天继续加仓,因此需要把今天操作过的记录保存下来,有没有什么函数或者例子可以使用?或者需要怎么做呢?
用全局变量的话,如果系统自动重启,或者自己重启,之前的数据就归零了,所以还是需要有个什么手段把数据保存起来,重启后再读取
解决方案
在 JoinQuant (聚宽) 平台中,要把今天操作的数据保存至明天,并且防止系统重启或手动重启导致数据归零,主要有两种标准的方法:
方法一:正确使用全局变量 g(平台自带持久化)
很多用户误以为系统重启后全局变量 g 会清零,其实在模拟交易中,聚宽平台每天结束时会自动使用 pickle 将 g 对象序列化保存到磁盘。第二天重启时,会恢复 g 的状态,并且不会再次执行 initialize 函数。
注意事项:
- 只有在模拟盘生命周期内,
g才会持久化。如果是重新创建模拟盘或修改了代码导致某些重置,可能会丢失。 - 不能被
pickle序列化的对象(如数据库连接、网络请求对象)不能保存在g中。 - 以双下划线
__开头的变量(如g.__test)不会被保存。
方法二:使用 write_file 和 read_file 进行文件持久化(最稳妥)
如果您希望数据绝对安全,甚至在不同回测、不同模拟盘之间共享,或者防止意外的 g 变量丢失,可以使用聚宽提供的文件读写 API,将操作记录保存为 JSON 文件存放在您的“投资研究”目录下。
核心 API:
write_file(path, content, append=False):将内容写入文件。read_file(path):读取文件内容。
具体实现代码示例:
假设我们需要记录某只股票最近一次加仓的日期,以防止连续几天重复加仓:
import jqdata
import json
import datetime
# 定义保存状态的文件路径
STATUS_FILE = 'trade_status.json'
def initialize(context):
set_benchmark('000300.XSHG')
set_option('use_real_price', True)
g.security = '000001.XSHE'
# 每天开盘运行
run_daily(market_open, time='09:30')
# 辅助函数:读取状态
def load_trade_status():
try:
content = read_file(STATUS_FILE)
return json.loads(content)
except Exception as e:
# 如果文件不存在或解析失败,返回空字典
return {}
# 辅助函数:保存状态
def save_trade_status(status_dict):
content = json.dumps(status_dict)
write_file(STATUS_FILE, content, append=False)
def market_open(context):
security = g.security
current_date = context.current_dt.strftime('%Y-%m-%d')
# 1. 读取历史操作记录
trade_status = load_trade_status()
# 获取该股票最后一次加仓的日期
last_buy_date = trade_status.get(security, None)
# 2. 判断是否需要加仓(这里用伪代码代替您的加仓信号)
buy_signal = True # 假设今天有加仓信号
if buy_signal:
# 如果之前没有加仓记录,或者最后一次加仓不是今天(甚至可以限制为不是最近3天)
if last_buy_date != current_date:
log.info(f"触发加仓信号,执行加仓: {security}")
order_value(security, 10000)
# 3. 更新操作记录并持久化保存到文件
trade_status[security] = current_date
save_trade_status(trade_status)
log.info("加仓状态已持久化保存。")
else:
log.info(f"{security} 今天已经加过仓了,忽略本次信号。")
总结
- 常规状态保持:直接挂载在
g对象上即可,聚宽模拟盘底层会自动帮您pickle序列化并在第二天恢复。 - 高可靠性/跨策略共享:使用
write_file和read_file结合json库,将字典状态写入研究环境的本地文件。每次需要判断时读取,操作完毕后写入。这种方法即使您手动停止并新建模拟盘,只要读取同一个文件,状态依然存在。