import gradio as ui import yfinance as yf import pandas as pd from prophet import Prophet import plotly.graph_objects as go from huggingface_hub import InferenceClient # 🌍 מאגר המדדים והנכסים MARKET_ASSETS = { "✡️ מדד תל אביב 125 (ישראל)": "^TA125.TA", "S&P 500": "^GSPC", "Nasdaq 100 (טכנולוגיה)": "^NDX", "Dow Jones 30": "^DJI", "VIX (מדד הפחד והחרדה)": "^VIX", "DAX 40 (גרמניה)": "^GDAXI", "FTSE 100 (בריטניה)": "^FTSE", "Nikkei 225 (יפן)": "^N225", "זהב (Gold)": "GC=F", "נפט גולמי (Crude Oil)": "CL=F", "ביטקוין (Bitcoin USD)": "BTC-USD" } client = InferenceClient("meta-llama/Meta-Llama-3-8B-Instruct") PRECOMPUTED_CACHE = {} def get_llm_analysis(asset_symbol, asset_name, summary_stats, character): """מנוע ה-LLM המתוקן - משתמש ב-chat_completion יציב ומהיר יותר""" # 1. מגדירים את ה-System Prompt (האופי של הדמות) if character == "סבתא פולנייה (ציפי)": system_instruction = "אתה סבתא פולנייה פולשנית, פסימיסטית ומודאגת מאוד בשם ציפי. את חושבת שלשים כסף בבורסה זה הימור מסוכן שיגמור את החסכונות של הנכדים, ומזכירה שצריך לאכול משהו חם. דברי בסגנון פולני קלאסי ומשעשע." elif character == "הרבי מהאינסטגרם (רב ברוך)": system_instruction = "אתה 'הרבי מהאינסטגרם' בשם הרב ברוך. אתה מוצא השגחה פרטית ופסוקים בכל גרף. אם המניה עולה - זה חסדי שמיים, אם היא יורדת - זה ניסיון מלמעלה. שלב ביטויים כמו 'ברוך השם', 'בעזרת השם', ו'לתת מעשר'." else: system_instruction = "אתה מוישי, ברוקר חרדי מבוול סטריט (ניו יורק). אתה מדבר בקצב מהיר, משלב המון מילים באנגלית (Yiddish-English כמו Listen, My friend, Oh my god, Buy the dip, Gvalt). אתה לחוץ על כסף, מקצוען אבל עם אופי חסידי-אמריקאי תזזיתי." # 2. הבקשה הספציפית (User Prompt) user_prompt = f""" נתח בקצרה (עד 4 שורות) ובעברית את הנכס/מניה הבאה: {asset_name} (סימול: {asset_symbol}). נתונים פיננסיים אחרונים מהשוק: {summary_stats} התשובה חייבת להיות נאמנה לחלוטין לדמות שלך, ולשלב את הנתונים הפיננסיים בצורה הומוריסטית ובשפה עשירה. """ try: # שימוש במודל Llama 3.2 יציב ומהיר דרך chat_completion response = client.chat_completion( model="meta-llama/Llama-3.2-3B-Instruct", messages=[ {"role": "system", "content": system_instruction}, {"role": "user", "content": user_prompt} ], max_tokens=250, temperature=0.8 ) return response.choices[0].message.content.strip() except Exception as e: # אם יש שגיאה, נדפיס אותה ללוגים של Hugging Face כדי שנוכל לראות אותה, ונחזיר הודעה משעשעת print(f"LLM Error: {e}") return f"אוי גוואלד! השרת אומר: '{str(e)[:50]}...'. כנראה עין הרע, תנסה ללחוץ שוב!" def run_calculation(ticker_symbol, asset_name, history_period="2y", forecast_days=60): """פונקציית ליבה שמבצעת את הורדת הנתונים וחישוב ה-Prophet""" ticker = yf.Ticker(ticker_symbol) df = ticker.history(period=history_period) if df.empty or len(df) < 15: return None, None # חיזוי Prophet df_prophet = df.reset_index()[['Date', 'Close']] df_prophet['Date'] = df_prophet['Date'].dt.tz_localize(None) df_prophet.columns = ['ds', 'y'] model = Prophet(daily_seasonality=False, weekly_seasonality=True, yearly_seasonality=True) model.fit(df_prophet) future = model.make_future_dataframe(periods=int(forecast_days)) forecast = model.predict(future) # בניית גרף Plotly בצבעי כחול-לבן-תכלת fig = go.Figure() fig.add_trace(go.Scatter(x=df_prophet['ds'], y=df_prophet['y'], name='מה שקרה בפועל', line=dict(color='#0d47a1', width=3))) df_future = forecast.iloc[-int(forecast_days):] fig.add_trace(go.Scatter( x=pd.concat([df_future['ds'], df_future['ds'].iloc[::-1]]), y=pd.concat([df_future['yhat_upper'], df_future['yhat_lower'].iloc[::-1]]), fill='toself', fillcolor='rgba(100, 181, 246, 0.2)', line=dict(color='rgba(255,255,255,0)'), hoverinfo="skip", name='טווח הסטייה המשוער' )) fig.add_trace(go.Scatter(x=df_future['ds'], y=df_future['yhat'], name='התחזית של JEWMINI', line=dict(color='#1e88e5', width=3, dash='dash'))) fig.update_layout( title=f"📊 מגמות ונבואות עבור {asset_name}", xaxis_title="תאריך", yaxis_title="מחיר שוק", hovermode="x unified", template="plotly_white", margin=dict(l=20, r=20, t=60, b=20), plot_bgcolor='white', paper_bgcolor='white' ) # סטטיסטיקות last_price = df_prophet['y'].iloc[-1] start_price = df_prophet['y'].iloc[0] total_change = ((last_price - start_price) / start_price) * 100 future_price = df_future['yhat'].iloc[-1] predicted_change = ((future_price - last_price) / last_price) * 100 summary_stats = ( f"מחיר נוכחי בשוק: {last_price:,.2f}\n" f"תשואה היסטורית בתקופה: {total_change:+.2f}%\n" f"מחיר חזוי לעוד {forecast_days} ימים: {future_price:,.2f} ({predicted_change:+.2f}%)" ) return summary_stats, fig def precompute_all_assets(): """פונקציה שרצה בטעינת האפליקציה וממלאת את הזיכרון מראש""" for name, symbol in MARKET_ASSETS.items(): if name.startswith("--"): continue try: summary, fig = run_calculation(symbol, name) if summary and fig: PRECOMPUTED_CACHE[name] = {"summary": summary, "fig": fig, "symbol": symbol} except Exception as e: pass # הרצת הטעינה מראש precompute_all_assets() def analyze_and_forecast(selected_asset, custom_ticker, history_period, forecast_days, character): if custom_ticker and custom_ticker.strip(): ticker_symbol = custom_ticker.strip().upper() asset_name = f"מניית {ticker_symbol}" summary_stats, fig = run_calculation(ticker_symbol, asset_name, history_period, forecast_days) if not summary_stats: return f"שגיאה: לא נמצאו נתונים עבור הסימול '{ticker_symbol}'.", None, "שגיאה" else: if selected_asset.startswith("--"): return "נו באמת, תבחר נכס אמיתי כמו בנאדם.", None, "אויש נו." if history_period == "2y" and forecast_days == 60 and selected_asset in PRECOMPUTED_CACHE: summary_stats = PRECOMPUTED_CACHE[selected_asset]["summary"] fig = PRECOMPUTED_CACHE[selected_asset]["fig"] ticker_symbol = PRECOMPUTED_CACHE[selected_asset]["symbol"] asset_name = selected_asset else: ticker_symbol = MARKET_ASSETS[selected_asset] asset_name = selected_asset summary_stats, fig = run_calculation(ticker_symbol, asset_name, history_period, forecast_days) llm_insights = get_llm_analysis(ticker_symbol, asset_name, summary_stats, character) return summary_stats, fig, llm_insights # --- 🔵 עיצוב כחול-לבן מותאם אישית (Custom Theme & CSS) ⚪ --- blue_white_theme = ui.themes.Default( primary_hue="blue", secondary_hue="sky", neutral_hue="slate" ).set( body_background_fill="white", body_text_color="#0d47a1", block_background_fill="#f1f8ff", block_border_width="2px", block_border_color="#90caf9", button_primary_background_fill="#0d47a1", button_primary_background_fill_hover="#1565c0", button_primary_text_color="white" ) custom_css = """ body { direction: rtl !important; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } .markdown-text h1 { color: #0d47a1 !important; border-bottom: 3px solid #0d47a1; padding-bottom: 10px; } .markdown-text h3 { color: #1565c0 !important; } """ with ui.Blocks(theme=blue_white_theme, css=custom_css, title="JEWMINI AI") as demo: # כותרת האתר ui.Markdown(""" # ✡️ JEWMINI AI - חמ״ל פיננסי כחול-לבן דשבורד פיננסי חכם למדדים ומניות מהארץ ומהעולם. המערכת משתמשת במודל החיזוי **Prophet** ובבינה מלאכותית מבוססת דמויות לניתוח השוק. """) with ui.Row(): # עמודת שליטה בצד (כחלחל בהיר) with ui.Column(scale=1): ui.Markdown("### 🕵️‍♂️ 1. האנליסט שלך") character_dropdown = ui.Dropdown( choices=["סבתא פולנייה (ציפי)", "הרבי מהאינסטגרם (רב ברוך)", "מוישי הברוקר מוול סטריט"], value="סבתא פולנייה (ציפי)", label="בחר דמות לניתוח השוק" ) ui.Markdown("### 🔍 2. נכס או מניה") selected_asset = ui.Dropdown( choices=list(MARKET_ASSETS.keys()), value="✡️ מדד תל אביב 125 (ישראל)", label="בחר נכס מהרשימה" ) custom_ticker = ui.Textbox( label="או הקלד סימול חופשי (למשל: AAPL, NVDA, TSLA)", placeholder="הקלד באנגלית..." ) ui.Markdown("### ⚙️ הגדרות המודל") history_radio = ui.Radio( choices=["1y", "2y", "5y"], value="2y", label="טווח היסטוריית למידה" ) forecast_slider = ui.Slider( minimum=7, maximum=180, value=60, step=1, label="טווח החיזוי העתידי (בימים)" ) # כפתור כחול כהה בולט btn = ui.Button("🚀 הפעל ניתוח ונבואה", variant="primary") # עמודת תוצאות במרכז (לבן נקי עם אלמנטים כחולים) with ui.Column(scale=2): with ui.Group(): ui.Markdown("### 💬 ניתוח אנליטי (JEWMINI Insights)") llm_output = ui.Textbox(show_label=False, interactive=False, lines=5) output_text = ui.Textbox(label="📊 נתונים מספריים ותחזית", interactive=False, lines=3) output_chart = ui.Plot(label="📈 גרף הנביא (כחול-לבן)") # חיבור פונקציות לאירועים inputs = [selected_asset, custom_ticker, history_radio, forecast_slider, character_dropdown] outputs = [output_text, output_chart, llm_output] btn.click(fn=analyze_and_forecast, inputs=inputs, outputs=outputs) demo.load(fn=analyze_and_forecast, inputs=inputs, outputs=outputs) if __name__ == "__main__": demo.launch()