ypchangchatgpt
commited on
Commit
•
ef4de14
1
Parent(s):
a2f3e3c
Upload 2 files
Browse files- app.py +138 -0
- requirements.txt +5 -0
app.py
ADDED
@@ -0,0 +1,138 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# 不使用 for 迴圈。
|
2 |
+
# 發佈到 Hugging Face 伺服器,程式不能有 %reset -f (magic functions)
|
3 |
+
|
4 |
+
import numpy as np
|
5 |
+
from scipy import stats
|
6 |
+
import matplotlib
|
7 |
+
import matplotlib.pyplot as plt
|
8 |
+
import mpltw
|
9 |
+
|
10 |
+
matplotlib.use("Agg")
|
11 |
+
# 使用 gradio+matplotlib 套件,這行一定要寫。
|
12 |
+
|
13 |
+
font_size = 8
|
14 |
+
plt.rcParams.update({"font.size": font_size})
|
15 |
+
|
16 |
+
plt.close("all")
|
17 |
+
|
18 |
+
|
19 |
+
#%%
|
20 |
+
# quasi-random numbers 時,調整避免產生的模擬資料是 0 或 1。
|
21 |
+
# 寫為函數:
|
22 |
+
def generate_Sobol(Sobol_seq, n=1, epsilon=0):
|
23 |
+
quasi_random_numbers = Sobol_seq.random(n)
|
24 |
+
# quasi_random_numbers = epsilon + (1 - 2 * epsilon) * quasi_random_numbers
|
25 |
+
d = Sobol_seq.d
|
26 |
+
l_bounds = np.repeat(epsilon, d)
|
27 |
+
u_bounds = np.repeat(1-epsilon, d)
|
28 |
+
quasi_random_numbers = stats.qmc.scale(quasi_random_numbers, l_bounds, u_bounds)
|
29 |
+
return quasi_random_numbers
|
30 |
+
|
31 |
+
def Black_Scholes(S0, K, r, T, sigma, option_type):
|
32 |
+
d1 = (np.log(S0/K)+(r+sigma**2/2)*T)/(sigma*np.sqrt(T))
|
33 |
+
d2 = d1-sigma*np.sqrt(T)
|
34 |
+
if option_type == "call":
|
35 |
+
return S0*stats.norm.cdf(d1)-K*np.exp(-r*T)*stats.norm.cdf(d2)
|
36 |
+
if option_type == "put":
|
37 |
+
return K*np.exp(-r*T)*stats.norm.cdf(-d2)-S0*stats.norm.cdf(-d1)
|
38 |
+
|
39 |
+
def European_option_simulation(S0, K, r, T, sigma, Z):
|
40 |
+
ST = S0*np.exp((r-0.5*sigma**2)*T+sigma*np.sqrt(T)*Z)
|
41 |
+
payoff = np.maximum(ST-K, 0)
|
42 |
+
prices = np.exp(-r*T)*np.mean(payoff, axis=0)
|
43 |
+
return prices
|
44 |
+
|
45 |
+
|
46 |
+
#%%
|
47 |
+
def plot_European_option(S0, K, r, T, sigma, n, m, seed, bins, alpha):
|
48 |
+
S0 = np.float64(S0)
|
49 |
+
K = np.float64(K)
|
50 |
+
r = np.float64(r)
|
51 |
+
T = np.float64(T)
|
52 |
+
sigma = np.float64(sigma)
|
53 |
+
|
54 |
+
price_true = Black_Scholes(S0, K, r, T, sigma, option_type="call")
|
55 |
+
print("European call option price =", price_true)
|
56 |
+
|
57 |
+
n = int(n)
|
58 |
+
m = int(m)
|
59 |
+
seed = int(seed)
|
60 |
+
bins = int(bins)
|
61 |
+
alpha = np.float64(alpha)
|
62 |
+
|
63 |
+
# pseudo-random numbers
|
64 |
+
np.random.seed(seed)
|
65 |
+
u_pseudo = np.random.rand(n, m)
|
66 |
+
Z_pseudo = stats.norm.ppf(u_pseudo)
|
67 |
+
|
68 |
+
# quasi-random numbers
|
69 |
+
Sobol_seq = stats.qmc.Sobol(d=m, scramble=True, seed=seed)
|
70 |
+
"""
|
71 |
+
scramble 內建值為 True。
|
72 |
+
Scramble 是指將一個序列或集合中的元素加干擾的過程。
|
73 |
+
"""
|
74 |
+
|
75 |
+
u_quasi = generate_Sobol(Sobol_seq, n=n, epsilon=1e-8)
|
76 |
+
Z_quasi = stats.norm.ppf(u_quasi)
|
77 |
+
"""
|
78 |
+
Sobol_seq = stats.qmc.Sobol(d=n, seed=seed)
|
79 |
+
u_quasi = Sobol_seq.random(m)
|
80 |
+
Z_quasi = stats.norm.ppf(u_quasi).T
|
81 |
+
# 這個寫法沒有明顯效果,所以要注意 d 的設定。
|
82 |
+
"""
|
83 |
+
|
84 |
+
prices_pseudo = European_option_simulation(S0, K, r, T, sigma, Z_pseudo)
|
85 |
+
prices_quasi = European_option_simulation(S0, K, r, T, sigma, Z_quasi)
|
86 |
+
|
87 |
+
fig = plt.figure(figsize=(4, 8))
|
88 |
+
plt.subplot(211)
|
89 |
+
plt.hist(prices_pseudo,
|
90 |
+
bins=bins,
|
91 |
+
density=True,
|
92 |
+
alpha=alpha,
|
93 |
+
ec="black")
|
94 |
+
plt.axvline(x=price_true, color="red")
|
95 |
+
plt.xlabel("simulate option price")
|
96 |
+
plt.ylabel("density")
|
97 |
+
plt.title("Simulate option prices with pseudo-random numbers")
|
98 |
+
|
99 |
+
plt.subplot(212)
|
100 |
+
plt.hist(prices_quasi,
|
101 |
+
bins=bins,
|
102 |
+
density=True,
|
103 |
+
alpha=alpha,
|
104 |
+
ec="black")
|
105 |
+
plt.axvline(x=price_true, color="red")
|
106 |
+
plt.xlabel("simulate option price")
|
107 |
+
plt.ylabel("density")
|
108 |
+
plt.title("Simulate option prices with quasi-random numbers")
|
109 |
+
|
110 |
+
plt.tight_layout()
|
111 |
+
return fig
|
112 |
+
|
113 |
+
|
114 |
+
#%%
|
115 |
+
import gradio as gr
|
116 |
+
|
117 |
+
S0 = gr.Textbox(value="100", label="S0") # initial stock price
|
118 |
+
K = gr.Textbox(value="100", label="K") # strike price
|
119 |
+
r = gr.Textbox(value="0.02", label="r") # risk-free interest rate
|
120 |
+
T = gr.Textbox(value="0.5", label="T") # time to maturity
|
121 |
+
sigma = gr.Textbox(value="0.2", label="sigma") # volatility
|
122 |
+
n = gr.Textbox(value="10000", label="n") # number of simulations
|
123 |
+
m = gr.Textbox(value="1000", label="m") # number of repeated experiments
|
124 |
+
seed = gr.Textbox(value="123457", label="seed")
|
125 |
+
bins = gr.Slider(minimum=10, maximum=60, step=5, value=40, label="bins")
|
126 |
+
alpha = gr.Slider(minimum=0, maximum=1, step=0.1, value=0.6, label="alpha")
|
127 |
+
inputs = [S0, K, r, T, sigma, n, m, seed, bins, alpha]
|
128 |
+
|
129 |
+
outputs = [gr.Plot()]
|
130 |
+
|
131 |
+
interface = gr.Interface(fn=plot_European_option,
|
132 |
+
inputs=inputs,
|
133 |
+
outputs=outputs,
|
134 |
+
title="European call option")
|
135 |
+
|
136 |
+
interface.launch()
|
137 |
+
# share=True 一定要寫,瀏覽器才可以看到結果。
|
138 |
+
# 但發佈到 Hugging Face 伺服器,則 share=True 不能寫。
|
requirements.txt
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
numpy
|
2 |
+
scipy
|
3 |
+
matplotlib
|
4 |
+
mpltw
|
5 |
+
gradio
|