- regime.py: computed SPY/VIX/sector-momentum snapshot injected into every kickoff - journal.py: each agent sees its own past picks marked-to-market (learns from wins/losses) - committee.py: Chief-Risk-Officer LLM pass over the whole book — approve/reduce/veto per pick with reasons; memo lands in reports; executor enforces verdicts at open Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016DvdRZkyCy9NJpHYDdPqmS
65 lines
2.2 KiB
Python
65 lines
2.2 KiB
Python
"""Self-learning trade journal — each agent sees its own past picks AND how they worked out
|
|
before researching tonight. Losses and wins become explicit lessons instead of being forgotten.
|
|
|
|
Joins past theses with their execution price (orders table) and marks each to market via the
|
|
current price. Compact text block injected into the agent's kickoff.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from loguru import logger
|
|
|
|
from config.settings import get_settings
|
|
from state import db as statedb
|
|
from tools.market_data import latest_price
|
|
|
|
_MAX_ROWS = 10
|
|
|
|
|
|
def lessons_for(persona_id: str) -> str:
|
|
"""Past-pick scorecard for one agent. Empty string if no history/DB yet."""
|
|
s = get_settings()
|
|
if not s.db_path.exists():
|
|
return ""
|
|
try:
|
|
con = statedb.connect(s.db_path)
|
|
rows = con.execute(
|
|
"""
|
|
SELECT t.trade_date, t.ticker, t.direction, t.conviction, t.thesis,
|
|
o.est_price, o.status
|
|
FROM theses t
|
|
LEFT JOIN orders o
|
|
ON o.trade_date = t.trade_date AND o.agent = t.agent AND o.ticker = t.ticker
|
|
WHERE t.agent = ?
|
|
ORDER BY t.trade_date DESC, t.conviction DESC
|
|
LIMIT ?
|
|
""",
|
|
(persona_id, _MAX_ROWS),
|
|
).fetchall()
|
|
con.close()
|
|
except Exception as e:
|
|
logger.warning("journal query failed for {}: {}", persona_id, e)
|
|
return ""
|
|
if not rows:
|
|
return ""
|
|
|
|
lines = []
|
|
for r in rows:
|
|
entry = r["est_price"]
|
|
outcome = "not executed"
|
|
if entry:
|
|
px = latest_price(r["ticker"])
|
|
if px:
|
|
chg = (px / entry - 1) * 100
|
|
if (r["direction"] or "long") == "short":
|
|
chg = -chg
|
|
outcome = f"{chg:+.1f}% since {r['trade_date']} (entry ~{entry:.2f})"
|
|
lines.append(
|
|
f"- {r['trade_date']} {r['ticker']} {r['direction']} conv={r['conviction']}: {outcome}"
|
|
f" | thesis was: {(r['thesis'] or '')[:100]}"
|
|
)
|
|
return (
|
|
"YOUR TRACK RECORD (mark-to-market of your past picks — learn from it; double down on "
|
|
"what worked, avoid repeating what failed):\n" + "\n".join(lines)
|
|
)
|