QAway-to commited on
Commit
c1d305f
·
1 Parent(s): 08efbfa

New tabs and functions v2.5

Browse files
Files changed (3) hide show
  1. app.py +11 -6
  2. core/crypto_dashboard.py +78 -43
  3. core/ui_style.css +14 -17
app.py CHANGED
@@ -70,24 +70,27 @@ with gr.Blocks(css=custom_css) as demo:
70
  chart_out = gr.Plot(label="Alpha vs BTC")
71
  chart_btn.click(fn=build_alpha_chart, inputs=chart_in, outputs=chart_out)
72
 
73
- # --- Crypto Intelligence Dashboard (Refined layout) ---
74
  with gr.TabItem("Crypto Intelligence Dashboard"):
75
- gr.Markdown("### 💹 Coinlore Market Dashboard (Altair Edition)")
76
 
77
- # Controls
78
  with gr.Row():
79
  top_slider = gr.Slider(
80
  label="Top N coins", minimum=20, maximum=100, step=10, value=50, scale=70
81
  )
82
  load_btn = gr.Button("Generate Dashboard", variant="primary", scale=30)
83
 
84
- # Main layout
85
  with gr.Row(equal_height=True):
86
  with gr.Column(scale=70):
87
  treemap_plot = gr.Plot(label="Market Composition")
88
  with gr.Column(scale=30):
89
- ai_box = gr.Textbox(label="AI Market Summary", lines=18, elem_id="ai_summary_sidebar")
 
 
90
 
 
91
  with gr.Row(equal_height=True):
92
  movers_plot = gr.Plot(label="Top Movers", scale=50)
93
  scatter_plot = gr.Plot(label="Market Cap vs Volume", scale=50)
@@ -95,7 +98,9 @@ with gr.Blocks(css=custom_css) as demo:
95
  from core.crypto_dashboard import build_crypto_dashboard
96
 
97
 
98
- def run_dash(n): return build_crypto_dashboard(n)
 
 
99
 
100
  load_btn.click(
101
  fn=run_dash,
 
70
  chart_out = gr.Plot(label="Alpha vs BTC")
71
  chart_btn.click(fn=build_alpha_chart, inputs=chart_in, outputs=chart_out)
72
 
73
+ # --- Crypto Intelligence Dashboard (Coinlore, Plotly Edition) ---
74
  with gr.TabItem("Crypto Intelligence Dashboard"):
75
+ gr.Markdown("### 💹 Coinlore Market Dashboard (Plotly Edition)")
76
 
77
+ # --- Controls ---
78
  with gr.Row():
79
  top_slider = gr.Slider(
80
  label="Top N coins", minimum=20, maximum=100, step=10, value=50, scale=70
81
  )
82
  load_btn = gr.Button("Generate Dashboard", variant="primary", scale=30)
83
 
84
+ # --- Layout: Treemap + AI sidebar ---
85
  with gr.Row(equal_height=True):
86
  with gr.Column(scale=70):
87
  treemap_plot = gr.Plot(label="Market Composition")
88
  with gr.Column(scale=30):
89
+ ai_box = gr.Textbox(
90
+ label="AI Market Summary", lines=18, elem_id="ai_summary_sidebar"
91
+ )
92
 
93
+ # --- Layout: Lower charts (Movers + Scatter) ---
94
  with gr.Row(equal_height=True):
95
  movers_plot = gr.Plot(label="Top Movers", scale=50)
96
  scatter_plot = gr.Plot(label="Market Cap vs Volume", scale=50)
 
98
  from core.crypto_dashboard import build_crypto_dashboard
99
 
100
 
101
+ def run_dash(n):
102
+ return build_crypto_dashboard(n)
103
+
104
 
105
  load_btn.click(
106
  fn=run_dash,
core/crypto_dashboard.py CHANGED
@@ -1,10 +1,15 @@
1
  """
2
- Coinlore Dashboard — Power BI style (Altair)
 
3
  """
4
- import requests, pandas as pd, altair as alt
 
 
 
5
  from services.llm_client import llm_service
6
 
7
 
 
8
  def fetch_coinlore_data(limit=100):
9
  url = "https://api.coinlore.net/api/tickers/"
10
  data = requests.get(url).json()["data"]
@@ -15,60 +20,90 @@ def fetch_coinlore_data(limit=100):
15
  return df.head(limit)
16
 
17
 
 
18
  def build_crypto_dashboard(top_n=50):
19
  df = fetch_coinlore_data(top_n)
20
 
21
- # === 1️⃣ Treemap imitation ===
22
- base = alt.Chart(df).mark_rect().encode(
23
- x=alt.X('symbol:N', title=None, axis=None),
24
- y=alt.Y('market_cap_usd:Q', title=None, axis=None),
25
- color=alt.Color('percent_change_24h:Q',
26
- scale=alt.Scale(scheme='redyellowgreen'),
27
- title='24h Change %'),
28
- tooltip=['symbol', 'price_usd', 'market_cap_usd', 'percent_change_24h']
29
- ).properties(title="Market Composition (Top Coins)", height=300)
 
 
 
 
 
 
 
30
 
31
- # === 2️⃣ Bar chart (Top Movers 24h) ===
32
- movers = df.sort_values("percent_change_24h", ascending=False).head(15)
33
- bar = alt.Chart(movers).mark_bar(cornerRadiusEnd=4).encode(
34
- x=alt.X('percent_change_24h:Q', title='Change %'),
35
- y=alt.Y('symbol:N', sort='-x', title=None),
36
- color=alt.Color('percent_change_24h:Q', scale=alt.Scale(scheme='greenblue')),
37
- tooltip=['symbol', 'price_usd', 'percent_change_24h']
38
- ).properties(title="Top 15 Gainers (24h)", height=300)
 
 
 
 
 
 
 
 
 
 
39
 
40
- # === 3️⃣ Scatter (Market Cap vs Volume) ===
41
- scatter = alt.Chart(df).mark_circle(size=70).encode(
42
- x=alt.X('market_cap_usd:Q', scale=alt.Scale(type='log')),
43
- y=alt.Y('volume24:Q', scale=alt.Scale(type='log')),
44
- color=alt.Color('percent_change_7d:Q',
45
- scale=alt.Scale(scheme='redyellowgreen'),
46
- title='7d %'),
47
- tooltip=['symbol', 'price_usd', 'market_cap_usd', 'volume24', 'percent_change_7d']
48
- ).properties(title="Market Cap vs 24h Volume", height=350)
 
 
 
 
 
 
 
 
 
 
 
49
 
50
- # === LLM summary ===
51
- ai_comment = _generate_ai_summary(df)
52
 
53
- return base, bar, scatter, ai_comment
54
 
55
 
56
  def _generate_ai_summary(df):
57
- leaders = df.sort_values("percent_change_24h", ascending=False).head(3)
58
- laggards = df.sort_values("percent_change_24h").head(3)
 
59
  prompt = f"""
60
- Provide a brief professional summary of today's crypto market based on Coinlore data.
61
- Top gainers: {', '.join(leaders['symbol'].tolist())}.
62
- Top losers: {', '.join(laggards['symbol'].tolist())}.
63
  Include:
64
- - general sentiment
65
- - volatility trend
66
- - short-term outlook (bullish/bearish)
67
  """
68
- text = ""
69
  for delta in llm_service.stream_chat(
70
  messages=[{"role": "user", "content": prompt}],
71
- model="meta-llama/Meta-Llama-3.1-8B-Instruct"
72
  ):
73
- text += delta
74
- return text
 
1
  """
2
+ Crypto Dashboard — Plotly Edition (Coinlore API)
3
+ Power BI–style visualization with dense layout.
4
  """
5
+ import requests
6
+ import pandas as pd
7
+ import plotly.express as px
8
+ import plotly.graph_objects as go
9
  from services.llm_client import llm_service
10
 
11
 
12
+ # === Fetch data from Coinlore ===
13
  def fetch_coinlore_data(limit=100):
14
  url = "https://api.coinlore.net/api/tickers/"
15
  data = requests.get(url).json()["data"]
 
20
  return df.head(limit)
21
 
22
 
23
+ # === Main Dashboard ===
24
  def build_crypto_dashboard(top_n=50):
25
  df = fetch_coinlore_data(top_n)
26
 
27
+ # --- Treemap ---
28
+ fig_treemap = px.treemap(
29
+ df,
30
+ path=["symbol"],
31
+ values="market_cap_usd",
32
+ color="percent_change_24h",
33
+ color_continuous_scale="RdYlGn",
34
+ title="Market Composition by Market Cap (Top Coins)",
35
+ height=400,
36
+ )
37
+ fig_treemap.update_layout(
38
+ template="plotly_dark",
39
+ margin=dict(l=0, r=0, t=40, b=0),
40
+ paper_bgcolor="rgba(0,0,0,0)",
41
+ plot_bgcolor="rgba(0,0,0,0)",
42
+ )
43
 
44
+ # --- Top Gainers (24h) ---
45
+ top = df.sort_values("percent_change_24h", ascending=False).head(12)
46
+ fig_bar = px.bar(
47
+ top,
48
+ x="percent_change_24h",
49
+ y="symbol",
50
+ orientation="h",
51
+ color="percent_change_24h",
52
+ color_continuous_scale="Blues",
53
+ title="Top 12 Gainers (24h)",
54
+ height=350,
55
+ )
56
+ fig_bar.update_layout(
57
+ template="plotly_dark",
58
+ margin=dict(l=80, r=30, t=40, b=40),
59
+ paper_bgcolor="rgba(0,0,0,0)",
60
+ plot_bgcolor="rgba(0,0,0,0)",
61
+ )
62
 
63
+ # --- Market Cap vs Volume (Bubble) ---
64
+ fig_bubble = px.scatter(
65
+ df.head(60),
66
+ x="market_cap_usd",
67
+ y="volume24",
68
+ size="price_usd",
69
+ color="percent_change_7d",
70
+ hover_name="symbol",
71
+ log_x=True,
72
+ log_y=True,
73
+ color_continuous_scale="RdYlGn",
74
+ title="Market Cap vs 24h Volume",
75
+ height=350,
76
+ )
77
+ fig_bubble.update_layout(
78
+ template="plotly_dark",
79
+ margin=dict(l=60, r=30, t=40, b=40),
80
+ paper_bgcolor="rgba(0,0,0,0)",
81
+ plot_bgcolor="rgba(0,0,0,0)",
82
+ )
83
 
84
+ # --- AI Summary ---
85
+ summary = _generate_ai_summary(df)
86
 
87
+ return fig_treemap, fig_bar, fig_bubble, summary
88
 
89
 
90
  def _generate_ai_summary(df):
91
+ leaders = df.sort_values("percent_change_24h", ascending=False).head(3)["symbol"].tolist()
92
+ laggards = df.sort_values("percent_change_24h").head(3)["symbol"].tolist()
93
+
94
  prompt = f"""
95
+ Summarize today's crypto market based on Coinlore data.
96
+ Top gainers: {', '.join(leaders)}.
97
+ Top losers: {', '.join(laggards)}.
98
  Include:
99
+ - overall market sentiment
100
+ - volatility and liquidity notes
101
+ - short-term outlook
102
  """
103
+ summary = ""
104
  for delta in llm_service.stream_chat(
105
  messages=[{"role": "user", "content": prompt}],
106
+ model="meta-llama/Meta-Llama-3.1-8B-Instruct",
107
  ):
108
+ summary += delta
109
+ return summary
core/ui_style.css CHANGED
@@ -14,7 +14,7 @@ h2, h3, .gr-markdown {
14
  font-weight: 600 !important;
15
  }
16
 
17
- /* === Remove Gray Placeholder Icons (Plot Artefacts) === */
18
  [data-testid="plot-container"] svg {
19
  display: none !important;
20
  }
@@ -23,36 +23,28 @@ h2, h3, .gr-markdown {
23
  box-shadow: none !important;
24
  }
25
 
26
- /* === Plot Sizing and Spacing === */
27
  [data-testid="plot-container"] {
28
  width: 100% !important;
29
  margin: 0 auto 22px auto !important;
30
- background: transparent !important;
31
- border: none !important;
32
  }
33
  [data-testid="plot-container"] canvas {
34
  width: 100% !important;
35
  height: auto !important;
36
  }
37
 
38
- /* === Dashboard Layout === */
39
- .gr-row { gap: 18px !important; }
40
-
41
- /* Верхний график (Treemap) */
42
  #root [label="Market Composition"] canvas {
43
- height: 360px !important;
44
  }
45
-
46
- /* Нижние графики (Movers + Scatter) */
47
  #root [label="Top Movers"] canvas,
48
  #root [label="Market Cap vs Volume"] canvas {
49
- height: 320px !important;
50
  }
51
 
52
  /* === Sidebar (AI Summary) === */
53
- #ai_summary_sidebar textarea,
54
- #llm_comment_box textarea {
55
- height: 360px !important;
56
  background-color: #161b22 !important;
57
  color: #f0f6fc !important;
58
  border: 1px solid #30363d !important;
@@ -64,7 +56,7 @@ h2, h3, .gr-markdown {
64
  resize: none !important;
65
  }
66
 
67
- /* === Sliders, Buttons, Text === */
68
  .gr-button {
69
  border-radius: 6px !important;
70
  font-weight: 600 !important;
@@ -86,7 +78,7 @@ h2, h3, .gr-markdown {
86
  background: #6366f1 !important;
87
  }
88
 
89
- /* === Tables === */
90
  .gr-dataframe table {
91
  width: 100% !important;
92
  color: #c9d1d9 !important;
@@ -103,3 +95,8 @@ h2, h3, .gr-markdown {
103
  border-top: 1px solid #30363d !important;
104
  padding: 8px !important;
105
  }
 
 
 
 
 
 
14
  font-weight: 600 !important;
15
  }
16
 
17
+ /* === Remove Gray Placeholder Icons === */
18
  [data-testid="plot-container"] svg {
19
  display: none !important;
20
  }
 
23
  box-shadow: none !important;
24
  }
25
 
26
+ /* === Plot Size & Layout === */
27
  [data-testid="plot-container"] {
28
  width: 100% !important;
29
  margin: 0 auto 22px auto !important;
 
 
30
  }
31
  [data-testid="plot-container"] canvas {
32
  width: 100% !important;
33
  height: auto !important;
34
  }
35
 
36
+ /* --- Chart height tuning --- */
 
 
 
37
  #root [label="Market Composition"] canvas {
38
+ height: 400px !important;
39
  }
 
 
40
  #root [label="Top Movers"] canvas,
41
  #root [label="Market Cap vs Volume"] canvas {
42
+ height: 350px !important;
43
  }
44
 
45
  /* === Sidebar (AI Summary) === */
46
+ #ai_summary_sidebar textarea {
47
+ height: 400px !important;
 
48
  background-color: #161b22 !important;
49
  color: #f0f6fc !important;
50
  border: 1px solid #30363d !important;
 
56
  resize: none !important;
57
  }
58
 
59
+ /* === Buttons & Sliders === */
60
  .gr-button {
61
  border-radius: 6px !important;
62
  font-weight: 600 !important;
 
78
  background: #6366f1 !important;
79
  }
80
 
81
+ /* === Tables & spacing === */
82
  .gr-dataframe table {
83
  width: 100% !important;
84
  color: #c9d1d9 !important;
 
95
  border-top: 1px solid #30363d !important;
96
  padding: 8px !important;
97
  }
98
+
99
+ /* === Dashboard Layout === */
100
+ .gr-row {
101
+ gap: 18px !important;
102
+ }