ypchangchatgpt/European_option_simulation-gradio-plotly
0
1# 不使用 for 迴圈。2# 發佈到 Hugging Face 伺服器,程式不能有 %reset -f (magic functions)3 4import numpy as np5from scipy import stats6import plotly.graph_objects as go7from plotly.subplots import make_subplots8 9# quasi-random numbers 時,調整避免產生的模擬資料是 0 或 1。10# 寫為函數:11def generate_Sobol(Sobol_seq, n=1, epsilon=0):12 quasi_random_numbers = Sobol_seq.random(n)13 # quasi_random_numbers = epsilon + (1 - 2 * epsilon) * quasi_random_numbers14 d = Sobol_seq.d15 l_bounds = np.repeat(epsilon, d)16 u_bounds = np.repeat(1-epsilon, d)17 quasi_random_numbers = stats.qmc.scale(quasi_random_numbers, l_bounds, u_bounds)18 return quasi_random_numbers19 20def Black_Scholes(S0, K, r, T, sigma, option_type):21 d1 = (np.log(S0/K)+(r+sigma**2/2)*T)/(sigma*np.sqrt(T))22 d2 = d1-sigma*np.sqrt(T)23 if option_type == "call":24 return S0*stats.norm.cdf(d1)-K*np.exp(-r*T)*stats.norm.cdf(d2)25 if option_type == "put":26 return K*np.exp(-r*T)*stats.norm.cdf(-d2)-S0*stats.norm.cdf(-d1)27 28def European_option_simulation(S0, K, r, T, sigma, Z):29 ST = S0*np.exp((r-0.5*sigma**2)*T+sigma*np.sqrt(T)*Z)30 payoff = np.maximum(ST-K, 0)31 prices = np.exp(-r*T)*np.mean(payoff, axis=0)32 return prices33 34 35#%%36def plot_European_option(S0, K, r, T, sigma, n, m, seed, bins, alpha):37 S0 = np.float64(S0)38 K = np.float64(K)39 r = np.float64(r)40 T = np.float64(T)41 sigma = np.float64(sigma)42 43 price_true = Black_Scholes(S0, K, r, T, sigma, option_type="call")44 print("European call option price =", price_true)45 46 n = int(n)47 m = int(m)48 seed = int(seed)49 bins = int(bins)50 alpha = np.float64(alpha)51 52 # pseudo-random numbers53 np.random.seed(seed)54 u_pseudo = np.random.rand(n, m)55 Z_pseudo = stats.norm.ppf(u_pseudo)56 57 # quasi-random numbers58 Sobol_seq = stats.qmc.Sobol(d=m, scramble=True, seed=seed)59 # scramble 內建值為 True。60 # Scramble 是指將一個序列或集合中的元素加干擾的過程。61 62 u_quasi = generate_Sobol(Sobol_seq, n=n, epsilon=1e-8)63 Z_quasi = stats.norm.ppf(u_quasi)64 """65 Sobol_seq = stats.qmc.Sobol(d=n, seed=seed)66 u_quasi = Sobol_seq.random(m)67 Z_quasi = stats.norm.ppf(u_quasi).T68 # 這個寫法沒有明顯效果,所以要注意 d 的設定。69 """70 71 prices_pseudo = European_option_simulation(S0, K, r, T, sigma, Z_pseudo)72 prices_quasi = European_option_simulation(S0, K, r, T, sigma, Z_quasi)73 74 fig = make_subplots(rows=2, cols=1, subplot_titles=("pseudo-random numbers (np.random.uniform)",75 "quasi-random numbers (qmc.Sobol)"))76 nbinsx = 3077 fig.add_trace(78 go.Histogram(x=prices_pseudo,79 nbinsx=nbinsx,80 histnorm="probability density",81 name="pseudo-random numbers (np.random.uniform)",82 marker=dict(color="rgba(0,0,255,0.15)", line=dict(width=1, color="black")),83 opacity=1.0),84 row=1, col=1)85 86 fig.add_trace(87 go.Histogram(x=prices_quasi,88 nbinsx=nbinsx,89 histnorm="probability density",90 name="quasi-random numbers (qmc.Sobol)",91 marker=dict(color="rgba(255,0,0,0.15)", line=dict(width=1, color="black")),92 opacity=1.0),93 row=2, col=1)94 95 fig.add_vline(x=price_true,96 line_width=2,97 line_dash="dash",98 line_color="blue")99 100 fig.update_layout(101 title="不同方法計算的 call option 價格分布",102 height=900)103 104 fig.update_xaxes(title="call option 價格", row=1, col=1)105 fig.update_xaxes(title="call option 價格", row=2, col=1)106 107 fig.update_yaxes(title="density", row=1, col=1)108 fig.update_yaxes(title="density", row=2, col=1)109 return fig110 111 112#%%113# https://www.machinelearningnuggets.com/gradio-tutorial/114import gradio as gr115 116with gr.Blocks() as app:117 with gr.Row():118 with gr.Column(scale=15, min_width=0):119 S0 = gr.Textbox(value="100", label="S0")120 K = gr.Textbox(value="100", label="K") # strike price121 # risk-free interest rate122 r = gr.Textbox(value="0.02", label="r")123 T = gr.Textbox(value="0.5", label="T") # time to maturity124 sigma = gr.Textbox(value="0.2", label="sigma") # volatility125 # number of simulations126 n = gr.Textbox(value="10000", label="n")127 # number of repeated experiments128 m = gr.Textbox(value="1000", label="m")129 seed = gr.Textbox(value="123457", label="seed")130 bins = gr.Slider(minimum=10, maximum=60, step=5, value=40, label="bins")131 alpha = gr.Slider(minimum=0, maximum=1, step=0.1, value=0.6, label="alpha")132 inputs = [S0, K, r, T, sigma, n, m, seed, bins, alpha]133 134 button = gr.Button(value="Submit")135 136 with gr.Column(scale=85):137 outputs = [gr.Plot()]138 139 button.click(fn=plot_European_option,140 inputs=inputs,141 outputs=outputs)142 143app.launch(share=True)144# share=True 一定要寫,瀏覽器才可以看到結果。145# 但發佈到 Hugging Face 伺服器,則 share=True 可以不寫。146 