v1.3 infra integration: Qdrant memory RAG, Trilium journaling, n8n emit hooks
This commit is contained in:
54
bot.py
54
bot.py
@@ -13,6 +13,10 @@ from services import (
|
||||
place_order,
|
||||
market_open,
|
||||
positions_snapshot,
|
||||
qdrant_similar,
|
||||
qdrant_add_memory,
|
||||
trilium_log,
|
||||
n8n_emit,
|
||||
)
|
||||
|
||||
scheduler = BackgroundScheduler(timezone=settings.timezone)
|
||||
@@ -55,14 +59,15 @@ def run_cycle():
|
||||
|
||||
news = searx_news(symbol)
|
||||
strat = strategy_signals(symbol, news)
|
||||
decision = llm_final_decision(symbol, news, strat)
|
||||
memory_hits = qdrant_similar(symbol, json.dumps(news)[:2000], limit=5)
|
||||
decision = llm_final_decision(symbol, news, strat, memory_hits)
|
||||
|
||||
# Escalate to deeper research when model asks or confidence weak
|
||||
if decision.get("needs_more_research") or decision.get("confidence", 0) < settings.min_confidence:
|
||||
more = extra_research(symbol, decision.get("research_topics", []))
|
||||
if more:
|
||||
news = news + more
|
||||
decision = llm_final_decision(symbol, news, strat)
|
||||
memory_hits = qdrant_similar(symbol, json.dumps(news)[:2000], limit=5)
|
||||
decision = llm_final_decision(symbol, news, strat, memory_hits)
|
||||
|
||||
drow = BotDecision(
|
||||
symbol=symbol,
|
||||
@@ -77,19 +82,11 @@ def run_cycle():
|
||||
db.commit()
|
||||
db.refresh(drow)
|
||||
|
||||
should_trade = (
|
||||
decision["action"] in {"buy", "sell"}
|
||||
and decision["confidence"] >= settings.min_confidence
|
||||
)
|
||||
should_trade = decision["action"] in {"buy", "sell"} and decision["confidence"] >= settings.min_confidence
|
||||
|
||||
if should_trade:
|
||||
# Fee/slippage-aware cap for tiny bankroll
|
||||
effective_cost = settings.fee_per_trade_usd + (settings.slippage_bps / 10000.0) * decision["order_usd"]
|
||||
notional = min(
|
||||
settings.max_order_usd,
|
||||
decision["order_usd"],
|
||||
settings.max_daily_notional - spent,
|
||||
)
|
||||
notional = min(settings.max_order_usd, decision["order_usd"], settings.max_daily_notional - spent)
|
||||
if notional <= effective_cost:
|
||||
drow.status = "risk_blocked"
|
||||
db.add(drow)
|
||||
@@ -100,21 +97,46 @@ def run_cycle():
|
||||
ok = bool(res and res.get("ok"))
|
||||
drow.status = "executed" if ok else "failed"
|
||||
db.add(drow)
|
||||
db.add(TradeExecution(
|
||||
|
||||
trade = TradeExecution(
|
||||
symbol=symbol,
|
||||
side=decision["action"],
|
||||
qty=float((res or {}).get("json", {}).get("qty", 0) or 0),
|
||||
notional=notional,
|
||||
alpaca_order_id=(res or {}).get("json", {}).get("id", ""),
|
||||
raw=json.dumps({"decision": decision, "strategy": strat, "broker": res})[:60000],
|
||||
))
|
||||
raw=json.dumps({"decision": decision, "strategy": strat, "memory": memory_hits, "broker": res})[:60000],
|
||||
)
|
||||
db.add(trade)
|
||||
db.commit()
|
||||
|
||||
# learning memory + notes + orchestration signal
|
||||
qdrant_add_memory(symbol, f"{symbol} {decision['action']} conf={decision['confidence']} reason={decision['reason']}", {
|
||||
"status": drow.status,
|
||||
"action": decision["action"],
|
||||
"confidence": decision["confidence"],
|
||||
"ts": datetime.utcnow().isoformat(),
|
||||
})
|
||||
trilium_log(
|
||||
f"Trade {symbol} {decision['action']} {drow.status}",
|
||||
f"## Decision\n- symbol: {symbol}\n- action: {decision['action']}\n- confidence: {decision['confidence']:.2f}\n- status: {drow.status}\n- notional: ${notional:.2f}\n\n## Reason\n{decision['reason']}\n\n## Strategy\n{json.dumps(strat, indent=2)}\n"
|
||||
)
|
||||
n8n_emit({"event": "trade", "symbol": symbol, "status": drow.status, "decision": decision, "notional": notional})
|
||||
|
||||
if ok:
|
||||
spent += notional
|
||||
else:
|
||||
drow.status = "skipped"
|
||||
db.add(drow)
|
||||
db.commit()
|
||||
|
||||
# store non-trade decisions too for memory
|
||||
qdrant_add_memory(symbol, f"{symbol} decision={decision['action']} conf={decision['confidence']} status={drow.status}", {
|
||||
"status": drow.status,
|
||||
"action": decision["action"],
|
||||
"confidence": decision["confidence"],
|
||||
"ts": datetime.utcnow().isoformat(),
|
||||
})
|
||||
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user