77 lines
2.2 KiB
Python
77 lines
2.2 KiB
Python
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", {}),
|
|
}
|