fix: ornith leads when confident (>0.55), qwen vetoes borderline only. Was too tight — 2/2 agreement blocked all trades.
This commit is contained in:
34
bot.py
34
bot.py
@@ -342,15 +342,13 @@ def llm_vote(cfg, price, mom, mom_score, conn):
|
||||
except Exception as ex:
|
||||
fast_v, fast_c, fast_w = "BORDERLINE", 0.50, f"gate: {str(ex)[:40]}"
|
||||
|
||||
# ── 2-model ensemble: qwen3.5 (MacBook) + ornith (GamingPC RTX 3070) ──
|
||||
# Disagreement = SKIP (conservative). No diverifier — avoids VRAM contention.
|
||||
# ── 2-model: ornith leads when confident, qwen vetoes borderline ──
|
||||
NO_PROXY = {"proxies": {"http": None, "https": None}}
|
||||
votes = []
|
||||
# Model 1: qwen3.5 fast gate (MacBook — already ran)
|
||||
v1 = fast_v if fast_v in ("UP","DOWN","SKIP") else "SKIP"
|
||||
votes.append((v1, fast_c if fast_v in ("UP","DOWN","SKIP") else 0.50, fast_w, "qwen3.5"))
|
||||
c1 = fast_c if fast_v in ("UP","DOWN","SKIP") else 0.50
|
||||
|
||||
# Model 2: ornith deep verify (GamingPC RTX 3070 — always hot)
|
||||
# Model 2: ornith deep verify (GamingPC RTX 3070)
|
||||
try:
|
||||
r2 = requests.post("http://10.30.20.186:11434/api/generate",
|
||||
json={"model": "ornith:latest", "prompt": prompt, "stream": False, "think": False, "keep_alive": "10m",
|
||||
@@ -360,20 +358,24 @@ def llm_vote(cfg, price, mom, mom_score, conn):
|
||||
d2 = json.loads(txt2[s2:e2]) if s2 >= 0 else {}
|
||||
v2 = str(d2.get("vote","SKIP")).upper()
|
||||
if v2 not in ("UP","DOWN","SKIP"): v2 = "SKIP"
|
||||
votes.append((v2, float(d2.get("conf",0)), str(d2.get("why",""))[:120], "ornith"))
|
||||
c2 = float(d2.get("conf",0))
|
||||
w2 = str(d2.get("why",""))[:120]
|
||||
except Exception as ex2:
|
||||
LOG.warning(f"ornith failed: {ex2}")
|
||||
votes.append(("SKIP", 0.0, "ornith offline", "ornith"))
|
||||
return v1, c1, f"[qwen-only: {v1} {c1:.2f}] {fast_w[:80]}"
|
||||
|
||||
# Majority: only trade if BOTH agree (2/2). Any disagreement = SKIP.
|
||||
tally = {"UP": 0, "DOWN": 0, "SKIP": 0}
|
||||
for v, c, w, src in votes:
|
||||
tally[v] += 1
|
||||
winner = "UP" if tally["UP"] == 2 else ("DOWN" if tally["DOWN"] == 2 else "SKIP")
|
||||
avg_conf = sum(v[1] for v in votes if v[0] == winner) / max(1, tally[winner])
|
||||
reasons = " | ".join(f"{src}={v}" for v, _, _, src in votes)
|
||||
tag = "ENSEMBLE" if winner != "SKIP" else "SPLIT"
|
||||
return winner, avg_conf, f"[{tag}: {tally['UP']}U/{tally['DOWN']}D/{tally['SKIP']}S] {reasons}"
|
||||
# ornith confident (>0.55) → lead, regardless of qwen
|
||||
if v2 in ("UP","DOWN") and c2 >= 0.55:
|
||||
return v2, c2, f"[ornith-lead {v2} {c2:.2f} | qwen={v1}] {w2[:60]}"
|
||||
# both agree → go
|
||||
if v1 == v2 and v1 in ("UP","DOWN"):
|
||||
avg = (c1 + c2) / 2
|
||||
return v1, avg, f"[agree {v1} {avg:.2f}] {w2[:60]}"
|
||||
# qwen confident + ornith uncertain → use qwen
|
||||
if v1 in ("UP","DOWN") and c1 >= 0.65 and c2 < 0.55:
|
||||
return v1, c1, f"[qwen-lead {v1} {c1:.2f} | ornith={v2}] {fast_w[:60]}"
|
||||
# disagreement or both uncertain → skip
|
||||
return "SKIP", 0.0, f"[split qwen={v1}({c1:.2f}) ornith={v2}({c2:.2f})] {w2[:50]}"
|
||||
|
||||
def decide(cfg, conn, price):
|
||||
"""Two-tier decision: qwen fast-gate → ornith deep-verify.
|
||||
|
||||
Reference in New Issue
Block a user