File size: 4,110 Bytes
f4505cc
 
 
 
 
 
b59b790
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2a180f0
c561271
b59b790
 
 
 
 
1c7d42a
b59b790
f0a10e4
b59b790
 
 
 
 
 
 
 
 
 
 
 
 
 
7fb7f14
b59b790
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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

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

st.title("Analisis Portofolio Saham Optimal (Model Markowitz)")

def get_recommended_stocks(): return "KLBF.JK, SIDO.JK, KAEF.JK, TLKM.JK, UNVR.JK"  # Saham relevan saat pandemi

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

st.write("Rekomendasi Saham yang Bertahan Saat COVID-19:") st.write(get_recommended_stocks())

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"): 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)

st.subheader("Statistik Saham")
        st.write(stock_data.describe())
        
        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)
            
            fig, ax = plt.subplots()
            ax.pie(optimal_weights, labels=stock_data.columns, autopct='%1.1f%%', startangle=140)
            ax.axis('equal')
            st.pyplot(fig)
            
            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.")