Refactor code for improved readability and consistency

- Cleaned up whitespace and formatting in various files including http.py, language.py, logger.py, safe_exec.py, and SQL migration scripts.
- Consolidated import statements and removed unnecessary blank lines.
- Updated logging configuration for better clarity.
- Enhanced the safe execution code with improved error handling and logging.
- Removed commented-out code and unnecessary variables in backfill_zero_trades.py and other scripts.
- Added a pyproject.toml for Ruff and Vulture configuration.
- Introduced requirements-dev.txt for development dependencies.
- Removed commented-out stock entries in init.sql for cleaner migration scripts.
This commit is contained in:
dienakdz
2026-04-09 14:30:51 +07:00
parent 103055b3df
commit 87f2845483
157 changed files with 19026 additions and 17773 deletions
+81 -99
View File
@@ -4,7 +4,7 @@ MetaTrader 5 Trading API Routes
Provides REST API for MT5 trading operations.
"""
from flask import Blueprint, request, jsonify
from flask import Blueprint, jsonify, request
from app.utils.logger import get_logger
@@ -23,7 +23,9 @@ def _ensure_mt5_imports():
global MT5Client, MT5Config
if MT5Client is None or MT5Config is None:
try:
from app.services.mt5_trading import MT5Client as _MT5Client, MT5Config as _MT5Config
from app.services.mt5_trading import MT5Client as _MT5Client
from app.services.mt5_trading import MT5Config as _MT5Config
MT5Client = _MT5Client
MT5Config = _MT5Config
except ImportError as e:
@@ -45,6 +47,7 @@ def _get_client():
# ==================== Connection Management ====================
@mt5_bp.route("/status", methods=["GET"])
def get_status():
"""Get MT5 connection status."""
@@ -54,11 +57,9 @@ def get_status():
status = client.get_connection_status()
return jsonify(status)
except ImportError as e:
return jsonify({
"connected": False,
"error": str(e),
"hint": "MetaTrader5 library is not installed or not on Windows"
})
return jsonify(
{"connected": False, "error": str(e), "hint": "MetaTrader5 library is not installed or not on Windows"}
)
except Exception as e:
logger.error(f"Get MT5 status failed: {e}")
return jsonify({"connected": False, "error": str(e)})
@@ -68,7 +69,7 @@ def get_status():
def connect():
"""
Connect to MT5 terminal.
Request body:
{
"login": 12345678, // MT5 account number
@@ -78,64 +79,53 @@ def connect():
}
"""
global _client
try:
_ensure_mt5_imports()
data = request.get_json() or {}
login = data.get("login") or data.get("mt5_login")
password = data.get("password") or data.get("mt5_password")
server = data.get("server") or data.get("mt5_server")
terminal_path = data.get("terminal_path") or data.get("mt5_terminal_path") or ""
if not login or not password or not server:
return jsonify({
"success": False,
"error": "Missing required fields: login, password, server"
}), 400
return jsonify({"success": False, "error": "Missing required fields: login, password, server"}), 400
config = MT5Config(
login=int(login),
password=str(password),
server=str(server),
terminal_path=str(terminal_path),
)
# Create new client with config
_client = MT5Client(config)
if _client.connect():
account_info = _client.get_account_info()
return jsonify({
"success": True,
"message": "Connected to MT5",
"account": account_info
})
return jsonify({"success": True, "message": "Connected to MT5", "account": account_info})
else:
return jsonify({
"success": False,
"error": "Failed to connect to MT5. Check credentials and ensure terminal is running."
}), 400
return jsonify(
{
"success": False,
"error": "Failed to connect to MT5. Check credentials and ensure terminal is running.",
}
), 400
except ImportError as e:
return jsonify({
"success": False,
"error": str(e)
}), 500
return jsonify({"success": False, "error": str(e)}), 500
except Exception as e:
logger.error(f"MT5 connect failed: {e}")
return jsonify({
"success": False,
"error": str(e)
}), 500
return jsonify({"success": False, "error": str(e)}), 500
@mt5_bp.route("/disconnect", methods=["POST"])
def disconnect():
"""Disconnect from MT5 terminal."""
global _client
try:
if _client is not None:
_client.disconnect()
@@ -148,6 +138,7 @@ def disconnect():
# ==================== Account Queries ====================
@mt5_bp.route("/account", methods=["GET"])
def get_account():
"""Get account information."""
@@ -155,7 +146,7 @@ def get_account():
client = _get_client()
if not client.connected:
return jsonify({"success": False, "error": "Not connected to MT5"}), 400
info = client.get_account_info()
return jsonify(info)
except Exception as e:
@@ -170,7 +161,7 @@ def get_positions():
client = _get_client()
if not client.connected:
return jsonify({"success": False, "error": "Not connected to MT5"}), 400
symbol = request.args.get("symbol")
positions = client.get_positions(symbol=symbol)
return jsonify({"success": True, "positions": positions})
@@ -186,7 +177,7 @@ def get_orders():
client = _get_client()
if not client.connected:
return jsonify({"success": False, "error": "Not connected to MT5"}), 400
symbol = request.args.get("symbol")
orders = client.get_orders(symbol=symbol)
return jsonify({"success": True, "orders": orders})
@@ -202,7 +193,7 @@ def get_symbols():
client = _get_client()
if not client.connected:
return jsonify({"success": False, "error": "Not connected to MT5"}), 400
group = request.args.get("group", "*")
symbols = client.get_symbols(group=group)
return jsonify({"success": True, "symbols": symbols})
@@ -213,11 +204,12 @@ def get_symbols():
# ==================== Trading ====================
@mt5_bp.route("/order", methods=["POST"])
def place_order():
"""
Place an order.
Request body:
{
"symbol": "EURUSD",
@@ -231,28 +223,22 @@ def place_order():
client = _get_client()
if not client.connected:
return jsonify({"success": False, "error": "Not connected to MT5"}), 400
data = request.get_json() or {}
symbol = data.get("symbol")
side = data.get("side")
volume = data.get("volume") or data.get("quantity")
order_type = data.get("orderType", "market").lower()
price = data.get("price")
comment = data.get("comment", "QuantDinger")
if not symbol or not side or not volume:
return jsonify({
"success": False,
"error": "Missing required fields: symbol, side, volume"
}), 400
return jsonify({"success": False, "error": "Missing required fields: symbol, side, volume"}), 400
if order_type == "limit":
if not price:
return jsonify({
"success": False,
"error": "Limit order requires price"
}), 400
return jsonify({"success": False, "error": "Limit order requires price"}), 400
result = client.place_limit_order(
symbol=symbol,
side=side,
@@ -267,23 +253,22 @@ def place_order():
volume=float(volume),
comment=comment,
)
if result.success:
return jsonify({
"success": True,
"order_id": result.order_id,
"deal_id": result.deal_id,
"filled": result.filled,
"price": result.price,
"status": result.status,
"message": result.message,
})
return jsonify(
{
"success": True,
"order_id": result.order_id,
"deal_id": result.deal_id,
"filled": result.filled,
"price": result.price,
"status": result.status,
"message": result.message,
}
)
else:
return jsonify({
"success": False,
"error": result.message
}), 400
return jsonify({"success": False, "error": result.message}), 400
except Exception as e:
logger.error(f"MT5 place order failed: {e}")
return jsonify({"success": False, "error": str(e)}), 500
@@ -293,7 +278,7 @@ def place_order():
def close_position():
"""
Close a position.
Request body:
{
"ticket": 123456789, // Position ticket
@@ -304,38 +289,34 @@ def close_position():
client = _get_client()
if not client.connected:
return jsonify({"success": False, "error": "Not connected to MT5"}), 400
data = request.get_json() or {}
ticket = data.get("ticket")
volume = data.get("volume")
if not ticket:
return jsonify({
"success": False,
"error": "Missing required field: ticket"
}), 400
return jsonify({"success": False, "error": "Missing required field: ticket"}), 400
result = client.close_position(
ticket=int(ticket),
volume=float(volume) if volume else None,
)
if result.success:
return jsonify({
"success": True,
"order_id": result.order_id,
"deal_id": result.deal_id,
"filled": result.filled,
"price": result.price,
"message": result.message,
})
return jsonify(
{
"success": True,
"order_id": result.order_id,
"deal_id": result.deal_id,
"filled": result.filled,
"price": result.price,
"message": result.message,
}
)
else:
return jsonify({
"success": False,
"error": result.message
}), 400
return jsonify({"success": False, "error": result.message}), 400
except Exception as e:
logger.error(f"MT5 close position failed: {e}")
return jsonify({"success": False, "error": str(e)}), 500
@@ -348,12 +329,12 @@ def cancel_order(ticket: int):
client = _get_client()
if not client.connected:
return jsonify({"success": False, "error": "Not connected to MT5"}), 400
if client.cancel_order(ticket):
return jsonify({"success": True, "message": f"Order {ticket} cancelled"})
else:
return jsonify({"success": False, "error": "Failed to cancel order"}), 400
except Exception as e:
logger.error(f"MT5 cancel order failed: {e}")
return jsonify({"success": False, "error": str(e)}), 500
@@ -361,11 +342,12 @@ def cancel_order(ticket: int):
# ==================== Market Data ====================
@mt5_bp.route("/quote", methods=["GET"])
def get_quote():
"""
Get real-time quote.
Query params:
- symbol: Trading symbol (e.g., EURUSD)
"""
@@ -373,14 +355,14 @@ def get_quote():
client = _get_client()
if not client.connected:
return jsonify({"success": False, "error": "Not connected to MT5"}), 400
symbol = request.args.get("symbol")
if not symbol:
return jsonify({"success": False, "error": "Missing symbol parameter"}), 400
quote = client.get_quote(symbol)
return jsonify(quote)
except Exception as e:
logger.error(f"MT5 get quote failed: {e}")
return jsonify({"success": False, "error": str(e)}), 500