feat: wire up stop levels, circuit breaker daily loss, profit-taking, real portfolio/decisions/history endpoints

This commit is contained in:
Celes Renata
2026-04-16 15:52:46 +00:00
parent 1329df0bbf
commit 63287903d0
3 changed files with 318 additions and 57 deletions
+79 -4
View File
@@ -363,11 +363,60 @@ async def set_capital(body: CapitalRequest) -> dict[str, Any]:
async def list_decisions(
ticker: Optional[str] = None,
decision: Optional[str] = None,
is_micro_trade: Optional[bool] = None,
limit: int = Query(default=50, le=200),
offset: int = 0,
) -> list[dict[str, Any]]:
"""Return recent trading decisions (placeholder — paginated)."""
return []
"""Return recent trading decisions from the database."""
if engine is None or engine.pool is None:
return []
conditions = ["1=1"]
params: list[Any] = []
idx = 1
if ticker:
conditions.append(f"ticker = ${idx}")
params.append(ticker.upper())
idx += 1
if decision:
conditions.append(f"decision = ${idx}")
params.append(decision)
idx += 1
if is_micro_trade is not None:
conditions.append(f"is_micro_trade = ${idx}")
params.append(is_micro_trade)
idx += 1
where = " AND ".join(conditions)
params.extend([limit, offset])
try:
rows = await engine.pool.fetch(
f"SELECT id, recommendation_id, decision, skip_reason, ticker, "
f"computed_position_size, computed_share_quantity, "
f"risk_tier_at_decision, portfolio_heat_at_decision, "
f"active_pool_at_decision, reserve_pool_at_decision, "
f"circuit_breaker_status, is_micro_trade, created_at "
f"FROM trading_decisions WHERE {where} "
f"ORDER BY created_at DESC LIMIT ${idx} OFFSET ${idx + 1}",
*params,
)
from decimal import Decimal as _Dec
result = []
for r in rows:
d = dict(r)
for k, v in d.items():
if isinstance(v, _Dec):
d[k] = float(v)
elif isinstance(v, datetime):
d[k] = v.isoformat()
elif hasattr(v, '__str__') and not isinstance(v, (str, int, float, bool, type(None))):
d[k] = str(v)
result.append(d)
return result
except Exception:
return []
# ---------------------------------------------------------------------------
@@ -401,8 +450,34 @@ async def current_metrics() -> dict[str, Any]:
async def metrics_history(
limit: int = Query(default=30, le=365),
) -> list[dict[str, Any]]:
"""Return historical daily snapshots (placeholder)."""
return []
"""Return historical daily portfolio snapshots."""
if engine is None or engine.pool is None:
return []
try:
rows = await engine.pool.fetch(
"SELECT id, snapshot_date, portfolio_value, active_pool, reserve_pool, "
"daily_return, cumulative_return, unrealized_pnl, realized_pnl, "
"win_count, loss_count, win_rate, sharpe_ratio, max_drawdown, "
"current_drawdown_pct, portfolio_heat, risk_tier, created_at "
"FROM portfolio_snapshots ORDER BY snapshot_date DESC LIMIT $1",
limit,
)
from decimal import Decimal as _Dec
result = []
for r in rows:
d = dict(r)
for k, v in d.items():
if isinstance(v, _Dec):
d[k] = float(v)
elif isinstance(v, datetime):
d[k] = v.isoformat()
elif hasattr(v, '__str__') and not isinstance(v, (str, int, float, bool, type(None))):
d[k] = str(v)
result.append(d)
return result
except Exception:
return []
# ---------------------------------------------------------------------------