IDX-Chronos-API / app.py
omniverse1's picture
Update app.py
380e150 verified
raw
history blame
4.77 kB
import gradio as gr
import yfinance as yf
from utils import (
calculate_technical_indicators,
generate_trading_signals,
get_fundamental_data,
create_price_chart,
create_technical_chart,
create_prediction_chart,
predict_prices,
)
import pandas as pd
def analyze_stock(symbol, mode, pred_days):
try:
stock = yf.Ticker(symbol)
data = stock.history(period="1y")
if data.empty:
return "No data found", None, None, None
indicators = calculate_technical_indicators(data)
signals = generate_trading_signals(data, indicators)
fundamentals = get_fundamental_data(stock)
fig_price = create_price_chart(data, indicators)
fig_technical = create_technical_chart(data, indicators)
if mode == "AI Prediction":
prediction = predict_prices(data, prediction_days=pred_days)
fig_prediction = create_prediction_chart(data, prediction)
return fundamentals, signals, fig_price, fig_technical, fig_prediction, prediction
else:
return fundamentals, signals, fig_price, fig_technical, None, None
except Exception as e:
return f"Error analyzing {symbol}: {e}", None, None, None, None, None
def format_fundamental_output(f):
return f"""
<h3>COMPANY FUNDAMENTALS</h3>
<b>Name:</b> {f['name']}<br>
<b>Current Price:</b> Rp{f['current_price']:,.2f}<br>
<b>Market Cap:</b> {f['market_cap']:,}<br>
<b>P/E Ratio:</b> {f['pe_ratio']:.2f}<br>
<b>Dividend Yield:</b> {f['dividend_yield']:.2f}%<br>
<b>Volume:</b> {f['volume']:,}<br>
"""
def format_signal_output(s):
details = s["details"].split("\n")
formatted_details = "<ul>" + "".join(f"<li>{d}</li>" for d in details) + "</ul>"
return f"""
<h3>TECHNICAL SIGNAL SUMMARY</h3>
<b>Overall Trend:</b> {s['overall']}<br>
<b>Signal Strength:</b> {s['strength']:.2f}%<br>
<b>Support:</b> Rp{s['support']:,.2f}<br>
<b>Resistance:</b> Rp{s['resistance']:,.2f}<br>
<b>Stop Loss:</b> Rp{s['stop_loss']:,.2f}<br>
<br><b>Detailed Signals:</b>{formatted_details}
"""
def format_ai_output(p):
if not p:
return ""
tp1 = p["mean_30d"] * 0.97
tp2 = p["mean_30d"] * 1.02
sl = p["low_30d"] * 0.95
return f"""
<h3>30-DAY AI FORECAST (CHRONOS-BOLT)</h3>
<b>Predicted High:</b> Rp{p['high_30d']:,.2f}<br>
<b>Predicted Low:</b> Rp{p['low_30d']:,.2f}<br>
<b>Expected Change:</b> {p['change_pct']:.2f}%<br><br>
<b>TP1:</b> Rp{tp1:,.2f}<br>
<b>TP2:</b> Rp{tp2:,.2f}<br>
<b>Stop Loss:</b> Rp{sl:,.2f}<br><br>
<b>Model Insight:</b><br>{p['summary']}
"""
with gr.Blocks(css="""
body { font-family: 'Inter', sans-serif; background-color: #f9fafc; color: #222; }
.gradio-container { max-width: 1200px; margin: auto; }
h3 { color: #003366; border-bottom: 2px solid #d3d3d3; padding-bottom: 5px; }
.panel-box { background: white; padding: 20px; border-radius: 10px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }
""") as demo:
gr.HTML("<h1 style='text-align:center;color:#003366;'>📈 STOCK ANALYSIS DASHBOARD</h1>")
with gr.Row():
stock_input = gr.Textbox(label="Enter Stock Symbol (e.g. BBCA.JK, ADRO.JK)", placeholder="Type your stock symbol here...")
mode_input = gr.Radio(["Technical Analysis", "AI Prediction"], label="Select Analysis Mode", value="Technical Analysis")
pred_days_input = gr.Slider(7, 60, value=30, step=1, label="Prediction Days (for AI mode only)")
analyze_button = gr.Button("Analyze")
with gr.Row():
fundamentals_output = gr.HTML()
signal_output = gr.HTML()
ai_output = gr.HTML()
with gr.Row():
chart_price = gr.Plot(label="Price Chart")
chart_technical = gr.Plot(label="Technical Chart")
chart_prediction = gr.Plot(label="AI Prediction Chart")
def run_analysis(symbol, mode, pred_days):
fundamentals, signals, fig_price, fig_technical, fig_prediction, prediction = analyze_stock(symbol, mode, pred_days)
if isinstance(fundamentals, str):
return fundamentals, "", "", None, None, None
return (
format_fundamental_output(fundamentals),
format_signal_output(signals),
format_ai_output(prediction) if mode == "AI Prediction" else "",
fig_price,
fig_technical,
fig_prediction if mode == "AI Prediction" else None
)
analyze_button.click(
fn=run_analysis,
inputs=[stock_input, mode_input, pred_days_input],
outputs=[fundamentals_output, signal_output, ai_output, chart_price, chart_technical, chart_prediction]
)
demo.launch(server_name="0.0.0.0", server_port=7860)