This commit is contained in:
2026-09-03 11:33:43 +08:00
parent d5303cc22b
commit e6a5096353
38 changed files with 1911 additions and 2742 deletions

View File

@@ -6,14 +6,16 @@ from typing import Any
import httpx
from .errors import APIError, BusinessError
from .context import ContextMixin
from .data import DataMixin
from .errors import APIError
from .get import GetMixin
from .portfolio import PortfolioMixin
from .sys import SysMixin
from .trade import TradeMixin
def csv_join(items: list[str]) -> str:
return ",".join(item.strip() for item in items if item.strip())
class Client:
class HTTPClient:
"""复用连接池的同步 QMT HTTP 客户端。"""
def __init__(self, base_url: str, token: str, timeout: float = 15.0) -> None:
@@ -31,13 +33,13 @@ class Client:
def close(self) -> None:
self.http.close()
def __enter__(self) -> "Client":
def __enter__(self) -> "HTTPClient":
return self
def __exit__(self, *_args: object) -> None:
self.close()
def set_account_type(self, account_type: str) -> "Client":
def set_account_type(self, account_type: str) -> "HTTPClient":
if account_type.strip():
self.account_type = account_type
return self
@@ -91,28 +93,19 @@ class Client:
f"invalid JSON from {path}: {content[:512]!r}"
) from exc
def _get_field(self, path: str, key: str) -> Any:
return self._get_json(path).get(key)
def _post_field(self, path: str, body: Any, key: str) -> Any:
result = self._post_json(path, body)
if isinstance(result, dict) and result.get("error"):
raise BusinessError(result["error"])
return result.get(key, result) if key and isinstance(result, dict) else result
class Client(
ContextMixin,
GetMixin,
PortfolioMixin,
DataMixin,
TradeMixin,
SysMixin,
HTTPClient,
):
"""Client for the API exposed by ``qmt_rest_new.py``."""
def _is_idempotent(method: str, path: str) -> bool:
if method == "GET":
return True
prefixes = (
"/api/v2/",
"/api/holding",
"/api/money/",
"/api/context/",
"/api/check/",
"/api/data/",
"/api/trade/trade_detail_data",
"/api/order/deal",
)
unsafe = ("subscribe", "unsubscribe")
return path.startswith(prefixes) and not any(word in path for word in unsafe)
return path == "/api/data/full_tick"