File size: 5,632 Bytes
f4505cc
 
 
 
 
0cd95d3
f4505cc
b59b790
715f9f2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1aabc74
 
715f9f2
 
 
 
 
 
 
 
1aabc74
715f9f2
 
 
 
 
 
b59b790
715f9f2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b59b790
0cd95d3
 
 
 
 
a15fad3
0cd95d3
 
 
 
 
 
 
615b087
0cd95d3
 
 
 
 
 
 
b59b790
0cd95d3
b59b790
a15fad3
0cd95d3
b59b790
715f9f2
 
 
b59b790
715f9f2
0cd95d3
 
 
 
6b47695
0cd95d3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6b47695
0cd95d3
 
 
 
 
 
 
 
 
 
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
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.")