126 lines
3.2 KiB
Python
126 lines
3.2 KiB
Python
"""Portfolio request and response schemas."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
from typing import Any, Literal
|
|
|
|
from pydantic import BaseModel, ConfigDict, Field
|
|
|
|
|
|
class StrategySetResponse(BaseModel):
|
|
id: str
|
|
name: str
|
|
config: str
|
|
nick: str
|
|
created_at: datetime | None = None
|
|
|
|
|
|
class LedgerEntryResponse(BaseModel):
|
|
portfolio_id: str
|
|
recorded_at: datetime
|
|
action: str
|
|
price: float
|
|
quantity: float
|
|
fee_amount: float = 0.0
|
|
tax_amount: float = 0.0
|
|
cash_balance_after: float
|
|
asset_quantity_after: float
|
|
total_value_after: float
|
|
profit_buffer_after: float = 0.0
|
|
strategy_set_id: str = "manual"
|
|
note: str = ""
|
|
|
|
|
|
class PortfolioBase(BaseModel):
|
|
broker: str = "kis"
|
|
status: str = "enabled"
|
|
symbol: str
|
|
|
|
|
|
class PortfolioSummary(BaseModel):
|
|
portfolio_id: str
|
|
broker: str
|
|
status: str
|
|
symbol: str
|
|
cash_balance: float = 0.0
|
|
asset_quantity: float = 0.0
|
|
price: float = 0.0
|
|
profit_buffer: float = 0.0
|
|
active_strategy_id: str | None = None
|
|
avabile_strategies: list[str] | None = None
|
|
created_at: datetime | None = None
|
|
updated_at: datetime | None = None
|
|
last_trade_at: datetime | None = None
|
|
|
|
|
|
class PortfolioListItem(PortfolioSummary):
|
|
total_value: float = 0.0
|
|
|
|
|
|
class PortfolioDetailResponse(BaseModel):
|
|
portfolio: PortfolioSummary
|
|
recent_entries: list[LedgerEntryResponse] = Field(default_factory=list)
|
|
strategy_set: StrategySetResponse | None = None
|
|
live_quantity: float | None = None
|
|
|
|
|
|
class CreatePortfolioRequest(PortfolioBase):
|
|
portfolio_id: str
|
|
strategy_name: str = "target_value"
|
|
strategy_params: dict[str, Any] = Field(default_factory=dict)
|
|
active_strategy_id: str | None = None
|
|
avabile_strategies: list[str] | None = None
|
|
cash_balance: float = Field(default=0.0, ge=0.0)
|
|
asset_quantity: float = Field(default=0.0, ge=0.0)
|
|
asset_price: float = Field(default=0.0, ge=0.0)
|
|
profit_buffer: float = Field(default=0.0, ge=0.0)
|
|
|
|
|
|
class UpdatePortfolioRequest(BaseModel):
|
|
broker: str | None = None
|
|
status: str | None = None
|
|
symbol: str | None = None
|
|
strategy_name: str | None = None
|
|
strategy_params: dict[str, Any] | None = None
|
|
active_strategy_id: str | None = None
|
|
avabile_strategies: list[str] | None = None
|
|
asset_price: float | None = Field(default=None, ge=0.0)
|
|
|
|
|
|
class BuyRequest(BaseModel):
|
|
quantity: float = Field(gt=0.0)
|
|
price: float = Field(gt=0.0)
|
|
fee: float = Field(default=0.0, ge=0.0)
|
|
tax: float = Field(default=0.0, ge=0.0)
|
|
note: str = ""
|
|
|
|
|
|
class SellRequest(BaseModel):
|
|
quantity: float = Field(gt=0.0)
|
|
price: float = Field(gt=0.0)
|
|
fee: float = Field(default=0.0, ge=0.0)
|
|
tax: float = Field(default=0.0, ge=0.0)
|
|
note: str = ""
|
|
|
|
|
|
class InvestRequest(BaseModel):
|
|
movement_type: Literal["deposit", "profit", "withdraw"]
|
|
amount: float = Field(gt=0.0)
|
|
note: str = ""
|
|
|
|
|
|
class TransferRequest(BaseModel):
|
|
direction: Literal["to-buffer", "from-buffer"]
|
|
amount: float = Field(gt=0.0)
|
|
note: str = ""
|
|
|
|
|
|
class ResetPortfolioRequest(BaseModel):
|
|
infer_symbol: str | None = None
|
|
|
|
|
|
class ErrorResponse(BaseModel):
|
|
detail: str
|
|
model_config = ConfigDict(extra="ignore")
|