Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -5,11 +5,9 @@ import pandas as pd
|
|
| 5 |
import matplotlib.pyplot as plt
|
| 6 |
import seaborn as sns
|
| 7 |
import scipy.optimize as sco
|
| 8 |
-
import
|
| 9 |
-
|
| 10 |
-
from
|
| 11 |
-
from tensorflow.keras.layers import LSTM, Dense, Dropout
|
| 12 |
-
from sklearn.preprocessing import MinMaxScaler
|
| 13 |
|
| 14 |
def get_stock_data(tickers, start, end):
|
| 15 |
data = yf.download(tickers, start=start, end=end)
|
|
@@ -46,76 +44,46 @@ def optimize_portfolio(returns, cov_matrix):
|
|
| 46 |
result = sco.minimize(sharpe_ratio, init_guess, method='SLSQP', bounds=bounds, constraints=constraints)
|
| 47 |
return result.x if result.success else None
|
| 48 |
|
| 49 |
-
def
|
| 50 |
num_assets = len(returns)
|
| 51 |
-
|
|
|
|
| 52 |
|
| 53 |
-
for i in range(
|
| 54 |
weights = np.random.dirichlet(np.ones(num_assets), size=1)[0]
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
sharpe_ratio = portfolio_return / portfolio_volatility
|
| 58 |
-
|
| 59 |
-
results[0, i] = portfolio_return
|
| 60 |
-
results[1, i] = portfolio_volatility
|
| 61 |
-
results[2, i] = sharpe_ratio
|
| 62 |
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
fig, ax = plt.subplots()
|
| 68 |
-
sns.heatmap(correlation_matrix, annot=True, cmap="coolwarm", ax=ax)
|
| 69 |
-
st.pyplot(fig)
|
| 70 |
-
|
| 71 |
-
def plot_moving_averages(data, stock):
|
| 72 |
-
fig, ax = plt.subplots()
|
| 73 |
-
data[stock].plot(label='Harga', ax=ax)
|
| 74 |
-
data[stock].rolling(window=50).mean().plot(label='SMA 50', ax=ax)
|
| 75 |
-
data[stock].rolling(window=200).mean().plot(label='SMA 200', ax=ax)
|
| 76 |
-
ax.legend()
|
| 77 |
-
st.pyplot(fig)
|
| 78 |
|
| 79 |
-
def
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
fig, ax = plt.subplots()
|
| 84 |
-
total_value.plot(ax=ax, title='Simulasi Investasi DCA')
|
| 85 |
-
st.pyplot(fig)
|
| 86 |
-
|
| 87 |
-
def predict_stock_price(data, stock, days=30):
|
| 88 |
-
st.subheader(f"Prediksi Harga Saham {stock} (LSTM Model)")
|
| 89 |
-
scaler = MinMaxScaler(feature_range=(0, 1))
|
| 90 |
-
scaled_data = scaler.fit_transform(data[stock].values.reshape(-1,1))
|
| 91 |
-
|
| 92 |
-
X, y = [], []
|
| 93 |
-
for i in range(60, len(scaled_data) - days):
|
| 94 |
-
X.append(scaled_data[i-60:i, 0])
|
| 95 |
-
y.append(scaled_data[i:i+days, 0])
|
| 96 |
-
|
| 97 |
-
X, y = np.array(X), np.array(y)
|
| 98 |
-
X = np.reshape(X, (X.shape[0], X.shape[1], 1))
|
| 99 |
-
|
| 100 |
-
model = Sequential()
|
| 101 |
-
model.add(LSTM(units=50, return_sequences=True, input_shape=(X.shape[1], 1)))
|
| 102 |
-
model.add(LSTM(units=50, return_sequences=False))
|
| 103 |
-
model.add(Dense(units=25))
|
| 104 |
-
model.add(Dense(units=days))
|
| 105 |
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 119 |
|
| 120 |
st.title("Analisis Portofolio Saham Optimal (Model Markowitz)")
|
| 121 |
|
|
@@ -125,6 +93,7 @@ st.write("KLBF.JK, SIDO.JK, KAEF.JK, TLKM.JK, UNVR.JK")
|
|
| 125 |
tickers_list = st.text_input("Masukkan ticker saham", "KLBF.JK, SIDO.JK, KAEF.JK").split(", ")
|
| 126 |
start_date = st.date_input("Pilih tanggal mulai", pd.to_datetime("2020-01-01"))
|
| 127 |
end_date = st.date_input("Pilih tanggal akhir", pd.to_datetime("2023-12-31"))
|
|
|
|
| 128 |
|
| 129 |
if st.button("Analisis Portofolio"):
|
| 130 |
stock_data = get_stock_data(tickers_list, start_date, end_date)
|
|
@@ -132,25 +101,15 @@ if st.button("Analisis Portofolio"):
|
|
| 132 |
mean_returns, cov_matrix = calculate_returns(stock_data)
|
| 133 |
optimal_weights = optimize_portfolio(mean_returns, cov_matrix)
|
| 134 |
|
| 135 |
-
st.subheader("
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
st.
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
st.subheader("Moving Average untuk Prediksi Tren")
|
| 142 |
-
selected_stock = st.selectbox("Pilih saham untuk analisis MA", stock_data.columns)
|
| 143 |
-
plot_moving_averages(stock_data, selected_stock)
|
| 144 |
-
|
| 145 |
-
st.subheader("Simulasi Investasi Dollar Cost Averaging (DCA)")
|
| 146 |
-
simulate_dca(stock_data)
|
| 147 |
-
|
| 148 |
-
st.subheader("Prediksi Harga Saham dengan AI")
|
| 149 |
-
predict_stock_price(stock_data, selected_stock)
|
| 150 |
-
|
| 151 |
if optimal_weights is not None:
|
| 152 |
st.subheader("Bobot Portofolio Optimal")
|
| 153 |
portfolio_weights = {stock: weight for stock, weight in zip(stock_data.columns, optimal_weights)}
|
| 154 |
st.write(portfolio_weights)
|
| 155 |
-
|
| 156 |
-
|
|
|
|
| 5 |
import matplotlib.pyplot as plt
|
| 6 |
import seaborn as sns
|
| 7 |
import scipy.optimize as sco
|
| 8 |
+
import plotly.express as px
|
| 9 |
+
import plotly.graph_objects as go
|
| 10 |
+
from fpdf import FPDF
|
|
|
|
|
|
|
| 11 |
|
| 12 |
def get_stock_data(tickers, start, end):
|
| 13 |
data = yf.download(tickers, start=start, end=end)
|
|
|
|
| 44 |
result = sco.minimize(sharpe_ratio, init_guess, method='SLSQP', bounds=bounds, constraints=constraints)
|
| 45 |
return result.x if result.success else None
|
| 46 |
|
| 47 |
+
def simulate_monte_carlo(returns, cov_matrix, num_simulations=10000, time_horizon=252):
|
| 48 |
num_assets = len(returns)
|
| 49 |
+
simulated_returns = np.zeros(num_simulations)
|
| 50 |
+
simulated_volatility = np.zeros(num_simulations)
|
| 51 |
|
| 52 |
+
for i in range(num_simulations):
|
| 53 |
weights = np.random.dirichlet(np.ones(num_assets), size=1)[0]
|
| 54 |
+
simulated_returns[i] = np.dot(weights, returns)
|
| 55 |
+
simulated_volatility[i] = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
|
| 57 |
+
fig = px.scatter(x=simulated_volatility, y=simulated_returns, color=simulated_returns/simulated_volatility,
|
| 58 |
+
labels={'x': 'Volatilitas', 'y': 'Return'},
|
| 59 |
+
title='Simulasi Monte Carlo')
|
| 60 |
+
st.plotly_chart(fig)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
|
| 62 |
+
def stock_screener():
|
| 63 |
+
st.sidebar.header("Stock Screener")
|
| 64 |
+
pe_ratio = st.sidebar.slider("Maksimum P/E Ratio", 0, 100, 20)
|
| 65 |
+
market_cap = st.sidebar.selectbox("Market Cap", ["Small", "Mid", "Large"])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
|
| 67 |
+
# Simulasi data screener (contoh)
|
| 68 |
+
screener_data = pd.DataFrame({
|
| 69 |
+
'Ticker': ['AAPL', 'MSFT', 'GOOGL', 'TSLA', 'AMZN'],
|
| 70 |
+
'P/E Ratio': [30, 25, 35, 40, 28],
|
| 71 |
+
'Market Cap': ['Large', 'Large', 'Large', 'Mid', 'Large']
|
| 72 |
+
})
|
| 73 |
+
filtered_stocks = screener_data[(screener_data['P/E Ratio'] <= pe_ratio) & (screener_data['Market Cap'] == market_cap)]
|
| 74 |
+
st.sidebar.write("Saham yang memenuhi kriteria:")
|
| 75 |
+
st.sidebar.write(filtered_stocks)
|
| 76 |
+
|
| 77 |
+
def export_to_pdf(stock_data):
|
| 78 |
+
pdf = FPDF()
|
| 79 |
+
pdf.add_page()
|
| 80 |
+
pdf.set_font("Arial", size=12)
|
| 81 |
+
pdf.cell(200, 10, txt="Laporan Analisis Saham", ln=True, align='C')
|
| 82 |
+
pdf.ln(10)
|
| 83 |
+
for ticker in stock_data.columns:
|
| 84 |
+
pdf.cell(200, 10, txt=f"{ticker}: {stock_data[ticker].iloc[-1]}", ln=True)
|
| 85 |
+
pdf.output("stock_report.pdf")
|
| 86 |
+
st.success("Laporan PDF telah dibuat!")
|
| 87 |
|
| 88 |
st.title("Analisis Portofolio Saham Optimal (Model Markowitz)")
|
| 89 |
|
|
|
|
| 93 |
tickers_list = st.text_input("Masukkan ticker saham", "KLBF.JK, SIDO.JK, KAEF.JK").split(", ")
|
| 94 |
start_date = st.date_input("Pilih tanggal mulai", pd.to_datetime("2020-01-01"))
|
| 95 |
end_date = st.date_input("Pilih tanggal akhir", pd.to_datetime("2023-12-31"))
|
| 96 |
+
stock_screener()
|
| 97 |
|
| 98 |
if st.button("Analisis Portofolio"):
|
| 99 |
stock_data = get_stock_data(tickers_list, start_date, end_date)
|
|
|
|
| 101 |
mean_returns, cov_matrix = calculate_returns(stock_data)
|
| 102 |
optimal_weights = optimize_portfolio(mean_returns, cov_matrix)
|
| 103 |
|
| 104 |
+
st.subheader("Simulasi Monte Carlo")
|
| 105 |
+
simulate_monte_carlo(mean_returns, cov_matrix)
|
| 106 |
+
|
| 107 |
+
if st.button("Export to PDF"):
|
| 108 |
+
export_to_pdf(stock_data)
|
| 109 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 110 |
if optimal_weights is not None:
|
| 111 |
st.subheader("Bobot Portofolio Optimal")
|
| 112 |
portfolio_weights = {stock: weight for stock, weight in zip(stock_data.columns, optimal_weights)}
|
| 113 |
st.write(portfolio_weights)
|
| 114 |
+
else:
|
| 115 |
+
st.error("Optimasi portofolio gagal. Coba dengan saham yang berbeda.")
|