IDX-Chronos / app.py
omniverse1's picture
Update app.py
c54bdd8 verified
raw
history blame
8.62 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)
# Fetching data for a slightly longer period for better analysis base
data = stock.history(period="1y", 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": f"Error: {e}",
"tp1": 0,
"tp2": 0,
"sl": 0,
}
# Mengembalikan string kosong untuk data yang akan ditampilkan di Markdown
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 and "Error" in predictions.get("summary", ""):
# Jika terjadi error, kembalikan hasil error ke semua output
error_msg = f"**ERROR:** {predictions.get('summary')}"
return (
gr.Markdown.update(value=error_msg),
gr.Markdown.update(value=error_msg),
gr.Markdown.update(value=error_msg),
gr.Plot.update(value=None),
gr.Plot.update(value=None),
gr.Plot.update(value=None),
)
# --- Formatting Fundamental Data ---
fundamentals_text = 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):,}
"""
# --- Formatting Technical Signals ---
details_list = "".join(
[f"<li>{line.strip()}</li>" for line in signals.get("details", "").split("\n") if line.strip()]
)
trading_signal_text = 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: 8px; padding-left: 20px; line-height: 1.6;">
{details_list}
</ul>
"""
# --- Formatting Prediction Data ---
prediction_text = f"""
### 30-DAY AI FORECAST
- **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}%**
#### Trading Targets
- **TP1 (Target Price 1):** Rp{predictions.get('tp1', 0):,.2f}
- **TP2 (Target Price 2):** Rp{predictions.get('tp2', 0):,.2f}
- **Stop Loss:** Rp{predictions.get('sl', 0):,.2f}
#### Model Insight
> {predictions.get('summary', 'No analysis available')}
"""
return (
gr.Markdown.update(value=fundamentals_text),
gr.Markdown.update(value=trading_signal_text),
gr.Markdown.update(value=prediction_text),
fig_price,
fig_technical,
fig_prediction,
)
# --- STRUKTUR UI BARU ---
with gr.Blocks(
title="REXPRO FINANCIAL AI DASHBOARD",
# Menggunakan tema standar Gradio. Perbaikan layout yang membuat professional.
) as app:
gr.Markdown("# REXPRO FINANCIAL AI DASHBOARD")
gr.Markdown(
"Aplikasi Analisis Saham Komprehensif IDX, didukung oleh **Peramalan AI (CHRONOS-BOLT)** dan Analisis Teknikal."
)
# 1. Row Kontrol Utama
with gr.Row(variant="panel"): # Menggunakan panel untuk membedakan area kontrol
with gr.Column(scale=1):
symbol = gr.Textbox(
label="MASUKKAN SIMBOL SAHAM (IDX)",
value="BBCA",
placeholder="Contoh: BBCA, TLKM, ADRO, BMRI",
interactive=True,
show_label=True
)
with gr.Column(scale=1):
prediction_days = gr.Slider(
label="PERIODE PERAMALAN (HARI)",
minimum=5,
maximum=60,
step=5,
value=30,
interactive=True,
show_label=True
)
with gr.Column(min_width=150, scale=0):
# Tombol diletakkan di bawah input untuk tampilan yang lebih rapi
analyze_button = gr.Button("RUN ANALYSIS", size="lg")
# 2. Tab untuk Hasil
with gr.Tabs():
# Tab 1: Ringkasan Analisis (Textual)
with gr.TabItem("RINGKASAN & TARGET"):
# Menggunakan gr.Row untuk membuat 3 "kartu" atau kolom hasil
with gr.Row():
# Grup untuk Fundamental
with gr.Group():
fundamentals_output = gr.Markdown(
"Hasil Fundamental akan muncul di sini.",
elem_classes=["card"]
)
# Grup untuk Sinyal Teknikal
with gr.Group():
trading_signal_output = gr.Markdown(
"Ringkasan Sinyal Teknikal akan muncul di sini.",
elem_classes=["card"]
)
# Grup untuk Prediksi AI & Target
with gr.Group():
prediction_output = gr.Markdown(
"Hasil Peramalan AI & Target Trading akan muncul di sini.",
elem_classes=["card"]
)
# Tab 2: Grafik Analisis
with gr.TabItem("VISUALISASI GRAFIK"):
gr.Markdown("## Grafik Analisis Saham")
with gr.Row():
# Grafik 1: Harga & MA
with gr.Column(scale=1):
price_chart = gr.Plot(label="1. HARGA & RATA-RATA BERGERAK (MA)", height=450)
# Grafik 2: Indikator Teknikal
with gr.Column(scale=1):
technical_chart = gr.Plot(label="2. INDIKATOR TEKNIKAL UTAMA (RSI/MACD)", height=450)
gr.Markdown("---")
with gr.Row():
# Grafik 3: Prediksi AI
prediction_chart = gr.Plot(label="3. PROYEKSI PERAMALAN AI", height=500)
# Definisi Event Handler
analyze_button.click(
fn=update_analysis,
inputs=[symbol, prediction_days],
outputs=[
fundamentals_output,
trading_signal_output,
prediction_output,
price_chart,
technical_chart,
prediction_chart,
],
)
if __name__ == "__main__":
app.launch(server_name="0.0.0.0", server_port=7860, ssr_mode=True)