feat: 5-coin fleet (DOGE/SOL/ETH/XRP/BTC), enriched context (multi-TF trend, orderbook depth, BTC corr, WR history, regime), memory system (learned patterns), self-adapting overrides, fleet dashboard with per-coin RSI/mom
This commit is contained in:
30
dashboard.py
30
dashboard.py
@@ -201,7 +201,7 @@ h1{font-size:1rem;letter-spacing:3px}.dim{color:#0a5f2e}
|
||||
<div class="fleet" id="cards"></div>
|
||||
<div id="statusbar"></div>
|
||||
<script>
|
||||
const C={DOGE:"#c2a633",SOL:"#9945FF",ETH:"#627EEA"};
|
||||
const C={DOGE:"#c2a633",SOL:"#9945FF",ETH:"#627EEA",XRP:"#00AAE4",BTC:"#f7931a"};
|
||||
function fmt(c){return c<0?`<span class="dn">-${Math.abs(c)}¢</span>`:c>0?`<span class="up">+${c}¢</span>`:`<span class="skip">${c}¢</span>`}
|
||||
function ago(ts){const d=Date.now()/1000-ts;return d<60?Math.floor(d)+'s':d<3600?Math.floor(d/60)+'m':Math.floor(d/3600)+'h'}
|
||||
async function load(){
|
||||
@@ -335,7 +335,7 @@ def toggle_dry():
|
||||
@app.route("/api/fleet")
|
||||
def fleet_api():
|
||||
"""All active coins in one call — reads each coin's own DB."""
|
||||
COINS = {"🐶DOGE": "#c2a633", "🔮SOL": "#9945FF", "💎ETH": "#627EEA"}
|
||||
COINS = {"🐶DOGE": "#c2a633", "🔮SOL": "#9945FF", "💎ETH": "#627EEA", "🌊XRP": "#00AAE4", "₿BTC": "#f7931a"}
|
||||
result = {}
|
||||
for label, color in COINS.items():
|
||||
coin = label[1:] # strip leading emoji
|
||||
@@ -350,16 +350,34 @@ def fleet_api():
|
||||
now = time.time()
|
||||
ticks = [r[0] for r in conn.execute("SELECT price FROM ticks WHERE ts > ? ORDER BY ts", (now-1800,)).fetchall()]
|
||||
last_price = ticks[-1] if ticks else None
|
||||
# enriched per-coin data
|
||||
# enriched per-coin data — compute RSI + momentum directly (no cross-import)
|
||||
decs = [dict(r) for r in conn.execute("SELECT * FROM decisions ORDER BY id DESC LIMIT 3")]
|
||||
ords = [dict(r) for r in conn.execute("SELECT * FROM orders ORDER BY id DESC LIMIT 5")]
|
||||
live_bets = conn.execute("SELECT COUNT(*) FROM orders WHERE status IN ('placed','posted') AND dry=0").fetchone()[0]
|
||||
total_bets = conn.execute("SELECT COUNT(*) FROM orders WHERE dry=0").fetchone()[0]
|
||||
pnl = conn.execute("SELECT COALESCE(SUM(pnl_cents),0) FROM orders WHERE dry=0").fetchone()[0]
|
||||
won = conn.execute("SELECT COUNT(*) FROM orders WHERE status='won' AND dry=0").fetchone()[0]
|
||||
import sys; sys.path.insert(0, str(HOME))
|
||||
from bot import rsi as _rsi, momentum as _mom
|
||||
c_rsi = _rsi(conn); c_mom, c_score = _mom(conn)
|
||||
# RSI
|
||||
rows14 = conn.execute("SELECT price FROM ticks WHERE ts > ? ORDER BY ts DESC LIMIT 15", (now-900,)).fetchall()
|
||||
c_rsi = None
|
||||
if len(rows14) >= 15:
|
||||
px = [r[0] for r in rows14]
|
||||
gains = [max(0, b-a) for a, b in zip(px[:-1], px[1:])]
|
||||
losses = [max(0, a-b) for a, b in zip(px[:-1], px[1:])]
|
||||
ag = sum(gains)/14 if gains else 0; al = sum(losses)/14 if losses else 1e-9
|
||||
c_rsi = 100 - 100/(1 + ag/al) if al else (100 if ag > 0 else 50)
|
||||
# Momentum
|
||||
rows_t = conn.execute("SELECT ts, price FROM ticks WHERE ts > ? ORDER BY ts", (now-1800,)).fetchall()
|
||||
c_mom, c_score = "FLAT", 0.0
|
||||
if len(rows_t) >= 4:
|
||||
now_p = rows_t[-1][1]
|
||||
ref5 = min(rows_t, key=lambda r: abs(r[0]-(now-300)))[1]
|
||||
ref15 = min(rows_t, key=lambda r: abs(r[0]-(now-900)))[1]
|
||||
r5 = (now_p-ref5)/ref5*100 if ref5 else 0; r15 = (now_p-ref15)/ref15*100 if ref15 else 0
|
||||
sc = r5*0.6 + r15*0.4
|
||||
if sc > 0.008: c_mom, c_score = "UP", abs(sc)
|
||||
elif sc < -0.008: c_mom, c_score = "DOWN", abs(sc)
|
||||
else: c_mom, c_score = "FLAT", abs(sc)
|
||||
chg24 = c.get("chg24_cache", 0)
|
||||
result[coin] = {"label": label, "color": color, "series": c["series"],
|
||||
"price": last_price, "mode": c["mode"],
|
||||
|
||||
Reference in New Issue
Block a user