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 seaborn as sns | |
| import scipy.optimize as sco | |
| 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 | |
| if 'Adj Close' in data.columns: | |
| return data['Adj Close'] | |
| elif 'Close' in data.columns: | |
| st.warning("Menggunakan 'Close' karena 'Adj Close' tidak tersedia.") | |
| return data['Close'] | |
| else: | |
| st.error("Data harga penutupan tidak ditemukan.") | |
| return None | |
| def calculate_returns(data): | |
| log_returns = np.log(data / data.shift(1)) | |
| return log_returns.mean() * 252, log_returns.cov() * 252 | |
| 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 | |
| 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 | |
| def generate_efficient_frontier(returns, cov_matrix, num_portfolios=5000): | |
| num_assets = len(returns) | |
| results = np.zeros((3, num_portfolios)) | |
| for i in range(num_portfolios): | |
| weights = np.random.dirichlet(np.ones(num_assets), size=1)[0] | |
| portfolio_return = np.dot(weights, returns) | |
| portfolio_volatility = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights))) | |
| sharpe_ratio = portfolio_return / portfolio_volatility | |
| results[0, i] = portfolio_return | |
| results[1, i] = portfolio_volatility | |
| results[2, i] = sharpe_ratio | |
| return results | |
| def plot_correlation_heatmap(data): | |
| correlation_matrix = data.corr() | |
| fig, ax = plt.subplots() | |
| sns.heatmap(correlation_matrix, annot=True, cmap="coolwarm", ax=ax) | |
| st.pyplot(fig) | |
| def plot_moving_averages(data, stock): | |
| fig, ax = plt.subplots() | |
| data[stock].plot(label='Harga', ax=ax) | |
| data[stock].rolling(window=50).mean().plot(label='SMA 50', ax=ax) | |
| data[stock].rolling(window=200).mean().plot(label='SMA 200', ax=ax) | |
| ax.legend() | |
| st.pyplot(fig) | |
| def simulate_dca(data, investment_amount=100): | |
| investment_dates = data.index[::30] | |
| dca_values = data.loc[investment_dates].mean(axis=1) * investment_amount | |
| total_value = dca_values.cumsum() | |
| fig, ax = plt.subplots() | |
| total_value.plot(ax=ax, title='Simulasi Investasi DCA') | |
| st.pyplot(fig) | |
| st.title("Analisis Portofolio Saham Optimal (Model Markowitz)") | |
| st.write("Rekomendasi Saham yang Bertahan Saat COVID-19:") | |
| st.write("KLBF.JK, SIDO.JK, KAEF.JK, TLKM.JK, UNVR.JK") | |
| 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")) | |
| if st.button("Analisis Portofolio"): | |
| 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) | |
| st.subheader("Statistik Saham") | |
| st.write(stock_data.describe()) | |
| st.subheader("Heatmap Korelasi Saham") | |
| plot_correlation_heatmap(stock_data) | |
| st.subheader("Moving Average untuk Prediksi Tren") | |
| selected_stock = st.selectbox("Pilih saham untuk analisis MA", stock_data.columns) | |
| plot_moving_averages(stock_data, selected_stock) | |
| st.subheader("Simulasi Investasi Dollar Cost Averaging (DCA)") | |
| simulate_dca(stock_data) | |
| if optimal_weights is not None: | |
| st.subheader("Bobot Portofolio Optimal") | |
| portfolio_weights = {stock: weight for stock, weight in zip(stock_data.columns, optimal_weights)} | |
| st.write(portfolio_weights) | |
| # Pie Chart dengan pengelompokan saham kecil ke "Others" | |
| threshold = 0.05 | |
| large_weights = {k: v for k, v in portfolio_weights.items() if v >= threshold} | |
| small_weights = {k: v for k, v in portfolio_weights.items() if v < threshold} | |
| if small_weights: | |
| large_weights["Others"] = sum(small_weights.values()) | |
| fig, ax = plt.subplots() | |
| ax.pie(large_weights.values(), labels=large_weights.keys(), autopct='%1.1f%%', startangle=140) | |
| ax.axis('equal') | |
| st.pyplot(fig) | |
| # Efficient Frontier | |
| results = generate_efficient_frontier(mean_returns, cov_matrix) | |
| st.subheader("Efficient Frontier") | |
| fig, ax = plt.subplots() | |
| scatter = ax.scatter(results[1, :], results[0, :], c=results[2, :], cmap="viridis", marker='o') | |
| ax.set_xlabel("Risiko (Standar Deviasi)") | |
| ax.set_ylabel("Return Tahunan") | |
| ax.set_title("Efficient Frontier") | |
| fig.colorbar(scatter, label="Sharpe Ratio") | |
| st.pyplot(fig) | |
| else: | |
| st.error("Optimasi portofolio gagal. Coba dengan saham yang berbeda.") | |