pyroleli commited on
Commit
01fa4a1
·
verified ·
1 Parent(s): fb158f8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +56 -26
app.py CHANGED
@@ -25,77 +25,107 @@ def get_pro_chart(df, forecast_df, ticker):
25
  # Professional Subplots: Price + Indicators
26
  fig = make_subplots(rows=3, cols=1, shared_xaxes=True,
27
  vertical_spacing=0.05, row_heights=[0.5, 0.25, 0.25],
28
- subplot_titles=(f"{ticker} Forecast", "RSI Momentum", "MACD Trend"))
29
 
30
- # 1. Price + Forecast
31
- fig.add_trace(go.Scatter(x=df.index, y=df['Close'], name='Price', line=dict(color='#2962FF')), row=1, col=1)
32
- fig.add_trace(go.Scatter(x=forecast_df['ds'], y=forecast_df['AutoARIMA'], name='AI Forecast', line=dict(color='#F23645')), row=1, col=1)
 
 
 
 
 
 
 
 
 
33
 
34
- # 2. RSI
 
 
 
 
 
 
35
  fig.add_trace(go.Scatter(x=df.index, y=df['RSI'], name='RSI', line=dict(color='#FF9800')), row=2, col=1)
36
  fig.add_hline(y=70, line_dash="dot", line_color="red", row=2, col=1)
37
  fig.add_hline(y=30, line_dash="dot", line_color="green", row=2, col=1)
38
 
39
- # 3. MACD
40
- fig.add_trace(go.Bar(x=df.index, y=df['MACD'] - df['Signal'], name='Momentum'), row=3, col=1)
 
 
 
 
 
 
 
 
 
 
 
 
41
 
42
- fig.update_layout(template='plotly_dark', height=800, showlegend=False, paper_bgcolor='#131722', plot_bgcolor='#131722')
43
  return fig
44
 
45
  def analyze(ticker, horizon):
46
  try:
47
- # Step 1: Data + Analyst Targets
48
  stock = yf.Ticker(ticker)
49
  df = stock.history(period="1y")
50
- if df.empty: return None, "Symbol Error", ""
51
 
52
  info = stock.info
53
  target_high = info.get('targetHighPrice', 'N/A')
54
  current_price = df['Close'].iloc[-1]
55
 
56
- # Step 2: Accuracy Boost via Technicals
57
  df = calculate_indicators(df)
58
 
59
- # Step 3: Fast StatsForecast
60
  data = df.reset_index()[['Date', 'Close']]
61
  data.columns = ['ds', 'y']
62
  data['unique_id'] = ticker
63
 
64
- # Season length 5 = Weekly trading cycle
65
  sf = StatsForecast(models=[AutoARIMA(season_length=5)], freq='B')
66
  sf.fit(data)
 
 
67
  forecast = sf.predict(h=horizon, level=[80])
 
68
 
69
  # Step 4: Signal Analysis
70
  rsi_val = df['RSI'].iloc[-1]
71
- rsi_stat = "OVERSOLD (BUY)" if rsi_val < 30 else "OVERBOUGHT (SELL)" if rsi_val > 70 else "NEUTRAL"
72
 
73
  signal_html = f"""
74
- <div style='background: #1e222d; padding: 15px; border-radius: 10px; color: white;'>
75
- <p>Current Price: <b>${current_price:.2f}</b></p>
76
- <p>Wall St Target: <b style='color:#00ff88;'>${target_high}</b></p>
77
- <hr>
78
- <p>RSI (14d): <b>{rsi_val:.1f} ({rsi_stat})</b></p>
79
- <p>AI 30d Target: <b>${forecast['AutoARIMA'].iloc[-1]:.2f}</b></p>
 
80
  </div>
81
  """
82
 
83
  return get_pro_chart(df, forecast, ticker), signal_html
84
  except Exception as e:
85
- return None, f"Error: {str(e)}"
86
 
87
  # --- UI Layout ---
88
- with gr.Blocks(theme=gr.themes.Soft()) as demo:
89
- gr.Markdown("# 🏛️ INSTITUTIONAL QUANT TERMINAL")
90
  with gr.Row():
91
  with gr.Column(scale=1):
92
- t_in = gr.Textbox(label="Ticker Symbol", value="NVDA")
93
  h_in = gr.Slider(7, 90, value=30, label="Forecast Days")
94
- btn = gr.Button("RUN ANALYSIS", variant="primary")
95
  info_out = gr.HTML()
96
  with gr.Column(scale=4):
97
  plot_out = gr.Plot()
98
 
99
  btn.click(analyze, [t_in, h_in], [plot_out, info_out])
100
 
101
- demo.launch()
 
 
25
  # Professional Subplots: Price + Indicators
26
  fig = make_subplots(rows=3, cols=1, shared_xaxes=True,
27
  vertical_spacing=0.05, row_heights=[0.5, 0.25, 0.25],
28
+ subplot_titles=(f"{ticker} Forecast & Confidence Zone", "RSI Momentum", "MACD Trend"))
29
 
30
+ # --- 1. Price + Forecast + CONFIDENCE ZONE ---
31
+ # Shaded Confidence Area (AutoARIMA-hi-80 and AutoARIMA-lo-80)
32
+ fig.add_trace(go.Scatter(
33
+ x=forecast_df['ds'].tolist() + forecast_df['ds'].tolist()[::-1],
34
+ y=forecast_df['AutoARIMA-hi-80'].tolist() + forecast_df['AutoARIMA-lo-80'].tolist()[::-1],
35
+ fill='toself',
36
+ fillcolor='rgba(0, 210, 255, 0.2)',
37
+ line=dict(color='rgba(255,255,255,0)'),
38
+ hoverinfo="skip",
39
+ showlegend=True,
40
+ name='80% Confidence'
41
+ ), row=1, col=1)
42
 
43
+ # Historical Price
44
+ fig.add_trace(go.Scatter(x=df.index, y=df['Close'], name='Historical Price', line=dict(color='#00d2ff', width=2)), row=1, col=1)
45
+
46
+ # AI Mean Forecast Line
47
+ fig.add_trace(go.Scatter(x=forecast_df['ds'], y=forecast_df['AutoARIMA'], name='AI Target', line=dict(color='#F23645', dash='dot')), row=1, col=1)
48
+
49
+ # --- 2. RSI ---
50
  fig.add_trace(go.Scatter(x=df.index, y=df['RSI'], name='RSI', line=dict(color='#FF9800')), row=2, col=1)
51
  fig.add_hline(y=70, line_dash="dot", line_color="red", row=2, col=1)
52
  fig.add_hline(y=30, line_dash="dot", line_color="green", row=2, col=1)
53
 
54
+ # --- 3. MACD ---
55
+ fig.add_trace(go.Bar(x=df.index, y=df['MACD'] - df['Signal'], name='Momentum', marker_color='#9d50bb'), row=3, col=1)
56
+
57
+ # Styling to match your Aether UI
58
+ fig.update_layout(
59
+ template='plotly_dark',
60
+ height=800,
61
+ showlegend=True,
62
+ paper_bgcolor='rgba(0,0,0,0)', # Transparent to show your terminal background
63
+ plot_bgcolor='rgba(0,0,0,0)',
64
+ font=dict(family="Lato", size=12)
65
+ )
66
+ fig.update_xaxes(showgrid=False, zeroline=False)
67
+ fig.update_yaxes(showgrid=False, zeroline=False)
68
 
 
69
  return fig
70
 
71
  def analyze(ticker, horizon):
72
  try:
73
+ # Step 1: Data
74
  stock = yf.Ticker(ticker)
75
  df = stock.history(period="1y")
76
+ if df.empty: return None, "Symbol Error"
77
 
78
  info = stock.info
79
  target_high = info.get('targetHighPrice', 'N/A')
80
  current_price = df['Close'].iloc[-1]
81
 
82
+ # Step 2: Indicators
83
  df = calculate_indicators(df)
84
 
85
+ # Step 3: StatsForecast with Levels
86
  data = df.reset_index()[['Date', 'Close']]
87
  data.columns = ['ds', 'y']
88
  data['unique_id'] = ticker
89
 
 
90
  sf = StatsForecast(models=[AutoARIMA(season_length=5)], freq='B')
91
  sf.fit(data)
92
+
93
+ # We request 80% level to get the 'lo-80' and 'hi-80' columns
94
  forecast = sf.predict(h=horizon, level=[80])
95
+ forecast = forecast.reset_index()
96
 
97
  # Step 4: Signal Analysis
98
  rsi_val = df['RSI'].iloc[-1]
99
+ rsi_stat = "OVERSOLD" if rsi_val < 30 else "OVERBOUGHT" if rsi_val > 70 else "NEUTRAL"
100
 
101
  signal_html = f"""
102
+ <div style='background: rgba(255,255,255,0.05); padding: 20px; border-radius: 15px; border: 1px solid rgba(255,255,255,0.1); font-family: "Lato", sans-serif;'>
103
+ <p style='margin:0; color:#888; font-size:12px;'>CURRENT VALUE</p>
104
+ <h2 style='margin:0; color:#00d2ff;'>${current_price:.2f}</h2>
105
+ <hr style='border:0; border-top:1px solid #333; margin:15px 0;'>
106
+ <p>RSI Analysis: <b style='color:#FF9800;'>{rsi_stat} ({rsi_val:.1f})</b></p>
107
+ <p>AI Forecast ({horizon}d): <b style='color:#F23645;'>${forecast['AutoARIMA'].iloc[-1]:.2f}</b></p>
108
+ <p style='font-size:11px; color:#555;'>Confidence Zone: ${forecast['AutoARIMA-lo-80'].iloc[-1]:.2f} - ${forecast['AutoARIMA-hi-80'].iloc[-1]:.2f}</p>
109
  </div>
110
  """
111
 
112
  return get_pro_chart(df, forecast, ticker), signal_html
113
  except Exception as e:
114
+ return None, f"<p style='color:red;'>Error: {str(e)}</p>"
115
 
116
  # --- UI Layout ---
117
+ with gr.Blocks(theme=gr.themes.Default(primary_hue="blue", secondary_hue="slate")) as demo:
118
+ gr.Markdown("<h1 style='text-align: center; letter-spacing: 5px;'>AETHER BACKEND ENGINE</h1>")
119
  with gr.Row():
120
  with gr.Column(scale=1):
121
+ t_in = gr.Textbox(label="Ticker", value="NVDA")
122
  h_in = gr.Slider(7, 90, value=30, label="Forecast Days")
123
+ btn = gr.Button("UPDATE ENGINE", variant="primary")
124
  info_out = gr.HTML()
125
  with gr.Column(scale=4):
126
  plot_out = gr.Plot()
127
 
128
  btn.click(analyze, [t_in, h_in], [plot_out, info_out])
129
 
130
+ if __name__ == "__main__":
131
+ demo.launch()