from __future__ import annotations import json import re from datetime import date from http import HTTPStatus from urllib.parse import parse_qs class ScreenerRoutesMixin: def _handle_screener_get(self, parsed) -> bool: if parsed.path == "/api/screener/setup": query = parse_qs(parsed.query) trade_date = query.get("trade_date", [date.today().isoformat()])[0] try: self.send_json(self.application_service.screener_setup(trade_date)) except ValueError as exc: self.send_json({"error": str(exc)}, HTTPStatus.BAD_REQUEST) return True if parsed.path == "/api/screener/tracking": query = parse_qs(parsed.query) try: self.send_json( self.application_service.screener_tracking(int(query.get("limit", ["12"])[0])) ) except (TypeError, ValueError) as exc: self.send_json({"error": str(exc)}, HTTPStatus.BAD_REQUEST) return True return False def _handle_screener_post(self, parsed) -> bool: if parsed.path == "/api/screener/tracking": try: result = self.application_service.add_screener_tracking(self.read_json_body()) self.send_json({"ok": True, **result}) except (ValueError, json.JSONDecodeError) as exc: self.send_json({"error": str(exc)}, HTTPStatus.BAD_REQUEST) return True return False def _handle_screener_delete(self, parsed) -> bool: strategy_match = re.fullmatch(r"/api/screener/strategies/(\d+)", parsed.path) if strategy_match: try: result = self.application_service.delete_screener_strategy(int(strategy_match.group(1))) self.send_json({"ok": True, **result}) except ValueError as exc: self.send_json({"error": str(exc)}, HTTPStatus.BAD_REQUEST) return True tracking_match = re.fullmatch(r"/api/screener/tracking/(\d+)", parsed.path) if tracking_match: result = self.application_service.remove_screener_tracking(int(tracking_match.group(1))) self.send_json({"ok": True, **result}) return True return False def sync_screener_data(self) -> None: try: body = self.read_json_body() result = self.application_service.sync_screener_data( str(body.get("trade_date") or date.today().isoformat()), int(body.get("lookback") or 45), ) self.send_json({"ok": True, "result": result}) except ValueError as exc: self.send_json({"error": str(exc)}, HTTPStatus.BAD_REQUEST) except Exception as exc: self.send_json({"error": f"因子数据同步失败:{exc}"}, HTTPStatus.INTERNAL_SERVER_ERROR) def compile_screener_strategy(self) -> None: try: body = self.read_json_body() result = self.application_service.compile_screener_strategy( str(body.get("prompt") or ""), str(body.get("regime") or "") ) self.send_json({"ok": True, "strategy": result}) except ValueError as exc: self.send_json({"error": str(exc)}, HTTPStatus.BAD_REQUEST) def save_screener_strategy(self) -> None: try: body = self.read_json_body() result = self.application_service.save_screener_strategy(body) self.send_json({"ok": True, **result}) except ValueError as exc: self.send_json({"error": str(exc)}, HTTPStatus.BAD_REQUEST) def run_screener(self) -> None: try: body = self.read_json_body() result = self.application_service.run_screener(body) self.send_json({"ok": True, "result": result}) except ValueError as exc: self.send_json({"error": str(exc)}, HTTPStatus.BAD_REQUEST) except Exception as exc: self.send_json({"error": f"选股执行失败:{exc}"}, HTTPStatus.INTERNAL_SERVER_ERROR) def refresh_screener_tracking(self) -> None: try: body = self.read_json_body(True) trade_date = str(body.get("trade_date") or date.today().isoformat()) self.send_json({"ok": True, **self.application_service.refresh_screener_tracking(trade_date)}) except (ValueError, json.JSONDecodeError) as exc: self.send_json({"error": str(exc)}, HTTPStatus.BAD_REQUEST) except Exception as exc: self.send_json({"error": f"跟踪刷新失败:{exc}"}, HTTPStatus.INTERNAL_SERVER_ERROR)