الإجابة بمتوسطات سحوبات عشوائية
كثير من الأسئلة المالية بلا صيغة مرتبة: احتمال أن تخسر محفظة 20% خلال سنة، وسعر خيار يتوقف عائده على المسار كله. يجيب مونت كارلو عنها بالقوة الغاشمة. اكتب الكمية متوسطًا E[f(X)]، وحاكِ سحوبات كثيرة من X، وطبّق f على كل منها وخذ المتوسط. وبقانون الأعداد الكبيرة يتقارب متوسط العيّنة من التوقع الحقيقي. والاحتمال هو توقع مؤشر نعم/لا، فـ«نسبة المحاكاة التي وقع فيها الحدث» تقدّره.
import math
import numpy as np
# Estimate pi: the quarter circle x^2 + y^2 <= 1 covers pi/4 of the unit square
rng = np.random.default_rng(42)
x, y = rng.random(100000), rng.random(100000)
inside = x ** 2 + y ** 2 <= 1 # True/False for every point
print(round(4 * inside.mean(), 4)) # 3.1378 close to 3.1416, with 100,000 pointsمحاكاة الأسعار والاحتمالات
لمحاكاة سهم اسحب صدمات طبيعية معيارية ومرّرها في الصيغة اللوغاريتمية الطبيعية من الموضوع السابق: تخرج الأسعار النهائية n كلها من تعبير مصفوفي واحد. بعدها يصير أي سؤال عن توزيع الأسعار متوسطًا على المصفوفة. احتمال الانتهاء تحت 80 هو np.mean(prices < 80) والسعر المتوقع prices.mean() وكمّي الخسائر np.quantile(...). ومرّر المولّد rng إلى الدالة بدل إنشائه داخلها ليتحكم المستدعي في قابلية التكرار.
def simulate_terminal_prices(rng, s0, mu, sigma, t, n):
z = rng.standard_normal(n)
return s0 * np.exp((mu - 0.5 * sigma ** 2) * t + sigma * math.sqrt(t) * z)
prices = simulate_terminal_prices(np.random.default_rng(1), 100, 0.05, 0.2, 1, 200000)
print(round(float(np.mean(prices < 80)), 4)) # 0.1027 P(price below 80 after a year), about 10%
print(round(float(np.mean(prices > 130)), 4)) # 0.1216 P(price above 130)تسعير خيار
يدفع الكول الأوروبي max(S - K, 0) عند الاستحقاق. وفي العالم المحايد للمخاطر ينمو كل أصل بمعدل الخالي من المخاطر rate، فالسعر العادل هو العائد المتوقع المخصوم: حاكِ الأسعار النهائية بـ mu = rate، واحسب عائد كل منها، وخذ المتوسط، واضربه في exp(-rate * t). ولهذا الخيار البسيط صيغة مغلقة (بلاك-شولز، 10.4506 للأرقام أدناه) وتقترب المحاكاة منها. وفائدة مونت كارلو أن الأسطر القليلة نفسها تظل صالحة لعوائد لا صيغة لها أصلًا.
def mc_call_price(rng, s0, strike, rate, sigma, t, n):
prices = simulate_terminal_prices(rng, s0, rate, sigma, t, n) # risk-neutral: the price grows at the risk-free rate
payoff = np.maximum(prices - strike, 0) # max(S - K, 0) for every simulated path
return math.exp(-rate * t) * payoff.mean() # discounted average payoff
price = mc_call_price(np.random.default_rng(1), 100, 100, 0.05, 0.2, 1, 200000)
print(round(price, 4)) # 10.3993 the exact Black-Scholes price is 10.4506: the difference is Monte Carlo error# More points, less error (1 / sqrt(n)): the estimate of pi with the same seed
for n in (100, 10000, 1000000):
g = np.random.default_rng(42)
x, y = g.random(n), g.random(n)
print(n, round(4 * float((x * x + y * y <= 1).mean()), 4))
# 100 3.36
# 10000 3.1488
# 1000000 3.1424- مونت كارلو: اكتب الكمية متوسطًا
E[f(X)]وحاكِ سحوبات كثيرة وطبّقfوخذ المتوسط. - الاحتمال متوسط مقارنة:
np.mean(prices < 80)؛ ومرّر المولّد وسيطًا لتكون العملية قابلة للتكرار. - سعر الخيار =
exp(-rate * t) * mean(max(S - K, 0))مع أسعار محاكاة عندmu = rate؛ واذكر الخطأ أيضًا.
التالي: خطأ مونت كارلو والتقارب، مدى دقة التقدير وكيفية الحصول على أكثر بأقل.
المختبر: ما الذي يُقيَّم
- ارمِ سهامًا على مربع لإيجاد باي باستخدام
estimate_pi25 نقطة - عُدّ مرات وقوع حدث باستخدام
estimate_probability25 نقطة - حاكِ أين قد ينتهي سهم باستخدام
simulate_terminal_prices25 نقطة - سعّر خيارًا بالمحاكاة باستخدام
mc_call_price25 نقطة