σμ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›الوحدة 1 · أساسيات Python للمحللين الكميين›الموضوع 1.32·~45 دمبتدئ

المصفوفات والأنظمة الخطية

الموضع في المسارالوحدة 1 من 11 · الموضوع 32 من 33
1.32 المصفوفات والأنظمة الخطية
—درجة المختبر— / 100إجمالي XP—التتابع—

جدول أرقام يعمل على المتجهات

المصفوفة جدول مستطيل من الأرقام. نخزّنها في بايثون كقائمة صفوف، فـ[[1, 2], [3, 4]] مصفوفة 2×2 وتقرأ m[الصف][العمود] مدخلة واحدة. وتصف المصفوفات صفوفًا كثيرة من النوع نفسه من الحساب دفعة واحدة. فإذا كان كل صف يحمل أوزان محفظة وكان المتجه عوائد الأصول في اليوم فإن حاصل ضرب المصفوفة في المتجه هو عائد كل محفظة في خطوة واحدة. وكل مدخلة في الناتج هي الجداء النقطي لصف مع المتجه، فيجب أن يساوي طول الصف طول المتجه.

def dot(a, b):
    return sum(x * y for x, y in zip(a, b))

def mat_vec(matrix, vector):
    return [dot(row, vector) for row in matrix]

print(mat_vec([[1, 2], [3, 4]], [5, 6]))   # [17, 39]

# Two portfolios, three assets, one day of returns
weights = [[0.5, 0.3, 0.2],
           [0.2, 0.5, 0.3]]
returns = [0.02, -0.01, 0.03]
print([round(r, 4) for r in mat_vec(weights, returns)])   # [0.013, 0.008]

المنقول وضرب المصفوفات

المنقول يبدّل الصفوف والأعمدة: تصبح المدخلة (i, j) هي (j, i)، فتتحول مصفوفة 2×3 إلى 3×2. وفي بايثون تفعل ذلك [list(column) for column in zip(*m)]. وحاصل الضرب A @ B لمصفوفة n×k ومصفوفة k×m هو مصفوفة n×m مدخلتها (i, j) هي الجداء النقطي للصف i من A مع العمود j من B. وأعمدة B هي صفوف منقولها، مما يقصّر الكود. ويجب أن تتطابق الأبعاد الداخلية (k وk)، وعلى خلاف الأعداد يهم الترتيب: ففي العموم A @ B ليست B @ A.

def dot(a, b):
    return sum(x * y for x, y in zip(a, b))

def transpose(m):
    return [list(column) for column in zip(*m)]

def mat_mul(a, b):
    columns = transpose(b)
    return [[dot(row, column) for column in columns] for row in a]

print(transpose([[1, 2, 3], [4, 5, 6]]))   # [[1, 4], [2, 5], [3, 6]]

A = [[1, 2], [3, 4]]
B = [[5, 6], [7, 8]]
print(mat_mul(A, B))   # [[19, 22], [43, 50]]
print(mat_mul(B, A))   # [[23, 34], [31, 46]]  (a different answer: order matters)

حل نظام خطي

كثير من الأسئلة لها الصيغة: أوجد x بحيث A @ x = b. كم يلزم من كل أداة من أداتي تحوّط لإلغاء تعرّض معيّن؟ وأي أحمال للعوامل تعيد إنتاج العوائد المرصودة؟ هذا نظام خطي. وتحلّه طريقة الحذف لغاوس بتحويل المعادلات إلى مثلث: لكل عمود نختار الصف ذا أكبر قيمة مطلقة في ذلك العمود محورًا (ونرفعه إلى أعلى مما يُبقي أخطاء التقريب صغيرة)، ونطرح مضاعفاته من الصفوف التي تحته لنصنع أصفارًا، ثم نحل صعودًا بـالتعويض العكسي. وإذا كان المحور (شبه) صفر فالصفوف معتمدة بعضها على بعض والمصفوفة منفردة (singular) فلا جواب وحيد: ارفع خطأً بدل القسمة على صفر.

def solve(a, b):
    n = len(a)
    m = [list(map(float, row)) + [float(b[i])] for i, row in enumerate(a)]  # augmented matrix
    for col in range(n):
        pivot = max(range(col, n), key=lambda r: abs(m[r][col]))
        if abs(m[pivot][col]) < 1e-12:
            raise ValueError("the matrix is singular")
        m[col], m[pivot] = m[pivot], m[col]
        for r in range(col + 1, n):
            factor = m[r][col] / m[col][col]
            for c in range(col, n + 1):
                m[r][c] -= factor * m[col][c]
    x = [0.0] * n
    for i in range(n - 1, -1, -1):          # back-substitution
        known = sum(m[i][j] * x[j] for j in range(i + 1, n))
        x[i] = (m[i][n] - known) / m[i][i]
    return x

print(solve([[2, 1], [1, 3]], [3, 5]))                    # [0.8, 1.4]
print(solve([[1, 1, 1], [0, 2, 5], [2, 5, -1]], [6, -4, 27]))  # [5.0, 3.0, -2.0]

try:
    solve([[1, 2], [2, 4]], [1, 2])         # the second row is twice the first
except ValueError as error:
    print(error)                            # the matrix is singular
import math

def dot(a, b):
    return sum(x * y for x, y in zip(a, b))

def mat_vec(matrix, vector):
    return [dot(row, vector) for row in matrix]

# Check a solution by multiplying back: A x should give b again
A = [[2, 1], [1, 3]]
b = [3, 5]
x = [0.8, 1.4]                       # the answer from solve(A, b)
residual = [got - want for got, want in zip(mat_vec(A, x), b)]
print([abs(round(r, 12)) for r in residual])  # [0.0, 0.0]  (tiny rounding errors vanish)
print(all(math.isclose(g, w) for g, w in zip(mat_vec(A, x), b)))   # True

# The identity matrix leaves any vector unchanged
identity = [[1, 0], [0, 1]]
print(mat_vec(identity, [7, 9]))     # [7, 9]
حُلّ ولا تقلبتكتب الكتب x = A⁻¹ b، لكن في الكود لا تحسب المعكوس تقريبًا أبدًا: فالحذف المباشر أسرع وأدق. وتحقق أيضًا من الجواب بضربه من جديد (يجب أن تعيد A @ x القيمة b حتى حدود التقريب)، واعتبر المصفوفة شبه المنفردة، كأصلين شبه تامّي الارتباط، تحذيرًا من أن الحل سيكون غير مستقر. وستستخدم لاحقًا numpy.linalg.solve التي تؤدي العمل نفسه بكود مُترجَم.
  • المصفوفة قائمة صفوف؛ وmat_vec تأخذ الجداء النقطي لكل صف مع المتجه.
  • المنقول بـzip(*m)؛ وA @ B المدخلة (i, j) = صف i من A نقطي عمود j من B؛ والترتيب مهم.
  • حُلّ A x = b بالحذف مع المحور والتعويض العكسي؛ والمحور (شبه) الصفري يعني مصفوفة منفردة.

التالي: المتغيرات العشوائية والتوقّع، لغة عدم اليقين وراء كل نموذج مخاطر وتسعير.

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

  • طبّق مصفوفة على متجه باستخدام mat_vec25 نقطة
  • بدّل الصفوف والأعمدة باستخدام transpose25 نقطة
  • اضرب مصفوفتين باستخدام mat_mul25 نقطة
  • حُلّ A x = b بالحذف باستخدام solve25 نقطة
المستكشف · lab-32-1
▾ lab-32-1
…
bash · داخل المتصفح
learner@quantcraft:~/lab-32-1$
لم يتم تحميل Python بعدPythonLn 1, Col 1Spaces: 4UTF-8

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

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

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

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

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

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