107 lines
4.6 KiB
Python
107 lines
4.6 KiB
Python
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)
|