الدفع على المتوسط
يعتمد الكول العادي على سعر يوم واحد هو الأخير. أما الخيار الآسيوي فيعتمد على متوسط السعر عبر مجموعة تواريخ: الكول الآسيوي يدفع max(المتوسط - K, 0). وتستخدمه الشركات لتحوط كلفة تتحملها باستمرار، كشراء النفط شهريًا، ويصعب التلاعب به عند الانتهاء. وهو *معتمد على المسار* فلا توجد صيغة بلاك-شولز بسيطة للمتوسط الحسابي، والأداة المعتادة هي محاكاة مونت كارلو.
import numpy as np
# Two simulated paths: the starting price, then monthly prices; the last column is expiry
paths = np.array([[100.0, 90.0, 110.0, 130.0],
[100.0, 70.0, 80.0, 90.0]])
average = paths[:, 1:].mean(axis=1) # the monitoring dates only, not the starting price
print(average) # [110. 80.]
print(np.maximum(average - 100.0, 0.0)) # Asian call payoffs: [10. 0.]
print(np.maximum(paths[:, -1] - 100.0, 0.0)) # European call payoffs on the same paths: [30. 0.]محاكاة المسارات
تأتي المسارات من الحركة البراونية الهندسية بانجراف محايد للمخاطر: يحل المعدل r محل mu. نسحب مصفوفة طبيعية معيارية بصف لكل مسار وعمود لكل تاريخ رصد، ونحولها إلى حركات لوغاريتم السعر، ونجري مجموعًا تراكميًا على كل صف. فيحمل مصفوف واحد كل المسارات، وكل خطوة لاحقة (المتوسطات والمدفوعات) عملية متجهة على الصفوف بلا حلقة على المسارات.
import numpy as np
def simulate_paths(s0, rate, sigma, t, steps, n_paths, rng):
dt = t / steps
z = rng.standard_normal((n_paths, steps))
log_moves = (rate - 0.5 * sigma ** 2) * dt + sigma * np.sqrt(dt) * z
return s0 * np.exp(np.hstack([np.zeros((n_paths, 1)), np.cumsum(log_moves, axis=1)]))
rng = np.random.default_rng(1)
paths = simulate_paths(100.0, 0.05, 0.2, 1.0, 12, 50000, rng) # monthly monitoring for a year
print(paths.shape) # (50000, 13)
print(round(float(paths[:, -1].mean()), 2), round(100 * np.exp(0.05), 2)) # the risk-neutral mean of the final priceالسعر وهامش خطئه
سعر الخيار هو متوسط المدفوع المخصوم: exp(-r * T) * mean(payoffs). وسعر مونت كارلو تقدير، فأبلغ دائمًا عن خطئه المعياري std(payoffs) / sqrt(عدد المسارات) (مخصومًا)، وهو يبين مدى بعد الرقم عن الحقيقة: أربعة أضعاف المسارات تنصّفه. والكول الآسيوي أرخص من الأوروبي على السهم نفسه لأن المتوسط يملّس السعر ويخفض التقلب الفعلي.
import numpy as np
def simulate_paths(s0, rate, sigma, t, steps, n_paths, rng):
dt = t / steps
z = rng.standard_normal((n_paths, steps))
log_moves = (rate - 0.5 * sigma ** 2) * dt + sigma * np.sqrt(dt) * z
return s0 * np.exp(np.hstack([np.zeros((n_paths, 1)), np.cumsum(log_moves, axis=1)]))
def asian_price(paths, strike, rate, t):
payoff = np.maximum(paths[:, 1:].mean(axis=1) - strike, 0.0)
discount = np.exp(-rate * t)
return discount * payoff.mean(), discount * payoff.std(ddof=1) / np.sqrt(len(payoff))
rng = np.random.default_rng(1)
paths = simulate_paths(100.0, 0.05, 0.2, 1.0, 12, 100000, rng)
price, error = asian_price(paths, 100.0, 0.05, 1.0)
european = np.exp(-0.05) * np.maximum(paths[:, -1] - 100.0, 0.0).mean()
print(round(float(price), 3), "+/-", round(float(error), 3))
print(round(float(european), 3), "European call on the same paths")# Geometric and arithmetic averages of the same monitoring prices
import numpy as np
prices = np.array([90.0, 110.0, 130.0])
arithmetic = prices.mean()
geometric = np.exp(np.log(prices).mean())
print(round(float(arithmetic), 3), round(float(geometric), 3)) # 110.0 108.774: the geometric average is never larger- يدفع الخيار الآسيوي على متوسط تواريخ الرصد:
max(المتوسط - K, 0)؛ معتمد على المسار فلا صيغة بسيطة ومونت كارلو هي الأداة. - حاكِ كل المسارات في مصفوفة واحدة (الصفوف = مسارات والأعمدة = تواريخ) بانجراف محايد للمخاطر؛ والمتوسطات والمدفوعات متجهة على الصفوف.
- السعر =
exp(-r * T) * mean(payoffs)بخطأ معياريstd / sqrt(paths)؛ والتوسيط يجعله أرخص من الكول الأوروبي، والنسخة الهندسية متغير ضابط.
التالي: الخيارات ذات الحاجز، التي تُولد أو تموت عندما يلمس السعر مستوى معينًا.
المختبر: ما الذي يُقيَّم
- احسب المتوسط على طول كل مسار باستخدام
average_price25 نقطة - جرّب المتوسط الهندسي باستخدام
geometric_average25 نقطة - ادفع على المتوسط باستخدام
asian_call_payoff25 نقطة - سعّرها مع هامش الخطأ باستخدام
asian_price25 نقطة