| import streamlit as st |
| import pandas as pd |
| import yfinance as yf |
| from datetime import datetime |
| import time |
|
|
| st.set_page_config( |
| page_title="Pro Trading Signals", |
| page_icon="π", |
| layout="centered", |
| initial_sidebar_state="collapsed" |
| ) |
|
|
| st.markdown(""" |
| <style> |
| .main-title { font-size: 2.5rem; font-weight: bold; color: #FFD700; text-align: center; } |
| .signal-box { background: #1a1a1a; border-radius: 15px; padding: 25px; margin: 10px 0; } |
| .prob-big { font-size: 4rem; font-weight: bold; text-align: center; } |
| .buy-signal { color: #00E676; } |
| .sell-signal { color: #FF5252; } |
| .wait-signal { color: #FFD740; } |
| </style> |
| """, unsafe_allow_html=True) |
|
|
| st.markdown('<h1 class="main-title">π PRO TRADING SIGNALS</h1>', unsafe_allow_html=True) |
| st.markdown('<p style="text-align:center;color:#888;">Live Market Data β’ Technical Analysis</p>', unsafe_allow_html=True) |
|
|
| SYMBOL_MAP = { |
| "π₯ Gold (XAU/USD)": ["GC=F"], |
| "π₯ Silver (XAG/USD)": ["XAGUSD=X"], |
| "π’οΈ Crude Oil (CL)": ["CL=F"], |
| "β½ Natural Gas (NG)": ["NG=F"], |
| "π½ Corn (ZC)": ["ZC=F"], |
| "πΎ Wheat (ZW)": ["ZW=F"], |
| "EUR/USD": ["EURUSD=X"], |
| "GBP/USD": ["GBPUSD=X"], |
| "USD/JPY": ["USDJPY=X"], |
| "USD/CHF": ["USDCHF=X"], |
| "AUD/USD": ["AUDUSD=X"], |
| "USD/CAD": ["USDCAD=X"], |
| "BTC/USD": ["BTC-USD"], |
| "ETH/USD": ["ETH-USD"], |
| "AAPL": ["AAPL"], |
| "TSLA": ["TSLA"], |
| "NVDA": ["NVDA"], |
| } |
|
|
| TIMEFRAMES = { |
| "1 Min": {"interval": "1m", "period": "5d"}, |
| "5 Min": {"interval": "5m", "period": "5d"}, |
| "15 Min": {"interval": "15m", "period": "5d"}, |
| "30 Min": {"interval": "30m", "period": "10d"}, |
| "1 Hour": {"interval": "1h", "period": "30d"}, |
| "4 Hour": {"interval": "4h", "period": "60d"}, |
| "Daily": {"interval": "1d", "period": "180d"}, |
| } |
|
|
|
|
| def get_data(symbols: list, interval: str, period: str) -> pd.DataFrame: |
| for sym in symbols: |
| try: |
| ticker = yf.Ticker(sym) |
| df = ticker.history(period=period, interval=interval, timeout=30) |
| if not df.empty: |
| return df |
| except: |
| continue |
| return pd.DataFrame() |
|
|
|
|
| col1, col2, col3 = st.columns([2, 2, 1]) |
| with col1: |
| selected_pair = st.selectbox("π Asset", list(SYMBOL_MAP.keys()), label_visibility="collapsed") |
| with col2: |
| selected_tf = st.selectbox("β± Timeframe", list(TIMEFRAMES.keys()), label_visibility="collapsed") |
| with col3: |
| st.write("") |
| analyze_btn = st.button("β‘ ANALYZE", use_container_width=True) |
|
|
| if analyze_btn: |
| with st.spinner("π‘ Fetching market data..."): |
| try: |
| start_time = time.time() |
| symbols = SYMBOL_MAP[selected_pair] |
| tf = TIMEFRAMES[selected_tf] |
| |
| df = get_data(symbols, tf["interval"], tf["period"]) |
| |
| if df.empty or len(df) < 20: |
| st.error("β No data. Try different asset or check internet.") |
| else: |
| close = df['Close'] |
| |
| df['sma9'] = close.rolling(9).mean() |
| df['sma21'] = close.rolling(21).mean() |
| df['sma50'] = close.rolling(50).mean() |
| df['ema8'] = close.ewm(span=8, adjust=False).mean() |
| df['ema21'] = close.ewm(span=21, adjust=False).mean() |
| |
| delta = close.diff() |
| gain = delta.clip(lower=0) |
| loss = (-delta).clip(lower=0) |
| avg_gain = gain.ewm(alpha=1/14, adjust=False).mean() |
| avg_loss = loss.ewm(alpha=1/14, adjust=False).mean() |
| rs = avg_gain / loss.replace(0, 1e-12) |
| df['rsi'] = 100 - (100 / (1 + rs)) |
| |
| ema12 = close.ewm(span=12, adjust=False).mean() |
| ema26 = close.ewm(span=26, adjust=False).mean() |
| df['macd'] = ema12 - ema26 |
| df['macd_signal'] = df['macd'].ewm(span=9, adjust=False).mean() |
| df['macd_hist'] = df['macd'] - df['macd_signal'] |
| |
| high = df['High'] |
| low = df['Low'] |
| prev_close = close.shift(1) |
| tr = pd.concat([high - low, (high - prev_close).abs(), (low - prev_close).abs()], axis=1).max(axis=1) |
| df['atr'] = tr.ewm(alpha=1/14, adjust=False).mean() |
| |
| up_move = high.diff() |
| down_move = -low.diff() |
| plus_dm = ((up_move > down_move) & (up_move > 0)) * up_move |
| minus_dm = ((down_move > up_move) & (down_move > 0)) * down_move |
| tr_s = tr.ewm(alpha=1/14, adjust=False).mean() |
| p_dm_s = plus_dm.ewm(alpha=1/14, adjust=False).mean() |
| m_dm_s = minus_dm.ewm(alpha=1/14, adjust=False).mean() |
| tr_safe = tr_s.replace(0, 1e-12) |
| df['plus_di'] = 100 * (p_dm_s / tr_safe) |
| df['minus_di'] = 100 * (m_dm_s / tr_safe) |
| di_sum = (df['plus_di'] + df['minus_di']).replace(0, 1e-12) |
| dx = 100 * (df['plus_di'] - df['minus_di']).abs() / di_sum |
| df['adx'] = dx.ewm(alpha=1/14, adjust=False).mean() |
| |
| last = df.iloc[-1] |
| price = float(last['Close']) |
| atr = float(last['atr']) |
| |
| score_buy = 0 |
| score_sell = 0 |
| reasons = [] |
| |
| if price > last['sma50']: |
| score_buy += 1 |
| reasons.append("β Price > SMA50") |
| else: |
| score_sell += 1 |
| reasons.append("β Price < SMA50") |
| |
| if last['sma21'] > last['sma50']: |
| score_buy += 1 |
| reasons.append("β SMA21 > SMA50") |
| else: |
| score_sell += 1 |
| reasons.append("β SMA21 < SMA50") |
| |
| if last['ema8'] > last['ema21']: |
| score_buy += 1 |
| reasons.append("β EMA8 > EMA21") |
| else: |
| score_sell += 1 |
| reasons.append("β EMA8 < EMA21") |
| |
| if last['macd'] > last['macd_signal']: |
| score_buy += 1 |
| reasons.append("β MACD bullish") |
| else: |
| score_sell += 1 |
| reasons.append("β MACD bearish") |
| |
| if last['macd_hist'] > 0: |
| score_buy += 1 |
| reasons.append("β MACD histogram +") |
| else: |
| score_sell += 1 |
| reasons.append("β MACD histogram -") |
| |
| rsi = last['rsi'] |
| if 50 < rsi < 70: |
| score_buy += 1 |
| reasons.append(f"β RSI healthy ({rsi:.0f})") |
| elif 30 < rsi < 50: |
| score_sell += 1 |
| reasons.append(f"β RSI weak ({rsi:.0f})") |
| elif rsi >= 70: |
| score_sell += 1 |
| reasons.append(f"β RSI overbought") |
| elif rsi <= 30: |
| score_buy += 1 |
| reasons.append(f"β RSI oversold") |
| |
| adx = last['adx'] |
| if adx > 20: |
| if last['plus_di'] > last['minus_di']: |
| score_buy += 2 |
| reasons.append(f"β Strong uptrend (ADX:{adx:.0f})") |
| else: |
| score_sell += 2 |
| reasons.append(f"β Strong downtrend (ADX:{adx:.0f})") |
| else: |
| reasons.append(f"β Ranging market") |
| |
| if score_buy >= 5: |
| prob = min(95, 55 + (score_buy * 7)) |
| action = "π’ BUY" |
| color_class = "buy-signal" |
| tp = round(price + (atr * 2), 2) |
| sl = round(price - (atr * 1), 2) |
| elif score_sell >= 5: |
| prob = min(95, 55 + (score_sell * 7)) |
| action = "π΄ SELL" |
| color_class = "sell-signal" |
| tp = round(price - (atr * 2), 2) |
| sl = round(price + (atr * 1), 2) |
| else: |
| prob = max(40, 50 + (score_buy - score_sell) * 5) |
| action = "π‘ WAIT" |
| color_class = "wait-signal" |
| tp = sl = round(price, 2) |
| |
| fetch_time = round(time.time() - start_time, 2) |
| |
| st.markdown(f""" |
| <div class="signal-box"> |
| <h2 class="{color_class}" style="text-align:center;">{action}</h2> |
| <h1 class="prob-big {color_class}">{prob}%</h1> |
| <p style="text-align:center;color:#888;">WIN PROBABILITY β’ {fetch_time}s</p> |
| <hr style="border-color:#333;"> |
| <div style="display:flex;justify-content:space-around;text-align:center;"> |
| <div> |
| <p style="color:#888;">CURRENT PRICE</p> |
| <h3>${price:.2f}</h3> |
| </div> |
| <div> |
| <p style="color:#00E676;">TAKE PROFIT</p> |
| <h3>${tp:.2f}</h3> |
| </div> |
| <div> |
| <p style="color:#FF5252;">STOP LOSS</p> |
| <h3>${sl:.2f}</h3> |
| </div> |
| </div> |
| <hr style="border-color:#333;"> |
| <h4 style="color:#FFD700;">π TECHNICAL ANALYSIS</h4> |
| <p style="font-family:monospace;color:#ccc;">{chr(10).join(reasons)}</p> |
| <p style="color:#888;text-align:center;">{selected_pair} β’ {selected_tf} β’ {datetime.now().strftime('%H:%M:%S')}</p> |
| </div> |
| """, unsafe_allow_html=True) |
| |
| except Exception as e: |
| st.error(f"Error: {str(e)}") |
|
|
| st.markdown("---") |
| st.markdown('<p style="text-align:center;color:#555;font-size:12px;">Pro Trading Signals β’ Powered by Yahoo Finance</p>', unsafe_allow_html=True) |