Spaces:
Runtime error
Runtime error
ypchangchatgpt
commited on
Commit
•
faa7863
1
Parent(s):
5f6bd31
Upload 2 files
Browse files- Dockerfile +27 -0
- app.py +186 -0
Dockerfile
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
FROM python:3.8.9
|
2 |
+
|
3 |
+
WORKDIR /app
|
4 |
+
|
5 |
+
COPY ./requirements.txt /app/requirements.txt
|
6 |
+
COPY ./packages.txt /app/packages.txt
|
7 |
+
|
8 |
+
RUN apt-get update && xargs -r -a /app/packages.txt apt-get install -y && rm -rf /var/lib/apt/lists/*
|
9 |
+
RUN pip3 install --no-cache-dir -r /app/requirements.txt
|
10 |
+
|
11 |
+
# User
|
12 |
+
RUN useradd -m -u 1000 user
|
13 |
+
USER user
|
14 |
+
ENV HOME /home/user
|
15 |
+
ENV PATH $HOME/.local/bin:$PATH
|
16 |
+
|
17 |
+
WORKDIR $HOME
|
18 |
+
RUN mkdir app
|
19 |
+
WORKDIR $HOME/app
|
20 |
+
COPY . $HOME/app
|
21 |
+
|
22 |
+
EXPOSE 8501
|
23 |
+
CMD streamlit run app.py \
|
24 |
+
--server.headless true \
|
25 |
+
--server.enableCORS false \
|
26 |
+
--server.enableXsrfProtection false \
|
27 |
+
--server.fileWatcherType none
|
app.py
ADDED
@@ -0,0 +1,186 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
from scipy.stats import qmc, norm
|
3 |
+
import plotly.graph_objects as go
|
4 |
+
import streamlit as st
|
5 |
+
|
6 |
+
# 設置 Streamlit 頁面的基本配置
|
7 |
+
st.set_page_config(page_title="European option", # 設定網頁標題
|
8 |
+
layout="wide", # 設定頁面布局為寬屏模式
|
9 |
+
initial_sidebar_state="expanded") # 初始時側邊欄狀態為展開
|
10 |
+
|
11 |
+
st.title("Geometric Brownian motion 模型下,利用模擬方法得到歐式選擇權 (European option) 評價")
|
12 |
+
|
13 |
+
with st.sidebar.form(key="my_form"):
|
14 |
+
option_type = st.radio("選擇權型態",
|
15 |
+
("Call", "Put"),
|
16 |
+
horizontal=True)
|
17 |
+
|
18 |
+
S0 = st.slider("選擇期初股價 S0",
|
19 |
+
min_value=50,
|
20 |
+
max_value=300,
|
21 |
+
value=100)
|
22 |
+
|
23 |
+
K = st.slider("選擇履約價格 K",
|
24 |
+
min_value=50,
|
25 |
+
max_value=300,
|
26 |
+
value=100)
|
27 |
+
|
28 |
+
T = st.slider("選擇到期時間 T (年)",
|
29 |
+
min_value=0.1,
|
30 |
+
max_value=2.0,
|
31 |
+
value=1.0,
|
32 |
+
step=0.1)
|
33 |
+
|
34 |
+
r = st.slider("選擇無風險利率 r",
|
35 |
+
min_value=0.01,
|
36 |
+
max_value=0.10,
|
37 |
+
value=0.03,
|
38 |
+
step=0.01)
|
39 |
+
|
40 |
+
sigma = st.slider("選擇波動率 σ",
|
41 |
+
min_value=0.1,
|
42 |
+
max_value=0.5,
|
43 |
+
value=0.2,
|
44 |
+
step=0.05)
|
45 |
+
|
46 |
+
n_simulations = st.slider("選擇模擬次數",
|
47 |
+
min_value=1000,
|
48 |
+
max_value=20000,
|
49 |
+
value=10000,
|
50 |
+
step=1000)
|
51 |
+
|
52 |
+
n_experiments = st.slider("選擇實驗重複次數",
|
53 |
+
min_value=100,
|
54 |
+
max_value=10000,
|
55 |
+
value=1000,
|
56 |
+
step=100)
|
57 |
+
|
58 |
+
seed = st.text_input(label="亂數種子", value="123457")
|
59 |
+
|
60 |
+
submit_button = st.form_submit_button(label="Submit")
|
61 |
+
|
62 |
+
|
63 |
+
#%%
|
64 |
+
# 計算歐式選擇權價格並進行折現
|
65 |
+
def European_option_price(S0, K, r, T, sigma, option_type="Call"):
|
66 |
+
# Black-Scholes 公式
|
67 |
+
d1 = (np.log(S0/K)+(r+0.5*sigma**2)*T)/(sigma*np.sqrt(T))
|
68 |
+
d2 = d1-sigma*np.sqrt(T)
|
69 |
+
|
70 |
+
# 真實的 call option 價格
|
71 |
+
if option_type == "Call":
|
72 |
+
true_option_price = S0*norm.cdf(d1)-K*np.exp(-r*T)*norm.cdf(d2)
|
73 |
+
|
74 |
+
# 真實的 put option 價格
|
75 |
+
if option_type == "Put":
|
76 |
+
true_option_price = K*np.exp(-r*T)*norm.cdf(-d2)-S0*norm.cdf(-d1)
|
77 |
+
return true_option_price
|
78 |
+
|
79 |
+
def European_option_price_simulation(S0, K, r, T, sigma, z, option_type="Call"):
|
80 |
+
ST = S0*np.exp((r-0.5*sigma**2)*T+sigma*np.sqrt(T)*z)
|
81 |
+
if option_type == "Call":
|
82 |
+
payoff = np.maximum(ST-K, 0)
|
83 |
+
if option_type == "Put":
|
84 |
+
payoff = np.maximum(K-ST, 0)
|
85 |
+
option_price = np.exp(-r*T)*np.mean(payoff)
|
86 |
+
return option_price
|
87 |
+
|
88 |
+
option_prices_pseudo, option_prices_quasi, option_prices_numpy = [], [], []
|
89 |
+
if submit_button:
|
90 |
+
bar = st.progress(20, "Start calculation")
|
91 |
+
# 顯示進度條
|
92 |
+
|
93 |
+
np.random.seed(int(seed))
|
94 |
+
sobol_engine = qmc.Sobol(d=1, scramble=True, seed=int(seed))
|
95 |
+
for _ in range(n_experiments):
|
96 |
+
# 使用 pseudo-random numbers
|
97 |
+
u_pseudo_uniform = np.random.uniform(0, 1, n_simulations)
|
98 |
+
z_pseudo_random = norm.ppf(u_pseudo_uniform)
|
99 |
+
option_price_pseudo = European_option_price_simulation(S0, K, r, T, sigma, z_pseudo_random, option_type=option_type)
|
100 |
+
option_prices_pseudo.append(option_price_pseudo)
|
101 |
+
|
102 |
+
# 使用 quasi-random numbers
|
103 |
+
u_quasi_random = sobol_engine.random(n=n_simulations).flatten()
|
104 |
+
z_quasi_random = norm.ppf(u_quasi_random)
|
105 |
+
option_price_quasi = European_option_price_simulation(S0, K, r, T, sigma, z_quasi_random, option_type=option_type)
|
106 |
+
option_prices_quasi.append(option_price_quasi)
|
107 |
+
|
108 |
+
# 使用 Numpy random
|
109 |
+
z_numpy_random = np.random.normal(0, 1, n_simulations)
|
110 |
+
option_price_numpy = European_option_price_simulation(S0, K, r, T, sigma, z_numpy_random, option_type=option_type)
|
111 |
+
option_prices_numpy.append(option_price_numpy)
|
112 |
+
|
113 |
+
true_option_price = European_option_price(S0, K, r, T, sigma, option_type=option_type)
|
114 |
+
|
115 |
+
bar = bar.progress(80, "計算中")
|
116 |
+
|
117 |
+
|
118 |
+
#%%
|
119 |
+
from plotly.subplots import make_subplots
|
120 |
+
|
121 |
+
st.subheader(option_type+" option 價格分布比較")
|
122 |
+
|
123 |
+
# 創建包含三個子圖的圖表
|
124 |
+
fig = make_subplots(rows=3, cols=1, subplot_titles=("pseudo-random numbers (np.random.uniform)",
|
125 |
+
"quasi-random numbers (qmc.Sobol)",
|
126 |
+
"pseudo-random numbers (np.random.normal)"))
|
127 |
+
|
128 |
+
nbinsx = 30
|
129 |
+
fig.add_trace(
|
130 |
+
go.Histogram(x=option_prices_pseudo,
|
131 |
+
nbinsx=nbinsx,
|
132 |
+
histnorm="probability density",
|
133 |
+
name="pseudo-random numbers (np.random.uniform)",
|
134 |
+
marker=dict(color="rgba(0,0,255,0.15)", line=dict(width=1, color="black")),
|
135 |
+
opacity=1.0),
|
136 |
+
row=1, col=1)
|
137 |
+
|
138 |
+
fig.add_trace(
|
139 |
+
go.Histogram(x=option_prices_quasi,
|
140 |
+
nbinsx=nbinsx,
|
141 |
+
histnorm="probability density",
|
142 |
+
name="quasi-random numbers (qmc.Sobol)",
|
143 |
+
marker=dict(color="rgba(255,0,0,0.15)", line=dict(width=1, color="black")),
|
144 |
+
opacity=1.0),
|
145 |
+
row=2, col=1)
|
146 |
+
|
147 |
+
fig.add_trace(
|
148 |
+
go.Histogram(x=option_prices_numpy,
|
149 |
+
nbinsx=nbinsx,
|
150 |
+
histnorm="probability density",
|
151 |
+
name="pseudo-random numbers (np.random.normal)",
|
152 |
+
marker=dict(color="rgba(0,255,0,0.15)", line=dict(width=1, color="black")),
|
153 |
+
opacity=1.0),
|
154 |
+
row=3, col=1)
|
155 |
+
|
156 |
+
fig.add_vline(x=true_option_price,
|
157 |
+
line_width=2,
|
158 |
+
line_dash="dash",
|
159 |
+
line_color="blue")
|
160 |
+
|
161 |
+
fig.update_layout(
|
162 |
+
title="不同方法計算的 "+option_type+" option 價格分布",
|
163 |
+
height=900)
|
164 |
+
|
165 |
+
fig.update_xaxes(title=option_type+" option 價格", row=1, col=1)
|
166 |
+
fig.update_xaxes(title=option_type+" option 價格", row=2, col=1)
|
167 |
+
fig.update_xaxes(title=option_type+" option 價格", row=3, col=1)
|
168 |
+
|
169 |
+
fig.update_yaxes(title="density", row=1, col=1)
|
170 |
+
fig.update_yaxes(title="density", row=2, col=1)
|
171 |
+
fig.update_yaxes(title="density", row=3, col=1)
|
172 |
+
|
173 |
+
st.plotly_chart(fig)
|
174 |
+
|
175 |
+
bar = bar.progress(100, "OK")
|
176 |
+
|
177 |
+
# 打開 "命令提示字元" 或 "終端機",開始執行程式 (或進入 Command Prompt 視窗):
|
178 |
+
# (a) Anaconda => Anaconda Prompt (or Anaconda Powershell Prompt)
|
179 |
+
# (b) WinPython => WinPython Command Prompt.exe
|
180 |
+
# Streamlit run "c:\work\subject\112\simulation\tronclass\(2024.03.21) pseudo-random numbers vs quasi-random numbers-european_option\03-pseudo-random numbers vs quasi-random numbers-european_option-streamlit2.py"
|
181 |
+
# Google Chrome => http://localhost:8501/
|
182 |
+
# Google Chrome 不關掉,程式修改存檔後,可直接執行 Google Chrome output 畫面右上角的 Return。
|
183 |
+
# 指定 localhost port => streamlit run app.py --server.port 8502
|
184 |
+
# 需要終止該應用程式只需在終端中按 Ctrl + C。
|
185 |
+
# 路徑和檔名不能有中文。
|
186 |
+
# Mac 不能使用 MacOS 內建的 Safari 瀏覽器,改用 Google Chrome 就沒問題了。
|