mirror of
https://github.com/silencesdg/mt5_python_ea_suite.git
synced 2026-08-09 17:01:06 +00:00
MT5代理服务:新增自动重连机制和开机自启脚本
- 所有API端点请求前自动检查MT5连接,断开时自动重连 - 新增start_all.bat开机自启脚本(MT5 + 代理服务) - 新增setup_autostart.ps1注册Windows计划任务 Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
This commit is contained in:
@@ -31,6 +31,21 @@ _provider = LiveDataProvider()
|
|||||||
_lock = threading.Lock()
|
_lock = threading.Lock()
|
||||||
|
|
||||||
|
|
||||||
|
def _ensure_connected():
|
||||||
|
"""检查 MT5 连接,断开时自动重连"""
|
||||||
|
import MetaTrader5 as mt5
|
||||||
|
if mt5.terminal_info() is not None:
|
||||||
|
return True
|
||||||
|
logger.warning("MT5 连接已断开,尝试重连...")
|
||||||
|
with _lock:
|
||||||
|
ok = _provider.initialize()
|
||||||
|
if ok:
|
||||||
|
logger.info("MT5 重连成功")
|
||||||
|
else:
|
||||||
|
logger.error("MT5 重连失败")
|
||||||
|
return ok
|
||||||
|
|
||||||
|
|
||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def lifespan(app: FastAPI):
|
async def lifespan(app: FastAPI):
|
||||||
with _lock:
|
with _lock:
|
||||||
@@ -77,6 +92,7 @@ def api_shutdown():
|
|||||||
|
|
||||||
@app.get("/api/price/{symbol}")
|
@app.get("/api/price/{symbol}")
|
||||||
def api_price(symbol: str):
|
def api_price(symbol: str):
|
||||||
|
_ensure_connected()
|
||||||
with _lock:
|
with _lock:
|
||||||
data = _provider.get_current_price(symbol)
|
data = _provider.get_current_price(symbol)
|
||||||
if data is None:
|
if data is None:
|
||||||
@@ -88,6 +104,7 @@ def api_price(symbol: str):
|
|||||||
|
|
||||||
@app.get("/api/historical/{symbol}/{timeframe}/{count}")
|
@app.get("/api/historical/{symbol}/{timeframe}/{count}")
|
||||||
def api_historical(symbol: str, timeframe: int, count: int):
|
def api_historical(symbol: str, timeframe: int, count: int):
|
||||||
|
_ensure_connected()
|
||||||
with _lock:
|
with _lock:
|
||||||
rates = _provider.get_historical_data(symbol, timeframe, count)
|
rates = _provider.get_historical_data(symbol, timeframe, count)
|
||||||
if rates is None:
|
if rates is None:
|
||||||
@@ -97,6 +114,7 @@ def api_historical(symbol: str, timeframe: int, count: int):
|
|||||||
|
|
||||||
@app.get("/api/account")
|
@app.get("/api/account")
|
||||||
def api_account():
|
def api_account():
|
||||||
|
_ensure_connected()
|
||||||
with _lock:
|
with _lock:
|
||||||
info = _provider.get_account_info()
|
info = _provider.get_account_info()
|
||||||
if info is None:
|
if info is None:
|
||||||
@@ -106,6 +124,7 @@ def api_account():
|
|||||||
|
|
||||||
@app.get("/api/positions/{symbol}")
|
@app.get("/api/positions/{symbol}")
|
||||||
def api_positions(symbol: str):
|
def api_positions(symbol: str):
|
||||||
|
_ensure_connected()
|
||||||
with _lock:
|
with _lock:
|
||||||
positions = _provider.get_positions(symbol)
|
positions = _provider.get_positions(symbol)
|
||||||
if positions is None:
|
if positions is None:
|
||||||
@@ -115,6 +134,7 @@ def api_positions(symbol: str):
|
|||||||
|
|
||||||
@app.get("/api/symbol/{symbol}")
|
@app.get("/api/symbol/{symbol}")
|
||||||
def api_symbol(symbol: str):
|
def api_symbol(symbol: str):
|
||||||
|
_ensure_connected()
|
||||||
with _lock:
|
with _lock:
|
||||||
info = _provider.get_symbol_info(symbol)
|
info = _provider.get_symbol_info(symbol)
|
||||||
if info is None:
|
if info is None:
|
||||||
@@ -124,6 +144,7 @@ def api_symbol(symbol: str):
|
|||||||
|
|
||||||
@app.post("/api/order")
|
@app.post("/api/order")
|
||||||
def api_order(req: OrderRequest):
|
def api_order(req: OrderRequest):
|
||||||
|
_ensure_connected()
|
||||||
with _lock:
|
with _lock:
|
||||||
result = _provider.send_order(req.symbol, req.order_type, req.volume)
|
result = _provider.send_order(req.symbol, req.order_type, req.volume)
|
||||||
if result is None:
|
if result is None:
|
||||||
@@ -133,6 +154,7 @@ def api_order(req: OrderRequest):
|
|||||||
|
|
||||||
@app.post("/api/close")
|
@app.post("/api/close")
|
||||||
def api_close(req: CloseRequest):
|
def api_close(req: CloseRequest):
|
||||||
|
_ensure_connected()
|
||||||
with _lock:
|
with _lock:
|
||||||
success = _provider.close_position(req.ticket, req.symbol, req.volume)
|
success = _provider.close_position(req.ticket, req.symbol, req.volume)
|
||||||
return {"success": success}
|
return {"success": success}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
$action = New-ScheduledTaskAction -Execute "D:\projects\mt5_python_ea_suite\run\start_all.bat" -WorkingDirectory "D:\projects\mt5_python_ea_suite\run"
|
||||||
|
$trigger = New-ScheduledTaskTrigger -AtLogon -User $env:USERNAME
|
||||||
|
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -ExecutionTimeLimit (New-TimeSpan -Days 0)
|
||||||
|
Register-ScheduledTask -TaskName "MT5_EA_Suite_AutoStart" -Action $action -Trigger $trigger -Settings $settings -Description "MT5 + Proxy Server AutoStart" -Force
|
||||||
|
Write-Host "Done: MT5_EA_Suite_AutoStart registered"
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
@echo off
|
||||||
|
REM MT5 EA Suite 开机自启脚本
|
||||||
|
REM 1. 启动 MT5 终端
|
||||||
|
REM 2. 等待 MT5 初始化
|
||||||
|
REM 3. 启动代理服务
|
||||||
|
|
||||||
|
echo [%date% %time%] 启动 MT5 ...
|
||||||
|
start "" "E:\Program Files\MetaTrader 5\terminal64.exe"
|
||||||
|
|
||||||
|
echo [%date% %time%] 等待 MT5 初始化 (30秒) ...
|
||||||
|
timeout /t 30 /nobreak >nul
|
||||||
|
|
||||||
|
echo [%date% %time%] 启动代理服务 ...
|
||||||
|
cd /d "D:\projects\mt5_python_ea_suite"
|
||||||
|
python -m run.server
|
||||||
|
|
||||||
Reference in New Issue
Block a user