ypchangchatgpt's picture
Update app.py
4223977 verified
# 不使用 for 迴圈。
# 發佈到 Hugging Face 伺服器,程式不能有 %reset -f (magic functions)
import numpy as np
from scipy import stats
import matplotlib
import matplotlib.pyplot as plt
import mpltw
matplotlib.use("Agg")
# 使用 gradio+matplotlib 套件,這行一定要寫。
font_size = 8
plt.rcParams.update({"font.size": font_size})
plt.close("all")
#%%
# quasi-random numbers 時,調整避免產生的模擬資料是 0 或 1。
# 寫為函數:
def generate_Sobol(Sobol_seq, n=1, epsilon=0):
quasi_random_numbers = Sobol_seq.random(n)
# quasi_random_numbers = epsilon + (1 - 2 * epsilon) * quasi_random_numbers
d = Sobol_seq.d
l_bounds = np.repeat(epsilon, d)
u_bounds = np.repeat(1-epsilon, d)
quasi_random_numbers = stats.qmc.scale(quasi_random_numbers, l_bounds, u_bounds)
return quasi_random_numbers
def Black_Scholes(S0, K, r, T, sigma, option_type):
d1 = (np.log(S0/K)+(r+sigma**2/2)*T)/(sigma*np.sqrt(T))
d2 = d1-sigma*np.sqrt(T)
if option_type == "call":
return S0*stats.norm.cdf(d1)-K*np.exp(-r*T)*stats.norm.cdf(d2)
if option_type == "put":
return K*np.exp(-r*T)*stats.norm.cdf(-d2)-S0*stats.norm.cdf(-d1)
def European_option_simulation(S0, K, r, T, sigma, Z):
ST = S0*np.exp((r-0.5*sigma**2)*T+sigma*np.sqrt(T)*Z)
payoff = np.maximum(ST-K, 0)
prices = np.exp(-r*T)*np.mean(payoff, axis=0)
return prices
#%%
def plot_European_option(S0, K, r, T, sigma, n, m, seed, bins, alpha):
S0 = np.float64(S0)
K = np.float64(K)
r = np.float64(r)
T = np.float64(T)
sigma = np.float64(sigma)
price_true = Black_Scholes(S0, K, r, T, sigma, option_type="call")
print("European call option price =", price_true)
n = int(n)
m = int(m)
seed = int(seed)
bins = int(bins)
alpha = np.float64(alpha)
# pseudo-random numbers
np.random.seed(seed)
u_pseudo = np.random.rand(n, m)
Z_pseudo = stats.norm.ppf(u_pseudo)
# quasi-random numbers
Sobol_seq = stats.qmc.Sobol(d=m, scramble=True, seed=seed)
"""
scramble 內建值為 True。
Scramble 是指將一個序列或集合中的元素加干擾的過程。
"""
u_quasi = generate_Sobol(Sobol_seq, n=n, epsilon=1e-8)
Z_quasi = stats.norm.ppf(u_quasi)
"""
Sobol_seq = stats.qmc.Sobol(d=n, seed=seed)
u_quasi = Sobol_seq.random(m)
Z_quasi = stats.norm.ppf(u_quasi).T
# 這個寫法沒有明顯效果,所以要注意 d 的設定。
"""
prices_pseudo = European_option_simulation(S0, K, r, T, sigma, Z_pseudo)
prices_quasi = European_option_simulation(S0, K, r, T, sigma, Z_quasi)
fig = plt.figure(figsize=(4, 8))
plt.subplot(211)
plt.hist(prices_pseudo,
bins=bins,
density=True,
alpha=alpha,
ec="black")
plt.axvline(x=price_true, color="red")
plt.xlabel("simulate option price")
plt.ylabel("density")
plt.title("Simulate option prices with pseudo-random numbers")
plt.subplot(212)
plt.hist(prices_quasi,
bins=bins,
density=True,
alpha=alpha,
ec="black")
plt.axvline(x=price_true, color="red")
plt.xlabel("simulate option price")
plt.ylabel("density")
plt.title("Simulate option prices with quasi-random numbers")
plt.tight_layout()
return fig
#%%
import gradio as gr
S0 = gr.Textbox(value="100", label="S0") # initial stock price
K = gr.Textbox(value="100", label="K") # strike price
r = gr.Textbox(value="0.02", label="r") # risk-free interest rate
T = gr.Textbox(value="0.5", label="T") # time to maturity
sigma = gr.Textbox(value="0.2", label="sigma") # volatility
n = gr.Textbox(value="10000", label="n") # number of simulations
m = gr.Textbox(value="1000", label="m") # number of repeated experiments
seed = gr.Textbox(value="123457", label="seed")
bins = gr.Slider(minimum=10, maximum=60, step=5, value=40, label="bins")
alpha = gr.Slider(minimum=0, maximum=1, step=0.1, value=0.6, label="alpha")
inputs = [S0, K, r, T, sigma, n, m, seed, bins, alpha]
outputs = [gr.Plot()]
interface = gr.Interface(fn=plot_European_option,
inputs=inputs,
outputs=outputs,
title="European call option")
interface.launch(share=True)
# share=True 一定要寫,瀏覽器才可以看到結果。
# 但發佈到 Hugging Face 伺服器,則 share=True 可以不寫。