Files
worldquant-alpha-system/backend/app/backtests/routes.py
T

167 lines
5.9 KiB
Python

"""Authenticated adapters; every mutation is committed before the execution lane wakes."""
from fastapi import APIRouter, Depends, Query, Request
from ..business import Business
from ..security import require_auth
from .contracts import (
ControlInput,
DraftInput,
DraftUpdate,
EventPage,
PreviewInput,
PreviewOutput,
ReferenceInput,
RerunInput,
ResultPage,
RunOutput,
RunPage,
SchedulerInput,
SchedulerOutput,
StartInput,
SubsetInput,
)
router = APIRouter(prefix="/api/v1/backtests", tags=["backtests"], dependencies=[Depends(require_auth)])
@router.get("/capabilities")
async def capabilities(request: Request):
async with request.app.state.sessions() as db:
return await Business(db).backtests.capabilities()
@router.get("/config", response_model=SchedulerOutput)
async def config(request: Request):
async with request.app.state.sessions() as db:
return await Business(db).backtests.config()
@router.put("/config", response_model=SchedulerOutput)
async def configure(body: SchedulerInput, request: Request):
async with request.app.state.sessions.begin() as db:
result = await Business(db).backtests.configure(body)
request.app.state.runner.backtests.wake.set()
return result
@router.get("/drafts")
async def drafts(request: Request, limit: int = Query(25, ge=1, le=100), offset: int = Query(0, ge=0)):
async with request.app.state.sessions() as db:
return await Business(db).backtests.drafts(limit, offset)
@router.post("/drafts", status_code=201)
async def save_draft(body: DraftInput, request: Request):
async with request.app.state.sessions.begin() as db:
return await Business(db).backtests.save_draft(body)
@router.get("/drafts/{draft_id}")
async def draft(draft_id: str, request: Request):
async with request.app.state.sessions() as db:
return await Business(db).backtests.draft(draft_id)
@router.put("/drafts/{draft_id}")
async def update_draft(draft_id: str, body: DraftUpdate, request: Request):
async with request.app.state.sessions.begin() as db:
return await Business(db).backtests.save_draft(body, draft_id)
@router.post("/previews", status_code=201, response_model=PreviewOutput)
async def preview(body: PreviewInput, request: Request):
async with request.app.state.sessions.begin() as db:
return await Business(db).backtests.preview(body)
@router.get("/previews/{preview_id}", response_model=PreviewOutput)
async def get_preview(
preview_id: str, request: Request, limit: int = Query(25, ge=1, le=100), offset: int = Query(0, ge=0)
):
async with request.app.state.sessions() as db:
return await Business(db).backtests.get_preview(preview_id, limit, offset)
@router.post("/runs", status_code=202, response_model=RunOutput)
async def start(body: StartInput, request: Request):
async with request.app.state.sessions.begin() as db:
result = await Business(db).backtests.start(body)
request.app.state.runner.backtests.wake.set()
return result
@router.get("/runs", response_model=RunPage)
async def runs(
request: Request,
limit: int = Query(25, ge=1, le=100),
offset: int = Query(0, ge=0),
source: str | None = Query(None, max_length=100),
):
async with request.app.state.sessions() as db:
return await Business(db).backtests.runs(limit, offset, source)
@router.get("/runs/{run_id}", response_model=RunOutput)
async def run(run_id: str, request: Request):
async with request.app.state.sessions() as db:
return await Business(db).backtests.run(run_id)
@router.get("/runs/{run_id}/results", response_model=ResultPage)
async def results(
run_id: str, request: Request, limit: int = Query(25, ge=1, le=100), offset: int = Query(0, ge=0)
):
async with request.app.state.sessions() as db:
return await Business(db).backtests.results(run_id, limit, offset)
@router.get("/runs/{run_id}/events", response_model=EventPage)
async def events(
run_id: str, request: Request, after: int = Query(0, ge=0), limit: int = Query(100, ge=1, le=100)
):
async with request.app.state.sessions() as db:
return await Business(db).backtests.events(run_id, after, limit)
@router.get("/runs/{run_id}/attempts")
async def attempts(run_id: str, request: Request):
async with request.app.state.sessions() as db:
return await Business(db).backtests.attempts(run_id)
@router.post("/runs/{run_id}/control", response_model=RunOutput)
async def control(run_id: str, body: ControlInput, request: Request):
async with request.app.state.sessions.begin() as db:
result = await Business(db).backtests.control(run_id, body)
request.app.state.runner.backtests.wake.set()
return result
@router.post("/runs/{run_id}/rerun-preview", status_code=201, response_model=PreviewOutput)
async def rerun(run_id: str, body: RerunInput, request: Request):
async with request.app.state.sessions.begin() as db:
return await Business(db).backtests.rerun(run_id, body)
@router.post("/attempts/{attempt_id}/reference", response_model=RunOutput)
async def attach_reference(attempt_id: str, body: ReferenceInput, request: Request):
from fastapi import HTTPException
from ..worldquant import WqError
try:
body.progress_url = request.app.state.runner.client.simulation_url(body.progress_url)
except WqError as exc:
raise HTTPException(422, str(exc)) from None
async with request.app.state.sessions.begin() as db:
result = await Business(db).backtests.attach_reference(attempt_id, body)
request.app.state.runner.backtests.wake.set()
return result
@router.post("/previews/{preview_id}/subset", status_code=201, response_model=PreviewOutput)
async def subset(preview_id: str, body: SubsetInput, request: Request):
async with request.app.state.sessions.begin() as db:
return await Business(db).backtests.subset(preview_id, body)