import warnings import yfinance as yf from fastapi import FastAPI, HTTPException, Query from fastapi.responses import JSONResponse import uvicorn from utils import ( calculate_technical_indicators, generate_trading_signals, get_fundamental_data, predict_prices, create_price_chart, create_technical_chart, create_prediction_chart, ) warnings.filterwarnings("ignore") app = FastAPI( title="IDX Stock Analysis API", description="API untuk analisis teknikal, fundamental, dan prediksi AI untuk saham IDX.", version="1.0.0" ) def analyze_stock_logic(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(f"No price data available for stock: {symbol}") 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}") raise HTTPException(status_code=404, detail=str(e)) @app.get("/analyze/") async def get_stock_analysis( symbol: str = Query(..., description="Simbol saham IDX (contoh: BBCA, TLKM)"), prediction_days: int = Query(30, ge=5, le=60, description="Jumlah hari untuk prediksi ke depan") ): """ Menjalankan analisis lengkap untuk simbol saham yang diberikan. """ try: ( fundamental_info, indicators, signals, fig_price, fig_technical, fig_prediction, predictions, ) = analyze_stock_logic(symbol, prediction_days) # Ubah figur Plotly menjadi JSON agar bisa dikirim via API charts_json = { "price_chart": fig_price.to_json(), "technical_chart": fig_technical.to_json(), "prediction_chart": fig_prediction.to_json() } # Hapus data 'values' yang besar dari indicators agar response tidak terlalu besar # Klien bisa membuat chart ini dari data chart utama jika perlu if 'rsi' in indicators: indicators['rsi'].pop('values', None) if 'macd' in indicators: indicators['macd'].pop('macd_values', None) indicators['macd'].pop('signal_values', None) if 'bollinger' in indicators: indicators['bollinger'].pop('upper_values', None) indicators['bollinger'].pop('middle_values', None) indicators['bollinger'].pop('lower_values', None) if 'moving_averages' in indicators: indicators['moving_averages'].pop('sma_20_values', None) indicators['moving_averages'].pop('sma_50_values', None) return JSONResponse(content={ "symbol": symbol.upper() + ".JK", "fundamentals": fundamental_info, "technical_indicators": indicators, "trading_signals": signals, "ai_predictions": predictions, "charts_json": charts_json }) except HTTPException as http_exc: raise http_exc except Exception as e: raise HTTPException(status_code=500, detail=f"An internal error occurred: {str(e)}") if __name__ == "__main__": # Gunakan port 7860 yang merupakan default untuk Hugging Face Spaces uvicorn.run(app, host="0.0.0.0", port=7860)