Spaces:
Sleeping
Sleeping
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}") |