# coding:utf-8 """ QMT多终端交易系统启动器 版本:V2.0 (Multi-Terminal Edition) """ import sys import os import threading import logging import datetime import uvicorn # 将当前目录添加到Python路径,确保模块导入正常 current_dir = os.path.dirname(os.path.abspath(__file__)) if current_dir not in sys.path: sys.path.insert(0, current_dir) # 导入升级后的多终端管理器 from qmt_engine import MultiEngineManager from api_server import create_api_server def setup_logger(): """配置日志系统""" log_dir = "logs" if not os.path.exists(log_dir): os.makedirs(log_dir) log_file = os.path.join(log_dir, f"{datetime.date.today().strftime('%Y-%m-%d')}.log") logger = logging.getLogger("QMT_Run") logger.setLevel(logging.INFO) formatter = logging.Formatter( '[%(asctime)s] [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s', datefmt='%Y-%m-%d %H:%M:%S' ) file_handler = logging.FileHandler(log_file, mode='a', encoding='utf-8') file_handler.setFormatter(formatter) stream_handler = logging.StreamHandler(sys.stdout) stream_handler.setFormatter(formatter) logger.addHandler(file_handler) logger.addHandler(stream_handler) return logger def main(): """主函数 - 启动多终端QMT交易引擎管理中心和API服务器""" logger = setup_logger() # 强制设置环境变量,确保Python在Windows控制台输出不因编码崩溃 os.environ["PYTHONUTF8"] = "1" logger.info("="*50) logger.info(">>> QMT Multi-Terminal System Starting...") logger.info("="*50) # 1. 获取多终端管理器单例 manager = MultiEngineManager() logger.info("多终端管理器实例获取成功") try: # 2. 初始化引擎(加载配置、连接Redis、初始化各终端执行单元) logger.info("正在加载配置文件: config.json") manager.initialize('config.json') logger.info("Done: Multi-Manager initialized successfully.") except Exception as e: logger.error(f"Error: System initialization failed: {repr(e)}", exc_info=True) sys.exit(1) # 3. 启动全局监控与交易路由主循环线程 # 该线程负责:终端健康检查、断线重连、消息路由、收盘结算 logger.info("正在启动交易主循环线程...") trading_thread = threading.Thread(target=manager.run_trading_loop, name="MainTradeLoop", daemon=True) trading_thread.start() logger.info("Done: Global trading loop thread started.") # 4. 创建适配多终端的API服务器 logger.info("正在创建API服务器...") app = create_api_server(manager) logger.info("Done: API server created with multi-terminal support.") # 5. 启动Web服务 logger.info(">>> Web Dashboard: http://localhost:8001") try: # 建议关闭 access_log 以减少控制台刷屏 uvicorn.run( app, host="0.0.0.0", port=8001, log_level="warning", access_log=False ) except KeyboardInterrupt: logger.info(">>> Shutdown signal received. Closing terminals...") manager.stop() logger.info(">>> System safely closed.") _write_exit_code(0) sys.exit(0) def _write_exit_code(code): """将退出码写入临时文件,供 start.bat 读取""" logger = logging.getLogger("QMT_Run") try: exit_code_file = os.path.join(os.environ.get('TEMP', ''), 'exit_code.txt') with open(exit_code_file, 'w') as f: f.write(str(code)) logger.info(f">>> 退出码已写入: {code}") except Exception as e: logger.error(f">>> 退出码写入失败: {str(e)}") if __name__ == '__main__': # 最佳实践:使用 python -u run.py 运行以获得实时日志输出 main()