IDX-Chronos-API / app.py
omniverse1's picture
Update app.py
48cacc1 verified
raw
history blame
6.25 kB
import gradio as gr
import pandas as pd
import yfinance as yf
from utils import (
calculate_technical_indicators,
generate_trading_signals,
get_fundamental_data,
predict_prices,
create_price_chart,
create_technical_chart,
create_prediction_chart,
)
import warnings
warnings.filterwarnings("ignore")
def analyze_stock(symbol, prediction_days=30):
try:
if not symbol.strip():
raise ValueError("Please enter a valid stock symbol.")
if not symbol.endswith(".JK"):
symbol = symbol.upper() + ".JK"
stock = yf.Ticker(symbol)
data = stock.history(period="6mo", interval="1d")
if data.empty:
raise ValueError("No price data available for this stock.")
indicators = calculate_technical_indicators(data)
signals = generate_trading_signals(data, indicators)
fundamental_info = get_fundamental_data(stock)
predictions = predict_prices(data, prediction_days=prediction_days)
fig_price = create_price_chart(data, indicators)
fig_technical = create_technical_chart(data, indicators)
fig_prediction = create_prediction_chart(data, predictions)
return fundamental_info, indicators, signals, fig_price, fig_technical, fig_prediction, predictions
except Exception as e:
print(f"Error analyzing {symbol}: {e}")
empty_fig = gr.Plot.update(value=None)
empty_predictions = {
'high_30d': 0, 'low_30d': 0, 'change_pct': 0, 'summary': 'Prediction unavailable.'
}
return {}, {}, {}, empty_fig, empty_fig, empty_fig, empty_predictions
def update_analysis(symbol, prediction_days):
(
fundamental_info,
indicators,
signals,
fig_price,
fig_technical,
fig_prediction,
predictions,
) = analyze_stock(symbol, prediction_days)
if not fundamental_info:
return (
"❌ Unable to fetch stock data.",
gr.Plot.update(value=None),
gr.Plot.update(value=None),
gr.Plot.update(value=None),
"",
"0", "0", "0", ""
)
summary_text = f"""
### 🏒 {fundamental_info.get('name', 'N/A')} ({symbol.upper()})
**Current Price:** Rp{fundamental_info.get('current_price', 0):,.2f}
**Market Cap:** {fundamental_info.get('market_cap', 0):,}
**P/E Ratio:** {fundamental_info.get('pe_ratio', 0):.2f}
**Dividend Yield:** {fundamental_info.get('dividend_yield', 0):.2f}%
**Volume:** {fundamental_info.get('volume', 0):,}
"""
signal_text = f"""
### πŸ“ˆ Technical Trading Signal
**Overall Signal:** {signals.get('overall', 'N/A')}
**Strength:** {signals.get('strength', 0):.2f}%
**Support:** {signals.get('support', 0):,.2f}
**Resistance:** {signals.get('resistance', 0):,.2f}
**Stop Loss:** {signals.get('stop_loss', 0):,.2f}
**Signal Details:**
{signals.get('details', '')}
"""
prediction_text = f"""
### πŸ€– AI Forecast (Amazon Chronos-Bolt)
**Predicted High (30d):** Rp{predictions.get('high_30d', 0):,.2f}
**Predicted Low (30d):** Rp{predictions.get('low_30d', 0):,.2f}
**Expected Change:** {predictions.get('change_pct', 0):.2f}%
🧠 **Model Insight:**
{predictions.get('summary', 'No analysis available')}
"""
return (
summary_text,
fig_price,
fig_technical,
fig_prediction,
signal_text,
f"{predictions.get('high_30d', 0):,.2f}",
f"{predictions.get('low_30d', 0):,.2f}",
f"{predictions.get('change_pct', 0):.2f}%",
prediction_text,
)
with gr.Blocks(
title="AI Stock Forecast Dashboard",
theme=gr.themes.Soft(primary_hue="blue", secondary_hue="gray"),
css="""
#dashboard {padding: 20px; max-width: 1300px; margin: auto;}
.gradio-container {font-family: 'Inter', sans-serif;}
h1, h2, h3 {color: #1e293b;}
.gr-button {font-weight: 600; border-radius: 8px;}
.gr-markdown {background: #f8fafc; border-radius: 10px; padding: 15px;}
"""
) as app:
gr.Markdown("# ⚑ AI Stock Analysis Dashboard β€” Chronos-Bolt Edition", elem_id="dashboard")
gr.Markdown("Enter any **Indonesian stock ticker** (e.g., `BBCA`, `ADRO`, `TLKM`, `BMRI`) to get live market insights and AI-based 30-day forecasts.", elem_id="dashboard")
with gr.Row():
symbol = gr.Textbox(
label="Stock Symbol",
value="BBCA",
placeholder="Type e.g. BBCA, ADRO, TLKM ...",
interactive=True,
lines=1
)
prediction_days = gr.Slider(
label="Prediction Period (Days)",
minimum=5,
maximum=60,
step=5,
value=30,
interactive=True,
)
analyze_button = gr.Button("πŸš€ Analyze Stock")
gr.Markdown("---")
with gr.Row():
with gr.Column():
fundamentals_output = gr.Markdown(label="Fundamentals")
with gr.Column():
signal_output = gr.Markdown(label="Trading Signals")
gr.Markdown("---")
with gr.Tab("πŸ“Š Charts Overview"):
with gr.Row():
price_chart = gr.Plot(label="Price & Moving Averages")
technical_chart = gr.Plot(label="Technical Indicators")
gr.Markdown("---")
prediction_chart = gr.Plot(label="AI Forecast Projection")
with gr.Tab("πŸ€– AI Forecast Results"):
with gr.Row():
predicted_high = gr.Textbox(label="Predicted High (30d)")
predicted_low = gr.Textbox(label="Predicted Low (30d)")
predicted_change = gr.Textbox(label="Expected Change (%)")
gr.Markdown("---")
prediction_summary = gr.Markdown(label="Prediction Analysis")
analyze_button.click(
fn=update_analysis,
inputs=[symbol, prediction_days],
outputs=[
fundamentals_output,
price_chart,
technical_chart,
prediction_chart,
signal_output,
predicted_high,
predicted_low,
predicted_change,
prediction_summary,
],
)
if __name__ == "__main__":
app.launch(server_name="0.0.0.0", server_port=7860, ssr_mode=True)