Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import yfinance as yf | |
| import pandas as pd | |
| import numpy as np | |
| from datetime import datetime, timedelta | |
| import json | |
| import matplotlib.pyplot as plt | |
| import matplotlib.dates as mdates | |
| from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor | |
| from sklearn.preprocessing import StandardScaler, MinMaxScaler | |
| from sklearn.model_selection import train_test_split, TimeSeriesSplit | |
| from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score | |
| from sklearn.svm import SVR | |
| import plotly.graph_objects as go | |
| import plotly.express as px | |
| from plotly.subplots import make_subplots | |
| import tensorflow as tf | |
| from tensorflow.keras.models import Sequential | |
| from tensorflow.keras.layers import LSTM, Dense, Dropout, Bidirectional | |
| from tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau | |
| import requests | |
| from bs4 import BeautifulSoup | |
| import warnings | |
| warnings.filterwarnings('ignore') | |
| # GPU加速设置 | |
| physical_devices = tf.config.list_physical_devices('GPU') | |
| if physical_devices: | |
| tf.config.experimental.set_memory_growth(physical_devices[0], True) | |
| print("GPU acceleration enabled") | |
| else: | |
| print("No GPU available, using CPU") | |
| class KingStockAnalyzer: | |
| def __init__(self): | |
| self.models = { | |
| 'rf': RandomForestRegressor(n_estimators=200, random_state=42, n_jobs=-1), | |
| 'gb': GradientBoostingRegressor(n_estimators=200, random_state=42), | |
| 'svr': SVR(kernel='rbf', C=100, gamma=0.1, epsilon=0.1), | |
| 'lstm': None # Will be built later | |
| } | |
| self.scalers = { | |
| 'standard': StandardScaler(), | |
| 'minmax': MinMaxScaler() | |
| } | |
| self.is_trained = {model: False for model in self.models} | |
| self.sentiment_cache = {} | |
| def calculate_rsi(self, prices, period=14): | |
| delta = prices.diff() | |
| gain = delta.where(delta > 0, 0) | |
| loss = -delta.where(delta < 0, 0) | |
| avg_gain = gain.rolling(window=period).mean() | |
| avg_loss = loss.rolling(window=period).mean() | |
| rs = avg_gain / avg_loss | |
| rsi = 100 - (100 / (1 + rs)) | |
| return rsi | |
| def calculate_stochastic_rsi(self, prices, period=14): | |
| rsi = self.calculate_rsi(prices, period) | |
| rsi_min = rsi.rolling(window=period).min() | |
| rsi_max = rsi.rolling(window=period).max() | |
| stoch_rsi = (rsi - rsi_min) / (rsi_max - rsi_min) * 100 | |
| k_percent = stoch_rsi.rolling(window=3).mean() | |
| d_percent = k_percent.rolling(window=3).mean() | |
| return { | |
| 'k_percent': k_percent.iloc[-1] if not k_percent.empty else 50, | |
| 'd_percent': d_percent.iloc[-1] if not d_percent.empty else 50, | |
| 'stoch_rsi': stoch_rsi | |
| } | |
| def calculate_macd(self, prices, fast=12, slow=26, signal=9): | |
| ema_fast = prices.ewm(span=fast).mean() | |
| ema_slow = prices.ewm(span=slow).mean() | |
| macd_line = ema_fast - ema_slow | |
| signal_line = macd_line.ewm(span=signal).mean() | |
| histogram = macd_line - signal_line | |
| return { | |
| 'macd': macd_line, | |
| 'signal': signal_line, | |
| 'histogram': histogram, | |
| 'macd_value': macd_line.iloc[-1] if not macd_line.empty else 0, | |
| 'signal_value': signal_line.iloc[-1] if not signal_line.empty else 0, | |
| 'histogram_value': histogram.iloc[-1] if not histogram.empty else 0 | |
| } | |
| def calculate_bollinger_bands(self, prices, period=20, std_dev=2): | |
| sma = prices.rolling(window=period).mean() | |
| std = prices.rolling(window=period).std() | |
| upper_band = sma + (std * std_dev) | |
| lower_band = sma - (std * std_dev) | |
| return { | |
| 'upper': upper_band, | |
| 'middle': sma, | |
| 'lower': lower_band, | |
| 'upper_value': upper_band.iloc[-1] if not upper_band.empty else 0, | |
| 'middle_value': sma.iloc[-1] if not sma.empty else 0, | |
| 'lower_value': lower_band.iloc[-1] if not lower_band.empty else 0 | |
| } | |
| def calculate_adx(self, high, low, close, period=14): | |
| plus_dm = high.diff() | |
| minus_dm = low.diff() | |
| plus_dm[plus_dm < 0] = 0 | |
| minus_dm[minus_dm > 0] = 0 | |
| minus_dm = minus_dm.abs() | |
| tr1 = pd.DataFrame(high - low) | |
| tr2 = pd.DataFrame(abs(high - close.shift())) | |
| tr3 = pd.DataFrame(abs(low - close.shift())) | |
| tr = pd.concat([tr1, tr2, tr3], axis=1).max(axis=1) | |
| atr = tr.rolling(window=period).mean() | |
| plus_di = 100 * (plus_dm.rolling(window=period).mean() / atr) | |
| minus_di = 100 * (minus_dm.rolling(window=period).mean() / atr) | |
| dx = 100 * (abs(plus_di - minus_di) / (plus_di + minus_di)) | |
| adx = dx.rolling(window=period).mean() | |
| return { | |
| 'adx': adx, | |
| 'plus_di': plus_di, | |
| 'minus_di': minus_di, | |
| 'adx_value': adx.iloc[-1] if not adx.empty else 25, | |
| 'plus_di_value': plus_di.iloc[-1] if not plus_di.empty else 25, | |
| 'minus_di_value': minus_di.iloc[-1] if not minus_di.empty else 25 | |
| } | |
| def calculate_cci(self, high, low, close, period=20): | |
| tp = (high + low + close) / 3 | |
| sma = tp.rolling(window=period).mean() | |
| mad = tp.rolling(window=period).apply(lambda x: np.fabs(x - x.mean()).mean()) | |
| cci = (tp - sma) / (0.015 * mad) | |
| return { | |
| 'cci': cci, | |
| 'cci_value': cci.iloc[-1] if not cci.empty else 0 | |
| } | |
| def calculate_williams_r(self, high, low, close, period=14): | |
| highest_high = high.rolling(window=period).max() | |
| lowest_low = low.rolling(window=period).min() | |
| williams_r = -100 * (highest_high - close) / (highest_high - lowest_low) | |
| return { | |
| 'williams_r': williams_r, | |
| 'williams_r_value': williams_r.iloc[-1] if not williams_r.empty else -50 | |
| } | |
| def calculate_fibonacci_levels(self, high, low): | |
| diff = high - low | |
| levels = { | |
| '0%': high, | |
| '23.6%': high - (0.236 * diff), | |
| '38.2%': high - (0.382 * diff), | |
| '50%': high - (0.5 * diff), | |
| '61.8%': high - (0.618 * diff), | |
| '78.6%': high - (0.786 * diff), | |
| '100%': low | |
| } | |
| return levels | |
| def calculate_ichimoku_cloud(self, high, low, close, conversion_periods=9, base_periods=26, lagging_span2_periods=52, displacement=26): | |
| # Conversion Line | |
| conversion_line = (high.rolling(window=conversion_periods).max() + low.rolling(window=conversion_periods).min()) / 2 | |
| # Base Line | |
| base_line = (high.rolling(window=base_periods).max() + low.rolling(window=base_periods).min()) / 2 | |
| # Leading Span A | |
| leading_span_a = (conversion_line + base_line) / 2 | |
| # Leading Span B | |
| leading_span_b = (high.rolling(window=lagging_span2_periods).max() + low.rolling(window=lagging_span2_periods).min()) / 2 | |
| # Lagging Span | |
| lagging_span = close.shift(-displacement) | |
| return { | |
| 'conversion_line': conversion_line, | |
| 'base_line': base_line, | |
| 'leading_span_a': leading_span_a, | |
| 'leading_span_b': leading_span_b, | |
| 'lagging_span': lagging_span, | |
| 'conversion_value': conversion_line.iloc[-1] if not conversion_line.empty else 0, | |
| 'base_value': base_line.iloc[-1] if not base_line.empty else 0, | |
| 'leading_a_value': leading_span_a.iloc[-1] if not leading_span_a.empty else 0, | |
| 'leading_b_value': leading_span_b.iloc[-1] if not leading_span_b.empty else 0 | |
| } | |
| def calculate_volume_profile(self, data, bins=10): | |
| price_min = data['Low'].min() | |
| price_max = data['High'].max() | |
| price_range = price_max - price_min | |
| bin_size = price_range / bins | |
| volume_profile = {} | |
| total_volume = data['Volume'].sum() | |
| for i in range(bins): | |
| lower_bound = price_min + i * bin_size | |
| upper_bound = price_min + (i + 1) * bin_size | |
| bin_volume = data[(data['Close'] >= lower_bound) & (data['Close'] < upper_bound)]['Volume'].sum() | |
| volume_profile[f"{lower_bound:.2f}-{upper_bound:.2f}"] = { | |
| 'volume': bin_volume, | |
| 'percent': (bin_volume / total_volume) * 100 if total_volume > 0 else 0 | |
| } | |
| return volume_profile | |
| def calculate_market_sentiment(self, symbol): | |
| # Check cache first | |
| if symbol in self.sentiment_cache: | |
| return self.sentiment_cache[symbol] | |
| try: | |
| # This is a simplified sentiment analysis using news headlines | |
| # In a real application, you would use a proper news API and NLP model | |
| url = f"https://finance.yahoo.com/quote/{symbol}" | |
| headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'} | |
| response = requests.get(url, headers=headers) | |
| soup = BeautifulSoup(response.text, 'html.parser') | |
| # Extract headlines (simplified) | |
| headlines = [] | |
| for item in soup.select('h3'): | |
| headlines.append(item.get_text()) | |
| # Simple sentiment scoring based on keywords | |
| positive_words = ['rise', 'gain', 'up', 'high', 'bull', 'growth', 'profit', 'success', 'strong'] | |
| negative_words = ['fall', 'loss', 'down', 'low', 'bear', 'decline', 'risk', 'weak', 'drop'] | |
| sentiment_score = 0 | |
| for headline in headlines[:10]: # Only check first 10 headlines | |
| headline_lower = headline.lower() | |
| for word in positive_words: | |
| if word in headline_lower: | |
| sentiment_score += 1 | |
| for word in negative_words: | |
| if word in headline_lower: | |
| sentiment_score -= 1 | |
| # Normalize to -100 to 100 scale | |
| max_possible = len(headlines[:10]) * max(len(positive_words), len(negative_words)) | |
| if max_possible > 0: | |
| sentiment_score = (sentiment_score / max_possible) * 100 | |
| # Cache the result | |
| self.sentiment_cache[symbol] = { | |
| 'score': max(-100, min(100, sentiment_score)), | |
| 'headlines': headlines[:5] # Store first 5 headlines | |
| } | |
| return self.sentiment_cache[symbol] | |
| except Exception as e: | |
| print(f"Sentiment analysis error: {str(e)}") | |
| return {'score': 0, 'headlines': []} | |
| def build_lstm_model(self, input_shape): | |
| model = Sequential([ | |
| Bidirectional(LSTM(128, return_sequences=True), input_shape=input_shape), | |
| Dropout(0.2), | |
| Bidirectional(LSTM(64, return_sequences=True)), | |
| Dropout(0.2), | |
| Bidirectional(LSTM(32)), | |
| Dropout(0.2), | |
| Dense(32, activation='relu'), | |
| Dense(1) | |
| ]) | |
| model.compile(optimizer='adam', loss='mse', metrics=['mae']) | |
| return model | |
| def prepare_ml_features(self, data): | |
| df = data.copy() | |
| # Teknik göstergeler | |
| df['RSI'] = self.calculate_rsi(df['Close']) | |
| macd_data = self.calculate_macd(df['Close']) | |
| df['MACD'] = macd_data['macd'] | |
| df['MACD_Signal'] = macd_data['signal'] | |
| df['MACD_Hist'] = macd_data['histogram'] | |
| bb_data = self.calculate_bollinger_bands(df['Close']) | |
| df['BB_Upper'] = bb_data['upper'] | |
| df['BB_Middle'] = bb_data['middle'] | |
| df['BB_Lower'] = bb_data['lower'] | |
| df['BB_Width'] = (bb_data['upper'] - bb_data['lower']) / bb_data['middle'] | |
| adx_data = self.calculate_adx(df['High'], df['Low'], df['Close']) | |
| df['ADX'] = adx_data['adx'] | |
| df['Plus_DI'] = adx_data['plus_di'] | |
| df['Minus_DI'] = adx_data['minus_di'] | |
| cci_data = self.calculate_cci(df['High'], df['Low'], df['Close']) | |
| df['CCI'] = cci_data['cci'] | |
| williams_data = self.calculate_williams_r(df['High'], df['Low'], df['Close']) | |
| df['Williams_R'] = williams_data['williams_r'] | |
| ichimoku_data = self.calculate_ichimoku_cloud(df['High'], df['Low'], df['Close']) | |
| df['Conversion_Line'] = ichimoku_data['conversion_line'] | |
| df['Base_Line'] = ichimoku_data['base_line'] | |
| df['Leading_Span_A'] = ichimoku_data['leading_span_a'] | |
| df['Leading_Span_B'] = ichimoku_data['leading_span_b'] | |
| # Hareketli ortalamalar | |
| df['MA_5'] = df['Close'].rolling(window=5).mean() | |
| df['MA_10'] = df['Close'].rolling(window=10).mean() | |
| df['MA_20'] = df['Close'].rolling(window=20).mean() | |
| df['MA_50'] = df['Close'].rolling(window=50).mean() | |
| # Fiyat değişimleri | |
| df['Price_Change'] = df['Close'].pct_change() | |
| df['High_Low_Pct'] = (df['High'] - df['Low']) / df['Close'] | |
| df['Close_Open_Pct'] = (df['Close'] - df['Open']) / df['Open'] | |
| # Hacim göstergeleri | |
| df['Volume_Change'] = df['Volume'].pct_change() | |
| df['Volume_MA'] = df['Volume'].rolling(window=20).mean() | |
| df['Volume_Ratio'] = df['Volume'] / df['Volume_MA'] | |
| # Volatilite | |
| df['Volatility'] = df['Price_Change'].rolling(window=20).std() | |
| # Gelecek fiyat (tahmin edilecek hedef) | |
| df['Future_Price_1d'] = df['Close'].shift(-1) | |
| df['Future_Price_5d'] = df['Close'].shift(-5) | |
| df['Future_Price_10d'] = df['Close'].shift(-10) | |
| # Eksik değerleri temizle | |
| df.dropna(inplace=True) | |
| return df | |
| def prepare_lstm_data(self, data, look_back=30): | |
| df = self.prepare_ml_features(data) | |
| # Özellikler ve hedef | |
| features = df.drop(['Future_Price_1d', 'Future_Price_5d', 'Future_Price_10d', 'Dividends', 'Stock Splits'], axis=1, errors='ignore') | |
| targets = { | |
| '1d': df['Future_Price_1d'], | |
| '5d': df['Future_Price_5d'], | |
| '10d': df['Future_Price_10d'] | |
| } | |
| # Veriyi ölçeklendir | |
| features_scaled = self.scalers['minmax'].fit_transform(features) | |
| # LSTM için veri hazırlama | |
| X, y = {}, {} | |
| for horizon in ['1d', '5d', '10d']: | |
| X[horizon] = [] | |
| y[horizon] = [] | |
| for i in range(look_back, len(features_scaled)): | |
| X[horizon].append(features_scaled[i-look_back:i]) | |
| y[horizon].append(targets[horizon].iloc[i]) | |
| X[horizon] = np.array(X[horizon]) | |
| y[horizon] = np.array(y[horizon]) | |
| return X, y, features.columns | |
| def train_models(self, symbol, start_date, end_date): | |
| try: | |
| # Veri çekme | |
| stock = yf.Ticker(symbol) | |
| data = stock.history(start=start_date, end=end_date) | |
| if data.empty: | |
| return False | |
| # Geleneksel ML modelleri için veri hazırlama | |
| df = self.prepare_ml_features(data) | |
| if len(df) < 60: # Yeterli veri yoksa | |
| return False | |
| # Özellikler ve hedef | |
| features = df.drop(['Future_Price_1d', 'Future_Price_5d', 'Future_Price_10d', 'Dividends', 'Stock Splits'], axis=1, errors='ignore') | |
| target_1d = df['Future_Price_1d'] | |
| target_5d = df['Future_Price_5d'] | |
| target_10d = df['Future_Price_10d'] | |
| # Veriyi ölçeklendir | |
| features_scaled = self.scalers['standard'].fit_transform(features) | |
| # Geleneksel ML modellerini eğit | |
| for model_name in ['rf', 'gb', 'svr']: | |
| try: | |
| self.models[model_name].fit(features_scaled, target_5d) | |
| self.is_trained[model_name] = True | |
| except Exception as e: | |
| print(f"Error training {model_name}: {str(e)}") | |
| self.is_trained[model_name] = False | |
| # LSTM modelini eğit | |
| try: | |
| X_lstm, y_lstm, feature_names = self.prepare_lstm_data(data) | |
| # Modeli oluştur | |
| self.models['lstm'] = { | |
| '1d': self.build_lstm_model((X_lstm['1d'].shape[1], X_lstm['1d'].shape[2])), | |
| '5d': self.build_lstm_model((X_lstm['5d'].shape[1], X_lstm['5d'].shape[2])), | |
| '10d': self.build_lstm_model((X_lstm['10d'].shape[1], X_lstm['10d'].shape[2])) | |
| } | |
| # Callbacks | |
| early_stopping = EarlyStopping(patience=10, restore_best_weights=True) | |
| reduce_lr = ReduceLROnPlateau(factor=0.1, patience=5) | |
| # Her ufuk için modeli eğit | |
| for horizon in ['1d', '5d', '10d']: | |
| self.models['lstm'][horizon].fit( | |
| X_lstm[horizon], y_lstm[horizon], | |
| epochs=50, | |
| batch_size=32, | |
| validation_split=0.2, | |
| callbacks=[early_stopping, reduce_lr], | |
| verbose=0 | |
| ) | |
| self.is_trained['lstm'] = True | |
| except Exception as e: | |
| print(f"Error training LSTM: {str(e)}") | |
| self.is_trained['lstm'] = False | |
| return True | |
| except Exception as e: | |
| print(f"Model training error: {str(e)}") | |
| return False | |
| def predict_prices(self, data): | |
| predictions = {} | |
| try: | |
| # Geleneksel ML modelleri için veri hazırlama | |
| df = self.prepare_ml_features(data) | |
| if df.empty: | |
| return predictions | |
| # Son satırı al (güncel veri) | |
| last_row = df.iloc[-1:].drop(['Future_Price_1d', 'Future_Price_5d', 'Future_Price_10d', 'Dividends', 'Stock Splits'], axis=1, errors='ignore') | |
| # Ölçeklendir | |
| last_row_scaled = self.scalers['standard'].transform(last_row) | |
| # Geleneksel ML modelleri ile tahmin yap | |
| for model_name in ['rf', 'gb', 'svr']: | |
| if self.is_trained[model_name]: | |
| try: | |
| pred = self.models[model_name].predict(last_row_scaled)[0] | |
| predictions[model_name] = pred | |
| except Exception as e: | |
| print(f"Error predicting with {model_name}: {str(e)}") | |
| # LSTM ile tahmin yap | |
| if self.is_trained['lstm']: | |
| try: | |
| X_lstm, _, _ = self.prepare_lstm_data(data) | |
| for horizon in ['1d', '5d', '10d']: | |
| if horizon in X_lstm and len(X_lstm[horizon]) > 0: | |
| pred = self.models['lstm'][horizon].predict(X_lstm[horizon][-1:])[0][0] | |
| predictions[f'lstm_{horizon}'] = pred | |
| except Exception as e: | |
| print(f"Error predicting with LSTM: {str(e)}") | |
| return predictions | |
| except Exception as e: | |
| print(f"Prediction error: {str(e)}") | |
| return predictions | |
| def calculate_portfolio_metrics(self, data, risk_free_rate=0.02): | |
| try: | |
| # Günlük getirileri hesapla | |
| daily_returns = data['Close'].pct_change().dropna() | |
| # Yıllık getiriyi hesapla | |
| annual_return = daily_returns.mean() * 252 | |
| # Yıllık volatiliteyi hesapla | |
| annual_volatility = daily_returns.std() * np.sqrt(252) | |
| # Sharpe Oranı | |
| sharpe_ratio = (annual_return - risk_free_rate) / annual_volatility if annual_volatility > 0 else 0 | |
| # Maksimum Çekilme | |
| cumulative_returns = (1 + daily_returns).cumprod() | |
| running_max = cumulative_returns.cummax() | |
| drawdown = (cumulative_returns - running_max) / running_max | |
| max_drawdown = drawdown.min() | |
| # Sortino Oranı | |
| downside_returns = daily_returns[daily_returns < 0] | |
| downside_volatility = downside_returns.std() * np.sqrt(252) if len(downside_returns) > 0 else 0 | |
| sortino_ratio = (annual_return - risk_free_rate) / downside_volatility if downside_volatility > 0 else 0 | |
| # Calmar Oranı | |
| calmar_ratio = annual_return / abs(max_drawdown) if max_drawdown != 0 else 0 | |
| # VaR (Value at Risk) | |
| var_95 = daily_returns.quantile(0.05) | |
| return { | |
| 'annual_return': annual_return, | |
| 'annual_volatility': annual_volatility, | |
| 'sharpe_ratio': sharpe_ratio, | |
| 'max_drawdown': max_drawdown, | |
| 'sortino_ratio': sortino_ratio, | |
| 'calmar_ratio': calmar_ratio, | |
| 'var_95': var_95 | |
| } | |
| except Exception as e: | |
| print(f"Portfolio metrics error: {str(e)}") | |
| return {} | |
| def analyze_stock(self, symbol, start_date, end_date, investment_type): | |
| try: | |
| # Modeli eğit | |
| model_trained = self.train_models(symbol, start_date, end_date) | |
| # Veri çekme | |
| stock = yf.Ticker(symbol) | |
| data = stock.history(start=start_date, end=end_date) | |
| if data.empty: | |
| return f"❌ No data found for {symbol}", "", None, None | |
| # Temel bilgileri al | |
| info = stock.info | |
| company_name = info.get('shortName', 'Unknown') | |
| sector = info.get('sector', 'Unknown') | |
| industry = info.get('industry', 'Unknown') | |
| market_cap = info.get('marketCap', 0) | |
| pe_ratio = info.get('trailingPE', 0) | |
| eps = info.get('trailingEps', 0) | |
| # Mevcut fiyat | |
| current_price = data['Close'].iloc[-1] | |
| period_high = data['High'].max() | |
| period_low = data['Low'].min() | |
| # Piyasa duyarlılığı | |
| sentiment = self.calculate_market_sentiment(symbol) | |
| # Teknik göstergeler | |
| stoch_data = self.calculate_stochastic_rsi(data['Close']) | |
| k_percent = stoch_data['k_percent'] | |
| d_percent = stoch_data['d_percent'] | |
| macd_data = self.calculate_macd(data['Close']) | |
| macd = macd_data['macd_value'] | |
| macd_signal = macd_data['signal_value'] | |
| macd_hist = macd_data['histogram_value'] | |
| bb_data = self.calculate_bollinger_bands(data['Close']) | |
| bb_upper = bb_data['upper_value'] | |
| bb_middle = bb_data['middle_value'] | |
| bb_lower = bb_data['lower_value'] | |
| rsi = self.calculate_rsi(data['Close']).iloc[-1] | |
| adx_data = self.calculate_adx(data['High'], data['Low'], data['Close']) | |
| adx = adx_data['adx_value'] | |
| plus_di = adx_data['plus_di_value'] | |
| minus_di = adx_data['minus_di_value'] | |
| cci_data = self.calculate_cci(data['High'], data['Low'], data['Close']) | |
| cci = cci_data['cci_value'] | |
| williams_data = self.calculate_williams_r(data['High'], data['Low'], data['Close']) | |
| williams_r = williams_data['williams_r_value'] | |
| ichimoku_data = self.calculate_ichimoku_cloud(data['High'], data['Low'], data['Close']) | |
| conversion = ichimoku_data['conversion_value'] | |
| base = ichimoku_data['base_value'] | |
| leading_a = ichimoku_data['leading_a_value'] | |
| leading_b = ichimoku_data['leading_b_value'] | |
| # Hacim profili | |
| volume_profile = self.calculate_volume_profile(data) | |
| # Portföy metrikleri | |
| portfolio_metrics = self.calculate_portfolio_metrics(data) | |
| # Stochastic RSI Puanı | |
| if k_percent < 20 and d_percent < 20: | |
| if k_percent > d_percent: | |
| stoch_signal = "Strong Buy" | |
| stoch_score = 85 | |
| else: | |
| stoch_signal = "Oversold" | |
| stoch_score = 75 | |
| elif k_percent > 80 and d_percent > 80: | |
| if k_percent < d_percent: | |
| stoch_signal = "Strong Sell" | |
| stoch_score = 15 | |
| else: | |
| stoch_signal = "Overbought" | |
| stoch_score = 25 | |
| elif k_percent > d_percent: | |
| stoch_signal = "Bullish" | |
| stoch_score = 70 | |
| else: | |
| stoch_signal = "Bearish" | |
| stoch_score = 30 | |
| # MACD Puanı | |
| if macd > macd_signal and macd_hist > 0: | |
| macd_signal_text = "Bullish" | |
| macd_score = 75 | |
| elif macd < macd_signal and macd_hist < 0: | |
| macd_signal_text = "Bearish" | |
| macd_score = 25 | |
| else: | |
| macd_signal_text = "Neutral" | |
| macd_score = 50 | |
| # RSI Puanı | |
| if rsi < 30: | |
| rsi_signal = "Oversold" | |
| rsi_score = 80 | |
| elif rsi > 70: | |
| rsi_signal = "Overbought" | |
| rsi_score = 20 | |
| else: | |
| rsi_signal = "Neutral" | |
| rsi_score = 50 | |
| # Bollinger Bantları Puanı | |
| if current_price < bb_lower: | |
| bb_signal = "Below Lower Band - Buy Signal" | |
| bb_score = 80 | |
| elif current_price > bb_upper: | |
| bb_signal = "Above Upper Band - Sell Signal" | |
| bb_score = 20 | |
| else: | |
| bb_signal = "Within Bands" | |
| bb_score = 50 | |
| # ADX Puanı | |
| if adx > 25: | |
| if plus_di > minus_di: | |
| adx_signal = "Strong Bullish Trend" | |
| adx_score = 80 | |
| else: | |
| adx_signal = "Strong Bearish Trend" | |
| adx_score = 20 | |
| else: | |
| adx_signal = "Weak Trend" | |
| adx_score = 50 | |
| # CCI Puanı | |
| if cci < -100: | |
| cci_signal = "Oversold" | |
| cci_score = 80 | |
| elif cci > 100: | |
| cci_signal = "Overbought" | |
| cci_score = 20 | |
| else: | |
| cci_signal = "Neutral" | |
| cci_score = 50 | |
| # Williams %R Puanı | |
| if williams_r < -80: | |
| williams_signal = "Oversold" | |
| williams_score = 80 | |
| elif williams_r > -20: | |
| williams_signal = "Overbought" | |
| williams_score = 20 | |
| else: | |
| williams_signal = "Neutral" | |
| williams_score = 50 | |
| # Ichimoku Puanı | |
| if current_price > leading_a and current_price > leading_b and conversion > base: | |
| ichimoku_signal = "Strong Bullish" | |
| ichimoku_score = 85 | |
| elif current_price < leading_a and current_price < leading_b and conversion < base: | |
| ichimoku_signal = "Strong Bearish" | |
| ichimoku_score = 15 | |
| elif current_price > leading_a and conversion > base: | |
| ichimoku_signal = "Bullish" | |
| ichimoku_score = 70 | |
| elif current_price < leading_a and conversion < base: | |
| ichimoku_signal = "Bearish" | |
| ichimoku_score = 30 | |
| else: | |
| ichimoku_signal = "Neutral" | |
| ichimoku_score = 50 | |
| # Piyasa Duyarlılığı Puanı | |
| if sentiment['score'] > 30: | |
| sentiment_signal = "Bullish Sentiment" | |
| sentiment_score = 75 | |
| elif sentiment['score'] < -30: | |
| sentiment_signal = "Bearish Sentiment" | |
| sentiment_score = 25 | |
| else: | |
| sentiment_signal = "Neutral Sentiment" | |
| sentiment_score = 50 | |
| # Portföy Metrikleri Puanı | |
| sharpe = portfolio_metrics.get('sharpe_ratio', 0) | |
| max_dd = portfolio_metrics.get('max_drawdown', 0) | |
| if sharpe > 1.5 and max_dd > -0.2: | |
| portfolio_signal = "Excellent Risk-Return" | |
| portfolio_score = 85 | |
| elif sharpe > 1.0 and max_dd > -0.3: | |
| portfolio_signal = "Good Risk-Return" | |
| portfolio_score = 70 | |
| elif sharpe > 0.5 and max_dd > -0.4: | |
| portfolio_signal = "Average Risk-Return" | |
| portfolio_score = 55 | |
| else: | |
| portfolio_signal = "Poor Risk-Return" | |
| portfolio_score = 30 | |
| # Makine öğrenmesi tahminleri | |
| predictions = self.predict_prices(data) | |
| ml_scores = {} | |
| for model, pred in predictions.items(): | |
| if pred is not None: | |
| change_percent = ((pred - current_price) / current_price) * 100 | |
| if change_percent > 5: | |
| ml_scores[model] = {'signal': f"Strong Buy (+{change_percent:.2f}%)", 'score': 85} | |
| elif change_percent > 2: | |
| ml_scores[model] = {'signal': f"Buy (+{change_percent:.2f}%)", 'score': 70} | |
| elif change_percent < -5: | |
| ml_scores[model] = {'signal': f"Strong Sell ({change_percent:.2f}%)", 'score': 15} | |
| elif change_percent < -2: | |
| ml_scores[model] = {'signal': f"Sell ({change_percent:.2f}%)", 'score': 30} | |
| else: | |
| ml_scores[model] = {'signal': f"Neutral ({change_percent:.2f}%)", 'score': 50} | |
| else: | |
| ml_scores[model] = {'signal': "No Prediction", 'score': 50} | |
| # Tüm ML modellerinin ortalama puanı | |
| ml_avg_score = np.mean([ml_scores[model]['score'] for model in ml_scores]) if ml_scores else 50 | |
| # Fibonacci seviyeleri | |
| fib_levels = self.calculate_fibonacci_levels(period_high, period_low) | |
| # Fibonacci Puanı | |
| fib_score = 50 | |
| fib_position = "Neutral" | |
| if current_price <= fib_levels['78.6%']: | |
| fib_score = 85 | |
| fib_position = "Strong Support Zone" | |
| elif current_price <= fib_levels['61.8%']: | |
| fib_score = 75 | |
| fib_position = "Good Support Zone" | |
| elif current_price <= fib_levels['50%']: | |
| fib_score = 65 | |
| fib_position = "Medium Support" | |
| elif current_price <= fib_levels['38.2%']: | |
| fib_score = 55 | |
| fib_position = "Weak Support" | |
| elif current_price >= fib_levels['23.6%']: | |
| fib_score = 35 | |
| fib_position = "Resistance Zone" | |
| # Ağırlıklı final puanı | |
| weights = { | |
| 'short': { | |
| 'stoch': 0.15, 'macd': 0.15, 'rsi': 0.1, 'bb': 0.1, | |
| 'adx': 0.1, 'cci': 0.05, 'williams': 0.05, 'ichimoku': 0.1, | |
| 'sentiment': 0.05, 'portfolio': 0.05, 'fib': 0.05, 'ml': 0.05 | |
| }, | |
| 'medium': { | |
| 'stoch': 0.1, 'macd': 0.1, 'rsi': 0.08, 'bb': 0.08, | |
| 'adx': 0.08, 'cci': 0.05, 'williams': 0.05, 'ichimoku': 0.08, | |
| 'sentiment': 0.08, 'portfolio': 0.1, 'fib': 0.1, 'ml': 0.1 | |
| }, | |
| 'long': { | |
| 'stoch': 0.05, 'macd': 0.05, 'rsi': 0.05, 'bb': 0.05, | |
| 'adx': 0.05, 'cci': 0.05, 'williams': 0.05, 'ichimoku': 0.05, | |
| 'sentiment': 0.1, 'portfolio': 0.2, 'fib': 0.15, 'ml': 0.15 | |
| } | |
| } | |
| weight = weights[investment_type] | |
| final_score = ( | |
| stoch_score * weight['stoch'] + | |
| macd_score * weight['macd'] + | |
| rsi_score * weight['rsi'] + | |
| bb_score * weight['bb'] + | |
| adx_score * weight['adx'] + | |
| cci_score * weight['cci'] + | |
| williams_score * weight['williams'] + | |
| ichimoku_score * weight['ichimoku'] + | |
| sentiment_score * weight['sentiment'] + | |
| portfolio_score * weight['portfolio'] + | |
| fib_score * weight['fib'] + | |
| ml_avg_score * weight['ml'] | |
| ) | |
| # Tavsiye | |
| if final_score >= 75: | |
| recommendation = "🟢 STRONG BUY" | |
| elif final_score >= 60: | |
| recommendation = "🔵 BUY" | |
| elif final_score >= 40: | |
| recommendation = "🟡 HOLD" | |
| elif final_score >= 25: | |
| recommendation = "🟠 SELL" | |
| else: | |
| recommendation = "🔴 STRONG SELL" | |
| # Grafik oluştur | |
| price_chart = self.create_price_chart(data, symbol, bb_data, fib_levels, ichimoku_data) | |
| indicators_chart = self.create_indicators_chart(data, symbol, stoch_data, macd_data, rsi, adx_data, cci_data, williams_data) | |
| volume_profile_chart = self.create_volume_profile_chart(data, symbol, volume_profile) | |
| # Format çıktı | |
| result_text = f""" | |
| # 📊 {symbol.upper()} - {company_name} Analysis | |
| ## {recommendation} | |
| ## Score: {final_score:.1f}/100 | |
| ### 💰 Company Info: | |
| - **Sector:** {sector} | |
| - **Industry:** {industry} | |
| - **Market Cap:** ${market_cap:,.0f} | |
| - **P/E Ratio:** {pe_ratio:.2f} | |
| - **EPS:** ${eps:.2f} | |
| ### 💰 Price Info: | |
| - **Current Price:** ${current_price:.2f} | |
| - **Period High:** ${period_high:.2f} | |
| - **Period Low:** ${period_low:.2f} | |
| ### 🔄 Technical Indicators: | |
| - **Stochastic RSI:** {stoch_signal} ({k_percent:.1f}K, {d_percent:.1f}D) | |
| - **MACD:** {macd_signal_text} (MACD: {macd:.2f}, Signal: {macd_signal:.2f}) | |
| - **RSI:** {rsi_signal} ({rsi:.1f}) | |
| - **Bollinger Bands:** {bb_signal} | |
| - **ADX:** {adx_signal} ({adx:.1f}) | |
| - **CCI:** {cci_signal} ({cci:.1f}) | |
| - **Williams %R:** {williams_signal} ({williams_r:.1f}) | |
| - **Ichimoku:** {ichimoku_signal} | |
| ### 🔢 Fibonacci: | |
| - **Position:** {fib_position} | |
| ### 📈 Market Sentiment: | |
| - **Signal:** {sentiment_signal} | |
| - **Score:** {sentiment['score']:.1f}/100 | |
| ### 📊 Portfolio Metrics: | |
| - **Signal:** {portfolio_signal} | |
| - **Sharpe Ratio:** {sharpe:.2f} | |
| - **Max Drawdown:** {max_dd:.2%} | |
| - **Annual Return:** {portfolio_metrics.get('annual_return', 0):.2%} | |
| - **Volatility:** {portfolio_metrics.get('annual_volatility', 0):.2%} | |
| ### 🤖 Machine Learning Predictions: | |
| """ | |
| for model, pred_info in ml_scores.items(): | |
| result_text += f"- **{model.upper()}:** {pred_info['signal']}\n" | |
| result_text += f""" | |
| ### ⚖️ Weights ({investment_type.title()}): | |
| - **Stochastic RSI:** {weight['stoch']*100:.0f}% | |
| - **MACD:** {weight['macd']*100:.0f}% | |
| - **RSI:** {weight['rsi']*100:.0f}% | |
| - **Bollinger Bands:** {weight['bb']*100:.0f}% | |
| - **ADX:** {weight['adx']*100:.0f}% | |
| - **CCI:** {weight['cci']*100:.0f}% | |
| - **Williams %R:** {weight['williams']*100:.0f}% | |
| - **Ichimoku:** {weight['ichimoku']*100:.0f}% | |
| - **Sentiment:** {weight['sentiment']*100:.0f}% | |
| - **Portfolio Metrics:** {weight['portfolio']*100:.0f}% | |
| - **Fibonacci:** {weight['fib']*100:.0f}% | |
| - **Machine Learning:** {weight['ml']*100:.0f}% | |
| ### 📅 Period: {start_date} to {end_date} | |
| """ | |
| # JSON için | |
| json_result = { | |
| "symbol": symbol.upper(), | |
| "company_name": company_name, | |
| "sector": sector, | |
| "industry": industry, | |
| "final_score": round(final_score, 1), | |
| "recommendation": recommendation, | |
| "current_price": round(current_price, 2), | |
| "fundamentals": { | |
| "market_cap": market_cap, | |
| "pe_ratio": pe_ratio, | |
| "eps": eps | |
| }, | |
| "technical_indicators": { | |
| "stochastic_rsi": { | |
| "signal": stoch_signal, | |
| "k_percent": round(k_percent, 1), | |
| "d_percent": round(d_percent, 1), | |
| "score": stoch_score | |
| }, | |
| "macd": { | |
| "signal": macd_signal_text, | |
| "macd": round(macd, 2), | |
| "signal_line": round(macd_signal, 2), | |
| "histogram": round(macd_hist, 2), | |
| "score": macd_score | |
| }, | |
| "rsi": { | |
| "signal": rsi_signal, | |
| "value": round(rsi, 1), | |
| "score": rsi_score | |
| }, | |
| "bollinger_bands": { | |
| "signal": bb_signal, | |
| "upper": round(bb_upper, 2), | |
| "middle": round(bb_middle, 2), | |
| "lower": round(bb_lower, 2), | |
| "score": bb_score | |
| }, | |
| "adx": { | |
| "signal": adx_signal, | |
| "adx": round(adx, 1), | |
| "plus_di": round(plus_di, 1), | |
| "minus_di": round(minus_di, 1), | |
| "score": adx_score | |
| }, | |
| "cci": { | |
| "signal": cci_signal, | |
| "value": round(cci, 1), | |
| "score": cci_score | |
| }, | |
| "williams_r": { | |
| "signal": williams_signal, | |
| "value": round(williams_r, 1), | |
| "score": williams_score | |
| }, | |
| "ichimoku": { | |
| "signal": ichimoku_signal, | |
| "conversion": round(conversion, 2), | |
| "base": round(base, 2), | |
| "leading_a": round(leading_a, 2), | |
| "leading_b": round(leading_b, 2), | |
| "score": ichimoku_score | |
| } | |
| }, | |
| "fibonacci": { | |
| "position": fib_position, | |
| "score": fib_score, | |
| "levels": {k: round(v, 2) for k, v in fib_levels.items()} | |
| }, | |
| "market_sentiment": { | |
| "signal": sentiment_signal, | |
| "score": sentiment['score'], | |
| "headlines": sentiment['headlines'][:3] | |
| }, | |
| "portfolio_metrics": { | |
| "signal": portfolio_signal, | |
| "sharpe_ratio": sharpe, | |
| "max_drawdown": max_dd, | |
| "annual_return": portfolio_metrics.get('annual_return', 0), | |
| "annual_volatility": portfolio_metrics.get('annual_volatility', 0), | |
| "sortino_ratio": portfolio_metrics.get('sortino_ratio', 0), | |
| "calmar_ratio": portfolio_metrics.get('calmar_ratio', 0), | |
| "var_95": portfolio_metrics.get('var_95', 0), | |
| "score": portfolio_score | |
| }, | |
| "machine_learning": { | |
| "predictions": {model: {'signal': pred_info['signal'], 'score': pred_info['score']} for model, pred_info in ml_scores.items()}, | |
| "average_score": ml_avg_score, | |
| "models_trained": model_trained | |
| }, | |
| "analysis_date": datetime.now().isoformat() | |
| } | |
| return result_text, json.dumps(json_result, indent=2), price_chart, indicators_chart, volume_profile_chart | |
| except Exception as e: | |
| return f"❌ Error: {str(e)}", "", None, None, None | |
| def create_price_chart(self, data, symbol, bb_data, fib_levels, ichimoku_data): | |
| fig = make_subplots( | |
| rows=2, cols=1, | |
| shared_xaxes=True, | |
| vertical_spacing=0.1, | |
| subplot_titles=(f'{symbol} Price with Technical Indicators', 'Volume'), | |
| row_width=[0.7, 0.3] | |
| ) | |
| # Fiyat grafiği | |
| fig.add_trace(go.Candlestick( | |
| x=data.index, | |
| open=data['Open'], | |
| high=data['High'], | |
| low=data['Low'], | |
| close=data['Close'], | |
| name='Price' | |
| ), row=1, col=1) | |
| # Bollinger Bantları | |
| fig.add_trace(go.Scatter( | |
| x=data.index, | |
| y=bb_data['upper'], | |
| mode='lines', | |
| name='BB Upper', | |
| line=dict(color='red', width=1) | |
| ), row=1, col=1) | |
| fig.add_trace(go.Scatter( | |
| x=data.index, | |
| y=bb_data['middle'], | |
| mode='lines', | |
| name='BB Middle', | |
| line=dict(color='blue', width=1) | |
| ), row=1, col=1) | |
| fig.add_trace(go.Scatter( | |
| x=data.index, | |
| y=bb_data['lower'], | |
| mode='lines', | |
| name='BB Lower', | |
| line=dict(color='red', width=1) | |
| ), row=1, col=1) | |
| # Ichimoku Cloud | |
| fig.add_trace(go.Scatter( | |
| x=data.index, | |
| y=ichimoku_data['leading_span_a'], | |
| mode='lines', | |
| name='Leading Span A', | |
| line=dict(color='green', width=1), | |
| fill=None | |
| ), row=1, col=1) | |
| fig.add_trace(go.Scatter( | |
| x=data.index, | |
| y=ichimoku_data['leading_span_b'], | |
| mode='lines', | |
| name='Leading Span B', | |
| line=dict(color='red', width=1), | |
| fill='tonexty', | |
| fillcolor='rgba(0,255,0,0.1)' | |
| ), row=1, col=1) | |
| # Fibonacci seviyeleri | |
| for level, value in fib_levels.items(): | |
| fig.add_shape( | |
| type="line", line_color="purple", line_width=1, line_dash="dot", | |
| x0=data.index[0], x1=data.index[-1], y0=value, y1=value, | |
| row=1, col=1 | |
| ) | |
| fig.add_annotation( | |
| x=data.index[-1], y=value, | |
| text=f"Fib {level}: ${value:.2f}", | |
| showarrow=False, xshift=10, row=1, col=1 | |
| ) | |
| # Hacim grafiği | |
| colors = ['green' if row['Open'] - row['Close'] <= 0 else 'red' for index, row in data.iterrows()] | |
| fig.add_trace(go.Bar( | |
| x=data.index, | |
| y=data['Volume'], | |
| name='Volume', | |
| marker_color=colors | |
| ), row=2, col=1) | |
| # Grafik düzeni | |
| fig.update_layout( | |
| title=f'{symbol} Technical Analysis', | |
| xaxis_title='Date', | |
| yaxis_title='Price ($)', | |
| template='plotly_dark', | |
| height=800, | |
| legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1) | |
| ) | |
| fig.update_xaxes(rangeslider_visible=False) | |
| return fig | |
| def create_indicators_chart(self, data, symbol, stoch_data, macd_data, rsi, adx_data, cci_data, williams_data): | |
| fig = make_subplots( | |
| rows=3, cols=2, | |
| shared_xaxes=True, | |
| vertical_spacing=0.05, | |
| subplot_titles=( | |
| 'Stochastic RSI', 'RSI', | |
| 'MACD', 'ADX', | |
| 'CCI', 'Williams %R' | |
| ), | |
| row_heights=[0.33, 0.33, 0.33] | |
| ) | |
| # Stochastic RSI | |
| fig.add_trace(go.Scatter( | |
| x=data.index, | |
| y=stoch_data['stoch_rsi'], | |
| mode='lines', | |
| name='Stoch RSI', | |
| line=dict(color='blue') | |
| ), row=1, col=1) | |
| fig.add_hline(y=80, line_dash="dash", line_color="red", row=1, col=1) | |
| fig.add_hline(y=20, line_dash="dash", line_color="green", row=1, col=1) | |
| # RSI | |
| rsi_series = self.calculate_rsi(data['Close']) | |
| fig.add_trace(go.Scatter( | |
| x=data.index, | |
| y=rsi_series, | |
| mode='lines', | |
| name='RSI', | |
| line=dict(color='purple') | |
| ), row=1, col=2) | |
| fig.add_hline(y=70, line_dash="dash", line_color="red", row=1, col=2) | |
| fig.add_hline(y=30, line_dash="dash", line_color="green", row=1, col=2) | |
| # MACD | |
| fig.add_trace(go.Scatter( | |
| x=data.index, | |
| y=macd_data['macd'], | |
| mode='lines', | |
| name='MACD', | |
| line=dict(color='blue') | |
| ), row=2, col=1) | |
| fig.add_trace(go.Scatter( | |
| x=data.index, | |
| y=macd_data['signal'], | |
| mode='lines', | |
| name='Signal', | |
| line=dict(color='red') | |
| ), row=2, col=1) | |
| fig.add_trace(go.Bar( | |
| x=data.index, | |
| y=macd_data['histogram'], | |
| name='Histogram', | |
| marker_color='green' | |
| ), row=2, col=1) | |
| # ADX | |
| fig.add_trace(go.Scatter( | |
| x=data.index, | |
| y=adx_data['adx'], | |
| mode='lines', | |
| name='ADX', | |
| line=dict(color='black') | |
| ), row=2, col=2) | |
| fig.add_trace(go.Scatter( | |
| x=data.index, | |
| y=adx_data['plus_di'], | |
| mode='lines', | |
| name='+DI', | |
| line=dict(color='green') | |
| ), row=2, col=2) | |
| fig.add_trace(go.Scatter( | |
| x=data.index, | |
| y=adx_data['minus_di'], | |
| mode='lines', | |
| name='-DI', | |
| line=dict(color='red') | |
| ), row=2, col=2) | |
| fig.add_hline(y=25, line_dash="dash", line_color="blue", row=2, col=2) | |
| # CCI | |
| fig.add_trace(go.Scatter( | |
| x=data.index, | |
| y=cci_data['cci'], | |
| mode='lines', | |
| name='CCI', | |
| line=dict(color='orange') | |
| ), row=3, col=1) | |
| fig.add_hline(y=100, line_dash="dash", line_color="red", row=3, col=1) | |
| fig.add_hline(y=-100, line_dash="dash", line_color="green", row=3, col=1) | |
| # Williams %R | |
| fig.add_trace(go.Scatter( | |
| x=data.index, | |
| y=williams_data['williams_r'], | |
| mode='lines', | |
| name='Williams %R', | |
| line=dict(color='cyan') | |
| ), row=3, col=2) | |
| fig.add_hline(y=-20, line_dash="dash", line_color="red", row=3, col=2) | |
| fig.add_hline(y=-80, line_dash="dash", line_color="green", row=3, col=2) | |
| # Grafik düzeni | |
| fig.update_layout( | |
| title=f'{symbol} Technical Indicators', | |
| template='plotly_dark', | |
| height=800, | |
| legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1) | |
| ) | |
| fig.update_xaxes(rangeslider_visible=False) | |
| return fig | |
| def create_volume_profile_chart(self, data, symbol, volume_profile): | |
| # Create a volume profile chart | |
| price_levels = [] | |
| volumes = [] | |
| for price_range, info in volume_profile.items(): | |
| low, high = map(float, price_range.split('-')) | |
| mid_price = (low + high) / 2 | |
| price_levels.append(mid_price) | |
| volumes.append(info['volume']) | |
| fig = go.Figure() | |
| fig.add_trace(go.Bar( | |
| x=volumes, | |
| y=price_levels, | |
| orientation='h', | |
| marker_color='green', | |
| name='Volume Profile' | |
| )) | |
| # Add current price line | |
| current_price = data['Close'].iloc[-1] | |
| fig.add_hline(y=current_price, line_dash="dash", line_color="red", | |
| annotation_text=f"Current Price: ${current_price:.2f}") | |
| # Add high and low lines | |
| period_high = data['High'].max() | |
| period_low = data['Low'].min() | |
| fig.add_hline(y=period_high, line_dash="dot", line_color="blue", | |
| annotation_text=f"Period High: ${period_high:.2f}") | |
| fig.add_hline(y=period_low, line_dash="dot", line_color="blue", | |
| annotation_text=f"Period Low: ${period_low:.2f}") | |
| fig.update_layout( | |
| title=f'{symbol} Volume Profile', | |
| xaxis_title='Volume', | |
| yaxis_title='Price ($)', | |
| template='plotly_dark', | |
| height=600 | |
| ) | |
| return fig | |
| # Analyzer'ı başlat | |
| analyzer = KingStockAnalyzer() | |
| def analyze_interface(symbol, start_date, end_date, investment_type): | |
| return analyzer.analyze_stock(symbol, start_date, end_date, investment_type) | |
| def quick_analyze(symbol): | |
| end_date = datetime.now().strftime('%Y-%m-%d') | |
| start_date = (datetime.now() - timedelta(days=180)).strftime('%Y-%m-%d') | |
| return analyzer.analyze_stock(symbol, start_date, end_date, "medium") | |
| # Gradio arayüzü oluştur | |
| with gr.Blocks(title="King Hedge Fund Stock Analyzer", theme=gr.themes.Soft()) as demo: | |
| gr.Markdown("# 👑 King Hedge Fund Stock Analyzer") | |
| gr.Markdown("### Professional Technical Analysis with Machine Learning") | |
| gr.Markdown("10-15 levels above ChatGPT and Claude") | |
| with gr.Row(): | |
| with gr.Column(scale=3): | |
| symbol = gr.Textbox(label="Stock Symbol", value="AAPL", placeholder="Enter symbol (e.g., AAPL)") | |
| start_date = gr.Textbox(label="Start Date", value=(datetime.now() - timedelta(days=180)).strftime('%Y-%m-%d')) | |
| end_date = gr.Textbox(label="End Date", value=datetime.now().strftime('%Y-%m-%d')) | |
| investment_type = gr.Radio(["short", "medium", "long"], value="medium", label="Investment Type") | |
| analyze_btn = gr.Button("🚀 Analyze Stock", variant="primary") | |
| gr.Markdown("### Quick Analysis:") | |
| with gr.Row(): | |
| aapl_btn = gr.Button("AAPL") | |
| msft_btn = gr.Button("MSFT") | |
| googl_btn = gr.Button("GOOGL") | |
| tsla_btn = gr.Button("TSLA") | |
| amzn_btn = gr.Button("AMZN") | |
| meta_btn = gr.Button("META") | |
| with gr.Tabs(): | |
| with gr.TabItem("Analysis Results"): | |
| result_output = gr.Markdown(label="Analysis Results") | |
| with gr.TabItem("JSON Output"): | |
| json_output = gr.Code(label="JSON Output (for API integration)", language="json") | |
| with gr.TabItem("Price Chart"): | |
| price_chart_output = gr.Plot(label="Price Chart with Technical Indicators") | |
| with gr.TabItem("Indicators Chart"): | |
| indicators_chart_output = gr.Plot(label="Technical Indicators") | |
| with gr.TabItem("Volume Profile"): | |
| volume_profile_output = gr.Plot(label="Volume Profile") | |
| # Event handlers | |
| analyze_btn.click( | |
| analyze_interface, | |
| [symbol, start_date, end_date, investment_type], | |
| [result_output, json_output, price_chart_output, indicators_chart_output, volume_profile_output] | |
| ) | |
| aapl_btn.click(lambda: quick_analyze("AAPL"), outputs=[result_output, json_output, price_chart_output, indicators_chart_output, volume_profile_output]) | |
| msft_btn.click(lambda: quick_analyze("MSFT"), outputs=[result_output, json_output, price_chart_output, indicators_chart_output, volume_profile_output]) | |
| googl_btn.click(lambda: quick_analyze("GOOGL"), outputs=[result_output, json_output, price_chart_output, indicators_chart_output, volume_profile_output]) | |
| tsla_btn.click(lambda: quick_analyze("TSLA"), outputs=[result_output, json_output, price_chart_output, indicators_chart_output, volume_profile_output]) | |
| amzn_btn.click(lambda: quick_analyze("AMZN"), outputs=[result_output, json_output, price_chart_output, indicators_chart_output, volume_profile_output]) | |
| meta_btn.click(lambda: quick_analyze("META"), outputs=[result_output, json_output, price_chart_output, indicators_chart_output, volume_profile_output]) | |
| if __name__ == "__main__": | |
| demo.launch( | |
| server_name="0.0.0.0", | |
| server_port=7860, | |
| share=True | |
| ) |