Spaces:
Sleeping
Sleeping
Enes Berke Karaoğlan
commited on
Commit
·
abf2ca2
1
Parent(s):
a8b14d1
fix: Veri çekme hatası düzeltildi, hata kontrolleri geliştirildi
Browse files
app.py
CHANGED
@@ -2,133 +2,166 @@ import streamlit as st
|
|
2 |
import pandas as pd
|
3 |
import numpy as np
|
4 |
import yfinance as yf
|
|
|
5 |
import plotly.express as px
|
|
|
6 |
|
7 |
-
|
8 |
-
st.title('Portföy Yönetim Aracı')
|
9 |
|
10 |
-
#
|
11 |
-
st.sidebar.header("
|
12 |
-
|
13 |
-
symbols = [sym.strip().upper() for sym in
|
14 |
|
15 |
-
|
16 |
-
|
17 |
for sym in symbols:
|
18 |
-
amount = st.sidebar.number_input(f
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
if not df.empty and not df.isnull().all().all():
|
46 |
-
# Portföy performansını hesaplayın
|
47 |
-
total_investment = sum(amounts.values())
|
48 |
|
|
|
|
|
49 |
if not df.empty:
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
# Grafikler
|
59 |
-
st.subheader("📈 Hisse Senedi Fiyatları")
|
60 |
-
fig = px.line(df, title="Hisse Senedi Fiyatları")
|
61 |
-
st.plotly_chart(fig)
|
62 |
-
|
63 |
-
st.subheader("📊 Portföy Dağılım Grafiği")
|
64 |
-
fig = px.bar(x=amounts.keys(), y=portfolio_value, labels={"x": 'Yatırım Araçları', 'y': 'Portföy Değeri'})
|
65 |
-
st.plotly_chart(fig)
|
66 |
-
|
67 |
-
# Getiri hesaplamaları
|
68 |
-
st.subheader("📅 Günlük Getiriler")
|
69 |
-
daily_returns = df.pct_change().dropna()
|
70 |
-
st.dataframe(daily_returns)
|
71 |
-
|
72 |
-
st.subheader("📅 Aylık Getiriler")
|
73 |
-
monthly_returns = df.resample('M').ffill().pct_change().dropna()
|
74 |
-
st.dataframe(monthly_returns)
|
75 |
-
|
76 |
-
st.subheader("📅 Yıllık Getiriler")
|
77 |
-
annual_returns = df.resample('Y').ffill().pct_change().dropna()
|
78 |
-
st.dataframe(annual_returns)
|
79 |
-
|
80 |
-
# Risk Analizi
|
81 |
-
st.subheader("📊 Volatilite (Yıllık)")
|
82 |
-
volatility = daily_returns.std() * np.sqrt(252)
|
83 |
-
st.dataframe(volatility)
|
84 |
-
|
85 |
-
st.subheader("📉 Beta Değeri")
|
86 |
-
if not daily_returns.empty:
|
87 |
-
beta = daily_returns.cov() / daily_returns.var()
|
88 |
-
st.dataframe(beta)
|
89 |
-
|
90 |
-
# Hareketli Ortalama
|
91 |
-
st.subheader("📊 Hareketli Ortalama")
|
92 |
-
window_size = st.sidebar.slider("Hareketli Ortalama Penceresi (Gün)", 5, 100, 20)
|
93 |
-
moving_avg = df.rolling(window=window_size).mean()
|
94 |
-
st.line_chart(moving_avg)
|
95 |
-
|
96 |
-
# Tarih Aralığı Filtreleme
|
97 |
-
st.subheader("📅 Tarih Aralığına Göre Veri Filtreleme")
|
98 |
-
start_date = st.sidebar.date_input("📅 Başlangıç Tarihi", pd.to_datetime("2023-01-01"))
|
99 |
-
end_date = st.sidebar.date_input("📅 Bitiş Tarihi", pd.to_datetime("2024-01-01"))
|
100 |
-
|
101 |
-
if start_date < end_date:
|
102 |
-
filtered_data = df[(df.index >= start_date) & (df.index <= end_date)]
|
103 |
-
st.line_chart(filtered_data)
|
104 |
else:
|
105 |
-
st.
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
for symbol in symbols:
|
119 |
-
if symbol in df.columns:
|
120 |
-
price_series = [df[symbol].iloc[-1]]
|
121 |
-
for _ in range(365): # 1 yıl
|
122 |
-
price_series.append(price_series[-1] * (1 + np.random.normal(mean_returns[symbol], volatility[symbol])))
|
123 |
-
simulated_prices.append(price_series)
|
124 |
-
|
125 |
-
if simulated_prices:
|
126 |
-
simulation_df[x] = pd.Series([np.sum(sim) for sim in zip(*simulated_prices)])
|
127 |
-
|
128 |
-
st.line_chart(simulation_df)
|
129 |
else:
|
130 |
-
st.warning("
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
import pandas as pd
|
3 |
import numpy as np
|
4 |
import yfinance as yf
|
5 |
+
import plotly.graph_objects as go
|
6 |
import plotly.express as px
|
7 |
+
from datetime import datetime
|
8 |
|
9 |
+
st.title("Portföy Yönetim Aracı")
|
|
|
10 |
|
11 |
+
# Yan panel girdileri
|
12 |
+
st.sidebar.header("Kullanıcı Girdileri")
|
13 |
+
symbols_input = st.sidebar.text_input("Hisse Senedi Sembolleri (virgülle ayrılmış)", value="AAPL, MSFT, TSLA")
|
14 |
+
symbols = [sym.strip().upper() for sym in symbols_input.split(",") if sym.strip()]
|
15 |
|
16 |
+
investment_amounts = {}
|
17 |
+
st.sidebar.subheader("Yatırım Miktarları (Adet)")
|
18 |
for sym in symbols:
|
19 |
+
amount = st.sidebar.number_input(f"{sym} için adet", min_value=0.0, value=0.0, step=1.0)
|
20 |
+
investment_amounts[sym] = amount
|
21 |
+
|
22 |
+
st.sidebar.header("Tarih Aralığı")
|
23 |
+
start_date = st.sidebar.date_input("Başlangıç Tarihi", value=datetime(2022, 1, 3))
|
24 |
+
end_date = st.sidebar.date_input("Bitiş Tarihi", value=datetime(2024, 1, 1))
|
25 |
+
|
26 |
+
st.sidebar.header("Hareketli Ortalama")
|
27 |
+
ma_window = st.sidebar.number_input("Hareketli Ortalama Pencere Boyutu (gün)", min_value=1, value=20, step=1)
|
28 |
+
|
29 |
+
@st.cache_data # st.cache yerine st.cache_data kullanılması önerilir
|
30 |
+
def load_data(symbol, start_date, end_date):
|
31 |
+
try:
|
32 |
+
data = yf.download(symbol, start=start_date, end=end_date)
|
33 |
+
if data.empty:
|
34 |
+
st.warning(f"{symbol} için veri bulunamadı veya boş döndü.")
|
35 |
+
return data
|
36 |
+
except Exception as e:
|
37 |
+
st.error(f"{symbol} verisi çekilirken hata oluştu: {e}")
|
38 |
+
return None
|
39 |
+
|
40 |
+
data_dict = {}
|
41 |
+
for sym in symbols:
|
42 |
+
df = load_data(sym, start_date, end_date)
|
43 |
+
if df is not None:
|
44 |
+
data_dict[sym] = df
|
|
|
|
|
|
|
|
|
45 |
|
46 |
+
st.header("Hisse Senedi Fiyatları")
|
47 |
+
for sym, df in data_dict.items():
|
48 |
if not df.empty:
|
49 |
+
fig = go.Figure()
|
50 |
+
fig.add_trace(go.Scatter(x=df.index, y=df['Close'], mode='lines', name='Kapanış Fiyatı'))
|
51 |
+
fig.add_trace(go.Scatter(x=df.index,
|
52 |
+
y=df['Close'].rolling(window=int(ma_window)).mean(),
|
53 |
+
mode='lines',
|
54 |
+
name=f'{ma_window} Günlük MA'))
|
55 |
+
fig.update_layout(title=f"{sym} Fiyat Grafiği", xaxis_title="Tarih", yaxis_title="Fiyat (USD)")
|
56 |
+
st.plotly_chart(fig)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
57 |
else:
|
58 |
+
st.warning(f"{sym} için çizilecek veri yok.")
|
59 |
+
|
60 |
+
st.header("Portföy Performansı")
|
61 |
+
portfolio_value = 0
|
62 |
+
portfolio_values = {}
|
63 |
+
|
64 |
+
for sym, df in data_dict.items():
|
65 |
+
# Eğer df boş değilse hesaplamaları yap
|
66 |
+
if df is not None and not df.empty:
|
67 |
+
latest_price = df['Close'].iloc[-1]
|
68 |
+
value = latest_price * investment_amounts[sym]
|
69 |
+
portfolio_values[sym] = value
|
70 |
+
portfolio_value += value
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
71 |
else:
|
72 |
+
st.warning(f"{sym} veri seti boş veya None, hesaplamalar atlanıyor.")
|
73 |
+
|
74 |
+
st.write("Güncel Portföy Değeri: $", round(portfolio_value, 2))
|
75 |
+
portfolio_df = pd.DataFrame({
|
76 |
+
"Sembol": list(portfolio_values.keys()),
|
77 |
+
"Değer": list(portfolio_values.values())
|
78 |
+
})
|
79 |
+
fig_bar = px.bar(portfolio_df, x="Sembol", y="Değer", title="Portföy Dağılım Grafiği", labels={"Değer": "Değer ($)"})
|
80 |
+
st.plotly_chart(fig_bar)
|
81 |
+
|
82 |
+
# Getiri Hesaplamaları
|
83 |
+
st.header("Getiri Hesaplamaları")
|
84 |
+
returns_data = {}
|
85 |
+
for sym, df in data_dict.items():
|
86 |
+
df = df.copy()
|
87 |
+
df['Daily Return'] = df['Close'].pct_change()
|
88 |
+
returns_data[sym] = df['Daily Return']
|
89 |
+
|
90 |
+
# Günlük Getiri Tablosu
|
91 |
+
st.subheader("Günlük Getiriler")
|
92 |
+
daily_returns_df = pd.DataFrame({sym: data['Daily Return'] for sym, data in data_dict.items()})
|
93 |
+
st.dataframe(daily_returns_df.tail())
|
94 |
+
|
95 |
+
# Aylık Getiri Hesaplaması
|
96 |
+
st.subheader("Aylık Getiriler")
|
97 |
+
monthly_returns = {}
|
98 |
+
for sym, df in data_dict.items():
|
99 |
+
df = df.copy()
|
100 |
+
df['Monthly Return'] = df['Close'].resample('M').ffill().pct_change()
|
101 |
+
monthly_returns[sym] = df['Monthly Return']
|
102 |
+
monthly_returns_df = pd.DataFrame(monthly_returns)
|
103 |
+
st.dataframe(monthly_returns_df.tail())
|
104 |
+
|
105 |
+
# Yıllık Getiri Hesaplaması
|
106 |
+
st.subheader("Yıllık Getiriler")
|
107 |
+
annual_returns = {}
|
108 |
+
for sym, df in data_dict.items():
|
109 |
+
df = df.copy()
|
110 |
+
df['Annual Return'] = df['Close'].resample('Y').ffill().pct_change()
|
111 |
+
annual_returns[sym] = df['Annual Return']
|
112 |
+
annual_returns_df = pd.DataFrame(annual_returns)
|
113 |
+
st.dataframe(annual_returns_df.tail())
|
114 |
+
|
115 |
+
# Risk Analizi
|
116 |
+
st.header("Risk Analizi")
|
117 |
+
risk_metrics = {}
|
118 |
+
for sym, df in data_dict.items():
|
119 |
+
df = df.copy()
|
120 |
+
daily_vol = df['Daily Return'].std()
|
121 |
+
annual_vol = daily_vol * np.sqrt(252)
|
122 |
+
risk_metrics[sym] = {"Günlük Volatilite": daily_vol, "Yıllık Volatilite": annual_vol}
|
123 |
+
|
124 |
+
risk_df = pd.DataFrame(risk_metrics).T
|
125 |
+
st.dataframe(risk_df)
|
126 |
+
|
127 |
+
# Portföyün Günlük Getirilerinin Hesaplanması (Yatırım miktarlarına göre ağırlıklandırma)
|
128 |
+
portfolio_daily_returns = pd.Series(0, index=list(data_dict.values())[0].index)
|
129 |
+
total_investment = sum(investment_amounts[sym] for sym in symbols if sym in investment_amounts and investment_amounts[sym] > 0)
|
130 |
+
for sym, df in data_dict.items():
|
131 |
+
weight = investment_amounts[sym] / total_investment if total_investment > 0 else 0
|
132 |
+
portfolio_daily_returns += df['Daily Return'] * weight
|
133 |
+
|
134 |
+
# Beta Hesaplaması: Her hisse için, portföy getirisine göre beta = cov(ha, portföy)/var(portföy)
|
135 |
+
beta_values = {}
|
136 |
+
for sym, df in data_dict.items():
|
137 |
+
covariance = np.cov(df['Daily Return'].dropna(), portfolio_daily_returns.dropna())[0, 1]
|
138 |
+
variance = np.var(portfolio_daily_returns.dropna())
|
139 |
+
beta = covariance / variance if variance != 0 else np.nan
|
140 |
+
beta_values[sym] = beta
|
141 |
+
|
142 |
+
beta_df = pd.DataFrame.from_dict(beta_values, orient='index', columns=["Beta"])
|
143 |
+
st.subheader("Beta Değerleri")
|
144 |
+
st.dataframe(beta_df)
|
145 |
+
|
146 |
+
# Monte Carlo Simülasyonu: Portföyün 1 yıl sonraki değeri için 1000 simülasyon
|
147 |
+
st.header("Monte Carlo Simülasyonu ile Gelecek Portföy Değeri Tahmini")
|
148 |
+
simulations = 1000
|
149 |
+
days = 365
|
150 |
+
last_portfolio_value = portfolio_value
|
151 |
+
|
152 |
+
# Portföy günlük getirilerinin ortalama ve standart sapması
|
153 |
+
portfolio_daily_mean = portfolio_daily_returns.mean()
|
154 |
+
portfolio_daily_std = portfolio_daily_returns.std()
|
155 |
+
|
156 |
+
simulation_results = []
|
157 |
+
for i in range(simulations):
|
158 |
+
simulated_value = last_portfolio_value
|
159 |
+
for d in range(days):
|
160 |
+
simulated_return = np.random.normal(portfolio_daily_mean, portfolio_daily_std)
|
161 |
+
simulated_value *= (1 + simulated_return)
|
162 |
+
simulation_results.append(simulated_value)
|
163 |
+
|
164 |
+
fig_hist = px.histogram(simulation_results, nbins=50,
|
165 |
+
title="Monte Carlo Simülasyonu Sonuçları (1 Yıl Sonra Portföy Değeri Dağılımı)",
|
166 |
+
labels={"value": "Portföy Değeri", "count": "Frekans"})
|
167 |
+
st.plotly_chart(fig_hist)
|