Contract Checks¶
The keeks.checks module is the contract harness for contributors, on the
scikit-learn check_estimator pattern: each check runs a contributor’s
implementation against the documented contract of its base class - the bets a
binary strategy sizes, the weights an allocator returns, the draws a
joint-return model samples - and fails with the first violation it meets,
so an implementation can be verified without running a simulator.
Contract checks for strategies and joint-return models, on the
check_estimator pattern.
The strategy contracts are enforced at the base classes: a concrete
evaluate returning a contract-violating vector fails loudly at its own
call site. A contributor implementing
keeks.binary_strategies.BaseStrategy,
keeks.allocation.BaseAllocationStrategy, or
keeks.allocation.models.JointReturnModel has nonetheless had no way
to verify an implementation against the documented contract without running
a simulator. The checks here are that harness: each runs the contract’s
probes and raises - ValueError naming the expectation and the received
value for a contract violation, TypeError for a subject outside the
check’s ABC - and passes silently when everything holds.
Examples
>>> from keeks import FixedWeights, check_allocation_strategy
>>> check_allocation_strategy(FixedWeights([0.25, 0.75]))
- keeks.checks.check_allocation_strategy(strategy: BaseAllocationStrategy) None[source]¶
Verify an allocator against the documented weight contract.
Runs the contract probes:
evaluateat a positive bankroll returns a valid long-only weight vector (one finite weight per option, each within[0, 1], summing to no more than one withinPROBABILITY_SUM_TOLERANCE); a nonpositive bankroll returns all zeros - there is nothing left to allocate - with one weight per option at every bankroll.- Parameters:
strategy (BaseAllocationStrategy) – The allocation strategy to check.
- Raises:
TypeError – If
strategyis not akeeks.allocation.BaseAllocationStrategysubclass.ValueError – If any probe violates the contract.
Examples
>>> from keeks import BaseAllocationStrategy, check_allocation_strategy >>> class _OverBudget(BaseAllocationStrategy): ... def evaluate(self, current_bankroll): ... return (0.6, 0.6) >>> check_allocation_strategy(_OverBudget()) Traceback (most recent call last): ... ValueError: Strategy weights must sum to no more than one; got (0.6, 0.6)
- keeks.checks.check_model(model: JointReturnModel) None[source]¶
Verify a joint-return model against the documented sampling contract.
Runs the contract probes:
sample(n_samples, rng)returns a finite(n_samples, N)matrix of joint simple returns withN >= 1; the same generator state produces the same draws (the house reproducibility contract); every sample count carries one column per option; andmoments(), when the model knows them, returns a shape(N,)mean and(N, N)covariance -Noneis the documented answer for a model without closed-form moments.- Parameters:
model (JointReturnModel) – The joint-return model to check.
- Raises:
TypeError – If
modelis not akeeks.allocation.models.JointReturnModelsubclass.ValueError – If any probe violates the contract.
Examples
>>> from keeks import binary_bets_model, check_model >>> check_model(binary_bets_model([(0.55, 2.0, 1.0), (0.30, 2.5, 1.0)]))
A model that ignores its generator breaks reproducibility:
>>> import numpy as np >>> from keeks.allocation.models import JointReturnModel >>> class _DriftingModel(JointReturnModel): ... def sample(self, n_samples, rng): ... return np.random.default_rng().uniform(size=(n_samples, 2)) >>> check_model(_DriftingModel()) Traceback (most recent call last): ... ValueError: sample must be deterministic given a generator's state - the same generator state must produce the same draws (the house reproducibility contract), but two identically-seeded generators diverged
- keeks.checks.check_strategy(strategy: BaseStrategy) None[source]¶
Verify a binary strategy against the documented
BaseStrategycontract.Runs the contract probes:
evaluatereturns a single finite bankroll fraction within[0, 1]across a probability grid; a nonpositive bankroll returns exactly0.0- there is nothing left to stake;get_max_safe_betstays a fraction within[0, 1]and answers0.0for a nonpositive bankroll; and the optional simulator hooksupdate_bankrollandrecord_settlement, when defined, are callable - the shapes the simulators resolvegetattr-style.- Parameters:
strategy (BaseStrategy) – The binary strategy to check.
- Raises:
TypeError – If
strategyis not akeeks.binary_strategies.BaseStrategysubclass.ValueError – If any probe violates the contract.
Examples
>>> from keeks import KellyCriterion, check_strategy >>> check_strategy(KellyCriterion(payoff=2.0, loss=1.0, transaction_cost_rate=0.01))
A contract violation raises with the expectation and the received value:
>>> class _Reckless(KellyCriterion): ... def evaluate(self, probability, current_bankroll): ... return 1.5 >>> check_strategy(_Reckless(payoff=2.0, loss=1.0, transaction_cost_rate=0.01)) Traceback (most recent call last): ... ValueError: evaluate(0.0, 1000.0) must return a bankroll fraction between 0 and 1, got 1.5