feat(tools): run_python, web search/fetch, market data, options, portfolio
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
f41cf75d8a
commit
63085113ed
6 files changed
+552
No files matched your search
@@ -0,0 +1,56 @@
|
||||
"""get_portfolio — persona-scoped. Each agent sees ONLY its own paper account's holdings
|
||||
(written by execution/reconcile.py, keyed by persona id), so picks build on that book.
|
||||
Built per-persona via make_get_portfolio() in tools/build_toolset.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
|
||||
from langchain_core.tools import tool
|
||||
|
||||
from config.settings import get_settings
|
||||
from state import db as statedb
|
||||
|
||||
|
||||
def make_get_portfolio(account: str):
|
||||
"""Return a get_portfolio tool bound to one account (persona id)."""
|
||||
|
||||
@tool
|
||||
def get_portfolio() -> str:
|
||||
"""Return YOUR current paper-account holdings, unrealized PnL, and cash.
|
||||
|
||||
Use this BEFORE proposing trades so you account for what you already own.
|
||||
"""
|
||||
path = get_settings().db_path
|
||||
if not path.exists():
|
||||
return "No portfolio data yet (fresh account, no trades recorded)."
|
||||
try:
|
||||
con = statedb.connect(path)
|
||||
snap = statedb.latest_snapshot(con, account or None)
|
||||
con.close()
|
||||
except Exception as e:
|
||||
return f"No portfolio data yet ({e})."
|
||||
if snap is None:
|
||||
return "No holdings yet (fresh account, all cash)."
|
||||
|
||||
lines = [
|
||||
f"As of {snap['ts']}: equity=${snap['equity']:,.2f}, "
|
||||
f"cash=${snap['cash']:,.2f}, buying_power=${snap['buying_power']:,.2f}"
|
||||
]
|
||||
try:
|
||||
positions = json.loads(snap["positions_json"] or "[]")
|
||||
except Exception:
|
||||
positions = []
|
||||
if not positions:
|
||||
lines.append("Holdings: none (all cash).")
|
||||
else:
|
||||
lines.append("Holdings:")
|
||||
for p in positions:
|
||||
lines.append(
|
||||
f" {p.get('symbol')}: {p.get('qty')} @ {p.get('avg_entry')} "
|
||||
f"-> mv={p.get('market_value')}, unrealized_pl={p.get('unrealized_pl')}"
|
||||
)
|
||||
return "\n".join(lines)
|
||||
|
||||
return get_portfolio
|
||||
Reference in new issue
Block a user