FIN_ASSISTANT / core /crypto_dashboard.py
QAway-to
Revert "New tabs and functions v4.5"
e55ebde
raw
history blame
4.05 kB
"""
Crypto Dashboard — Plotly Edition (clean layout)
• убраны colorbar заголовки (percent_change_*)
• уменьшены отступы KPI
• без глобального Markdown-заголовка
"""
import requests
import pandas as pd
import plotly.express as px
from services.llm_client import llm_service
def fetch_coinlore_data(limit=100):
url = "https://api.coinlore.net/api/tickers/"
data = requests.get(url).json()["data"]
df = pd.DataFrame(data)
for col in ["price_usd", "market_cap_usd", "volume24",
"percent_change_1h", "percent_change_24h", "percent_change_7d"]:
df[col] = pd.to_numeric(df[col], errors="coerce")
return df.head(limit)
def _kpi_line(df) -> str:
"""Формирует компактную KPI-строку без лишних пробелов"""
tracked = ["BTC", "ETH", "SOL", "DOGE"]
parts = []
for sym in tracked:
row = df[df["symbol"] == sym]
if row.empty:
continue
price = float(row["price_usd"])
ch = float(row["percent_change_24h"])
arrow = "↑" if ch > 0 else "↓"
color = "#4ade80" if ch > 0 else "#f87171"
parts.append(
f"<b>{sym}</b> ${price:,.0f} "
f"<span style='color:{color}'>{arrow} {abs(ch):.2f}%</span>"
)
return " , ".join(parts)
def build_crypto_dashboard(top_n=50):
df = fetch_coinlore_data(top_n)
# === Treemap ===
fig_treemap = px.treemap(
df,
path=["symbol"],
values="market_cap_usd",
color="percent_change_24h",
color_continuous_scale="RdYlGn",
height=420,
)
fig_treemap.update_layout(
title=None,
template="plotly_dark",
coloraxis_colorbar=dict(title=None), # 🔹 убираем надпись percent_change_24h
margin=dict(l=5, r=5, t=5, b=5),
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
)
# === Bar chart (Top gainers) ===
top = df.sort_values("percent_change_24h", ascending=False).head(12)
fig_bar = px.bar(
top,
x="percent_change_24h",
y="symbol",
orientation="h",
color="percent_change_24h",
color_continuous_scale="Blues",
height=320,
)
fig_bar.update_layout(
title=None,
template="plotly_dark",
coloraxis_colorbar=dict(title=None), # 🔹 убираем надпись percent_change_24h
margin=dict(l=40, r=10, t=5, b=18),
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
)
# === Scatter (Market Cap vs Volume) ===
fig_bubble = px.scatter(
df.head(60),
x="market_cap_usd",
y="volume24",
size="price_usd",
color="percent_change_7d",
hover_name="symbol",
log_x=True,
log_y=True,
color_continuous_scale="RdYlGn",
height=320,
)
fig_bubble.update_layout(
title=None,
template="plotly_dark",
coloraxis_colorbar=dict(title=None), # 🔹 убираем надпись percent_change_7d
margin=dict(l=36, r=10, t=5, b=18),
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
)
# === LLM summary ===
summary = _ai_summary(df)
kpi_text = _kpi_line(df)
return fig_treemap, fig_bar, fig_bubble, summary, kpi_text
def _ai_summary(df):
leaders = df.sort_values("percent_change_24h", ascending=False).head(3)["symbol"].tolist()
laggards = df.sort_values("percent_change_24h").head(3)["symbol"].tolist()
prompt = f"""
Summarize today's crypto market based on Coinlore data.
Top gainers: {', '.join(leaders)}.
Top losers: {', '.join(laggards)}.
Include: overall sentiment, volatility/liquidity, short-term outlook.
"""
text = ""
for delta in llm_service.stream_chat(
messages=[{"role": "user", "content": prompt}],
model="meta-llama/Meta-Llama-3.1-8B-Instruct",
):
text += delta
return text