import pandas as pd import yfinance as yf import streamlit as st from datetime import datetime, timedelta import requests import numpy as np @st.cache_data(ttl=300) # Veriyi 5 dakika cache'le (daha sık güncelleme) def get_stock_data_cached(symbol, period="1y", interval="1d"): """ Belirtilen sembolün hisse senedi verilerini cache'leyerek alır. İlk olarak yfinance kullanarak gerçek veri almayı dener, başarısız olursa simüle edilmiş veri döndürür. """ try: # Symbol formatını düzelt if not symbol.endswith('.IS'): yahoo_symbol = f"{symbol}.IS" else: yahoo_symbol = symbol stock = yf.Ticker(yahoo_symbol) data = stock.history(period=period, interval=interval) # Veri boş değilse, başarıyla verileri aldık demektir if len(data) > 0: # GERÇEK ZAMANLI FİYAT GÜNCELLEMESİ EKLE try: # İlk önce fast_info ile dene (daha hızlı) try: fast_info = stock.fast_info if hasattr(fast_info, 'last_price') and fast_info.last_price is not None: current_market_price = fast_info.last_price print(f"Anlık fiyat (fast_info) - {symbol}: {current_market_price}") # En son veri noktasının Close değerini güncelle data.loc[data.index[-1], 'Close'] = current_market_price else: raise Exception("fast_info kullanılamadı") except: # fast_info çalışmazsa info ile dene info = stock.info current_price_keys = ['regularMarketPrice', 'currentPrice', 'previousClose'] current_market_price = None for key in current_price_keys: if key in info and info[key] is not None and info[key] > 0: current_market_price = info[key] print(f"Anlık fiyat ({key}) - {symbol}: {current_market_price}") break if current_market_price: # En son veri noktasının Close değerini güncelle data.loc[data.index[-1], 'Close'] = current_market_price # High ve Low değerlerini de kontrol et last_high = data.loc[data.index[-1], 'High'] last_low = data.loc[data.index[-1], 'Low'] # Current price, high'tan büyükse high'ı güncelle if current_market_price > last_high: data.loc[data.index[-1], 'High'] = current_market_price # Current price, low'dan küçükse low'ı güncelle if current_market_price < last_low: data.loc[data.index[-1], 'Low'] = current_market_price except Exception as price_e: print(f"Anlık fiyat güncelleme hatası - {symbol}: {str(price_e)}") print(f"Gerçek veri alındı: {symbol}") return data # Veri boşsa, farklı periyotları dene for backup_period in ["1y", "6mo", "3mo", "1mo", "5d"]: if backup_period != period: try: data = stock.history(period=backup_period, interval=interval) if not data.empty: print(f"Yedek periyot kullanıldı - {symbol}: {backup_period}") return data except: continue # Hiçbir periyotta veri alınamazsa simüle edilmiş veriyi döndür print(f"Gerçek veri alınamadı, simülasyon kullanılıyor: {symbol}") return get_simulated_stock_data(symbol, period, interval) except Exception as e: print(f"Veri alınırken hata oluştu ({symbol}): {e}") # Hata durumunda simüle edilmiş veriyi döndür return get_simulated_stock_data(symbol, period, interval) def get_simulated_stock_data(symbol, period="1y", interval="1d"): """ Test için simüle edilmiş veri üretir. Args: symbol (str): Hisse senedi sembolü period (str): Veri periyodu (1d, 5d, 1mo, 3mo, 6mo, 1y, 2y, 5y, 10y, ytd, max) interval (str): Veri aralığı (1m, 2m, 5m, 15m, 30m, 60m, 90m, 1h, 1d, 5d, 1wk, 1mo, 3mo) Returns: pd.DataFrame: Simüle edilmiş hisse verisi """ from datetime import datetime, timedelta # Sembolden sayısal değer üret (tutarlılık için) seed = sum(ord(c) for c in symbol) np.random.seed(seed) # Periyodu işle end_date = datetime.now() if period == "1d": days = 1 elif period == "5d": days = 5 elif period == "1mo": days = 30 elif period == "3mo": days = 90 elif period == "6mo": days = 180 elif period == "1y": days = 365 elif period == "2y": days = 365 * 2 elif period == "5y": days = 365 * 5 elif period == "10y": days = 365 * 10 elif period == "ytd": days = (end_date - datetime(end_date.year, 1, 1)).days else: # max veya bilinmeyen format days = 365 start_date = end_date - timedelta(days=days) # Aralığı işle ve veri noktası sayısını belirle is_intraday = interval in ['1m', '2m', '5m', '15m', '30m', '60m', '90m', '1h'] if is_intraday: # Gün içi veri için sadece son 7 günü kullan if days > 7: start_date = end_date - timedelta(days=7) # Yalnızca çalışma saatlerini (9:30-18:00) içeren tarih aralığı oluştur business_hours = [] current_date = start_date while current_date <= end_date: if current_date.weekday() < 5: # Pazartesi-Cuma for hour in range(9, 18): for minute in range(0, 60, 5): # 5 dakikalık aralıklar if hour == 9 and minute < 30: continue # 9:30'dan önce işlem yok if hour == 17 and minute > 0: break # 17:00'dan sonra işlem yok business_hours.append(datetime(current_date.year, current_date.month, current_date.day, hour, minute)) current_date += timedelta(days=1) dates = business_hours else: # Günlük veya daha büyük aralıklar için normal tarih aralığı oluştur if interval == '1d': # Her iş günü dates = pd.date_range(start=start_date, end=end_date, freq='B') elif interval == '5d': # Her 5 iş günü dates = pd.date_range(start=start_date, end=end_date, freq='5B') elif interval == '1wk': # Her hafta dates = pd.date_range(start=start_date, end=end_date, freq='W') elif interval == '1mo': # Her ay dates = pd.date_range(start=start_date, end=end_date, freq='M') elif interval == '3mo': # Her 3 ay dates = pd.date_range(start=start_date, end=end_date, freq='3M') else: # Varsayılan olarak iş günleri dates = pd.date_range(start=start_date, end=end_date, freq='B') # Temel fiyat değerleri (hisse sembolü bazında) # BIST hisseleri için gerçekçi fiyat aralıkları (10-500 TL arası) base_price = np.random.uniform(10, 500) # Fiyat trendini belirle (yükseliş, düşüş veya yatay) trend = np.random.choice(['up', 'down', 'sideways'], p=[0.5, 0.3, 0.2]) n = len(dates) if n == 0: # Boş tarih aralığı oluşursa # Varsayılan olarak bir günlük veri oluştur dates = [end_date] n = 1 # Trend bazlı fiyat hareketi oluştur if trend == 'up': daily_change = np.random.uniform(0.001, 0.01, n) # Ortalama %0.1 - %1 yükseliş elif trend == 'down': daily_change = np.random.uniform(-0.01, -0.001, n) # Ortalama %0.1 - %1 düşüş else: # sideways daily_change = np.random.uniform(-0.005, 0.005, n) # -%0.5 - %0.5 değişim # Rastgele dalgalanma ekle volatility = np.random.uniform(0.005, 0.03) # %0.5 - %3 volatilite noise = np.random.normal(0, volatility, n) daily_returns = daily_change + noise # Kümülatif getiri hesapla cumulative_returns = np.cumprod(1 + daily_returns) # Başlangıç fiyatını uygula close_prices = base_price * cumulative_returns # Açılış, yüksek ve düşük fiyatları oluştur intraday_volatility = volatility * 0.5 open_prices = close_prices * (1 + np.random.normal(0, intraday_volatility, n)) high_prices = np.maximum(close_prices, open_prices) * (1 + np.abs(np.random.normal(0, intraday_volatility, n))) low_prices = np.minimum(close_prices, open_prices) * (1 - np.abs(np.random.normal(0, intraday_volatility, n))) # Hacim değerlerini oluştur - fiyat hareketine bağlı olarak hacim değişimi base_volume = np.random.randint(50000, 5000000) volume_change = np.abs(daily_returns) * 10 # Büyük fiyat değişimleri daha yüksek hacim volume = base_volume * (1 + volume_change) # DataFrame oluştur df = pd.DataFrame({ 'Open': open_prices, 'High': high_prices, 'Low': low_prices, 'Close': close_prices, 'Volume': volume.astype(int) }, index=dates) return df def get_stock_data(symbol, period="6mo"): """ Hisse senedi verilerini alır Args: symbol (str): Hisse senedi sembolü period (str): Veri periyodu ("1mo", "3mo", "6mo", "1y", "2y", "5y", "max") Returns: pd.DataFrame: Hisse senedi verileri """ try: # Symbol formatını düzelt if not symbol.endswith('.IS'): yahoo_symbol = f"{symbol}.IS" else: yahoo_symbol = symbol symbol = symbol.replace('.IS', '') # İstenen periyodun uzunluğunu değerlendir # Çok uzun periyotlar için veri yoksa kademeli olarak azalt periods_to_try = [period] # 5y istendiyse ve başarısız olursa, daha kısa periyotları dene if period == "5y": periods_to_try.extend(["3y", "2y", "1y", "6mo"]) elif period == "3y": periods_to_try.extend(["2y", "1y", "6mo"]) elif period == "2y": periods_to_try.extend(["1y", "6mo"]) data = pd.DataFrame() used_period = period stock = yf.Ticker(yahoo_symbol) # İlk başarılı periyodu kullan for p in periods_to_try: temp_data = stock.history(period=p) if len(temp_data) >= 30: # En az 30 gün veri olsun data = temp_data used_period = p break if data.empty: print(f"Hisse verisi alınamadı: {symbol}") return pd.DataFrame() # GÜNCEL FİYAT KONTROLÜ VE DÜZELTME try: # Şu anki piyasa fiyatını yf.Ticker.info'dan al stock_info = stock.info # Güncel fiyat bilgisini al current_price = None # Farklı alanları kontrol et (güncel fiyat için) if 'regularMarketPrice' in stock_info and stock_info['regularMarketPrice'] is not None: current_price = stock_info['regularMarketPrice'] elif 'currentPrice' in stock_info and stock_info['currentPrice'] is not None: current_price = stock_info['currentPrice'] elif 'lastPrice' in stock_info and stock_info['lastPrice'] is not None: current_price = stock_info['lastPrice'] if current_price is not None: # Son günün verilerini güncelle - gerçek zamanlı fiyat için last_date = data.index[-1] if datetime.now().date() == last_date.date(): # Bugünkü veri varsa, Close değerini güncelle data.loc[last_date, 'Close'] = current_price # Eğer current_price, günün en yüksek değerinden büyükse, High değerini de güncelle if current_price > data.loc[last_date, 'High']: data.loc[last_date, 'High'] = current_price # Eğer current_price, günün en düşük değerinden küçükse, Low değerini de güncelle if current_price < data.loc[last_date, 'Low']: data.loc[last_date, 'Low'] = current_price else: # Bugünkü veri yoksa ve piyasa açıksa, yeni bir satır ekle now = datetime.now() # Türkiye saatiyle piyasa açık mı kontrol et (9:30-18:00 arası) is_market_open = ( now.weekday() < 5 and # Pazartesi-Cuma ((now.hour == 9 and now.minute >= 30) or now.hour > 9) and # 9:30'dan sonra now.hour < 18 # 18:00'den önce ) if is_market_open: # Yeni bir satır ekle new_row = pd.DataFrame({ 'Open': [current_price], 'High': [current_price], 'Low': [current_price], 'Close': [current_price], 'Volume': [0] # Hacim bilgisi henüz yok }, index=[pd.Timestamp(now)]) # Yeni satırı veri setine ekle data = pd.concat([data, new_row]) print(f"Güncel fiyat alındı ({symbol}): {current_price}") except Exception as e: print(f"Güncel fiyat alınamadı ({symbol}): {str(e)}") if used_period != period: print(f"İstenen periyot ({period}) için veri bulunamadı. Bunun yerine {used_period} kullanıldı.") return data except Exception as e: print(f"Hisse verisi alınırken hata oluştu ({symbol}): {str(e)}") return pd.DataFrame() @st.cache_data(ttl=86400) # 24 saat cache'le def get_company_info(symbol): """ Belirtilen sembol için şirket bilgilerini döndürür Args: symbol (str): Hisse senedi sembolü (BIST) Returns: dict: Şirket bilgilerini içeren sözlük { 'name': Şirket adı, 'sector': Sektör, 'industry': Endüstri, 'website': Web sitesi, 'description': Açıklama, ... } """ try: if symbol and not symbol.endswith('.IS'): yahoo_symbol = f"{symbol}.IS" else: yahoo_symbol = symbol # Yahoo Finance'den şirket bilgilerini al stock = yf.Ticker(yahoo_symbol) info = stock.info # Şirket bilgilerini döndür if info and 'longName' in info: return { 'name': info.get('longName', ''), 'sector': info.get('sector', ''), 'industry': info.get('industry', ''), 'website': info.get('website', ''), 'description': info.get('longBusinessSummary', ''), 'country': info.get('country', 'Türkiye'), 'exchange': info.get('exchange', 'BIST'), 'currency': info.get('currency', 'TRY'), 'symbol': symbol } except Exception as e: print(f"Şirket bilgileri alınamadı ({symbol}): {e}") # Hata durumunda boş sözlük döndür return {} @st.cache_data(ttl=300) # 5 dakika cachele (daha sık güncelleme) def get_market_summary(): """ Piyasa özeti verilerini alır """ try: # BIST 100 endeks verileri bist100 = yf.Ticker("XU100.IS") bist100_data = bist100.history(period="2d") # USD/TRY verileri usdtry = yf.Ticker("USDTRY=X") usdtry_data = usdtry.history(period="2d") # Altın verileri gold = yf.Ticker("GC=F") gold_data = gold.history(period="2d") result = {} # BIST 100 verilerini işle if not bist100_data.empty and len(bist100_data) >= 2: current_price = bist100_data["Close"].iloc[-1] prev_close = bist100_data["Close"].iloc[-2] change = current_price - prev_close change_percent = (change / prev_close) * 100 volume = bist100_data["Volume"].iloc[-1] if "Volume" in bist100_data.columns else 0 status = "yükseliş" if change > 0 else ("düşüş" if change < 0 else "sabit") result["bist100"] = { "value": current_price, "change": change, "change_percent": change_percent, "volume": volume / 1e9, # Milyar TL cinsinden "status": status } else: result["bist100"] = { "value": 0, "change": 0, "change_percent": 0, "volume": 0, "status": "sabit" } # USD/TRY verilerini işle if not usdtry_data.empty and len(usdtry_data) >= 2: current_price = usdtry_data["Close"].iloc[-1] prev_close = usdtry_data["Close"].iloc[-2] change = current_price - prev_close change_percent = (change / prev_close) * 100 high = usdtry_data["High"].iloc[-1] low = usdtry_data["Low"].iloc[-1] status = "yükseliş" if change > 0 else ("düşüş" if change < 0 else "sabit") result["usdtry"] = { "value": current_price, "change": change, "change_percent": change_percent, "range": f"{low:.2f} - {high:.2f}", "status": status } else: result["usdtry"] = { "value": 0, "change": 0, "change_percent": 0, "range": "0.00 - 0.00", "status": "sabit" } # Altın verilerini işle if not gold_data.empty and len(gold_data) >= 2: current_price = gold_data["Close"].iloc[-1] prev_close = gold_data["Close"].iloc[-2] change = current_price - prev_close change_percent = (change / prev_close) * 100 high = gold_data["High"].iloc[-1] low = gold_data["Low"].iloc[-1] status = "yükseliş" if change > 0 else ("düşüş" if change < 0 else "sabit") result["gold"] = { "value": current_price, "change": change, "change_percent": change_percent, "range": f"{low:.1f} - {high:.1f}", "status": status } else: result["gold"] = { "value": 0, "change": 0, "change_percent": 0, "range": "0.0 - 0.0", "status": "sabit" } return result except Exception as e: # Hata durumunda varsayılan değerler döndür return { "bist100": { "value": 0, "change": 0, "change_percent": 0, "volume": 0, "status": "sabit" }, "usdtry": { "value": 0, "change": 0, "change_percent": 0, "range": "0.00 - 0.00", "status": "sabit" }, "gold": { "value": 0, "change": 0, "change_percent": 0, "range": "0.0 - 0.0", "status": "sabit" }, "error": f"Piyasa özeti alınamadı: {str(e)}" } @st.cache_data(ttl=300) # 5 dakika cachele (daha sık güncelleme) def get_popular_stocks(): """ Popüler hisselerin detaylı verilerini döndürür """ popular_stocks_symbols = [ "THYAO", "GARAN", "ASELS", "SISE", "AKBNK", "TCELL", "EREGL", "KCHOL", "VAKBN", "PETKM", "BIMAS", "TUPRS", "SAHOL", "HALKB", "ISCTR", "KOZAA", "PGSUS", "ARCLK", "DOHOL", "GUBRF" ] # Hisse isimlerini tanımla stock_names = { "THYAO": "Türk Hava Yolları", "GARAN": "Garanti BBVA", "ASELS": "Aselsan", "SISE": "Şişe Cam", "AKBNK": "Akbank", "TCELL": "Turkcell", "EREGL": "Erdemir", "KCHOL": "Koç Holding", "VAKBN": "VakıfBank", "PETKM": "Petkim", "BIMAS": "BİM", "TUPRS": "Tüpraş", "SAHOL": "Sabancı Holding", "HALKB": "Halkbank", "ISCTR": "İş Bankası", "KOZAA": "Koza Altın", "PGSUS": "Pegasus", "ARCLK": "Arçelik", "DOHOL": "Doğan Holding", "GUBRF": "Gübre Fabrikaları" } result = [] for symbol in popular_stocks_symbols: try: # Hisse verilerini al stock_data = get_stock_data_cached(f"{symbol}.IS", period="2d") if stock_data is not None and not stock_data.empty and len(stock_data) >= 2: current_price = stock_data["Close"].iloc[-1] prev_close = stock_data["Close"].iloc[-2] change_percent = ((current_price - prev_close) / prev_close) * 100 result.append({ "symbol": symbol, "name": stock_names.get(symbol, symbol), "value": current_price, "change_percent": change_percent }) else: # Veri alınamazsa varsayılan değerler result.append({ "symbol": symbol, "name": stock_names.get(symbol, symbol), "value": 0.0, "change_percent": 0.0 }) except Exception as e: # Hata durumunda varsayılan değerler result.append({ "symbol": symbol, "name": stock_names.get(symbol, symbol), "value": 0.0, "change_percent": 0.0 }) return result @st.cache_data(ttl=600) # 10 dakika cachele (haberler için) def get_stock_news(symbol, limit=5): """ Belirtilen hisse senedi sembolü için haberleri getirir. Args: symbol (str): Hisse senedi sembolü (örn: THYAO) limit (int): Gösterilecek maksimum haber sayısı Returns: list: Haberler listesi [ { "title": Haber başlığı, "publisher": Yayıncı, "link": Haber linki, "published": Yayın tarihi }, ... ] """ try: # Sembol formatını kontrol et if not symbol.endswith('.IS'): yahoo_symbol = f"{symbol}.IS" else: yahoo_symbol = symbol # Yahoo Finance'den haberleri al stock = yf.Ticker(yahoo_symbol) news = stock.news # Sonuçları formatlama formatted_news = [] if news: for item in news[:limit]: formatted_news.append({ "title": item.get("title", ""), "publisher": item.get("publisher", ""), "link": item.get("link", ""), "published": datetime.fromtimestamp(item.get("providerPublishTime", 0)).strftime("%d.%m.%Y %H:%M") }) return formatted_news except Exception as e: st.error(f"Haberler alınırken hata oluştu: {e}") return [] @st.cache_data(ttl=86400) # 24 saat cache'le def get_stock_list(index_name="BIST 100"): """ Belirtilen endekse ait hisse listesini döndürür Args: index_name (str): Endeks adı ('BIST 30', 'BIST 50', 'BIST 100') Returns: list: Endeksteki hisse kodlarını içeren liste (.IS uzantılı) """ try: bist30_stocks = [ "AKBNK.IS", "ARCLK.IS", "ASELS.IS", "BIMAS.IS", "EKGYO.IS", "EREGL.IS", "FROTO.IS", "GARAN.IS", "HALKB.IS", "HEKTS.IS", "ISCTR.IS", "KCHOL.IS", "KOZAA.IS", "KOZAL.IS", "KRDMD.IS", "PETKM.IS", "PGSUS.IS", "SAHOL.IS", "SASA.IS", "SISE.IS", "TCELL.IS", "THYAO.IS", "TOASO.IS", "TUPRS.IS", "VAKBN.IS", "VESTL.IS", "YKBNK.IS", "TAVHL.IS", "ENJSA.IS", "SOKM.IS" ] bist50_stocks = bist30_stocks + [ "ALARK.IS", "ALBRK.IS", "CIMSA.IS", "DOHOL.IS", "ESEN.IS", "GESAN.IS", "IPEKE.IS", "ISGYO.IS", "KLMSN.IS", "KONTR.IS", "ODAS.IS", "OYAKC.IS", "PRKME.IS", "SMRTG.IS", "TSKB.IS", "TRGYO.IS", "TTKOM.IS", "ULKER.IS", "YBTAS.IS", "ZOREN.IS" ] bist100_stocks = bist50_stocks + [ "AEFES.IS", "AGHOL.IS", "AKFYE.IS", "AKSA.IS", "AKSEN.IS", "ALGYO.IS", "ASUZU.IS", "AYDEM.IS", "BAGFS.IS", "BASGZ.IS", "BRSAN.IS", "BRISA.IS", "CCOLA.IS", "CEMTS.IS", "ENKAI.IS", "ERBOS.IS", "EUPWR.IS", "GLYHO.IS", "GUBRF.IS", "HSVGY.IS", "INDES.IS", "ISDMR.IS", "ISGSY.IS", "ISMEN.IS", "KARTN.IS", "KERVT.IS", "LOGO.IS", "MGROS.IS", "MPARK.IS", "NETAS.IS", "NUHCM.IS", "OTKAR.IS", "OYAKT.IS", "SELEC.IS", "SKBNK.IS", "TATGD.IS", "TKFEN.IS", "TUKAS.IS", "VESBE.IS", "YATAS.IS", "ZRGYO.IS", "AGESA.IS", "AKSA.IS", "BRYAT.IS", "DOAS.IS", "GWIND.IS", "KMPUR.IS", "MAVI.IS", "SDTTR.IS", "SMRTG.IS" ] if index_name == "BIST 30": return bist30_stocks elif index_name == "BIST 50": return bist50_stocks elif index_name == "BIST 100": return bist100_stocks else: st.warning(f"Bilinmeyen endeks: {index_name}. BIST 100 döndürülüyor.") return bist100_stocks except Exception as e: st.error(f"Hisse listesi alınırken hata: {str(e)}") return [] @st.cache_data(ttl=86400) # 24 saat cache'le def get_all_bist_stocks(): """ Borsa İstanbul'daki tüm hisse senetlerinin listesini döndürür. Returns: list: BIST'teki tüm hisse kodlarını içeren liste (uzantısız, örn: "THYAO") """ try: # BIST'teki tüm hisselerin statik listesi # Gerçek uygulamada bu liste bir API veya web scraping ile dinamik olarak alınabilir all_bist_stocks = [ "ACSEL", "ADEL", "ADESE", "AEFES", "AFYON", "AGESA", "AGHOL", "AGYO", "AHGAZ", "AKBNK", "AKCNS", "AKFGY", "AKFYE", "AKGRT", "AKMGY", "AKSA", "AKSEN", "AKSGY", "AKSUE", "AKYHO", "ALARK", "ALBRK", "ALCAR", "ALCTL", "ALFAS", "ALGYO", "ALKA", "ALKIM", "ALMAD", "ALTIN", "ALYAG", "ANACM", "ANELE", "ANGEN", "ANHYT", "ANSGR", "ARASE", "ARCEN", "ARCLK", "ARDYZ", "ARENA", "ARSAN", "ARZUM", "ASELS", "ASGYO", "ASTOR", "ASUZU", "ATAGY", "ATATP", "ATEKS", "ATLAS", "ATSYH", "AVGYO", "AVHOL", "AVOD", "AVTUR", "AYCES", "AYDEM", "AYEN", "AYES", "AYGAZ", "AZTEK", "BAGFS", "BAKAB", "BALAT", "BANVT", "BARMA", "BASGZ", "BAYRK", "BEYAZ", "BIGCH", "BIMAS", "BIOEN", "BIZIM", "BJKAS", "BLCYT", "BNTAS", "BOBET", "BOSSA", "BRISA", "BRKSN", "BRMEN", "BRLSM", "BRSAN", "BRYAT", "BSOKE", "BTCIM", "BUCIM", "BURCE", "BURVA", "BVSAN", "CANTE", "CASA", "CCOLA", "CELHA", "CEMAS", "CEMTS", "CEOEM", "CIMSA", "CLEBI", "CONSE", "COSMO", "CRDFA", "CRFSA", "CUSAN", "DAGHL", "DAGI", "DAPGM", "DENGE", "DERHL", "DERIM", "DESA", "DESPC", "DEVA", "DGATE", "DIRIT", "DITAS", "DMSAS", "DNISI", "DOAS", "DOBUR", "DOCO", "DOGUB", "DOHOL", "DOKTA", "DURDO", "DYOBY", "ECILC", "ECZYT", "EDIP", "EGCEY", "EGCYO", "EGEEN", "EGEPO", "EGGUB", "EGPRO", "EGSER", "EKGYO", "EKIZ", "EKSUN", "ELITE", "EMKEL", "EMNIS", "ENJSA", "ENKAI", "ENSRI", "EPLAS", "ERBOS", "EREGL", "ERSU", "ESCAR", "ESCOM", "ESEN", "ETILR", "ETYAT", "EUPWR", "EUREN", "EUHOL", "EUKYO", "EUYO", "FADE", "FBBNK", "FENER", "FLAP", "FMIZP", "FONET", "FORMT", "FRIGO", "FROTO", "GARAN", "GARFA", "GEDIK", "GEDZA", "GEREL", "GESAN", "GLBMD", "GLCVY", "GLDTR", "GLRYH", "GLYHO", "GMTAS", "GOODY", "GOZDE", "GRNYO", "GRSEL", "GRTRK", "GSDDE", "GSDHO", "GSRAY", "GUBRF", "GWIND", "GZNMI", "HALKB", "HATEK", "HDFGS", "HEDEF", "HEKTS", "HKTM", "HLGYO", "HTTBT", "HUBVC", "HUNER", "HURGZ", "ICBCT", "IDEAS", "IDGYO", "IEYHO", "IHEVA", "IHGZT", "IHLAS", "IHLGM", "IHYAY", "INDES", "INFO", "INTEM", "INVEO", "IPEKE", "ISATR", "ISBTR", "ISCTR", "ISDMR", "ISFIN", "ISGSY", "ISGYO", "ISKPL", "ISYAT", "ITTFH", "IZFAS", "IZINV", "JANTS", "KAPLM", "KAREL", "KARSN", "KARTN", "KARYE", "KATMR", "KAYSE", "KCAER", "KCHOL", "KENT", "KERVN", "KERVT", "KFEIN", "KGYO", "KLGYO", "KLMSN", "KLNMA", "KLRHO", "KMPUR", "KNFRT", "KONKA", "KONTR", "KONYA", "KORDS", "KORFZ", "KORTS", "KOSLF", "KOZAA", "KOZAL", "KPHOL", "KRDMA", "KRDMB", "KRDMD", "KRGYO", "KRONT", "KRPLS", "KRSTL", "KRTEK", "KRVGD", "KSTUR", "KTSKR", "KUTPO", "KUYAS", "LIDFA", "LINK", "LKMNH", "LOGO", "LUKSK", "LVENT", "MACKO", "MAKIM", "MAKTK", "MANAS", "MARKA", "MARTI", "MAVI", "MEDTR", "MEGAP", "MERCN", "MERIT", "MERKO", "METRO", "METUR", "MGROS", "MIATK", "MIPAZ", "MMCAS", "MNDRS", "MNDTR", "MOBTL", "MPARK", "MRGYO", "MRSHL", "MSGYO", "MTRKS", "MTRYO", "MZHLD", "NATEN", "NETAS", "NETHO", "NIKAY", "NTGAZ", "NTHOL", "NUGYO", "NUHCM", "ODAS", "OLMIP", "ORGE", "ORMA", "OSMEN", "OYLUM", "OZGYO", "OZKGY", "OZRDN", "OZSUB", "PAGYO", "PAMEL", "PAPIL", "PARSN", "PASEU", "PCILT", "PEGYO", "PEKGY", "PENGD", "PENTA", "PETKM", "PETUN", "PGSUS", "PINSU", "PKART", "PKENT", "PLTUR", "PNLSN", "POLHO", "POLTK", "PRKAB", "PRKME", "PRZMA", "PSDTC", "PSGYO", "QNBFB", "QNBFL", "QUAGR", "RALYH", "RAYSG", "RHYAY", "RODRG", "ROYAL", "RTALB", "RUBNS", "RYGYO", "RYSAS", "SAFKR", "SAHOL", "SAMAT", "SANEL", "SANFM", "SANKO", "SARKY", "SASA", "SAYAS", "SDTTR", "SEGYO", "SELEC", "SELGD", "SELVA", "SEYKM", "SISE", "SKBNK", "SKTAS", "SMART", "SMRTG", "SNGYO", "SNKRN", "SNPAM", "SODSN", "SOKM", "SONME", "SRVGY", "SUMAS", "SUNTK", "SUWEN", "TARIS", "TATGD", "TAVHL", "TBORG", "TCELL", "TDGYO", "TEKTU", "TERA", "TETMT", "TEZOL", "TFNVK", "TGSAS", "THYAO", "TIMUR", "TKFEN", "TKNSA", "TKURU", "TLMAN", "TMPOL", "TMSN", "TOASO", "TRCAS", "TRGYO", "TRILC", "TSGYO", "TSKB", "TSPOR", "TTKOM", "TTRAK", "TUCLK", "TUKAS", "TUPRS", "TUREX", "TURGG", "TURSG", "TVCKS", "TVRKS", "ULUFA", "ULUSE", "ULUUN", "UMPAS", "UNLU", "USAK", "UZERB", "VAKBN", "VAKKO", "VAKVK", "VANGD", "VBTYZ", "VERTU", "VERUS", "VESBE", "VESTL", "VKFYO", "VKGYO", "VKING", "YAPRK", "YATAS", "YAYLA", "YBTAS", "YDSYO", "YEOTK", "YESIL", "YGGYO", "YGYO", "YKBNK", "YKSLN", "YONGA", "YUNSA", "YYAPI", "YYLGD", "ZOREN", "ZRGYO" ] return all_bist_stocks except Exception as e: st.error(f"Tüm hisse listesi alınırken hata: {str(e)}") return []