SigmaField
Mathematical Foundations for Quant Finance
0 of 256 lessons
      1. 5.2.1 Random variables, PMFs and CDFsConcept · 25 min
      2. 5.2.2 Bernoulli, binomial and geometric distributionsConcept · 30 min
      3. 5.2.3 The Poisson distributionConcept · 30 min
      4. 5.2.4 Practice set: discrete distributionsPractice set · 25 min
      5. 5.2.5 Case study: the one-period binomial model, and counting defaultsCase study · 35 min

Level 5, Probability and statistics 5.2 Discrete random variables Lesson 4 of 5

Practice setLesson 5.2.4 in Level 5, Probability and statistics. About 25 minutes.

Practice set: discrete distributions

Random variables, PMFs and CDFs

Random variables, PMFs and CDFs (lesson 5.2.1)

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.

Bernoulli, binomial and geometric distributions

Bernoulli, binomial and geometric distributions (lesson 5.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.

The Poisson distribution

The Poisson distribution (lesson 5.2.3)

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

Binomial and Poisson probabilities

Write three functions with the math module only. The tests compare them with scipy.stats.

  1. binomial_pmf(k, n, p) returns (nk)pk(1−p)n−k\binom{n}{k}p^k(1 - p)^{n - k} (lesson 5.2.2).
  2. poisson_pmf(k, lam) returns e−λλkk!e^{-\lambda}\frac{\lambda^k}{k!} (lesson 5.2.3).
  3. cdf(pmf, x) returns P(X≤x)P(X \le x) for a random variable with whole-number values from 0 up, whose pmf is the function pmf (lesson 5.2.1). It adds pmf(k) for k=0,1,…k = 0, 1, \ldots up to xx, and works for any number xx.

The rules, as in the lessons:

  • A pmf is 0 at any kk the variable cannot take. That means a negative kk, a kk that is not whole, such as 2.5, and for the binomial a kk above nn.
  • Raise ValueError if pp is outside [0,1][0, 1], if nn is not a whole number from 0 up, or if λ≤0\lambda \le 0. Both p=0p = 0 and p=1p = 1 are allowed.
  • Some tests use large numbers, such as (20001000)\binom{2000}{1000} and 150200150^{200}, which are too big for a float. Compute the logarithm of the pmf first and take math.exp at the end; math.lgamma(k + 1) is ln⁡k!\ln k!.
See the tests
import math


def test_binomial_value():
    """Bin(10, 0.3) gives P(X = 3) = 0.2668"""
    expect_close(binomial_pmf(3, 10, 0.3), 0.2668279319999998, what="binomial_pmf(3, 10, 0.3)", rel=1e-9)


def test_binomial_sums_to_one():
    """The pmf of Bin(12, 0.35) adds up to 1 over k = 0 to 12"""
    expect_close(sum(binomial_pmf(k, 12, 0.35) for k in range(13)), 1.0, what="sum of the pmf", rel=1e-9)


def test_binomial_outside():
    """Bin(5, 0.5) is 0 at k = −1, 6 and 2.5"""
    for k in (-1, 6, 2.5):
        expect_close(binomial_pmf(k, 5, 0.5), 0.0, what=f"binomial_pmf({k}, 5, 0.5)")


def test_binomial_certain():
    """With p = 0 there are no successes; with p = 1 every trial succeeds"""
    expect_close(binomial_pmf(0, 5, 0), 1.0, what="binomial_pmf(0, 5, 0)")
    expect_close(binomial_pmf(2, 5, 0), 0.0, what="binomial_pmf(2, 5, 0)")
    expect_close(binomial_pmf(5, 5, 1), 1.0, what="binomial_pmf(5, 5, 1)")
    expect_close(binomial_pmf(2, 5, 1), 0.0, what="binomial_pmf(2, 5, 1)")


def test_binomial_large():
    """Bin(2000, 0.5) gives P(X = 1000) = 0.01784, though C(2000, 1000) is too big for a float"""
    expect_close(binomial_pmf(1000, 2000, 0.5), 0.017839011145854313, what="binomial_pmf(1000, 2000, 0.5)", rel=1e-9)


def test_binomial_bad_inputs():
    """p = 1.5, p = −0.1 and n = 2.5 raise ValueError"""
    for args in ((2, 5, 1.5), (2, 5, -0.1), (2, 2.5, 0.5)):
        try:
            binomial_pmf(*args)
        except ValueError:
            continue
        raise AssertionError(f"expected ValueError for binomial_pmf{args}")


def test_poisson_values():
    """Poisson(2) gives P(X = 2) = 2e⁻² and Poisson(3) gives P(X = 0) = e⁻³"""
    expect_close(poisson_pmf(2, 2), 2 * math.exp(-2), what="poisson_pmf(2, 2)", rel=1e-9)
    expect_close(poisson_pmf(0, 3), math.exp(-3), what="poisson_pmf(0, 3)", rel=1e-9)


def test_poisson_outside():
    """Poisson(2) is 0 at k = −1 and 1.5"""
    expect_close(poisson_pmf(-1, 2), 0.0, what="poisson_pmf(-1, 2)")
    expect_close(poisson_pmf(1.5, 2), 0.0, what="poisson_pmf(1.5, 2)")


def test_poisson_large():
    """Poisson(150) gives P(X = 200) = 1.5038e-05, though 150²⁰⁰ is too big for a float"""
    expect_close(poisson_pmf(200, 150), 1.5038027878284683e-05, what="poisson_pmf(200, 150)", rel=1e-8)


def test_poisson_bad_rate():
    """A rate of 0 or below raises ValueError"""
    for lam in (0, -1):
        try:
            poisson_pmf(1, lam)
        except ValueError:
            continue
        raise AssertionError(f"expected ValueError for poisson_pmf(1, {lam})")


def test_cdf_binomial():
    """For Bin(10, 0.3), F(2) = F(2.5) = 0.3828, F(−0.5) = 0 and F(15) = 1"""
    pmf = lambda k: binomial_pmf(k, 10, 0.3)
    expect_close(cdf(pmf, 2), 0.3827827863999998, what="cdf at 2", rel=1e-9)
    expect_close(cdf(pmf, 2.5), 0.3827827863999998, what="cdf at 2.5", rel=1e-9)
    expect_close(cdf(pmf, -0.5), 0.0, what="cdf at -0.5")
    expect_close(cdf(pmf, 15), 1.0, what="cdf at 15", rel=1e-9)


def test_cdf_interval():
    """For Poisson(2), P(2 < X ≤ 5) = F(5) − F(2) = 0.3068"""
    pmf = lambda k: poisson_pmf(k, 2)
    expect_close(cdf(pmf, 5) - cdf(pmf, 2), 0.30675997533632215, what="F(5) - F(2)", rel=1e-9)


def test_cdf_geometric():
    """Rolls until a six (values from 1): F(6) = 1 − (5/6)⁶"""
    pmf = lambda k: (5 / 6) ** (k - 1) / 6 if k >= 1 else 0.0
    expect_close(cdf(pmf, 6), 1 - (5 / 6) ** 6, what="cdf at 6", rel=1e-9)

Free further reading

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