참고한 상품 정보 보는 사이트
Basic Step Down 신금투 21425
import time
import numpy as np
start = time.time()
S0 = 100 # 최초기준가격
r_1 = 0.00160 # 1년만기 무위험수익률
r_2 = 0.00190
r_3 = -0.00536
q_1 = 0.013240 # 배당
q_2 = 0.026810
q_3 = 0.021550
sigma_1 = 0.2643 # 변동성
sigma_2 = 0.2551
sigma_3 = 0.2514
rho_12 = 0.13245 # 상관계수
rho_13 = 0.60590
rho_23 = 0.26899
T = 3.0 # 만기
D = 252 # 영업일
dt = 1 / D # time step: 일별 종가기준
I = 50000 # Iteration
R = np.ones((3,3))
R[0,1] = rho_12
R[1,0] = rho_12
R[0,2] = rho_13
R[2,0] = rho_13
R[1,2] = rho_23
R[2,1] = rho_23
L = np.linalg.cholesky(R) # Correlation matrix를 cholesky decomposition 한 후 남은 lower triangular matrix
S_1 = np.zeros((252*3 + 1, I))
S_1[0] = S0
S_2 = np.zeros((252*3 + 1, I))
S_2[0] = S0
S_3 = np.zeros((252*3 + 1, I))
S_3[0] = S0
for t in range(1, 757):
A = np.random.standard_normal((3, I))
B = np.dot(L, A) # 상관관계가 고려된 난수 생성
S_1[t] = S_1[t-1] * np.exp((r_1 - q_1 - 0.5 * sigma_1 ** 2) * dt + sigma_1 * np.sqrt(dt) * B[0])
S_2[t] = S_2[t-1] * np.exp((r_2 - q_2 - 0.5 * sigma_2 ** 2) * dt + sigma_2 * np.sqrt(dt) * B[1])
S_3[t] = S_3[t-1] * np.exp((r_3 - q_3 - 0.5 * sigma_3 ** 2) * dt + sigma_3 * np.sqrt(dt) * B[2])
WP = np.zeros((252*3 + 1, I))
WP = np.min((S_1, S_2, S_3), axis = 0)
P = np.zeros(I) # ELS의 path별 PV Matrix
C = np.zeros((6,1)) # PV matrix
C[0] = np.exp(-0.01092 * 0.5) * 101.95 #액면 금액 * 101.95%
C[1] = np.exp(-0.01307 * 1.0) * 103.90 #액면 금액 * 103.90%
C[2] = np.exp(- 0.01480 * 1.5) * 105.85 #액면 금액 * 105.85%
C[3] = np.exp(-0.01655 * 2.0) * 107.80 #액면 금액 * 107.80%
C[4] = np.exp(-0.01753* 2.5) * 109.75 #액면 금액 * 109.75%
C[5] = np.exp(-0.01832 * 3.0) * 111.70 #액면 금액 * 111.70%
for r in range(0, I):
if WP[126, r] >= 85:
P[r] = C[0]
elif WP[252, r] >= 85:
P[r] = C[1]
elif WP[378, r] >= 80:
P[r] = C[2]
elif WP[504, r] >= 80:
P[r] = C[3]
elif WP[630, r] >= 75:
P[r] = C[4]
elif WP[756, r] >= 70: # 여기까지가 자동조기상환 성공 시나리오
P[r] = C[5]
elif WP[:, r].min() > 50: # 자동조기상환은 실패했지만, 모든 날짜의 종가가 50%미만 하락하지 않은 경우
P[r] = C[5]
else: # 원금손실 (참여율 100%)
P[r] = WP[-1, r] * np.exp(-0.01832 * 3.0)
PV = np.mean(P) * 100
PV
print(PV.round(2))
print('time :', time.time() - start)
8900.44 time : 12.904228925704956
Monthly Coupon NH투증 21102
import time
import numpy as np
start = time.time()
S0 = 100 # 최초기준가격
r_1 = 0.00161 # 1년만기 무위험이자율
r_2 = -0.00542
q_1 = 0.005816 # 배당
q_2 = 0.020980
sigma_1 = 0.246606 # 변동성
sigma_2 = 0.253700
rho_12 = 0.22825 # 상관계수
df = 0.0150 # 할인율
T = 3
Nt = 252 # 영업일
dt = 1 / Nt # time step: 일별 종가기준
I = 50000 # Iteration
R = np.ones((2, 2)) # Correlation matrix
R[0,1] = rho_12
R[1,0] = rho_12
L = np.linalg.cholesky(R)
S_1 = np.zeros((int(Nt*T + 1), I))
S_1[0] = S0
S_2 = np.zeros((int(Nt*T + 1), I))
S_2[0] = S0
for t in range(1, int(Nt*T + 1)):
A = np.random.standard_normal((2, I))
B = np.dot(L, A)
S_1[t] = S_1[t-1] * np.exp((r_1 - q_1 - 0.5 * sigma_1 ** 2) * dt + sigma_1 * np.sqrt(dt) * B[0])
S_2[t] = S_2[t-1] * np.exp((r_2 - q_2 - 0.5 * sigma_2 ** 2) * dt + sigma_2 * np.sqrt(dt) * B[1])
WP = np.zeros((Nt * T + 1, I))
WP = np.min((S_1, S_2), axis = 0)
P = np.zeros(I) # ELS의 path별 상환금액의 PV
C = np.zeros((6,1)) # Payoff의 PV matrix
C[0] = np.exp(-0.011020 * 0.5) * 100
C[1] = np.exp(-0.013240 * 1.0) * 100
C[2] = np.exp(- 0.014680 * 1.5) * 100
C[3] = np.exp(-0.016030 * 2.0) * 100
C[4] = np.exp(-0.017210* 2.5) * 100
C[5] = np.exp(-0.018080 * 3.0) * 100
Cpn = np.zeros(I) # 쿠폰지급액의 PV
for r in range(0, I):
if WP[126, r] >= 95:
P[r] = C[0]
for c in range(1,7):
if WP[21*c, r] >= 60:
Cpn[r] = Cpn[r] + (100 * 0.005) * np.exp(-df * 21 * c / Nt) # 쿠폰을 각각의 현재가치로 더함
P[r] = P[r] + Cpn[r]
elif WP[252, r] >= 90:
P[r] = C[1]
for c in range(1,13):
if WP[21*c, r] >= 60:
Cpn[r] = Cpn[r] + (100 * 0.005) * np.exp(-df * 21 * c / Nt)
P[r] = P[r] + Cpn[r]
elif WP[378, r] >= 85:
P[r] = C[2]
for c in range(1,19):
if WP[21*c, r] >= 60:
Cpn[r] = Cpn[r] + (100 * 0.005) * np.exp(-df * 21 * c / Nt)
P[r] = P[r] + Cpn[r]
elif WP[504, r] >= 85:
P[r] = C[3]
for c in range(1,25):
if WP[21*c, r] >= 60:
Cpn[r] = Cpn[r] + (100 * 0.005) * np.exp(-df * 21 * c / Nt)
P[r] = P[r] + Cpn[r]
elif WP[630, r] >= 80:
P[r] = C[4]
for c in range(1,31):
if WP[21*c, r] >= 60:
Cpn[r] = Cpn[r] + (100 * 0.005) * np.exp(-df * 21 * c / Nt)
P[r] = P[r] + Cpn[r]
elif WP[756, r] >= 80: # 여기까지가 자동조기상환 성공 시나리오
P[r] = C[5]
for c in range(1,37):
if WP[21*c, r] >= 60:
Cpn[r] = Cpn[r] + (100 * 0.005) * np.exp(-df * 21 * c / Nt)
P[r] = P[r] + Cpn[r]
elif WP[:, r].min() > 50: # 자동조기상환은 실패했지만, 모든 날짜의 종가가 50%미만 하락하지 않은 경우
P[r] = C[5]
for c in range(1,37):
if WP[21*c, r] >= 60:
Cpn[r] = Cpn[r] + (100 * 0.005) * np.exp(-df * 21 * c / Nt)
P[r] = P[r] + Cpn[r]
else: # 원금손실 (참여율 100%)
P[r] = WP[-1, r] * np.exp(-0.018080 * 3.0)
for c in range(1,37):
if WP[21*c, r] >= 60:
Cpn[r] = Cpn[r] + (100 * 0.005) * np.exp(-df * 21 * c / Nt)
P[r] = P[r] + Cpn[r]
PV = np.mean(P)*100
print(PV.round(2))
print('time :', time.time() - start)
9418.54 time : 7.833194017410278
Shooting Up 삼성증권 26661
import time
import numpy as np
#Shooting up: 주식에 투자하는데 투자손실은 -5%로 제한하고,
#주가 상승에 따른 수익을 일정 비율(참여율)만큼 누릴 수 있는 구조로
#변동성 장세에 위험관리와 수익추구를 동시에 추구할 수 있는 상품으로 설계가 되었다.
start = time.time()
S0 = 100 #최초기준가격
r_1 = 0.00150 # 1년만기 무위험이자율
q_1 = 0.00562 # 배당
sigma_1 = 0.240152 # 변동성
T = 0.5 #만기
Nt = 252 # 영업일
dt = 1 / 252 # time step: 일별 종가기준
I = 50000 # Iteration
S_1 = np.zeros((int(Nt*T + 1), I))
S_1[0] = S0
for t in range(1, int(Nt*T + 1)):
A = np.random.standard_normal(I)
S_1[t] = S_1[t-1] * np.exp((r_1 - q_1 - 0.5 * sigma_1 ** 2) * dt + sigma_1 * np.sqrt(dt) * A)
P = np.zeros(I) # ELS의 path별 PV Matrix
for r in range(0, I):
if np.mean(S_1[-3:, r]) >= 100:
P[r] = np.exp(-0.0112 * T) * 100 * (1 + 0.22 * (np.mean(S_1[-3:, r]) / 100 - 1))
elif np.mean(S_1[-3:, r]) >= 90:
P[r] = np.exp(-0.0112 * T) * 100 * (0.9 + (np.mean(S_1[-3:, r]) / 100 - 0.9))
else:
P[r] = np.exp(-0.0112 * T) * 100 * 0.9
PV = np.mean(P)*100
print(PV.round(2))
print('time :', time.time() - start)
9675.89 time : 1.849083423614502