feat(execution): per-account Alpaca GTC brackets, guardrails, shorts, options, reconcile
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016DvdRZkyCy9NJpHYDdPqmS
This commit is contained in:
1 parent
aa1ae0c95e
commit
709870b1d5
8 files changed
+813
No files matched your search
@@ -0,0 +1,46 @@
|
||||
"""Snapshot one persona's Alpaca account into the state DB (keyed by persona id), so the
|
||||
dashboard and the next nightly run (via get_portfolio) see that account's holdings + PnL.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from execution.broker import Broker
|
||||
from state import db
|
||||
|
||||
|
||||
def _f(x, default=0.0) -> float:
|
||||
try:
|
||||
return float(x)
|
||||
except (TypeError, ValueError):
|
||||
return default
|
||||
|
||||
|
||||
def reconcile(db_path, account: str, broker: Broker) -> dict:
|
||||
acct = broker.get_account()
|
||||
positions = broker.get_positions()
|
||||
|
||||
pos_list = [
|
||||
{
|
||||
"symbol": p.symbol,
|
||||
"qty": _f(p.qty),
|
||||
"avg_entry": _f(p.avg_entry_price),
|
||||
"market_value": _f(p.market_value),
|
||||
"unrealized_pl": _f(p.unrealized_pl),
|
||||
}
|
||||
for p in positions
|
||||
]
|
||||
|
||||
con = db.connect(db_path)
|
||||
db.record_snapshot(
|
||||
con, account=account, equity=_f(acct.equity), cash=_f(acct.cash),
|
||||
buying_power=_f(acct.buying_power), positions=pos_list,
|
||||
)
|
||||
for p in pos_list:
|
||||
db.upsert_position(con, account=account, **p)
|
||||
con.commit()
|
||||
con.close()
|
||||
|
||||
logger.info("reconciled {}: equity=${:.2f} positions={}", account, _f(acct.equity), len(pos_list))
|
||||
return {"account": account, "equity": _f(acct.equity), "positions": pos_list}
|
||||
Reference in new issue
Block a user