feat: 实盘登陆失败, 发送邮件, 并每小时尝试连接
This commit is contained in:
parent
1c1b19383c
commit
0d491d14e3
@ -9,7 +9,7 @@ class Config:
|
|||||||
|
|
||||||
# Trading settings
|
# Trading settings
|
||||||
TRADE_TIMEOUT = 5 # 交易超时时间(秒)
|
TRADE_TIMEOUT = 5 # 交易超时时间(秒)
|
||||||
SIMULATION_MODE = True
|
SIMULATION_MODE = False
|
||||||
|
|
||||||
# Trading hours
|
# Trading hours
|
||||||
MARKET_OPEN_TIME = "09:20"
|
MARKET_OPEN_TIME = "09:20"
|
||||||
|
@ -16,7 +16,7 @@ logger = get_logger('real_trader')
|
|||||||
|
|
||||||
class MyXtQuantTraderCallback:
|
class MyXtQuantTraderCallback:
|
||||||
def __init__(self, trader_instance):
|
def __init__(self, trader_instance):
|
||||||
self.trader_instance: XtTrader = trader_instance
|
self.trader_instance = trader_instance
|
||||||
def on_connected(self):
|
def on_connected(self):
|
||||||
logger.info("连接成功")
|
logger.info("连接成功")
|
||||||
def on_disconnected(self):
|
def on_disconnected(self):
|
||||||
@ -102,16 +102,44 @@ class XtTrader(BaseTrader):
|
|||||||
return self.is_logged_in() and not self.connection_failed
|
return self.is_logged_in() and not self.connection_failed
|
||||||
|
|
||||||
def login(self):
|
def login(self):
|
||||||
if not self.started:
|
"""尝试登录交易系统
|
||||||
self.xt_trader.start()
|
|
||||||
self.started = True
|
Returns:
|
||||||
if not self.connected:
|
bool: 登录是否成功
|
||||||
result = self.xt_trader.connect()
|
"""
|
||||||
self.connected = (result == 0)
|
success = True
|
||||||
if not self.subscribed:
|
|
||||||
result = self.xt_trader.subscribe(self.account)
|
try:
|
||||||
self.subscribed = (result == 0)
|
if not self.started:
|
||||||
return self.connected and self.subscribed
|
self.xt_trader.start()
|
||||||
|
self.started = True
|
||||||
|
|
||||||
|
if not self.connected:
|
||||||
|
result = self.xt_trader.connect()
|
||||||
|
self.connected = (result == 0)
|
||||||
|
if not self.connected:
|
||||||
|
success = False
|
||||||
|
|
||||||
|
if not self.subscribed and self.connected:
|
||||||
|
result = self.xt_trader.subscribe(self.account)
|
||||||
|
self.subscribed = (result == 0)
|
||||||
|
if not self.subscribed:
|
||||||
|
success = False
|
||||||
|
|
||||||
|
# 登录失败,设置失败状态
|
||||||
|
if not success:
|
||||||
|
self.connection_failed = True
|
||||||
|
self.last_reconnect_time = time.time()
|
||||||
|
self.notify_connection_failure("登录失败")
|
||||||
|
|
||||||
|
return success
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"登录异常: {str(e)}")
|
||||||
|
# 设置失败状态
|
||||||
|
self.connection_failed = True
|
||||||
|
self.last_reconnect_time = time.time()
|
||||||
|
self.notify_connection_failure(f"登录异常: {str(e)}")
|
||||||
|
return False
|
||||||
|
|
||||||
def logout(self):
|
def logout(self):
|
||||||
if self.started:
|
if self.started:
|
||||||
@ -347,9 +375,13 @@ class XtTrader(BaseTrader):
|
|||||||
logger.error(f"获取行情失败: {code}, {str(e)}")
|
logger.error(f"获取行情失败: {code}, {str(e)}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def notify_connection_failure(self):
|
def notify_connection_failure(self, message="交易连接断开且重连失败"):
|
||||||
"""通知交易连接失败"""
|
"""通知交易连接失败
|
||||||
self.connection_error_message = f"交易系统连接失败,将在{self.reconnect_interval//60}分钟后自动尝试重连"
|
|
||||||
|
Args:
|
||||||
|
message: 错误信息
|
||||||
|
"""
|
||||||
|
self.connection_error_message = f"交易系统连接失败:{message},将在{self.reconnect_interval//60}分钟后自动尝试重连"
|
||||||
|
|
||||||
# 调用回调通知上层应用
|
# 调用回调通知上层应用
|
||||||
if self.connect_failed_callback:
|
if self.connect_failed_callback:
|
||||||
@ -364,7 +396,7 @@ class XtTrader(BaseTrader):
|
|||||||
|
|
||||||
时间:{time_str}
|
时间:{time_str}
|
||||||
{trader_info}
|
{trader_info}
|
||||||
错误信息:交易连接断开且重连失败
|
错误信息:{message}
|
||||||
|
|
||||||
系统将在{self.reconnect_interval//60}分钟后自动尝试重连。如需立即恢复,请手动重启交易系统。
|
系统将在{self.reconnect_interval//60}分钟后自动尝试重连。如需立即恢复,请手动重启交易系统。
|
||||||
"""
|
"""
|
||||||
|
@ -49,9 +49,9 @@ def get_trader():
|
|||||||
return _trader_instance
|
return _trader_instance
|
||||||
|
|
||||||
def login():
|
def login():
|
||||||
try:
|
global _trader_instance
|
||||||
global _trader_instance
|
|
||||||
|
|
||||||
|
try:
|
||||||
# 如果已经有实例,先销毁
|
# 如果已经有实例,先销毁
|
||||||
if _trader_instance is not None and is_real_mode():
|
if _trader_instance is not None and is_real_mode():
|
||||||
_trader_instance.logout()
|
_trader_instance.logout()
|
||||||
@ -61,16 +61,40 @@ def login():
|
|||||||
_trader_instance = SimulationTrader() if Config.SIMULATION_MODE else XtTrader(connect_failed_callback=on_connect_failed)
|
_trader_instance = SimulationTrader() if Config.SIMULATION_MODE else XtTrader(connect_failed_callback=on_connect_failed)
|
||||||
|
|
||||||
logger.info("开始登录")
|
logger.info("开始登录")
|
||||||
_trader_instance.login()
|
|
||||||
result = _trader_instance.get_balance()
|
# 模拟交易直接返回成功
|
||||||
if result and result["account_id"] is not None:
|
if Config.SIMULATION_MODE:
|
||||||
logger.info(f"查询余额成功: {result}")
|
return True
|
||||||
|
|
||||||
|
# 如果是实盘交易,调用login方法
|
||||||
|
login_success = _trader_instance.login()
|
||||||
|
|
||||||
|
# 验证连接
|
||||||
|
if login_success:
|
||||||
|
result = _trader_instance.get_balance()
|
||||||
|
if result and result.get("account_id") is not None:
|
||||||
|
logger.info(f"查询余额成功: {result}")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
logger.error(f"登录成功但查询余额失败: {result}")
|
||||||
|
_trader_instance.connection_failed = True
|
||||||
|
_trader_instance.last_reconnect_time = time.time()
|
||||||
|
_trader_instance.notify_connection_failure("登录成功但查询余额失败")
|
||||||
|
return False
|
||||||
else:
|
else:
|
||||||
logger.error(f"登录失败: {result}")
|
logger.error("登录失败")
|
||||||
raise Exception(f"登录失败: {result}")
|
# 不需要在这里设置失败状态,在XtTrader.login方法中已设置
|
||||||
|
return False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"登录失败: {e}")
|
logger.error(f"登录初始化异常: {str(e)}")
|
||||||
raise Exception(f"登录失败: {e}")
|
# 如果是实盘模式并且已经成功创建了实例,设置失败状态
|
||||||
|
if is_real_mode() and _trader_instance is not None:
|
||||||
|
_trader_instance.connection_failed = True
|
||||||
|
_trader_instance.last_reconnect_time = time.time()
|
||||||
|
_trader_instance.notify_connection_failure(f"登录初始化异常: {str(e)}")
|
||||||
|
return False
|
||||||
|
# 如果创建实例失败,则抛出异常
|
||||||
|
raise Exception(f"登录失败,无法创建交易实例: {e}")
|
||||||
|
|
||||||
def logout():
|
def logout():
|
||||||
global _trader_instance
|
global _trader_instance
|
||||||
@ -125,12 +149,26 @@ def _check_reconnect():
|
|||||||
logger.error(f"重连检查错误: {str(e)}")
|
logger.error(f"重连检查错误: {str(e)}")
|
||||||
|
|
||||||
|
|
||||||
# 程序启动时初始化交易实例
|
# 初始化交易系统
|
||||||
login()
|
try:
|
||||||
|
# 程序启动时初始化交易实例 - 尝试登录,但即使失败也继续启动服务
|
||||||
|
login_success = login()
|
||||||
|
if not login_success and is_real_mode():
|
||||||
|
logger.warning("初始登录失败,系统将在稍后定期尝试重连")
|
||||||
|
|
||||||
|
# 设置并启动调度器
|
||||||
|
setup_scheduler()
|
||||||
|
|
||||||
# 设置并启动调度器
|
logger.info("交易系统初始化完成")
|
||||||
setup_scheduler()
|
except Exception as e:
|
||||||
|
logger.error(f"交易系统初始化异常: {e}")
|
||||||
|
# 即使初始化失败也尝试启动调度器
|
||||||
|
try:
|
||||||
|
setup_scheduler()
|
||||||
|
logger.info("调度器启动成功,将尝试定期重新初始化交易系统")
|
||||||
|
except Exception as scheduler_e:
|
||||||
|
logger.error(f"调度器启动失败: {scheduler_e}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user