Exercise · m00_ipo_allotment.py
Retail IPO allotment by lottery
not run yet
Not saved: sign up to keep your code"""Exercise: retail IPO allotment by lottery (notes §0.5).
Implement every function, then run from the repo root:
cd exercises && .venv/bin/python -m pytest modules/M00-market-on-ramp/tests/test_m00_ipo_allotment.py
Model (SEBI ICDR basis of allotment for retail individual investors, as
described in the notes): the retail portion holds K = floor(R / L) minimum
lots. If the number of valid applications N exceeds K, K applications are
drawn uniformly at random without replacement and each receives one lot,
whatever the number of lots it applied for. If N <= K, every application
receives one lot and the remaining K - N lots go proportionately to the
unmet demand.
"""
from __future__ import annotations
from typing import Sequence
import numpy as np
def lots_available(reserved_shares: int, lot_size: int) -> int:
"""K = floor(reserved_shares / lot_size). Raise ValueError if lot_size <= 0."""
raise NotImplementedError
def allotment_probability(n_applications: int, n_lots: int) -> float:
"""P(a given application wins a lot) = min(1, K / N) (notes Proposition 0.3)."""
raise NotImplementedError
def prob_at_least_one(n_applications: int, n_lots: int, m: int) -> float:
"""P(at least one of m distinct applications wins) when K of N are drawn
without replacement: 1 - C(N - m, K) / C(N, K) = 1 - prod_{j=0}^{m-1} (N-K-j)/(N-j).
Return 1.0 when K >= N (and m > 0) or when m > N - K. Avoid huge binomials.
"""
raise NotImplementedError
def expected_lots(applied_lots: Sequence[int], n_lots: int) -> np.ndarray:
"""Expected lots allotted to each application (array, same order).
If N > K: each gets K / N.
If N <= K: each gets 1 lot; the spare K - N lots are split in proportion to
the unmet demand a_i - 1, capped at the demand (if total unmet demand is at
most the spare lots, everyone gets everything they applied for).
"""
raise NotImplementedError
def probability_from_subscription(subscription_times: float, avg_lots_per_application: float) -> float:
"""If retail bids total x times the reserved shares and the average
application is for a lots, then N = x K / a and P = min(1, a / x)."""
raise NotImplementedError
def simulate_lottery(n_applications: int, n_lots: int, n_sims: int, seed: int) -> float:
"""Monte Carlo check: fraction of n_sims lotteries (K of N drawn without
replacement, rng = np.random.default_rng(seed)) in which application 0 wins."""
raise NotImplementedError
No runs yet
The stub's functions raise
NotImplementedError until you write them. Fill in one, press
Run tests, and watch its tests turn green.Reference solution
Available after your first run, with an account approved for code runs.