markowitz / app.py
GarGerry's picture
Update app.py
ad0953c verified
raw
history blame
3.23 kB
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
# Fungsi untuk mengunduh data saham
def get_stock_data(tickers, start, end):
data = yf.download(tickers, start=start, end=end)
if data.empty:
st.error("Data saham tidak ditemukan. Periksa ticker atau rentang tanggal.")
return None
# Cek semua kolom yang tersedia dalam data
st.write("Kolom yang tersedia dalam data:", data.columns.tolist())
if 'Adj Close' not in data.columns:
st.error("Kolom 'Adj Close' tidak ditemukan. Data yang tersedia ditampilkan di atas.")
return None
return data['Adj Close']
# Fungsi untuk menghitung return tahunan dan matriks kovarians
def calculate_returns(data):
log_returns = np.log(data / data.shift(1))
return log_returns.mean() * 252, log_returns.cov() * 252
# Fungsi untuk menghitung portofolio optimal
def optimize_portfolio(returns, cov_matrix):
num_assets = len(returns)
def sharpe_ratio(weights):
portfolio_return = np.dot(weights, returns)
portfolio_volatility = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))
return -portfolio_return / portfolio_volatility # Negatif untuk minimisasi
constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1})
bounds = tuple((0, 1) for _ in range(num_assets))
init_guess = num_assets * [1. / num_assets]
result = sco.minimize(sharpe_ratio, init_guess, method='SLSQP', bounds=bounds, constraints=constraints)
return result.x if result.success else None
# Streamlit UI
st.title("Analisis Portofolio Saham Optimal (Model Markowitz)")
# Input Saham & Tanggal
tickers_list = st.text_input("Masukkan ticker saham (contoh: BBCA.JK, TLKM.JK, BBRI.JK)", "BBCA.JK, TLKM.JK, BBRI.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("2020-12-31"))
if st.button("Analisis Portofolio"):
try:
# Ambil data saham
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)
# Optimasi portofolio
optimal_weights = optimize_portfolio(mean_returns, cov_matrix)
if optimal_weights is not None:
st.subheader("Bobot Portofolio Optimal:")
for i, stock in enumerate(tickers_list):
st.write(f"{stock}: {optimal_weights[i]:.2%}")
# Plot Efficient Frontier
st.subheader("Efficient Frontier")
fig, ax = plt.subplots()
ax.scatter(np.sqrt(np.diag(cov_matrix)), mean_returns, c=mean_returns / np.sqrt(np.diag(cov_matrix)), marker='o')
ax.set_xlabel("Risiko (Standar Deviasi)")
ax.set_ylabel("Return Tahunan")
ax.set_title("Efficient Frontier")
st.pyplot(fig)
else:
st.error("Optimasi portofolio gagal. Coba dengan saham yang berbeda.")
except Exception as e:
st.error(f"Terjadi kesalahan: {e}")