import redis import json import datetime # --- 模块级全局变量 --- _BACKTEST_SEND_COUNT = 0 def send_qmt_signal(code, target_total_slots, price, context, redis_config): """ 发送信号到 Redis (基于槽位状态判断买卖意图) 参数: - code: 股票代码 (聚宽格式: 000001.XSHE) - target_total_slots: * 意向持仓时: 传入策略设定的总槽位数 (例如 5)。此时 action 判定为 BUY。 * 意向清仓时: 传入 0。此时 action 判定为 SELL。 - price: 当前最新价格 (用于实盘限价单参考) - context: 聚宽上下文对象 - redis_config: Redis配置字典 """ global _BACKTEST_SEND_COUNT try: # --------------------------------------------------------- # 1. 环境判断与流量控制 # --------------------------------------------------------- run_type = context.run_params.type is_backtest = run_type in ['simple_backtest', 'full_backtest'] if is_backtest: if _BACKTEST_SEND_COUNT >= 10: return _BACKTEST_SEND_COUNT += 1 # --------------------------------------------------------- # 2. 建立 Redis 连接 # --------------------------------------------------------- r = redis.Redis( host=redis_config['host'], port=redis_config['port'], password=redis_config.get('password'), db=redis_config.get('db', 0), decode_responses=True, socket_timeout=1 ) # --------------------------------------------------------- # 3. 数据转换与规范化 # --------------------------------------------------------- # 股票代码格式转换: 聚宽(.XSHE/.XSHG) -> QMT(.SZ/.SH) qmt_code = code if code.endswith('.XSHE'): qmt_code = code.replace('.XSHE', '.SZ') elif code.endswith('.XSHG'): qmt_code = code.replace('.XSHG', '.SH') # 【核心逻辑修改】:根据 target_total_slots 判断动作 # 不再通过函数名判断,而是看目标状态 if target_total_slots > 0: action = 'BUY' slots_val = int(target_total_slots) # 告知后端:我是基于“N只模型”中的一只 else: action = 'SELL' slots_val = 0 # 清仓 # --------------------------------------------------------- # 4. 构建消息体 # --------------------------------------------------------- base_strategy_name = redis_config.get('strategy_name', 'default_strategy') ts_str = context.current_dt.strftime('%Y-%m-%d %H:%M:%S') msg = { 'strategy_name': base_strategy_name, 'stock_code': qmt_code, 'action': action, 'price': price, 'total_slots': slots_val, 'timestamp': ts_str, 'is_backtest': is_backtest } json_payload = json.dumps(msg) # --------------------------------------------------------- # 5. 队列路由 # --------------------------------------------------------- queue_key = f"{base_strategy_name}_backtest" if is_backtest else f"{base_strategy_name}_real" expire_seconds = 3600 if is_backtest else 604800 r.rpush(queue_key, json_payload) r.expire(queue_key, expire_seconds) # --------------------------------------------------------- # 6. 控制台输出 # --------------------------------------------------------- log_prefix = "【回测】" if is_backtest else "【实盘】" desc = f"目标总持仓:{slots_val}只" if action == 'BUY' else "清仓释放槽位" print(f"{log_prefix} 信号同步 -> {qmt_code} | 动作:{action} | {desc} | 时间:{ts_str}") except Exception as e: print(f"[Error] 发送QMT信号失败: {e}")