Files
NewStock/qmt/run.py
liaozhaorun 086af75b3e fix(qmt): 消除静默异常处理并统一日志系统
- 修复6处静默except块(撤单、错误回调、线程停止、健康检查等)
- 统一入口模块使用logging替代print
- 增强交易日志可追踪性
- 添加完整堆栈跟踪日志
2026-01-27 01:21:22 +08:00

118 lines
3.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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()