deveshc23 commited on
Commit
068cd22
·
verified ·
1 Parent(s): 867371b

Upload app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +63 -27
app.py CHANGED
@@ -149,6 +149,22 @@ def refresh_market_data(tickers_str: str, period: str = "1y"):
149
  return tickers
150
 
151
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
  # -----------------------------------------------------------------------------
153
  # Visual Component Builders (Continuous Marquee & Cyber HUDs)
154
  # -----------------------------------------------------------------------------
@@ -410,7 +426,22 @@ def plot_stock_candle(
410
  STATE["market_data"][cache_key] = df
411
  df = STATE["market_data"][cache_key]
412
 
413
- dates = list(df.index)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
414
 
415
  # 4 rows: Price (52%), Volume (16%), RSI (16%), MACD (16%)
416
  fig = make_subplots(
@@ -421,67 +452,67 @@ def plot_stock_candle(
421
 
422
  # 1. Candlestick
423
  fig.add_trace(go.Candlestick(
424
- x=dates, open=df['open'], high=df['high'], low=df['low'], close=df['close'],
425
  name="OHLC", increasing_line_color='#00ff87', decreasing_line_color='#ff3366', showlegend=False
426
  ), row=1, col=1)
427
 
428
  # Overlays: SMA 20 & SMA 50
429
  if "SMA 20 & SMA 50" in overlays:
430
- if 'sma20' in df:
431
  fig.add_trace(go.Scatter(
432
- x=dates, y=df['sma20'], line=dict(color='#ffb703', width=1.5), name="SMA 20"
433
  ), row=1, col=1)
434
- if 'sma50' in df:
435
  fig.add_trace(go.Scatter(
436
- x=dates, y=df['sma50'], line=dict(color='#00f2fe', width=1.5), name="SMA 50"
437
  ), row=1, col=1)
438
 
439
  # Overlays: Bollinger Bands
440
- if "Bollinger Bands (20, 2σ)" in overlays and 'bb_upper' in df and 'bb_lower' in df:
441
  fig.add_trace(go.Scatter(
442
- x=dates, y=df['bb_upper'], line=dict(color='rgba(0, 242, 254, 0.35)', width=1), showlegend=False
443
  ), row=1, col=1)
444
  fig.add_trace(go.Scatter(
445
- x=dates, y=df['bb_lower'], line=dict(color='rgba(0, 242, 254, 0.35)', width=1),
446
  fill='tonexty', fillcolor='rgba(0, 242, 254, 0.05)', showlegend=False
447
  ), row=1, col=1)
448
 
449
  # Overlays: VWAP
450
- if "VWAP" in overlays and 'vwap' in df:
451
  fig.add_trace(go.Scatter(
452
- x=dates, y=df['vwap'], line=dict(color='#d500f9', width=1.2, dash='dash'), name="VWAP"
453
  ), row=1, col=1)
454
 
455
  # 2. Volume
456
- vol_colors = ['#00ff87' if c >= o else '#ff3366' for c, o in zip(df['close'], df['open'])]
457
  fig.add_trace(go.Bar(
458
- x=dates, y=df['volume'], marker_color=vol_colors, name="Volume", showlegend=False
459
  ), row=2, col=1)
460
  if "Volume + 20D MA" in overlays:
461
- vol_ma = df['volume'].rolling(20, min_periods=1).mean()
462
  fig.add_trace(go.Scatter(
463
  x=dates, y=vol_ma, line=dict(color='#00f2fe', width=1.2), name="Vol MA20", showlegend=False
464
  ), row=2, col=1)
465
 
466
  # 3. RSI (14)
467
- if 'rsi' in df:
468
  fig.add_trace(go.Scatter(
469
- x=dates, y=df['rsi'], line=dict(color='#00f2fe', width=1.5), name="RSI(14)", showlegend=False
470
  ), row=3, col=1)
471
  fig.add_hline(y=70, line_dash='dot', line_color='#ff3366', line_width=1, row=3, col=1)
472
  fig.add_hline(y=30, line_dash='dot', line_color='#00ff87', line_width=1, row=3, col=1)
473
 
474
  # 4. MACD
475
- if 'macd_line' in df and 'macd_signal' in df and 'macd_hist' in df:
476
  fig.add_trace(go.Scatter(
477
- x=dates, y=df['macd_line'], line=dict(color='#00f2fe', width=1.2), name="MACD", showlegend=False
478
  ), row=4, col=1)
479
  fig.add_trace(go.Scatter(
480
- x=dates, y=df['macd_signal'], line=dict(color='#ffb703', width=1.2), name="Signal", showlegend=False
481
  ), row=4, col=1)
482
- macd_colors = ['#00ff87' if h >= 0 else '#ff3366' for h in df['macd_hist']]
483
  fig.add_trace(go.Bar(
484
- x=dates, y=df['macd_hist'], marker_color=macd_colors, name="Histogram", showlegend=False
485
  ), row=4, col=1)
486
 
487
  # Watermark Badges (Zero-collision top-left annotations)
@@ -524,7 +555,7 @@ def plot_stock_candle(
524
  )
525
 
526
  # X-Axes: Robust Category Axis with evenly spaced horizontal tick labels (No weekend gaps, zero collapse)
527
- tick_indices = np.linspace(0, len(dates)-1, min(8, len(dates)), dtype=int)
528
  tickvals = [dates[i] for i in tick_indices]
529
 
530
  fig.update_xaxes(
@@ -550,6 +581,7 @@ def plot_stock_candle(
550
  tickfont=dict(family='JetBrains Mono', size=10, color='#94a3b8'),
551
  row=r, col=1
552
  )
 
553
 
554
  kpi_card = generate_kpi_card_html(ticker)
555
  return fig, kpi_card
@@ -563,6 +595,7 @@ def plot_backtest_cumulative(record: dict) -> go.Figure:
563
  )
564
  days = 252
565
  dates = pd.date_range(end=pd.Timestamp.now(), periods=days, freq='B')
 
566
  ann_ret = record.get("annualized_return_pct", 15.0) / 100.0
567
  sharpe = record.get("sharpe", 1.5)
568
  vol = abs(ann_ret / sharpe) if sharpe != 0 else 0.15
@@ -573,12 +606,15 @@ def plot_backtest_cumulative(record: dict) -> go.Figure:
573
  rolling_max = np.maximum.accumulate(cum_ret)
574
  dd = (cum_ret - rolling_max) / rolling_max
575
 
 
 
 
576
  fig.add_trace(go.Scatter(
577
- x=dates, y=cum_ret, line=dict(color='#00ff87', width=2), name="Strategy Equity"
578
  ), row=1, col=1)
579
 
580
  fig.add_trace(go.Scatter(
581
- x=dates, y=dd * 100, fill='tozeroy', line=dict(color='#ff3366', width=1), name="Drawdown %"
582
  ), row=2, col=1)
583
 
584
  fig.add_annotation(
@@ -646,7 +682,7 @@ def plot_factor_quantiles(record: dict) -> go.Figure:
646
  def plot_portfolio_allocation(weights: dict) -> go.Figure:
647
  """Plots interactive donut chart of optimized asset allocation."""
648
  labels = list(weights.keys())
649
- values = [w * 100 for w in weights.values()]
650
 
651
  fig = go.Figure(data=[go.Pie(
652
  labels=labels, values=values, hole=0.52,
@@ -734,8 +770,8 @@ def handle_train_xgboost():
734
  """
735
  importances = res.get("feature_importances", {})
736
  fig = go.Figure(data=[go.Bar(
737
- x=list(importances.keys()),
738
- y=list(importances.values()),
739
  marker_color='#00f2fe'
740
  )])
741
  fig.update_layout(
 
149
  return tickers
150
 
151
 
152
+ # -----------------------------------------------------------------------------
153
+ # Clean Data Normalizer for Gradio / Plotly Web Serialization
154
+ # (Prevents numpy arrays from serializing as bdata binary buffers in Gradio)
155
+ # -----------------------------------------------------------------------------
156
+ def to_clean_list(series, default_val=None):
157
+ if series is None:
158
+ return []
159
+ out = []
160
+ for val in series:
161
+ if val is None or pd.isna(val) or (isinstance(val, (int, float)) and np.isnan(val)):
162
+ out.append(default_val)
163
+ else:
164
+ out.append(round(float(val), 4))
165
+ return out
166
+
167
+
168
  # -----------------------------------------------------------------------------
169
  # Visual Component Builders (Continuous Marquee & Cyber HUDs)
170
  # -----------------------------------------------------------------------------
 
426
  STATE["market_data"][cache_key] = df
427
  df = STATE["market_data"][cache_key]
428
 
429
+ dates = [str(d)[:10] for d in df.index]
430
+
431
+ open_vals = to_clean_list(df['open'])
432
+ high_vals = to_clean_list(df['high'])
433
+ low_vals = to_clean_list(df['low'])
434
+ close_vals = to_clean_list(df['close'])
435
+ vol_vals = to_clean_list(df['volume'], 0.0)
436
+ sma20_vals = to_clean_list(df['sma20']) if 'sma20' in df else []
437
+ sma50_vals = to_clean_list(df['sma50']) if 'sma50' in df else []
438
+ bb_u = to_clean_list(df['bb_upper']) if 'bb_upper' in df else []
439
+ bb_l = to_clean_list(df['bb_lower']) if 'bb_lower' in df else []
440
+ vwap_vals = to_clean_list(df['vwap']) if 'vwap' in df else []
441
+ rsi_vals = to_clean_list(df['rsi'], 50.0) if 'rsi' in df else []
442
+ macd_vals = to_clean_list(df['macd_line'], 0.0) if 'macd_line' in df else []
443
+ sig_vals = to_clean_list(df['macd_signal'], 0.0) if 'macd_signal' in df else []
444
+ hist_vals = to_clean_list(df['macd_hist'], 0.0) if 'macd_hist' in df else []
445
 
446
  # 4 rows: Price (52%), Volume (16%), RSI (16%), MACD (16%)
447
  fig = make_subplots(
 
452
 
453
  # 1. Candlestick
454
  fig.add_trace(go.Candlestick(
455
+ x=dates, open=open_vals, high=high_vals, low=low_vals, close=close_vals,
456
  name="OHLC", increasing_line_color='#00ff87', decreasing_line_color='#ff3366', showlegend=False
457
  ), row=1, col=1)
458
 
459
  # Overlays: SMA 20 & SMA 50
460
  if "SMA 20 & SMA 50" in overlays:
461
+ if sma20_vals:
462
  fig.add_trace(go.Scatter(
463
+ x=dates, y=sma20_vals, line=dict(color='#ffb703', width=1.5), name="SMA 20"
464
  ), row=1, col=1)
465
+ if sma50_vals:
466
  fig.add_trace(go.Scatter(
467
+ x=dates, y=sma50_vals, line=dict(color='#00f2fe', width=1.5), name="SMA 50"
468
  ), row=1, col=1)
469
 
470
  # Overlays: Bollinger Bands
471
+ if "Bollinger Bands (20, 2σ)" in overlays and bb_u and bb_l:
472
  fig.add_trace(go.Scatter(
473
+ x=dates, y=bb_u, line=dict(color='rgba(0, 242, 254, 0.35)', width=1), showlegend=False
474
  ), row=1, col=1)
475
  fig.add_trace(go.Scatter(
476
+ x=dates, y=bb_l, line=dict(color='rgba(0, 242, 254, 0.35)', width=1),
477
  fill='tonexty', fillcolor='rgba(0, 242, 254, 0.05)', showlegend=False
478
  ), row=1, col=1)
479
 
480
  # Overlays: VWAP
481
+ if "VWAP" in overlays and vwap_vals:
482
  fig.add_trace(go.Scatter(
483
+ x=dates, y=vwap_vals, line=dict(color='#d500f9', width=1.2, dash='dash'), name="VWAP"
484
  ), row=1, col=1)
485
 
486
  # 2. Volume
487
+ vol_colors = ['#00ff87' if (c or 0) >= (o or 0) else '#ff3366' for c, o in zip(close_vals, open_vals)]
488
  fig.add_trace(go.Bar(
489
+ x=dates, y=vol_vals, marker_color=vol_colors, name="Volume", showlegend=False
490
  ), row=2, col=1)
491
  if "Volume + 20D MA" in overlays:
492
+ vol_ma = to_clean_list(df['volume'].rolling(20, min_periods=1).mean(), 0.0)
493
  fig.add_trace(go.Scatter(
494
  x=dates, y=vol_ma, line=dict(color='#00f2fe', width=1.2), name="Vol MA20", showlegend=False
495
  ), row=2, col=1)
496
 
497
  # 3. RSI (14)
498
+ if rsi_vals:
499
  fig.add_trace(go.Scatter(
500
+ x=dates, y=rsi_vals, line=dict(color='#00f2fe', width=1.5), name="RSI(14)", showlegend=False
501
  ), row=3, col=1)
502
  fig.add_hline(y=70, line_dash='dot', line_color='#ff3366', line_width=1, row=3, col=1)
503
  fig.add_hline(y=30, line_dash='dot', line_color='#00ff87', line_width=1, row=3, col=1)
504
 
505
  # 4. MACD
506
+ if macd_vals and sig_vals and hist_vals:
507
  fig.add_trace(go.Scatter(
508
+ x=dates, y=macd_vals, line=dict(color='#00f2fe', width=1.2), name="MACD", showlegend=False
509
  ), row=4, col=1)
510
  fig.add_trace(go.Scatter(
511
+ x=dates, y=sig_vals, line=dict(color='#ffb703', width=1.2), name="Signal", showlegend=False
512
  ), row=4, col=1)
513
+ macd_colors = ['#00ff87' if (h or 0) >= 0 else '#ff3366' for h in hist_vals]
514
  fig.add_trace(go.Bar(
515
+ x=dates, y=hist_vals, marker_color=macd_colors, name="Histogram", showlegend=False
516
  ), row=4, col=1)
517
 
518
  # Watermark Badges (Zero-collision top-left annotations)
 
555
  )
556
 
557
  # X-Axes: Robust Category Axis with evenly spaced horizontal tick labels (No weekend gaps, zero collapse)
558
+ tick_indices = [int(i) for i in np.linspace(0, len(dates)-1, min(8, len(dates)), dtype=int)]
559
  tickvals = [dates[i] for i in tick_indices]
560
 
561
  fig.update_xaxes(
 
581
  tickfont=dict(family='JetBrains Mono', size=10, color='#94a3b8'),
582
  row=r, col=1
583
  )
584
+ fig.update_yaxes(range=[0, 100], row=3, col=1)
585
 
586
  kpi_card = generate_kpi_card_html(ticker)
587
  return fig, kpi_card
 
595
  )
596
  days = 252
597
  dates = pd.date_range(end=pd.Timestamp.now(), periods=days, freq='B')
598
+ date_strs = [d.strftime('%Y-%m-%d') for d in dates]
599
  ann_ret = record.get("annualized_return_pct", 15.0) / 100.0
600
  sharpe = record.get("sharpe", 1.5)
601
  vol = abs(ann_ret / sharpe) if sharpe != 0 else 0.15
 
606
  rolling_max = np.maximum.accumulate(cum_ret)
607
  dd = (cum_ret - rolling_max) / rolling_max
608
 
609
+ cum_ret_clean = [round(float(v), 4) for v in cum_ret]
610
+ dd_clean = [round(float(v * 100), 2) for v in dd]
611
+
612
  fig.add_trace(go.Scatter(
613
+ x=date_strs, y=cum_ret_clean, line=dict(color='#00ff87', width=2), name="Strategy Equity"
614
  ), row=1, col=1)
615
 
616
  fig.add_trace(go.Scatter(
617
+ x=date_strs, y=dd_clean, fill='tozeroy', line=dict(color='#ff3366', width=1), name="Drawdown %"
618
  ), row=2, col=1)
619
 
620
  fig.add_annotation(
 
682
  def plot_portfolio_allocation(weights: dict) -> go.Figure:
683
  """Plots interactive donut chart of optimized asset allocation."""
684
  labels = list(weights.keys())
685
+ values = [round(float(w * 100), 2) for w in weights.values()]
686
 
687
  fig = go.Figure(data=[go.Pie(
688
  labels=labels, values=values, hole=0.52,
 
770
  """
771
  importances = res.get("feature_importances", {})
772
  fig = go.Figure(data=[go.Bar(
773
+ x=[str(k) for k in importances.keys()],
774
+ y=[round(float(v), 4) for v in importances.values()],
775
  marker_color='#00f2fe'
776
  )])
777
  fig.update_layout(