fix: extend polling budget for slow WorldQuant PnL

This commit is contained in:
yuxuanhui
2026-09-09 19:34:08 +08:00
parent ba0ed9d03f
commit 3d85b073a4
3 changed files with 59 additions and 4 deletions
+1
View File
@@ -24,6 +24,7 @@ class Settings(BaseSettings):
wq_base_url: str = "https://api.worldquantbrain.com"
request_timeout: float = 30
retry_attempts: int = Field(default=4, ge=1, le=8)
pnl_poll_attempts: int = Field(default=120, ge=1, le=1000)
enable_runner: bool = True
mcp_enabled: bool = False
ai_request_limit: int = Field(default=12, ge=1, le=30)
+12 -4
View File
@@ -268,14 +268,15 @@ class WqClient:
async def get(self, path: str, params=None, headers=None):
return await self._read_json("GET", path, params=params, headers=headers)
async def _read_json(self, method: str, path: str, *, allow_list=False, **kwargs):
async def _read_json(self, method: str, path: str, *, allow_list=False, poll_attempts=None, **kwargs):
"""Authenticated read with shared refresh/retry handling; callers use GET or OPTIONS."""
if not self.credentials:
raise WqError("请先连接 WorldQuant", "disconnected")
if not self.authenticated:
await self.authenticate(*self.credentials)
refreshed = False
for attempt in range(self.settings.retry_attempts):
attempts = self.settings.retry_attempts if poll_attempts is None else poll_attempts
for attempt in range(attempts):
generation = self.auth_generation
response = await self._request(method, path, **kwargs)
if response.status_code == 401 and not refreshed:
@@ -293,7 +294,7 @@ class WqClient:
response.headers.get("Retry-After")
and self.retry_delay(response.headers["Retry-After"], 0) > 0
):
if attempt + 1 == self.settings.retry_attempts:
if attempt + 1 == attempts:
raise WqError("平台数据仍在准备,请稍后重试", "pending")
delay = self.retry_delay(response.headers["Retry-After"], attempt)
if self.on_retry:
@@ -390,7 +391,14 @@ class WqClient:
return await self.get(f"/alphas/{alpha_id}")
async def pnl(self, alpha_id):
return await self.get(f"/alphas/{alpha_id}/recordsets/pnl")
"""Wait for slow PnL generation separately from transport-error retries.
Each pending response uses the platform's Retry-After delay. Exhausting
the bounded polling budget raises WqError with code 'pending'.
"""
return await self._read_json(
"GET", f"/alphas/{alpha_id}/recordsets/pnl", poll_attempts=self.settings.pnl_poll_attempts
)
async def catalog_page(self, scope, dataset_id, offset):
"""Read a single scoped page. IDs are query parameters, never upstream paths."""