ما سرعة تغيّره؟
المشتقة لدالة f عند x هي معدل تغيّرها اللحظي: ميل المنحنى عند تلك النقطة. وفي المالية تكاد كل حساسية تكون مشتقة. فـدلتا الخيار هي مقدار تحرك سعره لكل وحدة تحرك في الأصل الأساسي، وغاما هي سرعة تغيّر دلتا نفسها، ومدة السند مشتقة للسعر بالنسبة إلى العائد. يعطي التفاضل صيغًا دقيقة للدوال البسيطة (مشتقة x**2 هي 2*x)، لكن دوال التسعير الحقيقية كثيرًا ما تكون معقدة جدًا أو متاحة ككود فقط. عندها نقدّر المشتقة عدديًا.
# A function is just a Python function
def f(x):
return x * x
# Slope between two nearby points approaches the true slope (2x = 6 at x = 3)
x = 3.0
for h in (1.0, 0.1, 0.001):
slope = (f(x + h) - f(x)) / h
print(h, round(slope, 4))
# 1.0 7.0
# 0.1 6.1
# 0.001 6.001الفروق المنتهية: الأمامية والمركزية
تنظر الفروق الأمامية خطوة صغيرة h إلى الأمام: (f(x + h) - f(x)) / h. ويتناقص خطؤها بالتناسب مع h. وتنظر الفروق المركزية خطوة في كل اتجاه: (f(x + h) - f(x - h)) / (2 * h). فتتلاشى أخطاء الجانبين، ويتناقص خطؤها كمربع h وهي دقيقة تمامًا للدوال التربيعية. وتجمع المشتقة الثانية (غاما) ثلاث نقاط: (f(x + h) - 2 * f(x) + f(x - h)) / h**2. مرّر الدالة نفسها وسيطًا (f)، وهي مهارة من موضوعات الدوال.
import math
def forward_diff(f, x, h=1e-6):
return (f(x + h) - f(x)) / h
def central_diff(f, x, h=1e-5):
return (f(x + h) - f(x - h)) / (2 * h)
def second_derivative(f, x, h=1e-4):
return (f(x + h) - 2 * f(x) + f(x - h)) / h**2
print(round(central_diff(math.sin, 0.0), 6)) # 1.0 (cos 0)
print(round(central_diff(lambda x: x**3, 2.0), 4)) # 12.0 (3 x^2)
print(round(second_derivative(lambda x: x**3, 2.0), 3)) # 12.0 (6 x)
# A quadratic: central is exact even for a big step, forward is not
print(central_diff(lambda x: x * x, 3.0, h=0.5)) # 6.0
print(forward_diff(lambda x: x * x, 3.0, h=0.5)) # 6.5اختيار حجم الخطوة
يقلّل h الأصغر خطأ البتر في الصيغة، لكن طرح عددين متقاربين جدًا يُضيّع أرقامًا: ويكبر خطأ التقريب هذا كلما صغر h، وفي المشتقة الثانية يكبر أسرع لأننا نقسم أيضًا على h**2. وقد يعطي h صغير جدًا (مثل 1e-12) نتائج لا قيمة لها. التوفيق الجيد نحو 1e-5 للمشتقات الأولى بالفروق المركزية ونحو 1e-4 للثانية. وفي كود التسعير الفعلي، «ارفع وأعد التسعير» (bump and reprice) هو هذا بالضبط: أعد تشغيل المسعّر بسعر فوري مرفوع ومخفوض بمقدار صغير.
import math
def central_diff(f, x, h):
return (f(x + h) - f(x - h)) / (2 * h)
# True derivative of exp at 0 is 1; watch the error as h shrinks
for h in (1e-1, 1e-3, 1e-5, 1e-8, 1e-12):
error = abs(central_diff(math.exp, 0.0, h) - 1.0)
print(f"h={h:g} error={error:.1e}")
# h=0.1 error=1.7e-03
# h=0.001 error=1.7e-07
# h=1e-05 error=1.2e-11
# h=1e-08 error=5.3e-10 (rounding error takes over)
# h=1e-12 error=3.3e-05 (much worse: too small)استخدام المشتقات: طريقة نيوتن
تدلك المشتقة على الاتجاه الذي تتحرك فيه لبلوغ جذر، وهو نقطة f(x) = 0. تبدأ طريقة نيوتن من تخمين x وتستبدله مرارًا بـx - f(x) / f'(x) متتبعةً المماس نزولًا إلى الصفر. وتتقارب بسرعة كبيرة قرب الجذر، ولهذا تُستخدم لاستخلاص التقلب الضمني من سعر خيار. توقف حين تهبط abs(f(x)) دون تفاوت مسموح، واستسلم بعد عدد أقصى من التكرارات، وارفع خطأً إذا كانت المشتقة صفرًا أو لم تتقارب الحلقة بدل إرجاع رقم خاطئ.
def central_diff(f, x, h=1e-5):
return (f(x + h) - f(x - h)) / (2 * h)
def newton_root(f, x0, tol=1e-10, max_iter=50):
x = x0
for _ in range(max_iter):
if abs(f(x)) < tol:
return x
slope = central_diff(f, x)
if slope == 0:
raise ValueError("flat slope: Newton cannot continue")
x = x - f(x) / slope
raise ValueError("did not converge")
# The square root of 2 is the positive root of x^2 - 2
root = newton_root(lambda x: x * x - 2, 1.0)
print(round(root, 8)) # 1.41421356
# x^2 + 1 never reaches zero
try:
newton_root(lambda x: x * x + 1, 1.0)
except ValueError:
print("no root found") # no root foundx**2 أو sin) قبل الاعتماد عليها في مسعّر. وتوفر مكتبات مثل numpy وscipy نسخًا مُختبَرة؛ ومعرفة كيف تعمل تخبرك متى تثق بها.- الأمامية
(f(x+h) - f(x)) / h؛ المركزية(f(x+h) - f(x-h)) / (2h)؛ الثانية(f(x+h) - 2f(x) + f(x-h)) / h**2. - لا كبيرًا جدًا ولا صغيرًا جدًا: نحو
1e-5للمشتقات الأولى و1e-4للثانية. - نيوتن:
x = x - f(x) / f'(x)حتى تصبحabs(f(x))ضئيلة؛ وارفع خطأً إن لم تتقارب.
التالي: التكاملات في الكود، جمع شرائح رفيعة كثيرة لإيجاد المساحات والمجاميع والقيم المتوقعة.
المختبر: ما الذي يُقيَّم
- قدّر ميلًا بالنظر إلى الأمام باستخدام
forward_diff25 نقطة - قدّر ميلًا من الجانبين باستخدام
central_diff25 نقطة - قدّر الانحناء (غاما) باستخدام
second_derivative25 نقطة - اعثر على موضع انعدام دالة باستخدام
newton_root25 نقطة