QAway-to commited on
Commit
b9435d1
·
1 Parent(s): a41be0f

New tabs and functions v4.4

Browse files
Files changed (1) hide show
  1. app.py +42 -28
app.py CHANGED
@@ -4,18 +4,17 @@ from core.analyzer import PortfolioAnalyzer
4
  from core.comparer import PortfolioComparer
5
  from core.chat import ChatAssistant
6
  from core.metrics import show_metrics_table
7
- from core.crypto_dashboard import build_crypto_dashboard # (обновлено: KPI-line + более плотные графики)
8
- from core.multi_charts import build_echarts_html, build_highcharts_html # (обновлено: чистый HTML/JS)
9
 
10
  # === CSS loader ===
11
  def load_css(path: str) -> str:
12
  with open(path, "r", encoding="utf-8") as f:
13
  return f.read()
14
 
15
- # base + per-tab styles
16
  base_css = load_css("core/styles/base.css")
17
  crypto_css = load_css("core/styles/crypto_dashboard.css")
18
- multi_css = load_css("core/styles/multi_charts.css")
19
 
20
  # === Model setup ===
21
  MODEL_NAME = "meta-llama/Meta-Llama-3.1-8B-Instruct"
@@ -23,9 +22,13 @@ analyzer = PortfolioAnalyzer(llm_service, MODEL_NAME)
23
  comparer = PortfolioComparer(llm_service, MODEL_NAME)
24
  chatbot = ChatAssistant(llm_service, MODEL_NAME)
25
 
 
26
  with gr.Blocks(css=base_css) as demo:
27
  gr.Markdown("## Investment Portfolio Analyzer")
28
- gr.Markdown("Professional AI-driven analytics for investment and crypto markets.", elem_classes="subtitle")
 
 
 
29
 
30
  with gr.Tabs():
31
  # --- Analysis ---
@@ -39,7 +42,7 @@ with gr.Blocks(css=base_css) as demo:
39
  analyze_out = gr.Textbox(label="Analysis Result", lines=15, elem_id="analysis_output")
40
  analyze_btn.click(fn=analyzer.run, inputs=portfolio_input, outputs=analyze_out)
41
 
42
- # --- Comparison ---
43
  with gr.TabItem("Comparison Table"):
44
  from core.comparison_table import show_comparison_table
45
  pid_a = gr.Textbox(label="Portfolio A", value="3852a354-e66e-4bc5-97e9-55124e31e687")
@@ -56,39 +59,54 @@ with gr.Blocks(css=base_css) as demo:
56
  chat_out = gr.Textbox(label="AI Response", lines=8)
57
  chat_btn.click(fn=chatbot.run, inputs=chat_in, outputs=chat_out)
58
 
59
- # --- Metrics ---
60
  with gr.TabItem("Metrics Table"):
61
  metrics_in = gr.Textbox(label="Portfolio ID", value="b1ef37aa-5b9a-41b4-9394-8823f2de36bb")
62
  metrics_btn = gr.Button("Load Metrics", variant="primary")
63
  metrics_out = gr.Dataframe(label="Portfolio Metrics", wrap=True)
64
  metrics_btn.click(fn=show_metrics_table, inputs=metrics_in, outputs=metrics_out)
65
 
66
- # --- Visual Comparison (BTC vs ETH Plotly Edition) ---
67
- with gr.TabItem("Visual Comparison (BTC vs ETH)"):
68
- gr.Markdown("### 📈 BTC vs ETHMarket Comparison (Plotly Edition)")
69
-
70
- from core.visual_comparison import build_comparison_chart, build_volatility_chart
71
-
72
- compare_btn = gr.Button("Generate Comparison", variant="primary")
73
- price_plot = gr.Plot(label="Price Trend (BTC vs ETH)")
74
- vol_plot = gr.Plot(label="Daily Volatility (%)")
 
 
 
 
 
 
 
 
 
75
 
 
 
76
 
77
- def run_visuals():
78
- return build_comparison_chart(), build_volatility_chart()
 
 
 
 
79
 
80
- compare_btn.click(fn=run_visuals, outputs=[price_plot, vol_plot])
 
 
 
81
 
82
  # --- Crypto Intelligence Dashboard (Plotly Edition + KPI line) ---
83
  with gr.TabItem("Crypto Intelligence Dashboard"):
84
- # Подключаем стили вкладки
85
  gr.HTML(f"<style>{crypto_css}</style>")
86
 
87
- # KPI line (фиксированная строка без скачков, с минимальными отступами)
88
  with gr.Row(elem_id="kpi_row"):
89
  kpi_line = gr.HTML(elem_id="kpi_line")
90
 
91
- # Controls (Top N slider + кнопка)
92
  with gr.Row(elem_id="controls_row"):
93
  top_slider = gr.Slider(
94
  label="Top N coins",
@@ -100,7 +118,6 @@ with gr.Blocks(css=base_css) as demo:
100
  )
101
  load_btn = gr.Button("Generate Dashboard", variant="primary", scale=30)
102
 
103
- # Основной контент — графики и текстовый инсайт
104
  with gr.Row(equal_height=True, elem_id="main_charts_row"):
105
  with gr.Column(scale=70):
106
  treemap_plot = gr.Plot(label="Market Composition")
@@ -111,16 +128,12 @@ with gr.Blocks(css=base_css) as demo:
111
  elem_id="ai_summary_sidebar",
112
  )
113
 
114
- # Нижний ряд с двумя графиками
115
  with gr.Row(equal_height=True, elem_id="bottom_charts_row"):
116
  movers_plot = gr.Plot(label="Top Movers", scale=50)
117
  scatter_plot = gr.Plot(label="Market Cap vs Volume", scale=50)
118
 
119
-
120
- # === Callback ===
121
  def run_dash(n):
122
  fig_treemap, fig_bar, fig_bubble, ai_comment, kpi_text = build_crypto_dashboard(n)
123
- # KPI-строка уже готова, возвращаем её с обёрткой <div>
124
  return (
125
  fig_treemap,
126
  fig_bar,
@@ -129,7 +142,6 @@ with gr.Blocks(css=base_css) as demo:
129
  f"<div class='kpi-line'>{kpi_text}</div>",
130
  )
131
 
132
-
133
  load_btn.click(
134
  fn=run_dash,
135
  inputs=top_slider,
@@ -137,11 +149,13 @@ with gr.Blocks(css=base_css) as demo:
137
  show_progress="minimal",
138
  )
139
 
 
140
  gr.Markdown("---")
141
  gr.Markdown(
142
  "<center><small style='color:#6e7681;'>Developed with Featherless.ai • Powered by OpenAI-compatible API</small></center>",
143
  elem_classes="footer",
144
  )
145
 
 
146
  if __name__ == "__main__":
147
  demo.launch()
 
4
  from core.comparer import PortfolioComparer
5
  from core.chat import ChatAssistant
6
  from core.metrics import show_metrics_table
7
+ from core.crypto_dashboard import build_crypto_dashboard # Plotly dashboard + KPI-line
8
+ from core.visual_comparison import build_price_chart, build_volatility_chart # Interactive pair comparison
9
 
10
  # === CSS loader ===
11
  def load_css(path: str) -> str:
12
  with open(path, "r", encoding="utf-8") as f:
13
  return f.read()
14
 
15
+ # === Styles ===
16
  base_css = load_css("core/styles/base.css")
17
  crypto_css = load_css("core/styles/crypto_dashboard.css")
 
18
 
19
  # === Model setup ===
20
  MODEL_NAME = "meta-llama/Meta-Llama-3.1-8B-Instruct"
 
22
  comparer = PortfolioComparer(llm_service, MODEL_NAME)
23
  chatbot = ChatAssistant(llm_service, MODEL_NAME)
24
 
25
+ # === Main Interface ===
26
  with gr.Blocks(css=base_css) as demo:
27
  gr.Markdown("## Investment Portfolio Analyzer")
28
+ gr.Markdown(
29
+ "Professional AI-driven analytics for investment and crypto markets.",
30
+ elem_classes="subtitle",
31
+ )
32
 
33
  with gr.Tabs():
34
  # --- Analysis ---
 
42
  analyze_out = gr.Textbox(label="Analysis Result", lines=15, elem_id="analysis_output")
43
  analyze_btn.click(fn=analyzer.run, inputs=portfolio_input, outputs=analyze_out)
44
 
45
+ # --- Comparison Table ---
46
  with gr.TabItem("Comparison Table"):
47
  from core.comparison_table import show_comparison_table
48
  pid_a = gr.Textbox(label="Portfolio A", value="3852a354-e66e-4bc5-97e9-55124e31e687")
 
59
  chat_out = gr.Textbox(label="AI Response", lines=8)
60
  chat_btn.click(fn=chatbot.run, inputs=chat_in, outputs=chat_out)
61
 
62
+ # --- Metrics Table ---
63
  with gr.TabItem("Metrics Table"):
64
  metrics_in = gr.Textbox(label="Portfolio ID", value="b1ef37aa-5b9a-41b4-9394-8823f2de36bb")
65
  metrics_btn = gr.Button("Load Metrics", variant="primary")
66
  metrics_out = gr.Dataframe(label="Portfolio Metrics", wrap=True)
67
  metrics_btn.click(fn=show_metrics_table, inputs=metrics_in, outputs=metrics_out)
68
 
69
+ # --- Visual Comparison (Interactive Plotly Edition) ---
70
+ with gr.TabItem("Visual Comparison"):
71
+ gr.Markdown("### 📊 Market Pair ComparisonInteractive Plotly Edition")
72
+
73
+ available_pairs = [
74
+ ("bitcoin", "ethereum"),
75
+ ("bitcoin", "solana"),
76
+ ("ethereum", "bnb"),
77
+ ("solana", "dogecoin"),
78
+ ("bitcoin", "toncoin"),
79
+ ]
80
+
81
+ pair_selector = gr.Dropdown(
82
+ label="Select Pair for Comparison",
83
+ choices=[f"{a.capitalize()} vs {b.capitalize()}" for a, b in available_pairs],
84
+ value="Bitcoin vs Ethereum",
85
+ interactive=True,
86
+ )
87
 
88
+ price_plot = gr.Plot(label="Price Comparison")
89
+ vol_plot = gr.Plot(label="Volatility Comparison")
90
 
91
+ def update_visuals(selected_pair: str):
92
+ for a, b in available_pairs:
93
+ if selected_pair.lower() == f"{a} vs {b}":
94
+ return build_price_chart((a, b)), build_volatility_chart((a, b))
95
+ # fallback по умолчанию
96
+ return build_price_chart(("bitcoin", "ethereum")), build_volatility_chart(("bitcoin", "ethereum"))
97
 
98
+ # обновляем графики при смене пары
99
+ pair_selector.change(fn=update_visuals, inputs=pair_selector, outputs=[price_plot, vol_plot])
100
+ # первичная инициализация при запуске
101
+ demo.load(fn=update_visuals, inputs=None, outputs=[price_plot, vol_plot], _js="() => 'Bitcoin vs Ethereum'")
102
 
103
  # --- Crypto Intelligence Dashboard (Plotly Edition + KPI line) ---
104
  with gr.TabItem("Crypto Intelligence Dashboard"):
 
105
  gr.HTML(f"<style>{crypto_css}</style>")
106
 
 
107
  with gr.Row(elem_id="kpi_row"):
108
  kpi_line = gr.HTML(elem_id="kpi_line")
109
 
 
110
  with gr.Row(elem_id="controls_row"):
111
  top_slider = gr.Slider(
112
  label="Top N coins",
 
118
  )
119
  load_btn = gr.Button("Generate Dashboard", variant="primary", scale=30)
120
 
 
121
  with gr.Row(equal_height=True, elem_id="main_charts_row"):
122
  with gr.Column(scale=70):
123
  treemap_plot = gr.Plot(label="Market Composition")
 
128
  elem_id="ai_summary_sidebar",
129
  )
130
 
 
131
  with gr.Row(equal_height=True, elem_id="bottom_charts_row"):
132
  movers_plot = gr.Plot(label="Top Movers", scale=50)
133
  scatter_plot = gr.Plot(label="Market Cap vs Volume", scale=50)
134
 
 
 
135
  def run_dash(n):
136
  fig_treemap, fig_bar, fig_bubble, ai_comment, kpi_text = build_crypto_dashboard(n)
 
137
  return (
138
  fig_treemap,
139
  fig_bar,
 
142
  f"<div class='kpi-line'>{kpi_text}</div>",
143
  )
144
 
 
145
  load_btn.click(
146
  fn=run_dash,
147
  inputs=top_slider,
 
149
  show_progress="minimal",
150
  )
151
 
152
+ # --- Footer ---
153
  gr.Markdown("---")
154
  gr.Markdown(
155
  "<center><small style='color:#6e7681;'>Developed with Featherless.ai • Powered by OpenAI-compatible API</small></center>",
156
  elem_classes="footer",
157
  )
158
 
159
+ # === Launch ===
160
  if __name__ == "__main__":
161
  demo.launch()