When to Use
Use this skill when a position, a hedge or a mark involves a listed warrant: a covered call/put warrant issued by a bank, or a Turbo warrant / CBBC (Callable Bull/Bear Contract). Typical callers are a market maker hedging an issued book, a systematic strategy taking geared directional exposure through warrants, or a risk engine that has to mark and monitor a warrant line.
The skill exists because two properties of these instruments break naive option-pricing code:
- The entitlement ratio rescales every price and every Greek. Ten warrants to one share means the warrant's delta is $0.1$ shares, not $1$.
- A Turbo / CBBC is not a vanilla option. It is a knock-out barrier product that the market prices as intrinsic value plus funding cost with a delta of approximately one underlying unit. Pricing it with Black-Scholes $N(d_1)$ systematically under-hedges the book, because $N(d_1) < 1$ always.
Read these two conventions before passing any data in.
entitlement_ratiois the reciprocal of the exchange quote. HKEX quotes the entitlement ratio as warrants per share — "the number of products required to be converted into a unit of the underlying asset at the strike price on the expiry date". A term sheet reading "Entitlement ratio: 10" isentitlement_ratio = 0.1here. Pasting the exchange's10straight in is a 100× error in price, delta and hedge size, and nothing downstream flags it — every number stays positive and plausible. Useentitlement_ratio_from_conversion_ratio(10.0)rather than inverting by hand.position_warrantsis signed. Positive = warrants held long; negative = warrants sold or issued. The delta-neutral target is $-N_{\text{warrants}} \times \Delta$: a long call-warrant position is hedged by selling the underlying, an issued one by buying it. Version 1.1.0 returned $+N \times \Delta$, which inverts the hedge for a long holder and doubles the exposure it was meant to remove.
When NOT to Use
- For an autocallable note or any path-dependent structured product. An
autocallable needs a coupon and observation schedule and a barrier model, not
a single-strike valuation.
WarrantType.AUTOCALLABLE_NOTEexists only so that passing one raisesWarrantEngineError— version 1.1.0 let it fall through to the put branch and returned a plausible price with a negative delta. - For barrier-proximity risk on a CBBC. The delta-one convention returns $\Gamma = \text{Vega} = 0$ by construction. The real product is a barrier option whose gamma spikes violently as spot approaches the call price. Size that risk from the distance-to-call and the MCE monitor, never from these Greeks.
- As a smile-aware pricer for covered warrants. One flat $\sigma$, no skew,
no term structure. Calibrate with
options-implied-volatility-surface-constructionand treat this engine's output as a flat-vol reference point, not a mark. - For company-issued (dilutive) equity warrants. Those create new shares on exercise and need a dilution adjustment this engine does not model. Covered warrants and CBBCs are third-party issued and carry no dilution.
- For issuer credit risk. Covered warrants and CBBCs are non-collateralised
obligations of the issuing bank. See
counterparty-credit-risk-for-otc-derivatives. - At or past expiry as a pricing call.
days_to_expiry <= 0returns anEXPIREDvaluation at intrinsic with zero Greeks. An expired warrant is a settlement problem — seephysical-vs-cash-settlement-handling.
Prerequisites
- Python 3.10+ and the standard library only (
math,dataclasses,enum,typing,logging). No third-party dependencies. - Term-sheet data per line: warrant type,
strike_price,entitlement_ratio(shares per warrant),days_to_expiry, and for a Turbo / CBBC thebarrier_price(call price),cbbc_categoryandfunding_rate_annualfrom the launch announcement. - Market data as annualized decimals: underlying spot,
risk_free_rate,dividend_yield, and — for covered warrants only —implied_volatility > 0. - For gearing that matches the exchange's published figure, the warrant's own
traded price, passed as
market_price.
Workflow
- Build the contract from the term sheet, inverting the entitlement ratio.
- Decision point — is the ratio you were handed warrants-per-share or
shares-per-warrant? Exchange and issuer documents quote the former. Run it
through
entitlement_ratio_from_conversion_ratio(). A silent 100× error here reaches the order router as a 100× hedge. - For a Turbo / CBBC,
cbbc_categoryis mandatory: it decides whether a Mandatory Call Event pays a residual value or nothing. The engine refuses to price a CBBC left atNOT_APPLICABLErather than assuming one. - The engine enforces the term-sheet invariant that a bull CBBC's call price is $\ge$ its strike and a bear's is $\le$ its strike. A violation is a reference-data error, not a pricing input.
- Decision point — is the ratio you were handed warrants-per-share or
shares-per-warrant? Exchange and issuer documents quote the former. Run it
through
- Price with
price_warrant(spot, contract, market_price=None)and readpricing_modelon the result to confirm which model produced the mark.- Decision point — a Mandatory Call Event is checked before expiry. A
CBBC can be called on its last trading day, and the call terminates the
contract either way. The engine returns
KNOCKED_OUT, notEXPIRED. - Covered warrants take Black-Scholes-Merton with the continuous dividend yield $q$; a covered warrant on a dividend-paying underlying priced at $q = 0$ overstates the call and its delta.
- Turbos / CBBCs take
$P = R_{\text{ent}}\left[(S-K)^{+} + K \cdot f \cdot n/365\right]$ with
$\Delta = R_{\text{ent}}$. Leaving
funding_rate_annualat0.0prices the contract at pure intrinsic, below every real market quote.
- Decision point — a Mandatory Call Event is checked before expiry. A
CBBC can be called on its last trading day, and the call terminates the
contract either way. The engine returns
- Read gearing off the right price.
- Simple gearing is $S \cdot R_{\text{ent}} / P$; effective gearing is $\text{Simple} \times |\Delta_{\text{raw}}|$, which is the price elasticity $(S/P),\partial P/\partial S$. The entitlement ratio appears once, not twice — putting it in both factors squares it.
- Decision point — when the theoretical price is below the minimum tick,
gearing computed against it is meaningless. Pass the traded
market_price; the result records which basis it used ingearing_basis_price. Version 1.1.0 floored the price at0.0001instead and reported gearings of 100,000×.
- Size the hedge with
calculate_delta_hedge_signal(valuation, position_warrants, current_shares, rebalance_threshold_shares).- Decision point — sign
position_warrantsfor the book you actually hold. The target is $-N \times \Delta$. A wrong sign does not raise; it silently doubles the exposure. Cross-checkwarrant_book_delta_sharesagainst an independent position record before routing. - Set
rebalance_threshold_sharesto the underlying's board lot, not the default of one share, or the engine will generate sub-lot orders the exchange rejects. Seeminimum-fill-size-and-lot-rounding-logic.
- Decision point — sign
- Monitor the call price on every tick, not on a valuation schedule.
is_mandatory_call_triggered()is inclusive at the barrier: touching the call price triggers the call.- On a call, the valuation's delta is
0.0, so the hedge signal targets zero shares and unwinds the whole hedge in one instruction. Anything still held after a call is naked directional exposure, not a hedge. - Decision point — the residual value in the valuation is provisional.
The exchange settles a bull CBBC on the lowest underlying price over the
MCE valuation period (the session in which the call occurred and the one
after), so the realized residual is at most the provisional figure.
Recompute with
mandatory_call_residual_value(contract, settlement_price)once that period closes, and do not book the provisional number as a receivable.
Full procedure: see
references/workflows.md. Standards reference: seereferences/standards.md. Printable pre-flight checklist: seeassets/checklist.md.
Common Pitfalls
- Pasting the exchange's entitlement ratio in un-inverted. A term sheet's
"10" entered as
entitlement_ratio = 10.0instead of0.1scales the price, the delta and the hedge by 100×. Every output stays positive and plausible. - Pricing a Turbo / CBBC with vanilla Black-Scholes. HKEX and the HK issuers describe CBBCs as delta-one, in-the-price products whose price is intrinsic value plus funding cost. A vanilla $N(d_1)$ delta is always below one, so an issued book hedged on it is permanently under-hedged — and the shortfall is largest exactly where the position is largest.
- Signing the hedge as $+N \times \Delta$. That is the hedge for a short book. Applied to a long warrant position it buys underlying against long calls and doubles the delta instead of removing it.
- Leaving underlying shares on after a Mandatory Call Event. The CBBC's delta goes to zero the instant the call price is touched; the hedge behind it does not. Whatever is still held is an outright position taken at the worst moment in the underlying's session.
- Booking the provisional MCE residual as the recovery. A bull CBBC settles on the lowest underlying price of the valuation period, so the trigger-tick estimate is an upper bound. Category N contracts recover nothing at all — their call price equals their strike, so there is no buffer.
- Reading a CBBC's gamma or vega as risk. Both are identically zero under the delta-one convention. The real barrier product's convexity is concentrated at the call price, where this model shows none.
- Confusing simple with effective gearing. Simple gearing ignores delta. A deep out-of-the-money warrant can show high simple gearing and near-zero effective gearing, because it barely responds to the underlying at all.
- Computing gearing off a sub-tick theoretical price. A model price of $10^{-5}$ produces a five-figure gearing that describes nothing tradable. Pass the traded price.
- Pricing a covered warrant on a dividend-paying underlying at $q = 0$. It overstates the call, its delta and therefore the hedge. HK warrants are routinely written on dividend-paying equities and ETFs.
Verification
- Canonical anchor: with $R_{\text{ent}} = 1$, $q = 0$, the engine reproduces the standard worked example $\text{BS}(100, 100, 1\text{y}, 5%, 20%) = 10.450583572185565$ (call) and $5.5735260222569727$ (put) to 12 decimal places.
- Put-call parity: $C - P = R_{\text{ent}}(Se^{-qT} - Ke^{-rT})$ to 12 decimal places, which detects a mis-signed dividend or discount term.
- Greeks vs. finite differences: every Greek matches a Richardson-extrapolated central difference of the price — delta, gamma and vega to 9 decimal places, theta to 6 — at out-of-the-money, at-the-money and in-the-money strikes for both calls and puts.
- Theta regressions: call theta uses $N(d_2)$, not $N(d_1)$; put theta adds the rate term $+rKe^{-rT}N(-d_2)$. Version 1.1.0 got both wrong and overstated put decay by roughly 60%.
- CBBC convention: a bull CBBC's price equals $(S-K)R_{\text{ent}} + K f (n/365) R_{\text{ent}}$ by hand-computed arithmetic; its delta is exactly $R_{\text{ent}}$, confirmed by a $1.00$ move in spot moving the price by exactly $R_{\text{ent}}$; its theta equals the daily funding accrual, confirmed against a one-day roll-down.
- Gearing identity: effective gearing equals the numerically differentiated elasticity $(S/P),\partial P/\partial S$ to 8 decimal places, and is invariant to the entitlement ratio.
- MCE: the barrier is inclusive on both sides; Category R pays $\max(0, S_{\text{settle}} - K)R_{\text{ent}}$ against the strike, Category N pays zero, and a settlement below the trigger tick pays less than the provisional figure.
- Hedge sign: long call warrants produce
SELL, issued call warrantsBUY, issued put warrantsSELL; a called or expired warrant targets zero shares and unwinds the full hedge. - Negative checks: non-positive or non-finite
spot_price,strike_price,entitlement_ratioormarket_price; zero or NaNimplied_volatility; negativedividend_yieldorfunding_rate_annual; non-integerdays_to_expiry; a bull CBBC with its call price below its strike (and the bear mirror); a CBBC with no declared category; a fractional or booleanposition_warrants; andAUTOCALLABLE_NOTEmust all raiseWarrantEngineError.
Run the suite and confirm a 100% pass rate:
python -m unittest discover -s skills/warrants-and-structured-product-integration/scriptsRelated Skills
greeks-based-portfolio-hedging-automationoptions-greeks-real-time-portfolio-aggregationreal-time-greeks-recalculation-on-market-movesoptions-implied-volatility-surface-constructionamerican-vs-european-style-option-exercise-handlingphysical-vs-cash-settlement-handlingcounterparty-credit-risk-for-otc-derivativesminimum-fill-size-and-lot-rounding-logichong-kong-exchange-hkex-orion-apiquanto-options-and-cross-currency-derivative-structuresvariance-swap-and-volatility-derivative-pricingtotal-return-swap-synthetic-exposure