GarGerry commited on
Commit
715f9f2
Β·
verified Β·
1 Parent(s): 1aabc74

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +109 -67
app.py CHANGED
@@ -5,88 +5,130 @@ import pandas as pd
5
  import matplotlib.pyplot as plt
6
  import scipy.optimize as sco
7
 
8
- def get_stock_data(tickers, start, end): data = yf.download(tickers, start=start, end=end)
9
-
10
- if data.empty:
11
- st.error("Data saham tidak ditemukan. Periksa ticker atau rentang tanggal.")
12
- return None
13
-
14
- if 'Adj Close' in data.columns:
15
- return data['Adj Close']
16
- elif 'Close' in data.columns:
17
- st.warning("Menggunakan 'Close' karena 'Adj Close' tidak tersedia.")
18
- return data['Close']
19
- else:
20
- st.error("Data harga penutupan tidak ditemukan.")
21
- return None
22
-
23
- def calculate_returns(data):
 
24
  log_returns = np.log(data / data.shift(1))
25
  return log_returns.mean() * 252, log_returns.cov() * 252
 
 
 
 
 
 
 
 
26
 
27
- def optimize_portfolio(returns, cov_matrix): num_assets = len(returns)
 
 
 
 
 
28
 
29
- def sharpe_ratio(weights):
30
- portfolio_return = np.dot(weights, returns)
31
- portfolio_volatility = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))
32
- return -portfolio_return / portfolio_volatility
 
 
 
 
 
 
 
 
 
 
 
33
 
34
- constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1})
35
- bounds = tuple((0, 1) for _ in range(num_assets))
36
- init_guess = num_assets * [1. / num_assets]
37
 
38
- result = sco.minimize(sharpe_ratio, init_guess, method='SLSQP', bounds=bounds, constraints=constraints)
39
- return result.x if result.success else None
40
 
41
- def generate_efficient_frontier(returns, cov_matrix, num_portfolios=5000): num_assets = len(returns) results = np.zeros((3, num_portfolios))
 
 
 
 
 
42
 
43
- for i in range(num_portfolios):
44
- weights = np.random.dirichlet(np.ones(num_assets), size=1)[0]
45
- portfolio_return = np.dot(weights, returns)
46
- portfolio_volatility = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))
47
- sharpe_ratio = portfolio_return / portfolio_volatility
48
 
49
- results[0, i] = portfolio_return
50
- results[1, i] = portfolio_volatility
51
- results[2, i] = sharpe_ratio
52
 
53
- return results
 
 
 
 
 
54
 
55
- st.title("Analisis Portofolio Saham Optimal (Model Markowitz)")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
 
57
- def get_recommended_stocks(): return "KLBF.JK, SIDO.JK, KAEF.JK, TLKM.JK, UNVR.JK" # Saham relevan saat pandemi
58
 
59
- 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
60
 
61
- st.write("Rekomendasi Saham yang Bertahan Saat COVID-19:") st.write(get_recommended_stocks())
62
 
63
- 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"))
64
 
65
- 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)
66
 
67
- st.subheader("Statistik Saham")
68
- st.write(stock_data.describe())
69
-
70
- if optimal_weights is not None:
71
- st.subheader("Bobot Portofolio Optimal")
72
- portfolio_weights = {stock: weight for stock, weight in zip(stock_data.columns, optimal_weights)}
73
- st.write(portfolio_weights)
74
-
75
- fig, ax = plt.subplots()
76
- ax.pie(optimal_weights, labels=stock_data.columns, autopct='%1.1f%%', startangle=140)
77
- ax.axis('equal')
78
- st.pyplot(fig)
79
-
80
- results = generate_efficient_frontier(mean_returns, cov_matrix)
81
-
82
- st.subheader("Efficient Frontier")
83
- fig, ax = plt.subplots()
84
- scatter = ax.scatter(results[1, :], results[0, :], c=results[2, :], cmap="viridis", marker='o')
85
- ax.set_xlabel("Risiko (Standar Deviasi)")
86
- ax.set_ylabel("Return Tahunan")
87
- ax.set_title("Efficient Frontier")
88
- fig.colorbar(scatter, label="Sharpe Ratio")
89
- st.pyplot(fig)
90
- else:
91
- st.error("Optimasi portofolio gagal. Coba dengan saham yang berbeda.")
92
 
 
5
  import matplotlib.pyplot as plt
6
  import scipy.optimize as sco
7
 
8
+ def get_stock_data(tickers, start, end):
9
+ data = yf.download(tickers, start=start, end=end)
10
+
11
+ if data.empty:
12
+ st.error("Data saham tidak ditemukan. Periksa ticker atau rentang tanggal.")
13
+ return None
14
+
15
+ if 'Adj Close' in data.columns:
16
+ return data['Adj Close']
17
+ elif 'Close' in data.columns:
18
+ st.warning("Menggunakan 'Close' karena 'Adj Close' tidak tersedia.")
19
+ return data['Close']
20
+ else:
21
+ st.error("Data harga penutupan tidak ditemukan.")
22
+ return None
23
+
24
+ def calculate_returns(data):
25
  log_returns = np.log(data / data.shift(1))
26
  return log_returns.mean() * 252, log_returns.cov() * 252
27
+
28
+ def optimize_portfolio(returns, cov_matrix):
29
+ num_assets = len(returns)
30
+
31
+ def sharpe_ratio(weights):
32
+ portfolio_return = np.dot(weights, returns)
33
+ portfolio_volatility = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))
34
+ return -portfolio_return / portfolio_volatility
35
 
36
+ constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1})
37
+ bounds = tuple((0, 1) for _ in range(num_assets))
38
+ init_guess = num_assets * [1. / num_assets]
39
+
40
+ result = sco.minimize(sharpe_ratio, init_guess, method='SLSQP', bounds=bounds, constraints=constraints)
41
+ return result.x if result.success else None
42
 
43
+ def generate_efficient_frontier(returns, cov_matrix, num_portfolios=5000):
44
+ num_assets = len(returns)
45
+ results = np.zeros((3, num_portfolios))
46
+
47
+ for i in range(num_portfolios):
48
+ weights = np.random.dirichlet(np.ones(num_assets), size=1)[0]
49
+ portfolio_return = np.dot(weights, returns)
50
+ portfolio_volatility = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))
51
+ sharpe_ratio = portfolio_return / portfolio_volatility
52
+
53
+ results[0, i] = portfolio_return
54
+ results[1, i] = portfolio_volatility
55
+ results[2, i] = sharpe_ratio
56
+
57
+ return results
58
 
59
+ st.title("Analisis Portofolio Saham Optimal (Model Markowitz)")
 
 
60
 
61
+ def get_recommended_stocks():
62
+ return "KLBF.JK, SIDO.JK, KAEF.JK, TLKM.JK, UNVR.JK"
63
 
64
+ def validate_tickers(tickers):
65
+ invalid_tickers = [t for t in tickers if yf.Ticker(t).history(period='1d').empty]
66
+ if invalid_tickers:
67
+ st.warning(f"Ticker tidak valid atau tidak memiliki data: {', '.join(invalid_tickers)}")
68
+ return False
69
+ return True
70
 
71
+ st.write("Rekomendasi Saham yang Bertahan Saat COVID-19:")
72
+ st.write(get_recommended_stocks())
 
 
 
73
 
74
+ tickers_list = st.text_input("Masukkan ticker saham", "KLBF.JK, SIDO.JK, KAEF.JK").split(", ")
75
+ start_date = st.date_input("Pilih tanggal mulai", pd.to_datetime("2020-01-01"))
76
+ end_date = st.date_input("Pilih tanggal akhir", pd.to_datetime("2023-12-31"))
77
 
78
+ if st.button("Analisis Portofolio"):
79
+ if validate_tickers(tickers_list):
80
+ stock_data = get_stock_data(tickers_list, start_date, end_date)
81
+ if stock_data is not None:
82
+ mean_returns, cov_matrix = calculate_returns(stock_data)
83
+ optimal_weights = optimize_portfolio(mean_returns, cov_matrix)
84
 
85
+ st.subheader("Statistik Saham")
86
+ st.write(stock_data.describe())
87
+
88
+ if optimal_weights is not None:
89
+ st.subheader("Bobot Portofolio Optimal")
90
+ portfolio_weights = {stock: weight for stock, weight in zip(stock_data.columns, optimal_weights)}
91
+ st.write(portfolio_weights)
92
+
93
+ fig, ax = plt.subplots()
94
+ ax.pie(optimal_weights, labels=stock_data.columns, autopct='%1.1f%%', startangle=140)
95
+ ax.axis('equal')
96
+ st.pyplot(fig)
97
+
98
+ results = generate_efficient_frontier(mean_returns, cov_matrix)
99
+
100
+ st.subheader("Efficient Frontier")
101
+ fig, ax = plt.subplots()
102
+ scatter = ax.scatter(results[1, :], results[0, :], c=results[2, :], cmap="viridis", marker='o')
103
+ ax.set_xlabel("Risiko (Standar Deviasi)")
104
+ ax.set_ylabel("Return Tahunan")
105
+ ax.set_title("Efficient Frontier")
106
+ fig.colorbar(scatter, label="Sharpe Ratio")
107
+ st.pyplot(fig)
108
+ else:
109
+ st.error("Optimasi portofolio gagal. Coba dengan saham yang berbeda.")
110
 
 
111
 
112
+ Perbaikan yang dilakukan:
113
 
114
+ 1. Perbaikan indentasi dan struktur kode – Memastikan fungsi dan blok kode memiliki indentasi yang benar untuk menghindari error.
115
 
 
116
 
117
+ 2. Penanganan kesalahan lebih baik – Menambahkan pengecekan jika data saham tidak ditemukan, sehingga aplikasi tidak crash.
118
 
119
+
120
+ 3. Validasi ticker saham – Mengecek apakah ticker yang dimasukkan valid sebelum melakukan analisis.
121
+
122
+
123
+ 4. Penggunaan 'Adj Close' jika tersedia, atau 'Close' sebagai alternatif – Menyesuaikan format data dari Yahoo Finance.
124
+
125
+
126
+ 5. Pemisahan input ticker menggunakan split(", ") – Memastikan input pengguna diproses dengan benar.
127
+
128
+
129
+ 6. Peningkatan tampilan grafik – Menambahkan grafik pie untuk bobot portofolio dan warna pada Efficient Frontier.
130
+
131
+
132
+
133
+ Coba jalankan kode ini di Streamlit dan pastikan semua fungsi berjalan sesuai harapan.
 
 
 
 
 
 
 
 
 
 
134