fix: overlay Polygon prices on positions instead of stale Alpaca prices
ci/woodpecker/push/test Pipeline was successful
ci/woodpecker/push/build-3 Pipeline was successful
ci/woodpecker/push/finalize unknown status
ci/woodpecker/push/build-2 Pipeline failed
ci/woodpecker/push/build-1 Pipeline failed
Build and Push / lint-and-test (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.adapters.broker_adapter name:broker-adapter]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.aggregation.worker name:aggregation]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.extractor.worker name:extractor]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.ingestion.worker name:ingestion]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.lake_publisher.worker name:lake-publisher]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.parser.worker name:parser]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.recommendation.worker name:recommendation]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.scheduler.app name:scheduler]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.api.app:app --host 0.0.0.0 --port 8000 name:query-api]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.risk.app:app --host 0.0.0.0 --port 8000 name:risk]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.symbol_registry.app:app --host 0.0.0.0 --port 8000 name:symbol-registry]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.trading.app:app --host 0.0.0.0 --port 8000 name:trading-engine]) (push) Has been cancelled
Build and Push / build-dashboard (push) Has been cancelled
Build and Push / build-superset (push) Has been cancelled
Build and Push / integration-test (push) Has been cancelled
Build and Push / beta-gate (push) Has been cancelled
ci/woodpecker/push/test Pipeline was successful
ci/woodpecker/push/build-3 Pipeline was successful
ci/woodpecker/push/finalize unknown status
ci/woodpecker/push/build-2 Pipeline failed
ci/woodpecker/push/build-1 Pipeline failed
Build and Push / lint-and-test (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.adapters.broker_adapter name:broker-adapter]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.aggregation.worker name:aggregation]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.extractor.worker name:extractor]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.ingestion.worker name:ingestion]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.lake_publisher.worker name:lake-publisher]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.parser.worker name:parser]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.recommendation.worker name:recommendation]) (push) Has been cancelled
Build and Push / build-services (map[cmd:python -m services.scheduler.app name:scheduler]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.api.app:app --host 0.0.0.0 --port 8000 name:query-api]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.risk.app:app --host 0.0.0.0 --port 8000 name:risk]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.symbol_registry.app:app --host 0.0.0.0 --port 8000 name:symbol-registry]) (push) Has been cancelled
Build and Push / build-services (map[cmd:uvicorn services.trading.app:app --host 0.0.0.0 --port 8000 name:trading-engine]) (push) Has been cancelled
Build and Push / build-dashboard (push) Has been cancelled
Build and Push / build-superset (push) Has been cancelled
Build and Push / integration-test (push) Has been cancelled
Build and Push / beta-gate (push) Has been cancelled
Alpaca paper trading returns inaccurate current_price values. The positions endpoint now uses the latest Polygon close from market_snapshots and recomputes unrealized P&L from that.
This commit is contained in:
+31
-2
@@ -1179,7 +1179,12 @@ async def get_order(order_id: str):
|
|||||||
async def list_positions(
|
async def list_positions(
|
||||||
ticker: Optional[str] = None,
|
ticker: Optional[str] = None,
|
||||||
):
|
):
|
||||||
"""List current positions."""
|
"""List current positions with Polygon market prices overlaid.
|
||||||
|
|
||||||
|
The current_price from the broker (Alpaca paper) can be stale or
|
||||||
|
inaccurate. We overlay the latest close from market_snapshots
|
||||||
|
(Polygon daily bars) and recompute unrealized P&L from that.
|
||||||
|
"""
|
||||||
if ticker:
|
if ticker:
|
||||||
rows = await pool.fetch(
|
rows = await pool.fetch(
|
||||||
"""SELECT p.id, p.broker_account_id, p.ticker, p.quantity,
|
"""SELECT p.id, p.broker_account_id, p.ticker, p.quantity,
|
||||||
@@ -1195,7 +1200,31 @@ async def list_positions(
|
|||||||
p.unrealized_pnl, p.realized_pnl, p.updated_at
|
p.unrealized_pnl, p.realized_pnl, p.updated_at
|
||||||
FROM positions p ORDER BY p.ticker""",
|
FROM positions p ORDER BY p.ticker""",
|
||||||
)
|
)
|
||||||
return [_row_to_dict(r) for r in rows]
|
|
||||||
|
# Build a price map from the latest Polygon bars
|
||||||
|
tickers = list({r["ticker"] for r in rows})
|
||||||
|
price_map: dict[str, float] = {}
|
||||||
|
if tickers:
|
||||||
|
price_rows = await pool.fetch(
|
||||||
|
"""SELECT DISTINCT ON (ticker) ticker, (data->>'c')::float AS close
|
||||||
|
FROM market_snapshots
|
||||||
|
WHERE ticker = ANY($1) AND snapshot_type = 'bar'
|
||||||
|
ORDER BY ticker, captured_at DESC""",
|
||||||
|
tickers,
|
||||||
|
)
|
||||||
|
price_map = {r["ticker"]: r["close"] for r in price_rows if r["close"]}
|
||||||
|
|
||||||
|
results = []
|
||||||
|
for r in rows:
|
||||||
|
d = _row_to_dict(r)
|
||||||
|
polygon_price = price_map.get(d["ticker"])
|
||||||
|
if polygon_price:
|
||||||
|
d["current_price"] = polygon_price
|
||||||
|
qty = d.get("quantity", 0) or 0
|
||||||
|
entry = d.get("avg_entry_price", 0) or 0
|
||||||
|
d["unrealized_pnl"] = round(qty * (polygon_price - entry), 2)
|
||||||
|
results.append(d)
|
||||||
|
return results
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user