Files
xiaobaifupan/app/backend/features/market/insights_context.py
T

85 lines
3.1 KiB
Python

from __future__ import annotations
import json
from datetime import datetime, timedelta, timezone
from typing import TYPE_CHECKING, Any, Callable
from backend.data.providers.ifind_client import IfindHttpClient
from backend.data.providers.tushare_client import TushareClient, TushareError
if TYPE_CHECKING:
from database import ReviewDatabase
CHINA_TIMEZONE = timezone(timedelta(hours=8))
def _display_date(value: str) -> str:
text = str(value or "").replace("-", "")
if len(text) != 8:
return str(value or "")
return f"{text[:4]}-{text[4:6]}-{text[6:]}"
class MarketInsightsContextMixin:
def __init__(
self,
database: ReviewDatabase,
client: TushareClient,
now_provider: Callable[[], datetime] | None = None,
ifind: IfindHttpClient | None = None,
) -> None:
self.database = database
self.client = client
self._now_provider = now_provider or (lambda: datetime.now(CHINA_TIMEZONE))
self.ifind = ifind
def _trade_context(self, requested_date: str) -> tuple[str, str]:
"""Resolve trading dates without making cached feature pages depend on Tushare uptime."""
requested = str(requested_date or "").replace("-", "")
try:
return self.client.resolve_trade_context(requested)
except TushareError:
latest = self.database.get_latest_real_snapshot(requested) or {}
trade_date = str(
(latest.get("meta") or {}).get("trade_date")
or latest.get("_snapshot_date")
or requested
).replace("-", "")
previous = self.database.get_latest_real_snapshot(trade_date, strictly_before=True) or {}
previous_date = str(
(previous.get("meta") or {}).get("trade_date")
or previous.get("_snapshot_date")
or ""
).replace("-", "")
return trade_date, previous_date
def _latest_feature_snapshot(self, kind: str, trade_date: str) -> dict[str, Any] | None:
return self.database.get_latest_data_snapshot(kind, "", trade_date)
def _stock_master(self) -> dict[str, dict[str, Any]]:
rows = self.database.list_stock_master()
if not rows:
rows = self.client.query(
"stock_basic",
{"list_status": "L"},
"ts_code,name,industry,market,list_date",
)
self.database.upsert_stock_master(rows)
rows = self.database.list_stock_master()
return {str(row.get("ts_code") or ""): row for row in rows}
@staticmethod
def _parse_concepts(value: Any) -> list[str]:
if isinstance(value, list):
return [str(item) for item in value if str(item).strip()]
text = str(value or "").strip()
if not text:
return []
try:
parsed = json.loads(text)
if isinstance(parsed, list):
return [str(item) for item in parsed if str(item).strip()]
except json.JSONDecodeError:
pass
return [part.strip() for part in text.split(",") if part.strip()]