SigmaField
Mathematical Foundations for Quant Finance
0 of 256 lessons
      1. 6.1.1 Differential equations, and separable equationsConcept · 35 min
      2. 6.1.2 Linear first-order equations and integrating factorsConcept · 35 min
      3. 6.1.3 Practice set: first-order equationsPractice set · 25 min
      4. 6.1.4 Case study: bond prices under a deterministic short rateCase study · 35 min

Level 6, Differential equations 6.1 First-order ODEs Lesson 3 of 4

Practice setLesson 6.1.3 in Level 6, Differential equations. About 25 minutes.

Practice set: first-order equations

Separable equations and Euler's method

Differential equations and separable equations (lesson 6.1.1)

0 of 9 correct

  1. 1.
  2. 2.
  3. 3.
  4. 4.
  5. 5.
  6. 6.
  7. 7.
  8. 8.
  9. 9.
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.

Linear equations and solve_ivp

Linear equations and integrating factors (lesson 6.1.2)

0 of 9 correct

  1. 1.
  2. 2.
  3. 3.
  4. 4.
  5. 5.
  6. 6.
  7. 7.
  8. 8.
  9. 9.
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

Euler's method, and a step that halves itself

Write two functions for an equation y′=f(t,y)y' = f(t, y), where f(t, y) returns the slope.

  1. euler(f, t0, y0, t_end, n) takes n Euler steps from (t0,y0)(t_0, y_0) to t_end, each of length h=tend−t0nh = \frac{t_{\text{end}} - t_0}{n}. It returns two NumPy arrays of length n+1n + 1: the times t0+kht_0 + kh and the values yky_k. If t_end is before t0, hh is negative and the steps run backwards. Raise ValueError unless n is a positive whole number.
  2. euler_converge(f, t0, y0, t_end, tol, n0=10) starts with n0 steps and doubles the number until two answers in a row at t_end differ by less than tol. Return the last answer and its number of steps, as a pair.

Euler's error is about proportional to hh (lesson 6.1.1), so the gap between two answers in a row is about the error of the second. For y′=0.5yy' = 0.5y from y(0)=1y(0) = 1 to t=2t = 2 with tol=1e-3, the second function stops at 2,560 steps, about 0.00053 below ee.

See the tests
import math

import numpy as np


def growth(t, y):
    return 0.5 * y


def test_four_steps():
    """Four steps of 0.5 for y' = 0.5y from 1 give 1.25^4 = 2.441406"""
    ts, ys = euler(growth, 0, 1, 2, 4)
    expect_close(ys[-1], 1.25**4, what="y after 4 steps")


def test_arrays():
    """The times run from t0 to t_end in n + 1 values, with y0 first"""
    ts, ys = euler(growth, 0, 1, 2, 4)
    expect_equal(len(ts), 5, what="len(ts)")
    expect_equal(len(ys), 5, what="len(ys)")
    expect_close(ts, [0, 0.5, 1, 1.5, 2], what="ts")
    expect_close(ys[0], 1.0, what="ys[0]")


def test_slope_depends_on_t():
    """Two steps of 0.1 for y' = t + y from y(0) = 1 give 1.1, then 1.22"""
    ts, ys = euler(lambda t, y: t + y, 0, 1, 0.2, 2)
    expect_close(ys, [1, 1.1, 1.22], what="ys")


def test_backwards():
    """2,000 steps back from y(2) = e to t = 0 for y' = 0.5y land near 1"""
    ts, ys = euler(growth, 2, math.e, 0, 2000)
    expect_close(ts[-1], 0.0, what="last time")
    expect_close(ys[-1], 1.0, what="y at t = 0", rel=1e-3)


def test_bad_n():
    """n = 0 and n = 2.5 raise ValueError"""
    for n in (0, 2.5):
        try:
            euler(growth, 0, 1, 2, n)
        except ValueError:
            continue
        raise AssertionError(f"expected ValueError for n = {n}")


def test_converge():
    """For y' = 0.5y to t = 2 with tol 0.001, the steps double to 2,560 and land 0.00053 below e"""
    value, n = euler_converge(growth, 0, 1, 2, 1e-3)
    expect_equal(n, 2560, what="number of steps")
    expect_close(value, math.e, what="answer", rel=3e-4)


def test_converge_settling():
    """For y' = 0.8(2 - y) from 4 to t = 5 with tol 10^-5, the answer is within 10^-5 of 2 + 2e^-4"""
    value, n = euler_converge(lambda t, y: 0.8 * (2 - y), 0, 4, 5, 1e-5)
    expect_close(value, 2 + 2 * math.exp(-4), what="answer", rel=0, abs_tol=1e-5)

Free further reading

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