from typing import Any, Dict from pathlib import Path import sys from fastapi import APIRouter, Request from app.services.paper_broker_service import get_paper_broker from app.services.tenant import get_request_user_id from app.services.run_service import get_active_run_id PROJECT_ROOT = Path(__file__).resolve().parents[1] if str(PROJECT_ROOT) not in sys.path: sys.path.append(str(PROJECT_ROOT)) from indian_paper_trading_strategy.engine.db import engine_context from market import get_ltp from indian_paper_trading_strategy.engine.state import load_state router = APIRouter(prefix="/api/paper", tags=["paper-mtm"]) @router.get("/mtm") def paper_mtm(request: Request) -> Dict[str, Any]: user_id = get_request_user_id(request) run_id = get_active_run_id(user_id) with engine_context(user_id, run_id): broker = get_paper_broker(user_id) positions = broker.get_positions() state = load_state(mode="PAPER") cash = float(state.get("cash", 0)) initial_cash = float(state.get("initial_cash", 0)) ltp_payload = get_ltp(allow_cache=True) ltp_map = ltp_payload["ltp"] mtm_positions = [] positions_value = 0.0 for pos in positions: symbol = pos.get("symbol") if not symbol: continue qty = float(pos.get("qty", 0)) avg_price = float(pos.get("avg_price", 0)) ltp = ltp_map.get(symbol) if ltp is None: continue pnl = (ltp - avg_price) * qty positions_value += qty * ltp mtm_positions.append( { "symbol": symbol, "qty": qty, "avg_price": avg_price, "ltp": ltp, "pnl": pnl, } ) equity = cash + positions_value unrealized_pnl = equity - float(initial_cash) return { "ts": ltp_payload["ts"], "initial_cash": initial_cash, "cash": cash, "positions_value": positions_value, "equity": equity, "unrealized_pnl": unrealized_pnl, "positions": mtm_positions, "price_stale": ltp_payload.get("stale_any", False), "price_source": ltp_payload.get("source", {}), }