IDX-Chronos-API / app.py
omniverse1's picture
Update app.py
970d73a verified
raw
history blame
6.38 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)
# kalkulasi TP1, TP2, SL
last_price = data['Close'].iloc[-1]
tp1 = last_price * (1 + (predictions.get("change_pct", 0) / 200))
tp2 = last_price * (1 + (predictions.get("change_pct", 0) / 100))
sl = last_price * 0.95
predictions["tp1"] = tp1
predictions["tp2"] = tp2
predictions["sl"] = sl
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),
)
fundamentals = f"""
### 🏒 Company Fundamentals
**Name:** {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):,}
"""
details_list = "".join(
[f"<li>{line.strip()}</li>" for line in signals.get("details", "").split("\n") if line.strip()]
)
trading_signal = f"""
### πŸ“Š Technical Signal Summary
**Overall Trend:** {signals.get('overall', 'N/A')}
**Signal Strength:** {signals.get('strength', 0):.2f}%
**Support:** Rp{signals.get('support', 0):,.2f}
**Resistance:** Rp{signals.get('resistance', 0):,.2f}
**Stop Loss:** Rp{signals.get('stop_loss', 0):,.2f}
**Detailed Signals:**
<ul style="margin-top:6px; padding-left:20px;">{details_list}</ul>
"""
prediction = f"""
### πŸ€– 30-Day AI Forecast (Chronos-Bolt)
**Predicted High:** Rp{predictions.get('high_30d', 0):,.2f}
**Predicted Low:** Rp{predictions.get('low_30d', 0):,.2f}
**Expected Change:** {predictions.get('change_pct', 0):.2f}%
**TP1:** Rp{predictions.get('tp1', 0):,.2f}
**TP2:** Rp{predictions.get('tp2', 0):,.2f}
**Stop Loss:** Rp{predictions.get('sl', 0):,.2f}
**Model Insight:**
{predictions.get('summary', 'No analysis available')}
"""
combined = f"""
<div style="display:flex;flex-wrap:wrap;gap:12px;justify-content:space-between;">
<div style="flex:1;min-width:300px;background-color:white;border-radius:8px;padding:12px;border:1px solid #e5e7eb;">{fundamentals}</div>
<div style="flex:1;min-width:300px;background-color:white;border-radius:8px;padding:12px;border:1px solid #e5e7eb;">{trading_signal}</div>
<div style="flex:1;min-width:300px;background-color:white;border-radius:8px;padding:12px;border:1px solid #e5e7eb;">{prediction}</div>
</div>
"""
return (
combined,
fig_price,
fig_technical,
fig_prediction,
)
# ---------------------- UI ----------------------
with gr.Blocks(
title="REXPRO Financial AI Dashboard",
theme=gr.themes.Soft(primary_hue="blue", secondary_hue="gray"),
) as app:
gr.Markdown(
"""
# πŸ’Ή REXPRO Financial AI Dashboard
Analyze **Indonesian stocks (IDX)** using AI-powered forecasting and technical indicators.
"""
)
with gr.Row():
symbol = gr.Textbox(
label="Stock Symbol (IDX)",
value="BBCA",
placeholder="e.g., BBCA, TLKM, ADRO, BMRI",
)
prediction_days = gr.Slider(
label="Forecast Period (Days)",
minimum=5,
maximum=60,
step=5,
value=30,
)
analyze_button = gr.Button("πŸ” Run Analysis", variant="primary")
gr.Markdown("---")
report_section = gr.HTML(label="Analysis Summary")
gr.Markdown("---")
gr.Markdown("### πŸ“ˆ Market Charts")
with gr.Tabs():
with gr.Tab("Price Overview"):
price_chart = gr.Plot(label="Price & Moving Averages")
with gr.Tab("Technical Indicators"):
technical_chart = gr.Plot(label="Technical Indicator Overview")
with gr.Tab("AI Forecast"):
prediction_chart = gr.Plot(label="AI Forecast Projection")
analyze_button.click(
fn=update_analysis,
inputs=[symbol, prediction_days],
outputs=[report_section, price_chart, technical_chart, prediction_chart],
)
if __name__ == "__main__":
app.launch(server_name="0.0.0.0", server_port=7860, ssr_mode=True)