omniverse1 commited on
Commit
8dcd0a1
ยท
verified ยท
1 Parent(s): daab9d7

Update Gradio app with multiple files

Browse files
Files changed (3) hide show
  1. app.py +252 -37
  2. requirements.txt +1 -1
  3. utils.py +1 -1
app.py CHANGED
@@ -123,10 +123,33 @@ def update_analysis(symbol, prediction_days):
123
  # Gradio secara otomatis akan menata elemen-elemen ini dengan lebih standar
124
  return (
125
  f"""
126
- <div style="display: flex; flex-direction: row; gap: 16px;">
127
- <div style="flex: 1; min-width: 30%; border: 1px solid #ccc; padding: 10px; border-radius: 5px;">{fundamentals}</div>
128
- <div style="flex: 1; min-width: 30%; border: 1px solid #ccc; padding: 10px; border-radius: 5px;">{trading_signal}</div>
129
- <div style="flex: 1; min-width: 30%; border: 1px solid #ccc; padding: 10px; border-radius: 5px;">{prediction}</div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  </div>
131
  """,
132
  fig_price,
@@ -135,51 +158,243 @@ def update_analysis(symbol, prediction_days):
135
  )
136
 
137
 
138
- # --- Perubahan utama di sini ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
  with gr.Blocks(
140
- title="REXPRO FINANCIAL AI DASHBOARD"
141
- # Parameter theme dan css dihapus untuk kembali ke default Gradio
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  ) as app:
143
- gr.Markdown("# REXPRO FINANCIAL AI DASHBOARD")
144
- gr.Markdown(
145
- "Comprehensive stock analytics powered by **AI forecasting and technical analysis.**"
146
- )
147
-
 
 
 
 
 
 
 
 
 
 
148
  with gr.Row():
149
- symbol = gr.Textbox(
150
- label="STOCK SYMBOL (IDX)",
151
- value="BBCA",
152
- placeholder="Example: BBCA, TLKM, ADRO, BMRI",
153
- interactive=True,
154
- )
155
- prediction_days = gr.Slider(
156
- label="FORECAST PERIOD (DAYS)",
157
- minimum=5,
158
- maximum=60,
159
- step=5,
160
- value=30,
161
- interactive=True,
162
  )
163
- analyze_button = gr.Button("RUN ANALYSIS")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
 
165
- gr.Markdown("---")
166
- # Bagian report_section diubah agar lebih kompatibel dengan tema default,
167
- # menggunakan sedikit inline CSS untuk meniru tata letak tiga kolom dasar.
168
- report_section = gr.HTML()
169
- gr.Markdown("---")
170
-
171
- with gr.Tab("MARKET CHARTS"):
172
  with gr.Row():
173
- price_chart = gr.Plot(label="PRICE & MOVING AVERAGES")
174
- technical_chart = gr.Plot(label="TECHNICAL INDICATORS OVERVIEW")
175
- gr.Markdown("---")
176
- prediction_chart = gr.Plot(label="AI FORECAST PROJECTION")
177
 
178
  analyze_button.click(
179
  fn=update_analysis,
180
  inputs=[symbol, prediction_days],
181
  outputs=[report_section, price_chart, technical_chart, prediction_chart],
182
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
 
184
  if __name__ == "__main__":
185
  app.launch(server_name="0.0.0.0", server_port=7860, ssr_mode=True)
 
123
  # Gradio secara otomatis akan menata elemen-elemen ini dengan lebih standar
124
  return (
125
  f"""
126
+ <div class="panel-card" style="background: rgba(255,255,255,0.1); backdrop-filter: blur(10px); border: 1px solid rgba(255,255,255,0.2); border-radius: 15px; padding: 0; overflow: hidden;">
127
+ <div style="display: flex; flex-direction: row; gap: 0; height: auto;">
128
+ <div style="flex: 1; min-width: 30%; padding: 20px; border-right: 1px solid rgba(255,255,255,0.1);">
129
+ <div style="margin-bottom: 15px;">
130
+ <h3 style="margin: 0; font-size: 1.1rem; font-weight: 600; color: #4fc3f7;">๐Ÿข COMPANY FUNDAMENTALS</h3>
131
+ </div>
132
+ <div style="line-height: 1.8; font-size: 0.95rem;">
133
+ {fundamentals.replace('<h4>COMPANY FUNDAMENTALS</h4>', '').replace('<br>', '<br>')}
134
+ </div>
135
+ </div>
136
+ <div style="flex: 1; min-width: 30%; padding: 20px; border-right: 1px solid rgba(255,255,255,0.1);">
137
+ <div style="margin-bottom: 15px;">
138
+ <h3 style="margin: 0; font-size: 1.1rem; font-weight: 600; color: #81c784;">๐Ÿ“Š TECHNICAL SIGNAL SUMMARY</h3>
139
+ </div>
140
+ <div style="line-height: 1.8; font-size: 0.95rem;">
141
+ {trading_signal.replace('<h4>TECHNICAL SIGNAL SUMMARY</h4>', '').replace('<br>', '<br>').replace('<ul style="margin-top: 8px; padding-left: 20px; line-height: 1.6;">', '<ul style="margin-top: 8px; padding-left: 20px; line-height: 1.4; font-size: 0.9rem;">')}
142
+ </div>
143
+ </div>
144
+ <div style="flex: 1; min-width: 30%; padding: 20px;">
145
+ <div style="margin-bottom: 15px;">
146
+ <h3 style="margin: 0; font-size: 1.1rem; font-weight: 600; color: #ffb74d;">๐Ÿค– AI FORECAST INSIGHTS</h3>
147
+ </div>
148
+ <div style="line-height: 1.8; font-size: 0.95rem;">
149
+ {prediction.replace('<h4>30-DAY AI FORECAST (CHRONOS-BOLT)</h4>', '').replace('<br>', '<br>')}
150
+ </div>
151
+ </div>
152
+ </div>
153
  </div>
154
  """,
155
  fig_price,
 
158
  )
159
 
160
 
161
+ # Theme management
162
+ theme_state = gr.State(value="light")
163
+
164
+ def toggle_theme(current_theme):
165
+ return "dark" if current_theme == "light" else "light"
166
+
167
+ def get_theme_css(theme):
168
+ if theme == "dark":
169
+ return """
170
+ <style>
171
+ body { background-color: #1a1a1a; color: #ffffff; }
172
+ .main-container { background-color: #2a2a2a !important; }
173
+ .panel-modern {
174
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
175
+ color: white !important;
176
+ border-radius: 15px !important;
177
+ padding: 20px !important;
178
+ margin: 10px !important;
179
+ box-shadow: 0 10px 30px rgba(0,0,0,0.3) !important;
180
+ }
181
+ .panel-card {
182
+ background: rgba(255,255,255,0.05) !important;
183
+ backdrop-filter: blur(10px) !important;
184
+ border: 1px solid rgba(255,255,255,0.1) !important;
185
+ border-radius: 12px !important;
186
+ padding: 16px !important;
187
+ margin: 8px !important;
188
+ transition: all 0.3s ease !important;
189
+ }
190
+ .panel-card:hover {
191
+ transform: translateY(-2px) !important;
192
+ box-shadow: 0 8px 25px rgba(0,0,0,0.4) !important;
193
+ }
194
+ .header-gradient {
195
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
196
+ -webkit-background-clip: text !important;
197
+ -webkit-text-fill-color: transparent !important;
198
+ background-clip: text !important;
199
+ }
200
+ .theme-toggle {
201
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
202
+ border: none !important;
203
+ border-radius: 25px !important;
204
+ padding: 12px 20px !important;
205
+ color: white !important;
206
+ font-weight: bold !important;
207
+ box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4) !important;
208
+ transition: all 0.3s ease !important;
209
+ }
210
+ .theme-toggle:hover {
211
+ transform: translateY(-2px) !important;
212
+ box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6) !important;
213
+ }
214
+ .input-modern {
215
+ background: rgba(255,255,255,0.05) !important;
216
+ border: 1px solid rgba(255,255,255,0.1) !important;
217
+ border-radius: 10px !important;
218
+ color: white !important;
219
+ }
220
+ .tab-content {
221
+ background: rgba(255,255,255,0.02) !important;
222
+ border-radius: 12px !important;
223
+ padding: 20px !important;
224
+ }
225
+ </style>
226
+ """
227
+ else:
228
+ return """
229
+ <style>
230
+ body { background-color: #f8fafc; color: #1a202c; }
231
+ .main-container { background-color: #ffffff !important; }
232
+ .panel-modern {
233
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
234
+ color: white !important;
235
+ border-radius: 15px !important;
236
+ padding: 20px !important;
237
+ margin: 10px !important;
238
+ box-shadow: 0 10px 30px rgba(0,0,0,0.1) !important;
239
+ }
240
+ .panel-card {
241
+ background: rgba(255,255,255,0.9) !important;
242
+ backdrop-filter: blur(10px) !important;
243
+ border: 1px solid rgba(0,0,0,0.05) !important;
244
+ border-radius: 12px !important;
245
+ padding: 16px !important;
246
+ margin: 8px !important;
247
+ transition: all 0.3s ease !important;
248
+ }
249
+ .panel-card:hover {
250
+ transform: translateY(-2px) !important;
251
+ box-shadow: 0 8px 25px rgba(0,0,0,0.15) !important;
252
+ }
253
+ .header-gradient {
254
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
255
+ -webkit-background-clip: text !important;
256
+ -webkit-text-fill-color: transparent !important;
257
+ background-clip: text !important;
258
+ }
259
+ .theme-toggle {
260
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
261
+ border: none !important;
262
+ border-radius: 25px !important;
263
+ padding: 12px 20px !important;
264
+ color: white !important;
265
+ font-weight: bold !important;
266
+ box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4) !important;
267
+ transition: all 0.3s ease !important;
268
+ }
269
+ .theme-toggle:hover {
270
+ transform: translateY(-2px) !important;
271
+ box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6) !important;
272
+ }
273
+ .input-modern {
274
+ background: rgba(255,255,255,0.9) !important;
275
+ border: 1px solid rgba(0,0,0,0.1) !important;
276
+ border-radius: 10px !important;
277
+ }
278
+ .tab-content {
279
+ background: rgba(255,255,255,0.7) !important;
280
+ border-radius: 12px !important;
281
+ padding: 20px !important;
282
+ }
283
+ </style>
284
+ """
285
+
286
+ # --- Modern UI Redesign ---
287
  with gr.Blocks(
288
+ title="REXPRO FINANCIAL AI DASHBOARD",
289
+ css="""
290
+ .main-container {
291
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
292
+ max-width: 1400px;
293
+ margin: 0 auto;
294
+ padding: 20px;
295
+ }
296
+ .header-section {
297
+ text-align: center;
298
+ padding: 30px 0;
299
+ margin-bottom: 30px;
300
+ }
301
+ .control-panel {
302
+ background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
303
+ border-radius: 20px;
304
+ padding: 25px;
305
+ margin-bottom: 30px;
306
+ box-shadow: 0 8px 32px rgba(0,0,0,0.1);
307
+ }
308
+ """,
309
+ elem_classes=["main-container"]
310
  ) as app:
311
+
312
+ # Header Section
313
+ with gr.Row(elem_classes=["header-section"]):
314
+ gr.HTML("""
315
+ <div class="header-gradient">
316
+ <h1 style="font-size: 2.5rem; margin: 0; font-weight: 800;">
317
+ ๐Ÿš€ REXPRO FINANCIAL AI DASHBOARD
318
+ </h1>
319
+ <p style="font-size: 1.2rem; margin: 10px 0 0 0; opacity: 0.8;">
320
+ Comprehensive stock analytics powered by <strong>AI forecasting and technical analysis</strong>
321
+ </p>
322
+ </div>
323
+ """)
324
+
325
+ # Theme toggle
326
  with gr.Row():
327
+ theme_toggle = gr.Button(
328
+ "๐ŸŒ™ Switch to Dark Mode" if gr.load else "โ˜€๏ธ Switch to Light Mode",
329
+ variant="primary",
330
+ size="sm",
331
+ elem_classes=["theme-toggle"]
 
 
 
 
 
 
 
 
332
  )
333
+
334
+ # Control Panel
335
+ with gr.Row(elem_classes=["control-panel"]):
336
+ with gr.Column(scale=2):
337
+ symbol = gr.Textbox(
338
+ label="๐Ÿ“ˆ STOCK SYMBOL (IDX)",
339
+ value="BBCA",
340
+ placeholder="Example: BBCA, TLKM, ADRO, BMRI",
341
+ interactive=True,
342
+ elem_classes=["input-modern"]
343
+ )
344
+ with gr.Column(scale=1):
345
+ prediction_days = gr.Slider(
346
+ label="๐Ÿ”ฎ FORECAST PERIOD (DAYS)",
347
+ minimum=5,
348
+ maximum=60,
349
+ step=5,
350
+ value=30,
351
+ interactive=True,
352
+ elem_classes=["input-modern"]
353
+ )
354
+ with gr.Column(scale=1):
355
+ analyze_button = gr.Button(
356
+ "โšก RUN ANALYSIS",
357
+ variant="primary",
358
+ size="lg",
359
+ elem_classes=["theme-toggle"]
360
+ )
361
+
362
+ # Modern theme-aware CSS
363
+ theme_css = gr.HTML("")
364
+
365
+ gr.HTML('<div style="height: 20px;"></div>')
366
+
367
+ # Enhanced report section with modern styling
368
+ report_section = gr.HTML(elem_classes=["panel-modern"])
369
+
370
+ gr.HTML('<div style="height: 20px;"></div>')
371
 
372
+ with gr.Tab("๐Ÿ“Š MARKET CHARTS", elem_classes=["tab-content"]):
 
 
 
 
 
 
373
  with gr.Row():
374
+ price_chart = gr.Plot(label="๐Ÿ’น PRICE & MOVING AVERAGES", elem_classes=["panel-card"])
375
+ technical_chart = gr.Plot(label="๐Ÿ“ˆ TECHNICAL INDICATORS OVERVIEW", elem_classes=["panel-card"])
376
+ gr.HTML('<div style="height: 20px;"></div>')
377
+ prediction_chart = gr.Plot(label="๐Ÿค– AI FORECAST PROJECTION", elem_classes=["panel-card"])
378
 
379
  analyze_button.click(
380
  fn=update_analysis,
381
  inputs=[symbol, prediction_days],
382
  outputs=[report_section, price_chart, technical_chart, prediction_chart],
383
  )
384
+
385
+ # Theme toggle functionality
386
+ theme_toggle.click(
387
+ fn=lambda x: toggle_theme(x),
388
+ inputs=[theme_state],
389
+ outputs=[theme_state]
390
+ )
391
+
392
+ # Update theme CSS when theme changes
393
+ theme_state.change(
394
+ fn=get_theme_css,
395
+ inputs=[theme_state],
396
+ outputs=[theme_css]
397
+ )
398
 
399
  if __name__ == "__main__":
400
  app.launch(server_name="0.0.0.0", server_port=7860, ssr_mode=True)
requirements.txt CHANGED
@@ -9,4 +9,4 @@ spaces>=0.20.0
9
  accelerate>=0.20.0
10
  tiktoken
11
  sentencepiece
12
- chronos-forecasting
 
9
  accelerate>=0.20.0
10
  tiktoken
11
  sentencepiece
12
+ chronos-forecasting
utils.py CHANGED
@@ -214,4 +214,4 @@ def create_technical_chart(data, indicators):
214
  fig.add_hline(y=70, line_dash="dash", line_color="red", row=2, col=2)
215
  fig.add_hline(y=30, line_dash="dash", line_color="green", row=2, col=2)
216
  fig.update_layout(title='Technical Indicators Overview', height=800, showlegend=False, hovermode='x unified')
217
- return fig
 
214
  fig.add_hline(y=70, line_dash="dash", line_color="red", row=2, col=2)
215
  fig.add_hline(y=30, line_dash="dash", line_color="green", row=2, col=2)
216
  fig.update_layout(title='Technical Indicators Overview', height=800, showlegend=False, hovermode='x unified')
217
+ return fig