-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathResearch Code.py
More file actions
402 lines (320 loc) · 12.5 KB
/
Research Code.py
File metadata and controls
402 lines (320 loc) · 12.5 KB
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
# -*- coding: utf-8 -*-
"""[] Optimalisasi Diversifikasi-Guede
Automatically generated by Colab.
# Install Module
"""
!pip install yfinance pandas openpyxl
"""# Pengambilan Data"""
import pandas as pd
daftar_saham = pd.read_excel('Daftar Saham IDX80.xlsx', sheet_name='Saham Konsisten')
ticker_saham = daftar_saham['Kode'].tolist()
ticker_saham
# Mengambil Data Saham
import yfinance as yf
def Scraping_Saham(tickers, start_date, end_date):
try:
data = yf.download(tickers, start=start_date, end=end_date)
closing_prices = data['Close']
return closing_prices
except Exception as e:
return None
start_date = '2022-12-31'
end_date = '2024-12-31'
Ticker_market = ('^JKSE')
data_market = Scraping_Saham(Ticker_market, start_date, end_date)
data_saham = pd.DataFrame()
ticker_gagal = []
for ticker in ticker_saham:
temp_data = Scraping_Saham(ticker, start_date, end_date)
if temp_data is not None:
data_saham = pd.concat([data_saham, temp_data], axis=1)
else:
ticker_gagal.append(ticker)
while ticker_gagal:
ticker_gagal_baru = []
for ticker in ticker_gagal:
temp_data = Scraping_Saham(ticker, start_date, end_date)
if temp_data is not None:
data_saham = pd.concat([data_saham, temp_data], axis=1)
else:
ticker_gagal_baru.append(ticker)
ticker_gagal = ticker_gagal_baru
data_close = pd.concat([data_market, data_saham], axis=1)
data_close
# Menyimpan Data Bunga Bebas Risiko
data_sukubunga = pd.read_excel('Suku Bunga BI.xlsx', sheet_name='Des 22 - Jan 25')
data_sukubunga_harian = data_sukubunga['Suku Bunga']/250
risk_free = data_sukubunga_harian.mean()
risk_free
"""# Return"""
def returns(data):
return_harian = ((data) - (data).shift(1)) / (data).shift(1)
return return_harian
return_saham = returns(data_saham)
return_market = returns(data_market)
data_return = pd.concat([return_market, return_saham], axis=1).iloc[1:]
data_return
# Expected Return
def expected_returns(data):
return data.mean()
ER_saham = expected_returns(data_return)
#Standar Deviasi
def st_dev(data):
return data.std()
std_saham = st_dev(data_return)
#Variance
def var(data):
return data.var()
var_saham = var(data_return)
#Covarian
def covarian(data):
cov_matrix = data.cov()
return cov_matrix[Ticker_market]
cov_saham = covarian(data_return)
pd.DataFrame({'Expected Return': ER_saham, 'St. Deviation': std_saham, 'Variance': var_saham, 'Covariance': cov_saham})
# Ambil yang Positif saja
def return_positif(data_return):
saham_return_positif = data_return.loc[:, data_return.mean() > 0]
return saham_return_positif
data_return = return_positif(data_return)
data_return = pd.concat([data_return], axis=1)
data_return
"""# Single Index Model"""
# Beta
def beta(data):
betas = {}
for saham in data.columns:
if saham == Ticker_market:
betas[saham] = 1
else:
betas[saham] = cov_saham[saham] / var_saham[Ticker_market]
return pd.Series(betas)
beta_saham = beta(data_return).iloc[1:]
# Alpha
def alpha(data):
alpha_saham = expected_returns(data) - beta(data) * ER_saham[Ticker_market]
return alpha_saham
alpha_saham = alpha(data_return).iloc[1:]
# Residual Variance
def residual_variance(data):
residual_variance = var(data) - (beta(data)* beta(data) * var_saham[Ticker_market])
return residual_variance
resvar_saham = residual_variance(data_return).iloc[1:]
pd.DataFrame({'Beta': beta_saham, 'Alpha': alpha_saham, 'Residual Variance': resvar_saham})
# Excess Return to Beta
def ERB(data):
ERB_saham = (expected_returns(data) - risk_free) / beta(data)
return ERB_saham
ERB_saham = ERB(data_return).iloc[1:]
ERB_saham
# A
def nilai_A(data):
nilai_A = ((expected_returns(data) - risk_free) * beta(data)) / residual_variance(data)
return nilai_A
A_saham = nilai_A(data_return).iloc[1:]
A_saham
# B
def nilai_B(data):
nilai_B = beta(data)**2 / residual_variance(data)
return nilai_B
B_saham = nilai_B(data_return).iloc[1:]
B_saham
# Cutoff
def Cutoff(data):
Cutoff_value = (var_saham[Ticker_market]*nilai_A(data))/(1+(var_saham[Ticker_market]*nilai_B(data)))
return Cutoff_value
Cutoff_saham = Cutoff(data_return).iloc[1:]
Cutoff_saham
pd.DataFrame({'ERB': ERB_saham, 'Nilai A': A_saham, 'Nilai B': B_saham, 'Cut Off': Cutoff_saham})
#Proportion
Max_cutoff = max(Cutoff_saham)
def proporsi(data):
nilai_proporsi = ((ERB(data) - Max_cutoff) * (beta(data) / residual_variance(data)))
return nilai_proporsi
proporsi_saham = proporsi(data_return).iloc[1:]
proporsi_saham
#Pemilihan Kandidat Portofolio
def kandidat(ERB_saham, Max_cutoff, proporsi_saham):
pemilihan_kandidat = []
for saham in ERB_saham.index:
if ERB_saham[saham] > Max_cutoff and proporsi_saham[saham] > 0:
pemilihan_kandidat.append(saham)
return pemilihan_kandidat
pemilihan_kandidat = kandidat(ERB_saham, Max_cutoff, proporsi_saham)
pemilihan_kandidat
"""# Pembentukan Kombinasi Saham
"""
import itertools
def kombinasi(pemilihan_kandidat, max_stocks=len(pemilihan_kandidat)):
kombinasi = []
for i in range(1, len(pemilihan_kandidat) + 1):
for combo in itertools.combinations(pemilihan_kandidat, i):
kombinasi.append(combo)
return kombinasi
kombinasi_saham = kombinasi(pemilihan_kandidat)
kombinasi_saham
def banyak_kombinasi(kombinasi):
banyaknya_kombinasi = {}
for N in kombinasi:
length = len(N)
banyaknya_kombinasi[length] = banyaknya_kombinasi.get(length, 0) + 1
return banyaknya_kombinasi
combination_counts = banyak_kombinasi(kombinasi_saham)
combination_counts
sum(combination_counts.values())
"""# Portofolio"""
# Penghitungan Bobot
import pandas as pd
def Bobot_SIM(kombinasi_saham, proportion_saham):
Nilai_Bobot = {}
for kombinasi in kombinasi_saham:
total_proportion = sum(proportion_saham[saham] for saham in kombinasi)
Bobot = {saham: proportion_saham[saham] / total_proportion for saham in kombinasi}
Nilai_Bobot[kombinasi] = Bobot
return Nilai_Bobot
Bobot_Portofolio = Bobot_SIM(kombinasi_saham, proporsi_saham)
Bobot_Portofolio
# Penghitungan Expected Return
def ER_Portofolio(bobot, kombinasi_saham, alpha_saham, beta_saham):
ER_Portofolio = {}
for kombinasi, bobot in bobot.items():
er_port = 0
for saham, bobot in bobot.items():
er_port += (bobot * alpha_saham[saham]) + (bobot * beta_saham[saham] * ER_saham[Ticker_market])
ER_Portofolio[kombinasi] = er_port
return ER_Portofolio
expected_return_Portofolio = ER_Portofolio(Bobot_Portofolio, kombinasi_saham, alpha_saham, beta_saham)
pd.DataFrame.from_dict(expected_return_Portofolio, orient = 'index')
# Penghitungan Risiko
def Risk_Portofolio(bobot, kombinasi_saham, beta_saham):
Risiko_Port = {}
for kombinasi_saham, bobot in bobot.items():
beta_port = 0
resvar_port = 0
for saham, bobot in bobot.items():
beta_port += (bobot * beta_saham[saham])
resvar_port += (bobot**2 * resvar_saham[saham])
Risiko_Port[kombinasi_saham] = (beta_port**2) * var_saham[Ticker_market] + resvar_port
return Risiko_Port
Risiko_Portofolio = Risk_Portofolio(Bobot_Portofolio, kombinasi_saham, beta_saham)
pd.DataFrame.from_dict(Risiko_Portofolio, orient = 'index')
import math
# Sharpe Index
def Indeks_Sharpe(ER_Portofolio, Risiko_portofolio):
Indeks_Sharpe = {}
for kombinasi, ER in ER_Portofolio.items():
sharpe = (ER - risk_free) / math.sqrt(Risiko_portofolio[kombinasi])
Indeks_Sharpe[kombinasi] = sharpe
return Indeks_Sharpe
Sharpe_Portofolio = Indeks_Sharpe(expected_return_Portofolio, Risiko_Portofolio)
pd.DataFrame.from_dict(Sharpe_Portofolio, orient = 'index')
"""# Kesimpulan"""
def kesimpulan(expected_return_Portofolio, Risiko_Portofolio, Sharpe_Portofolio):
lengths = range(1, len(pemilihan_kandidat) + 1)
average_values = {}
for length in lengths:
Portofolio_subset = [
key for key in expected_return_Portofolio.keys() if len(key) == length
]
if Portofolio_subset:
average_expected_return = sum(
expected_return_Portofolio[Portofolio] for Portofolio in Portofolio_subset
) / len(Portofolio_subset)
average_risk = sum(
Risiko_Portofolio[Portofolio] for Portofolio in Portofolio_subset
) / len(Portofolio_subset)
average_sharpe = sum(
Sharpe_Portofolio[Portofolio] for Portofolio in Portofolio_subset
) / len(Portofolio_subset)
average_values[length] = {
'expected_return_portofolio': average_expected_return,
'Risiko_Portofolio': average_risk,
'Sharpe_Portofolio': average_sharpe,
}
return average_values
Hasil_Portofolio = kesimpulan(expected_return_Portofolio, Risiko_Portofolio, Sharpe_Portofolio)
# Create DataFrame
Hasil_Portofolio = pd.DataFrame.from_dict(Hasil_Portofolio, orient='index')
Hasil_Portofolio
def kombinasi_riskmin(Risiko_Portofolio, expected_return_Portofolio, Sharpe_Portofolio):
info_min = {}
for kombinasi, risk in Risiko_Portofolio.items():
n = len(kombinasi)
if n not in info_min or risk < info_min[n]['min_risiko']:
info_min[n] = {
'kombinasi': kombinasi,
'min_risiko': risk,
'expected_return': expected_return_Portofolio[kombinasi],
'sharpe': Sharpe_Portofolio[kombinasi]
}
return info_min
Minimrisk_portofolio = kombinasi_riskmin(Risiko_Portofolio, expected_return_Portofolio, Sharpe_Portofolio)
pd.DataFrame.from_dict(Minimrisk_portofolio, orient='index')
import matplotlib.pyplot as plt
average_risk = Hasil_Portofolio['Risiko_Portofolio'].values
min_risk = [value['min_risiko'] for value in Minimrisk_portofolio.values()]
plt.figure(figsize=(10, 6))
plt.plot(average_risk, label ='Rata-Rata Risiko', marker ='o', color = 'b')
plt.plot(min_risk, label ='Minimum Risiko', marker = 'o', color = 'r')
plt.xlabel('Jumlah saham dalam portofolio')
plt.ylabel('Risiko')
plt.title('Rata-Rata Risiko vs. Minimum Risiko')
plt.legend()
plt.grid(True)
plt.xticks(range(len(average_risk)), range(1, len(average_risk) + 1))
plt.show()
def kombinasi_ermax(Risiko_Portofolio, expected_return_Portofolio, Sharpe_Portofolio):
info_max = {}
for kombinasi, ER in expected_return_Portofolio.items():
n = len(kombinasi)
if n not in info_max or ER > info_max[n]['ER Maksimal']:
info_max[n] = {
'Kombinasi': kombinasi,
'ER Maksimal': ER,
'Risiko Portofolio': Risiko_Portofolio[kombinasi],
'Sharpe': Sharpe_Portofolio[kombinasi]
}
return info_max
ERmax_portofolio = kombinasi_ermax(Risiko_Portofolio, expected_return_Portofolio, Sharpe_Portofolio)
pd.DataFrame.from_dict(ERmax_portofolio, orient='index')
import matplotlib.pyplot as plt
average_return = Hasil_Portofolio['expected_return_portofolio'].values
ERmaks = [value['ER Maksimal'] for value in ERmax_portofolio.values()]
plt.figure(figsize=(10, 6))
plt.plot(average_return, label ='Rata-rata Return', marker ='o', color = 'b')
plt.plot(ERmaks, label ='Return Maksimal', marker = 'o', color = 'r')
plt.xlabel('Jumlah saham dalam portofolio')
plt.ylabel('Return Portofolio')
plt.title('Rata-Rata Return vs Return Maksimal')
plt.legend()
plt.grid(True)
plt.xticks(range(len(average_risk)), range(1, len(average_risk) + 1))
plt.show()
def kombinasi_sharpemax(Risiko_Portofolio, expected_return_Portofolio, Sharpe_Portofolio):
info_maxs = {}
for kombinasi, Sharpe in Sharpe_Portofolio.items():
n = len(kombinasi)
if n not in info_maxs or Sharpe > info_maxs[n]['Sharpe Maksimal']:
info_maxs[n] = {
'Kombinasi': kombinasi,
'Sharpe Maksimal': Sharpe,
'Expected Return': expected_return_Portofolio[kombinasi],
'Risiko Portofolio': Risiko_Portofolio[kombinasi]
}
return info_maxs
Sharpemax_portofolio = kombinasi_sharpemax(Risiko_Portofolio, expected_return_Portofolio, Sharpe_Portofolio)
pd.DataFrame.from_dict(Sharpemax_portofolio, orient='index')
import matplotlib.pyplot as plt
average_sharpe = Hasil_Portofolio['Sharpe_Portofolio'].values
Sharpemaks = [value['Sharpe Maksimal'] for value in Sharpemax_portofolio.values()]
plt.figure(figsize=(10, 6))
plt.plot(average_sharpe, label ='Rata-rata Sharpe', marker ='o', color = 'b')
plt.plot(Sharpemaks, label ='Sharpe Maksimal', marker = 'o', color = 'r')
plt.xlabel('Jumlah saham dalam portofolio')
plt.ylabel('Sharpe Portofolio')
plt.title('Rata-Rata Sharpe vs Sharpe Maksimal')
plt.legend()
plt.grid(True)
plt.xticks(range(len(average_risk)), range(1, len(average_risk) + 1))
plt.savefig('sharpe_comparison.png')
plt.show()