GarGerry commited on
Commit
2a180f0
·
verified ·
1 Parent(s): 9711938

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +52 -50
app.py CHANGED
@@ -1,69 +1,71 @@
1
  import streamlit as st
2
- import pandas as pd
3
- import numpy as np
4
  import yfinance as yf
 
 
5
  import matplotlib.pyplot as plt
6
- from scipy.optimize import minimize
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
- st.write("Data mentah yang diunduh:")
12
- st.write(data.head()) # Menampilkan 5 baris pertama untuk debug
13
- if 'Adj Close' in data.columns:
14
- return data['Adj Close']
15
- else:
16
- st.error("Kolom 'Adj Close' tidak ditemukan. Coba cek ticker atau tanggal.")
17
- return None
18
 
19
- # Fungsi untuk menghitung return harian
20
- def calculate_daily_returns(data):
21
- return data.pct_change().dropna()
 
22
 
23
- # Fungsi untuk menghitung portofolio optimal dengan Model Markowitz
24
- def optimize_portfolio(returns):
25
- num_assets = len(returns.columns)
26
- weights = np.random.random(num_assets)
27
- weights /= np.sum(weights)
 
 
 
 
28
 
29
- def portfolio_performance(weights):
30
- port_return = np.sum(returns.mean() * weights) * 252
31
- port_volatility = np.sqrt(np.dot(weights.T, np.dot(returns.cov() * 252, weights)))
32
- return port_volatility
33
 
34
- constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1})
35
- bounds = tuple((0, 1) for _ in range(num_assets))
36
- result = minimize(portfolio_performance, weights, method='SLSQP', bounds=bounds, constraints=constraints)
37
-
38
- return result.x
39
 
40
  # Streamlit UI
41
- st.title("Analisis Portofolio Saham Model Markowitz")
42
 
43
- # Input pengguna untuk daftar saham
44
- tickers = st.text_input("Masukkan kode saham (pisahkan dengan koma)", "BBCA.JK,TLKM.JK,UNVR.JK")
45
  start_date = st.date_input("Pilih tanggal mulai", pd.to_datetime("2020-01-01"))
46
  end_date = st.date_input("Pilih tanggal akhir", pd.to_datetime("2020-12-31"))
47
 
48
- if st.button("Analisis"):
49
- tickers_list = [t.strip() for t in tickers.split(',')]
50
- data = get_stock_data(tickers_list, start_date, end_date)
51
-
52
- if not data.empty:
53
- st.write("Data Harga Saham")
54
- st.line_chart(data)
 
 
 
 
 
55
 
56
- returns = calculate_daily_returns(data)
57
- optimal_weights = optimize_portfolio(returns)
 
 
58
 
59
- st.write("Bobot Optimal Portofolio:")
60
- for ticker, weight in zip(tickers_list, optimal_weights):
61
- st.write(f"{ticker}: {weight:.2%}")
 
 
 
 
 
62
 
63
- # Visualisasi Portofolio
64
- fig, ax = plt.subplots()
65
- ax.pie(optimal_weights, labels=tickers_list, autopct='%1.1f%%', startangle=90)
66
- ax.axis("equal")
67
- st.pyplot(fig)
68
- else:
69
- st.error("Gagal mengambil data saham. Pastikan kode saham benar.")
 
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)['Adj Close']
11
+ return data
 
 
 
 
 
 
12
 
13
+ # Fungsi untuk menghitung return tahunan dan matriks kovarians
14
+ def calculate_returns(data):
15
+ log_returns = np.log(data / data.shift(1))
16
+ return log_returns.mean() * 252, log_returns.cov() * 252
17
 
18
+ # Fungsi untuk menghitung portofolio optimal
19
+ def optimize_portfolio(returns, cov_matrix):
20
+ num_assets = len(returns)
21
+
22
+ # Fungsi untuk menghitung rasio Sharpe (return / risiko)
23
+ def sharpe_ratio(weights):
24
+ portfolio_return = np.dot(weights, returns)
25
+ portfolio_volatility = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))
26
+ return -portfolio_return / portfolio_volatility # Negatif untuk minimisasi
27
 
28
+ constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1}) # Total bobot = 100%
29
+ bounds = tuple((0, 1) for _ in range(num_assets)) # Bobot saham antara 0 - 1
30
+ init_guess = num_assets * [1. / num_assets] # Tebakan awal
 
31
 
32
+ result = sco.minimize(sharpe_ratio, init_guess, method='SLSQP', bounds=bounds, constraints=constraints)
33
+ return result.x # Bobot optimal
 
 
 
34
 
35
  # Streamlit UI
36
+ st.title("Analisis Portofolio Saham Optimal (Model Markowitz)")
37
 
38
+ # Input Saham & Tanggal
39
+ tickers_list = st.text_input("Masukkan ticker saham (contoh: BBCA.JK, TLKM.JK, BBRI.JK)", "BBCA.JK, TLKM.JK, BBRI.JK").split(", ")
40
  start_date = st.date_input("Pilih tanggal mulai", pd.to_datetime("2020-01-01"))
41
  end_date = st.date_input("Pilih tanggal akhir", pd.to_datetime("2020-12-31"))
42
 
43
+ if st.button("Analisis Portofolio"):
44
+ try:
45
+ # Ambil data saham
46
+ stock_data = get_stock_data(tickers_list, start_date, end_date)
47
+ if stock_data.isnull().values.any():
48
+ st.error("Data tidak lengkap atau saham tidak ditemukan.")
49
+ else:
50
+ # Hitung return dan kovarians
51
+ mean_returns, cov_matrix = calculate_returns(stock_data)
52
+
53
+ # Optimasi portofolio
54
+ optimal_weights = optimize_portfolio(mean_returns, cov_matrix)
55
 
56
+ # Tampilkan hasil
57
+ st.subheader("Bobot Portofolio Optimal:")
58
+ for i, stock in enumerate(tickers_list):
59
+ st.write(f"{stock}: {optimal_weights[i]:.2%}")
60
 
61
+ # Plot Efficient Frontier
62
+ st.subheader("Efficient Frontier")
63
+ fig, ax = plt.subplots()
64
+ ax.scatter(np.sqrt(np.diag(cov_matrix)), mean_returns, c=mean_returns / np.sqrt(np.diag(cov_matrix)), marker='o')
65
+ ax.set_xlabel("Risiko (Standar Deviasi)")
66
+ ax.set_ylabel("Return Tahunan")
67
+ ax.set_title("Efficient Frontier")
68
+ st.pyplot(fig)
69
 
70
+ except Exception as e:
71
+ st.error(f"Terjadi kesalahan: {e}")