SigmaField
Mathematical Foundations for Quant Finance
0 of 256 lessons
      1. 4.2.1 The gradient and directional derivativesConcept · 30 min
      2. 4.2.2 The multivariable chain rule and the total differentialConcept · 35 min
      3. 4.2.3 Practice set: gradients and the chain rulePractice set · 20 min
      4. 4.2.4 Case study: attributing P&L to risk factorsCase study · 35 min

Level 4, Multivariable calculus and optimisation 4.2 Gradient and chain rule Lesson 3 of 4

Practice setLesson 4.2.3 in Level 4, Multivariable calculus and optimisation. About 20 minutes.

Practice set: gradients and the chain rule

The gradient and directional derivatives

The gradient and directional derivatives (lesson 4.2.1)

0 of 8 correct

  1. 1.
  2. 2.
  3. 3.
  4. 4.
  5. 5.
  6. 6.
  7. 7.
  8. 8.
How to type answers
  • Powers with ^: x^7, 2^(1/3), a^-2.
  • Multiply with * or by writing side by side: 3x^2, 2(x+1).
  • ln(x) is the natural log, log(x, 2) is log base 2, e is Euler's number, sqrt(x) is a square root.
  • sin(x), cos(x) and tan(x) take radians; write pi for π and sin(x)^2 for sin²x.
  • Your first answer to each question is saved: it counts towards your score and brings the question back for review.
  • Exact answers like ln(20)/ln(3) are best. Decimals need about 4 significant figures.

The chain rule and the total differential

The multivariable chain rule and the total differential (lesson 4.2.2)

0 of 7 correct

  1. 1.
  2. 2.
  3. 3.
  4. 4.
  5. 5.
  6. 6.
  7. 7.
How to type answers
  • Powers with ^: x^7, 2^(1/3), a^-2.
  • Multiply with * or by writing side by side: 3x^2, 2(x+1).
  • ln(x) is the natural log, log(x, 2) is log base 2, e is Euler's number, sqrt(x) is a square root.
  • sin(x), cos(x) and tan(x) take radians; write pi for π and sin(x)^2 for sin²x.
  • Your first answer to each question is saved: it counts towards your score and brings the question back for review.
  • Exact answers like ln(20)/ln(3) are best. Decimals need about 4 significant figures.

Coding exercise

Exercise

A numerical gradient and directional derivative

Write two functions, using lessons 4.1.2 and 4.2.1. Each takes a function f of one NumPy array and a point p, given as a list or an array.

  1. gradient(f, p, h=1e-5) returns ∇f(p)\nabla f(\mathbf{p}) as a float array, by central differences: component ii is f(p+hei)−f(p−hei)2h\frac{f(\mathbf{p} + h\mathbf{e}_i) - f(\mathbf{p} - h\mathbf{e}_i)}{2h}. It works for any number of inputs and leaves p unchanged.
  2. directional_derivative(f, p, v, h=1e-5) returns the slope of f at p in the direction of the arrow v, which need not have length 1. Raise ValueError if v is the zero vector or has a different number of components from p.

The tests use the tilted bowl x2+xy+y2−3xx^2 + xy + y^2 - 3x and a function of three variables.

They pass points as whole numbers, such as np.array([0, 1]). An integer array cannot hold a bump of 0.00001, so turn the point into floats first. They also check that the array you are given is the same afterwards.

See the tests
import math

import numpy as np


def _tilted(q):
    x, y = q
    return x**2 + x * y + y**2 - 3 * x


def _three(q):
    x, y, z = q
    return x**2 + y * z


def _raises_value_error(f, *args):
    try:
        f(*args)
    except ValueError:
        return True
    return False


def test_gradient_tilted():
    """The tilted bowl has gradient (−2, 2) at (0, 1)"""
    expect_close(gradient(_tilted, np.array([0.0, 1.0])), np.array([-2.0, 2.0]), what="gradient at (0, 1)", abs_tol=1e-6)


def test_gradient_three_variables():
    """x² + yz has gradient (2, 3, 2) at (1, 2, 3)"""
    expect_close(gradient(_three, np.array([1.0, 2.0, 3.0])), np.array([2.0, 3.0, 2.0]), what="gradient at (1, 2, 3)", abs_tol=1e-6)


def test_gradient_whole_numbers():
    """A point of whole numbers, as a list or an integer array, still gives (−2, 2)"""
    expect_close(gradient(_tilted, [0, 1]), np.array([-2.0, 2.0]), what="gradient(f, [0, 1])", abs_tol=1e-6)
    expect_close(gradient(_tilted, np.array([0, 1])), np.array([-2.0, 2.0]), what="gradient(f, np.array([0, 1]))", abs_tol=1e-6)


def test_point_unchanged():
    """gradient leaves the array it is given unchanged"""
    p = np.array([0.5, 1.5])
    before = p.copy()
    gradient(_tilted, p)
    expect_close(p, before, what="the point after calling gradient", rel=0, abs_tol=0)


def test_zero_at_lowest_point():
    """At the lowest point (2, −1) the gradient is (0, 0)"""
    expect_close(gradient(_tilted, [2, -1]), np.array([0.0, 0.0]), what="gradient at (2, −1)", abs_tol=1e-6)


def test_directional_unit():
    """Along the unit vector (0.6, 0.8) the slope at (0, 1) is 0.4"""
    expect_close(directional_derivative(_tilted, [0, 1], [0.6, 0.8]), 0.4, what="slope along (0.6, 0.8)")


def test_directional_normalises():
    """Along the arrow (3, 4) the slope at (0, 1) is still 0.4, not 2"""
    expect_close(directional_derivative(_tilted, [0, 1], [3, 4]), 0.4, what="slope along (3, 4)")


def test_steepest_and_level():
    """At (0, 1) the slope is 2√2 along the gradient and 0 along the level curve, (1, 1)"""
    expect_close(directional_derivative(_tilted, [0, 1], [-2, 2]), 2 * math.sqrt(2), what="slope along the gradient (−2, 2)")
    expect_close(directional_derivative(_tilted, [0, 1], [1, 1]), 0.0, what="slope along (1, 1)", abs_tol=1e-6)


def test_three_variable_direction():
    """x² + yz at (1, 2, 3) has slope 4 along the arrow (1, 2, 2)"""
    expect_close(directional_derivative(_three, [1, 2, 3], [1, 2, 2]), 4.0, what="slope along (1, 2, 2)")


def test_zero_direction():
    """The zero vector has no direction: ValueError"""
    assert _raises_value_error(directional_derivative, _tilted, [0, 1], [0, 0]), "expected ValueError for the direction (0, 0)"


def test_wrong_size():
    """A direction with three components for a point with two: ValueError"""
    assert _raises_value_error(directional_derivative, _tilted, [0, 1], [1, 0, 0]), "expected ValueError for a direction of the wrong size"

Free further reading

Optional. This lesson covers what you need; these add more examples and practice. All are free to read.