σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
uantCraft Academyالمسارات
Ctrl K
AO
+1.2k متعلّم
تسجيل الدخولانضم ↗
المسارات
AO
+1.2k متعلّم
تسجيل الدخول
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
مسار Python›الوحدة 8 · النماذج العشوائية والتعلم الآلي›الموضوع 8.5·~1 سمتقدم

الخيارات ذات الحواجز

الموضع في المسارالوحدة 8 من 11 · الموضوع 5 من 10
8.5 الخيارات ذات الحواجز
—درجة المختبر— / 100إجمالي XP—التتابع—

خيارات بباب سري

الخيار ذو الحاجز كول أو بوت له مفتاح تشغيل وإيقاف. فخيار الإلغاء (knock-out) يزول إذا لمس السعر الحاجز، وخيار التفعيل (knock-in) لا يوجد إلا إذا لمسه. ويكون الحاجز فوق نقطة البداية (up) أو تحتها (down). ولأن المشتري يتنازل عن جزء من المدفوع فهذه الخيارات أرخص من العادية، ولهذا تشيع، وفي المنتجات المهيكلة أيضًا. وهي كالآسيوية تعتمد على المسار كله، والأداة الطبيعية المحاكاة.

import numpy as np

paths = np.array([[100.0, 105.0, 112.0, 108.0],      # stays below 115
                  [100.0,  98.0, 103.0, 110.0],      # stays below 115
                  [100.0, 120.0,  95.0,  90.0]])     # touches 115 on day 1, then falls

hit_up = paths.max(axis=1) >= 115.0                  # the maximum of each path against the barrier
print(hit_up)                                        # [False False  True]
print(paths.min(axis=1) <= 96.0)                     # a down barrier at 96: [False False  True]
# hit_barrier for both directions, with an error for anything else
import numpy as np

def hit_barrier(paths, barrier, direction):
    if direction == "up":
        return paths.max(axis=1) >= barrier
    if direction == "down":
        return paths.min(axis=1) <= barrier
    raise ValueError("direction must be 'up' or 'down'")

paths = np.array([[100.0, 110.0, 105.0], [100.0, 109.9, 105.0]])
print(hit_barrier(paths, 110.0, "up"))                  # [ True False]: touching the barrier exactly counts
try:
    hit_barrier(paths, 110.0, "sideways")
except ValueError as error:
    print("rejected:", error)

الإلغاء والتفعيل ومجموعهما

احسب على كل مسار مدفوع الكول العادي max(S_T - K, 0) وعلامة الحاجز. يُبقي كول الإلغاء المدفوع حيث *لم* يُلمس الحاجز، ويُبقيه كول التفعيل حيث لُمس. وكل مسار أحد الحالين، فـ*التفعيل + الإلغاء = الكول العادي* مسارًا مسارًا، وهي متطابقة مفيدة: سعّر الأسهل واحصل على الآخر مجانًا واستخدمها لاختبار شيفرتك. وnp.where(hit, a, b) يختار بين مصفوفتين عنصرًا عنصرًا.

import numpy as np

paths = np.array([[100.0, 105.0, 112.0, 108.0],
                  [100.0,  98.0, 103.0, 110.0],
                  [100.0, 120.0,  95.0, 130.0]])
strike, barrier = 100.0, 115.0

vanilla = np.maximum(paths[:, -1] - strike, 0.0)
hit = paths.max(axis=1) >= barrier
knock_out = np.where(hit, 0.0, vanilla)
knock_in = np.where(hit, vanilla, 0.0)

print(vanilla, knock_out, knock_in)                      # [ 8. 10. 30.] [ 8. 10.  0.] [ 0.  0. 30.]
print(np.allclose(knock_in + knock_out, vanilla))        # True

التسعير وانحياز الرصد المتقطع

السعر هو متوسط المدفوع المخصوم كما سبق. لكن انتبه لفحص الحاجز: فالمحاكاة تنظر إلى السعر في تواريخ شبكتها فقط، بينما يُخترق الحاجز المستمر الحقيقي *بين* التواريخ أيضًا. ومع خطوات قليلة تعبر المسارات المحاكاة الحاجز دون أن يُرى، فيخرج كول الإلغاء أغلى مما يجب وكول التفعيل أرخص. وتقلل الخطوات الأكثر هذا الانحياز، وكذلك التصحيحات التي تزيح الحاجز بنحو 0.5826 * sigma * sqrt(dt).

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))
    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(moves, axis=1)]))

def knock_out_price(paths, strike, barrier, rate, t):
    vanilla = np.maximum(paths[:, -1] - strike, 0.0)
    payoff = np.where(paths.max(axis=1) >= barrier, 0.0, vanilla)
    return float(np.exp(-rate * t) * payoff.mean())

rng = np.random.default_rng(1)
for steps in (12, 52, 252):
    paths = simulate_paths(100.0, 0.05, 0.25, 1.0, steps, 40000, rng)
    print(steps, round(knock_out_price(paths, 100.0, 130.0, 0.05, 1.0), 3))        # the price falls as monitoring gets finer
مخاطر الحاجز مخاطر فجوةقرب الحاجز تقفز دلتا وغاما للخيار، وقد تشغّل حركة صغيرة جدًا في السعر المدفوع كله أو تطفئه. وهذا يصعّب تحوط خيار الإلغاء قرب حاجزه وتتقاضى المكاتب مقابل ذلك. واحذر أيضًا ممن يتحكم بالسعر قرب الحاجز: فالعقود تحدد بدقة أي الأسعار يُحتسب (سعر إغلاق أو طباعة بورصة) لأن إغراء دفع السوق حقيقي.
  • يُلمس الحاجز إذا بلغه أعلى المسار (up) أو أدناه (down) في أي تاريخ؛ فخيار الإلغاء يموت عند اللمس وخيار التفعيل يولد عنده.
  • في كل مسار: التفعيل + الإلغاء = مدفوع الكول العادي؛ وnp.where(hit, a, b) يختار؛ والخيارات ذات الحاجز أرخص من العادية.
  • المحاكاة على شبكة تفوّت العبور بين التواريخ فيبدو كول الإلغاء غاليًا جدًا: استخدم خطوات أكثر أو أزح الحاجز؛ واحذر مخاطر الفجوة قرب الحاجز.

التالي: المتغيرات المتقابلة، طريقة للحصول على دقة مونت كارلو نفسها بمحاكيات أقل.

المختبر: ما الذي يُقيَّم

  • اكتشف اللمس باستخدام hit_barrier25 نقطة
  • اقتل الخيار باستخدام knock_out_call_payoff25 نقطة
  • أحيِه باستخدام knock_in_call_payoff25 نقطة
  • حوّل المدفوعات إلى سعر باستخدام barrier_price25 نقطة
المستكشف · lab-106-1
▾ lab-106-1
…
bash · داخل المتصفح
learner@quantcraft:~/lab-106-1$
لم يتم تحميل Python بعدPythonLn 1, Col 1Spaces: 4UTF-8

هل تريد إعادة ضبط هذا الموضوع؟

سيعود كل ما في lab-106-1 إلى الملفات الابتدائية وستُمسح الطرفية. ستفقد حلّك الحالي ولا يمكن التراجع عن ذلك.

سيُعاد ضبطه
  • main.py ← الشيفرة الابتدائية
  • سجل الطرفية ومخرجات الاختبارات
  • التغييرات غير المُرسلة
سيُحتفظ به
  • أفضل درجة في المختبر
  • نقاط XP والتتابع
  • تقدّم المحاضرة والملاحظات

سجّل الدخول لتشغيل الكود الخاص بك.

قراءة كل المحاضرات مجانية. أنشئ حسابًا أو سجّل الدخول لتشغيل الكود وتنفيذ الاختبارات وتسليم هذا المختبر.

  • بيئة تطوير داخل المتصفح مع طرفية bash — لا حاجة لتثبيت أي شيء
  • تصحيح فوري ونقاط خبرة ومكانك في المسار
إنشاء حسابتسجيل الدخول
أو
المتابعة عبر GitHub