Files
robinhood/backend/app/api/account.py

64 lines
1.9 KiB
Python

from __future__ import annotations
from fastapi import APIRouter
from typing import Any, Dict, List
from datetime import datetime, timezone
from app.api.trading import simulation_state
from app.streaming.live_store import live_store
router = APIRouter(prefix="/account", tags=["Account"])
router_positions = APIRouter(tags=["Positions"])
def _latest_close(symbol: str, timeframe: str = "1m") -> float | None:
try:
history = live_store.get_history(symbol, timeframe)
if history:
return float(history[-1]["close"])
except Exception:
pass
return None
@router.get("")
async def get_account() -> Dict[str, Any]:
cash = float(simulation_state.get("cash", 0.0))
initial = float(simulation_state.get("initial_capital", 0.0))
pos = simulation_state.get("position")
position_value = 0.0
exposure: Dict[str, float] = {}
if pos:
symbol = pos.get("symbol", "XAU/USD")
last = _latest_close(symbol) or float(pos["avg_price"])
position_value = float(pos["quantity"]) * last
exposure[symbol] = position_value
equity = cash + position_value
return {
"time": datetime.now(timezone.utc).isoformat(),
"cash": cash,
"equity": equity,
"initial_capital": initial,
"margin_used": 0.0,
"exposure": exposure,
}
@router.get("/positions")
@router_positions.get("/positions")
async def get_positions() -> List[Dict[str, Any]]:
pos = simulation_state.get("position")
if not pos:
return []
symbol = pos.get("symbol", "XAU/USD")
last = _latest_close(symbol)
return [
{
"symbol": symbol,
"quantity": float(pos["quantity"]),
"avg_price": float(pos["avg_price"]),
"last_price": float(last) if last is not None else None,
"market_value": float(pos["quantity"]) * (float(last) if last is not None else float(pos["avg_price"]))
}
]