165 lines
5.4 KiB
Python
165 lines
5.4 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Annotated, Literal
|
|
|
|
from fastapi import APIRouter, Path, Query, Request
|
|
|
|
from backend.features.accounts.auth import AdminWritePrincipal, AuthenticatedPrincipal
|
|
from backend.features.market.schemas import (
|
|
ChartResponse,
|
|
EntityDetailResponse,
|
|
MarketInsightResponse,
|
|
MarketSummaryResponse,
|
|
MarketWorkspaceResponse,
|
|
ReferenceSyncResponse,
|
|
RotationMembersResponse,
|
|
SearchResponse,
|
|
SeatAliasRequest,
|
|
SeatAliasResponse,
|
|
SnapshotSyncResponse,
|
|
ThemeDetailResponse,
|
|
TradeContextResponse,
|
|
)
|
|
|
|
router = APIRouter(prefix="/market", tags=["market"])
|
|
|
|
|
|
@router.get("/context", response_model=TradeContextResponse)
|
|
def context(
|
|
request: Request,
|
|
_principal: AuthenticatedPrincipal,
|
|
requested_date: Annotated[str | None, Query(alias="date")] = None,
|
|
) -> dict:
|
|
return request.app.state.container.market.context(requested_date)
|
|
|
|
|
|
@router.get("/summary", response_model=MarketSummaryResponse)
|
|
def summary(
|
|
request: Request,
|
|
_principal: AuthenticatedPrincipal,
|
|
requested_date: Annotated[str | None, Query(alias="date")] = None,
|
|
) -> dict:
|
|
return request.app.state.container.market.summary(requested_date)
|
|
|
|
|
|
@router.get("/search", response_model=SearchResponse)
|
|
def search(
|
|
request: Request,
|
|
_principal: AuthenticatedPrincipal,
|
|
query: Annotated[str, Query(alias="q", max_length=80)] = "",
|
|
) -> dict:
|
|
return request.app.state.container.market.search(query)
|
|
|
|
|
|
@router.get("/entities/{entity_type}/{identifier}/charts/{interval}", response_model=ChartResponse)
|
|
def chart(
|
|
request: Request,
|
|
_principal: AuthenticatedPrincipal,
|
|
entity_type: Annotated[Literal["stock", "sector", "theme", "index"], Path()],
|
|
identifier: Annotated[str, Path(min_length=1, max_length=40)],
|
|
interval: Annotated[Literal["day", "minute"], Path()],
|
|
) -> dict:
|
|
return request.app.state.container.market.chart(entity_type, identifier, interval)
|
|
|
|
|
|
@router.get("/entities/{entity_type}/{identifier}/detail", response_model=EntityDetailResponse)
|
|
def entity_detail(
|
|
request: Request,
|
|
_principal: AuthenticatedPrincipal,
|
|
entity_type: Annotated[Literal["stock", "sector", "theme", "index"], Path()],
|
|
identifier: Annotated[str, Path(min_length=1, max_length=40)],
|
|
requested_date: Annotated[str | None, Query(alias="date")] = None,
|
|
) -> dict:
|
|
return request.app.state.container.market.entity_detail(
|
|
entity_type, identifier, requested_date
|
|
)
|
|
|
|
|
|
@router.post("/reference-sync", response_model=ReferenceSyncResponse)
|
|
def refresh_reference(request: Request, _principal: AdminWritePrincipal) -> dict[str, int | str]:
|
|
return request.app.state.container.market.refresh_reference()
|
|
|
|
|
|
@router.post("/snapshot-sync", response_model=SnapshotSyncResponse)
|
|
def sync_snapshot(
|
|
request: Request,
|
|
_principal: AdminWritePrincipal,
|
|
requested_date: Annotated[str | None, Query(alias="date")] = None,
|
|
) -> dict:
|
|
return request.app.state.container.operations.refresh(requested_date)
|
|
|
|
|
|
@router.get("/workspaces/{key}", response_model=MarketWorkspaceResponse)
|
|
def workspace(
|
|
request: Request,
|
|
_principal: AuthenticatedPrincipal,
|
|
key: Annotated[
|
|
Literal[
|
|
"emotion", "pool", "broken", "limit-down", "yesterday", "performance",
|
|
"ladder", "rotation",
|
|
],
|
|
Path(),
|
|
],
|
|
requested_date: Annotated[str | None, Query(alias="date")] = None,
|
|
) -> dict:
|
|
return request.app.state.container.market.workspace(key, requested_date)
|
|
|
|
|
|
@router.get("/rotation-members", response_model=RotationMembersResponse)
|
|
def rotation_members(
|
|
request: Request,
|
|
_principal: AuthenticatedPrincipal,
|
|
sector_name: Annotated[str, Query(alias="sector", min_length=1, max_length=60)],
|
|
requested_date: Annotated[str | None, Query(alias="date")] = None,
|
|
) -> dict:
|
|
return request.app.state.container.market.rotation_members(sector_name, requested_date)
|
|
|
|
|
|
@router.get("/insights/{key}", response_model=MarketInsightResponse)
|
|
def insight(
|
|
request: Request,
|
|
principal: AuthenticatedPrincipal,
|
|
key: Annotated[
|
|
Literal["auction", "themes", "popularity", "dragon-list"], Path()
|
|
],
|
|
requested_date: Annotated[str | None, Query(alias="date")] = None,
|
|
) -> dict:
|
|
return request.app.state.container.market.insight(
|
|
key, requested_date, principal.user.id
|
|
)
|
|
|
|
|
|
@router.post("/insights/{key}/sync", response_model=MarketInsightResponse)
|
|
def sync_insight(
|
|
request: Request,
|
|
principal: AdminWritePrincipal,
|
|
key: Annotated[
|
|
Literal["auction", "themes", "popularity", "dragon-list"], Path()
|
|
],
|
|
requested_date: Annotated[str | None, Query(alias="date")] = None,
|
|
) -> dict:
|
|
return request.app.state.container.market.sync_insight(
|
|
key, requested_date, principal.user.id
|
|
)
|
|
|
|
|
|
@router.get("/themes/{identifier}", response_model=ThemeDetailResponse)
|
|
def theme_detail(
|
|
request: Request,
|
|
_principal: AuthenticatedPrincipal,
|
|
identifier: Annotated[str, Path(min_length=1, max_length=40)],
|
|
requested_date: Annotated[str | None, Query(alias="date")] = None,
|
|
) -> dict:
|
|
return request.app.state.container.market.theme_detail(identifier, requested_date)
|
|
|
|
|
|
@router.put("/seat-aliases", response_model=SeatAliasResponse)
|
|
def save_seat_alias(
|
|
payload: SeatAliasRequest,
|
|
request: Request,
|
|
principal: AdminWritePrincipal,
|
|
) -> dict[str, str]:
|
|
return request.app.state.container.market.save_seat_alias(
|
|
payload.seat_name, payload.alias_name, principal.user.id
|
|
)
|