GarGerry commited on
Commit
b59b790
·
verified ·
1 Parent(s): 7fb7f14

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +80 -100
app.py CHANGED
@@ -1,105 +1,85 @@
1
- import streamlit as st
2
- import yfinance as yf
3
- import numpy as np
4
- import pandas as pd
5
- import matplotlib.pyplot as plt
6
- import scipy.optimize as sco
7
-
8
- # Fungsi untuk mengunduh data saham
9
- def get_stock_data(tickers, start, end):
10
- data = yf.download(tickers, start=start, end=end)
11
-
12
- if data.empty:
13
- st.error("Data saham tidak ditemukan. Periksa ticker atau rentang tanggal.")
14
- return None
15
-
16
- # Gunakan 'Adj Close' jika ada, jika tidak pakai 'Close'
17
- if 'Adj Close' in data.columns:
18
- return data['Adj Close']
19
- elif 'Close' in data.columns:
20
- st.warning("Menggunakan 'Close' karena 'Adj Close' tidak tersedia.")
21
- return data['Close']
22
- else:
23
- st.error("Data harga penutupan tidak ditemukan.")
24
- return None
25
-
26
- # Fungsi untuk menghitung return tahunan dan matriks kovarians
27
- def calculate_returns(data):
28
- log_returns = np.log(data / data.shift(1))
29
- return log_returns.mean() * 252, log_returns.cov() * 252
30
-
31
- # Fungsi untuk menghitung portofolio optimal
32
- def optimize_portfolio(returns, cov_matrix):
33
- num_assets = len(returns)
34
-
35
- def sharpe_ratio(weights):
36
- portfolio_return = np.dot(weights, returns)
37
- portfolio_volatility = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))
38
- return -portfolio_return / portfolio_volatility # Negatif untuk minimisasi
39
-
40
- constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1})
41
- bounds = tuple((0, 1) for _ in range(num_assets))
42
- init_guess = num_assets * [1. / num_assets]
43
-
44
- result = sco.minimize(sharpe_ratio, init_guess, method='SLSQP', bounds=bounds, constraints=constraints)
45
- return result.x if result.success else None
46
-
47
- # Fungsi untuk mensimulasikan portofolio acak
48
- def generate_efficient_frontier(returns, cov_matrix, num_portfolios=5000):
49
- num_assets = len(returns)
50
- results = np.zeros((3, num_portfolios))
51
-
52
- for i in range(num_portfolios):
53
- weights = np.random.dirichlet(np.ones(num_assets), size=1)[0]
54
- portfolio_return = np.dot(weights, returns)
55
- portfolio_volatility = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))
56
- sharpe_ratio = portfolio_return / portfolio_volatility
57
-
58
- results[0, i] = portfolio_return
59
- results[1, i] = portfolio_volatility
60
- results[2, i] = sharpe_ratio
61
-
62
- return results
63
-
64
- # Streamlit UI
65
  st.title("Analisis Portofolio Saham Optimal (Model Markowitz)")
66
 
67
- # Input Saham & Tanggal
68
- tickers_list = st.text_input("Masukkan ticker saham (contoh: BBCA.JK, TLKM.JK, BBRI.JK)", "BBCA.JK, TLKM.JK, BBRI.JK").split(", ")
69
- start_date = st.date_input("Pilih tanggal mulai", pd.to_datetime("2020-01-01"))
70
- end_date = st.date_input("Pilih tanggal akhir", pd.to_datetime("2023-12-31"))
 
71
 
72
- if st.button("Analisis Portofolio"):
73
- try:
74
- # Ambil data saham
75
- stock_data = get_stock_data(tickers_list, start_date, end_date)
76
 
77
- if stock_data is not None:
78
- st.write("Saham dengan data tersedia:", stock_data.columns) # Debugging
 
 
 
 
 
 
 
 
 
 
 
 
79
 
80
- mean_returns, cov_matrix = calculate_returns(stock_data)
81
-
82
- # Optimasi portofolio
83
- optimal_weights = optimize_portfolio(mean_returns, cov_matrix)
84
-
85
- if optimal_weights is not None:
86
- st.subheader("Bobot Portofolio Optimal:")
87
- for i, stock in enumerate(stock_data.columns):
88
- st.write(f"{stock}: {optimal_weights[i]:.2%}")
89
-
90
- # Simulasi Efficient Frontier
91
- results = generate_efficient_frontier(mean_returns, cov_matrix)
92
-
93
- st.subheader("Efficient Frontier")
94
- fig, ax = plt.subplots()
95
- scatter = ax.scatter(results[1, :], results[0, :], c=results[2, :], cmap="viridis", marker='o')
96
- ax.set_xlabel("Risiko (Standar Deviasi)")
97
- ax.set_ylabel("Return Tahunan")
98
- ax.set_title("Efficient Frontier")
99
- fig.colorbar(scatter, label="Sharpe Ratio")
100
- st.pyplot(fig)
101
- else:
102
- st.error("Optimasi portofolio gagal. Coba dengan saham yang berbeda.")
103
-
104
- except Exception as e:
105
- st.error(f"Terjadi kesalahan: {e}")
 
1
+ import streamlit as st import yfinance as yf import numpy as np import pandas as pd import matplotlib.pyplot as plt import scipy.optimize as sco
2
+
3
+ def get_stock_data(tickers, start, end): data = yf.download(tickers, start=start, end=end)
4
+
5
+ if data.empty:
6
+ st.error("Data saham tidak ditemukan. Periksa ticker atau rentang tanggal.")
7
+ return None
8
+
9
+ if 'Adj Close' in data.columns:
10
+ return data['Adj Close']
11
+ elif 'Close' in data.columns:
12
+ st.warning("Menggunakan 'Close' karena 'Adj Close' tidak tersedia.")
13
+ return data['Close']
14
+ else:
15
+ st.error("Data harga penutupan tidak ditemukan.")
16
+ return None
17
+
18
+ def calculate_returns(data): log_returns = np.log(data / data.shift(1)) return log_returns.mean() * 252, log_returns.cov() * 252
19
+
20
+ def optimize_portfolio(returns, cov_matrix): num_assets = len(returns)
21
+
22
+ def sharpe_ratio(weights):
23
+ portfolio_return = np.dot(weights, returns)
24
+ portfolio_volatility = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))
25
+ return -portfolio_return / portfolio_volatility
26
+
27
+ constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1})
28
+ bounds = tuple((0, 1) for _ in range(num_assets))
29
+ init_guess = num_assets * [1. / num_assets]
30
+
31
+ result = sco.minimize(sharpe_ratio, init_guess, method='SLSQP', bounds=bounds, constraints=constraints)
32
+ return result.x if result.success else None
33
+
34
+ def generate_efficient_frontier(returns, cov_matrix, num_portfolios=5000): num_assets = len(returns) results = np.zeros((3, num_portfolios))
35
+
36
+ for i in range(num_portfolios):
37
+ weights = np.random.dirichlet(np.ones(num_assets), size=1)[0]
38
+ portfolio_return = np.dot(weights, returns)
39
+ portfolio_volatility = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))
40
+ sharpe_ratio = portfolio_return / portfolio_volatility
41
+
42
+ results[0, i] = portfolio_return
43
+ results[1, i] = portfolio_volatility
44
+ results[2, i] = sharpe_ratio
45
+
46
+ return results
47
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  st.title("Analisis Portofolio Saham Optimal (Model Markowitz)")
49
 
50
+ def get_recommended_stocks(): return "KLBF.JK, SIDO.JK, KAEF.JK, TLKM.JK, UNVR.JK" # Saham relevan saat pandemi
51
+
52
+ def validate_tickers(tickers): invalid_tickers = [t for t in tickers if not yf.Ticker(t).history(period='1d').empty] if invalid_tickers: st.warning(f"Ticker tidak valid atau tidak memiliki data: {', '.join(invalid_tickers)}") return False return True
53
+
54
+ st.write("Rekomendasi Saham yang Bertahan Saat COVID-19:") st.write(get_recommended_stocks())
55
 
56
+ tickers_list = st.text_input("Masukkan ticker saham", "KLBF.JK, SIDO.JK, KAEF.JK").split(", ") start_date = st.date_input("Pilih tanggal mulai", pd.to_datetime("2020-01-01")) end_date = st.date_input("Pilih tanggal akhir", pd.to_datetime("2023-12-31"))
 
 
 
57
 
58
+ if st.button("Analisis Portofolio"): if validate_tickers(tickers_list): stock_data = get_stock_data(tickers_list, start_date, end_date) if stock_data is not None: mean_returns, cov_matrix = calculate_returns(stock_data) optimal_weights = optimize_portfolio(mean_returns, cov_matrix)
59
+
60
+ st.subheader("Statistik Saham")
61
+ st.write(stock_data.describe())
62
+
63
+ if optimal_weights is not None:
64
+ st.subheader("Bobot Portofolio Optimal")
65
+ portfolio_weights = {stock: weight for stock, weight in zip(stock_data.columns, optimal_weights)}
66
+ st.write(portfolio_weights)
67
+
68
+ fig, ax = plt.subplots()
69
+ ax.pie(optimal_weights, labels=stock_data.columns, autopct='%1.1f%%', startangle=140)
70
+ ax.axis('equal')
71
+ st.pyplot(fig)
72
 
73
+ results = generate_efficient_frontier(mean_returns, cov_matrix)
74
+
75
+ st.subheader("Efficient Frontier")
76
+ fig, ax = plt.subplots()
77
+ scatter = ax.scatter(results[1, :], results[0, :], c=results[2, :], cmap="viridis", marker='o')
78
+ ax.set_xlabel("Risiko (Standar Deviasi)")
79
+ ax.set_ylabel("Return Tahunan")
80
+ ax.set_title("Efficient Frontier")
81
+ fig.colorbar(scatter, label="Sharpe Ratio")
82
+ st.pyplot(fig)
83
+ else:
84
+ st.error("Optimasi portofolio gagal. Coba dengan saham yang berbeda.")
85
+