Files
portfolio-hub/app/schemas/v1.py
T
genichin 3509606c7e feat(REQ-005): implement TrEx Basic V1 API contract with auth, assets, ledger, and user endpoints
- Add V1 API routes for assets, ledger, and user info with complete CRUD operations
- Implement authentication scopes and request validation via auth_routes.py
- Extend schemas with V1-specific models for accounts, holdings, and positions
- Add database queries and aggregations for P&L, performance, and account data
- Include comprehensive test coverage for all V1 endpoints and integration flows
- Update batch and release documentation with implementation and verification evidence
- Sync project structure and runtime flows per V1 API contract requirements

Closes implementation phase of BAT-001 (TrEx Basic V1 API Contract)
2026-05-02 11:37:42 +00:00

94 lines
2.6 KiB
Python

"""Schemas for v1 (Consumer-Driven Contract) API endpoints."""
from __future__ import annotations
from datetime import datetime
from decimal import Decimal
from typing import Any, Literal
from pydantic import BaseModel, Field
# ---------------------------------------------------------------------------
# GET /v1/assets
# ---------------------------------------------------------------------------
class AssetItem(BaseModel):
asset_id: str
symbol: str
market: str | None = None
status: str
cash: float
quantity: float
broker_type: str
strategy_id: str | None = None
strategy_params: dict[str, Any] = {}
updated_at: datetime | None = None
# Additional informational fields
name: str | None = None
price: float | None = None
profit_buffer: float | None = None
tags: list[str] | None = None
owner_user_id: str | None = None
created_at: datetime | None = None
last_trade_at: datetime | None = None
class AssetsResponse(BaseModel):
assets: list[AssetItem]
total: int
# ---------------------------------------------------------------------------
# GET /v1/user_info
# ---------------------------------------------------------------------------
class BrokerItem(BaseModel):
broker: str
account_ref: str
credential_payload: dict[str, Any] | None = None
credential_version: int = 1
last_rotated_at: datetime | None = None
class UserInfoResponse(BaseModel):
runtime_id: str
trading_enabled: bool
disabled_reason: str | None = None
brokers: list[BrokerItem] = []
# Additional informational fields
user_id: str
username: str
email: str | None = None
permission: str
# ---------------------------------------------------------------------------
# POST /v1/assets/{asset_id}/ledger/trades
# ---------------------------------------------------------------------------
class LedgerTradeRequest(BaseModel):
order_id: str = Field(..., min_length=1)
execution_id: str = Field(..., min_length=1)
side: Literal["buy", "sell"]
quantity: Decimal = Field(..., gt=0)
price: Decimal = Field(..., gt=0)
fee_amount: Decimal = Field(default=Decimal("0"), ge=0)
tax_amount: Decimal = Field(default=Decimal("0"), ge=0)
executed_at: datetime
class LedgerTradeResponse(BaseModel):
ledger_entry_id: int
asset_id: str
order_id: str
execution_id: str
side: str
quantity: float
price: float
fee_amount: float
tax_amount: float
executed_at: datetime
recorded_at: datetime | None = None
status: Literal["new", "duplicate"] = "new"