Pool Hooks
Hooks are mixin classes that extend pool functionality by intercepting and modifying pool behavior at key points. They enable features like custom fee logic, performance tracking, and weight constraints without modifying the base pool implementations.
Using Hooks
Hooks are applied using the hookname__poolrule naming convention:
from quantammsim.pools.creator import create_pool
# Create a momentum pool with LVR tracking
pool = create_pool("lvr__momentum")
# Create a balancer pool with rebalancing comparison
pool = create_pool("rvr__balancer")
# Create a momentum pool with per-asset weight bounds
pool = create_pool("bounded__momentum")
Available Hooks
Loss Versus Rebalancing (LVR)
The lvr hook tracks Loss-Versus-Rebalancing, measuring how much value the pool
loses to arbitrageurs compared to a continuously rebalancing portfolio.
pool = create_pool("lvr__mean_reversion_channel")
This is useful for:
Measuring arbitrage extraction
Comparing pool efficiency across strategies
Understanding the cost of providing liquidity
Rebalancing Versus Rebalancing (RVR)
The rvr hook compares pool performance against a periodically rebalancing
benchmark portfolio.
pool = create_pool("rvr__balancer")
This helps evaluate whether the pool’s dynamic behavior adds value compared to simple periodic rebalancing.
Bounded Weights
The bounded hook adds per-asset minimum and maximum weight constraints.
See Per-Asset Weight Bounds for full documentation.
pool = create_pool("bounded__momentum")
params = {
"min_weights_per_asset": jnp.array([0.2, 0.2, 0.1]),
"max_weights_per_asset": jnp.array([0.5, 0.5, 0.3]),
# ... other parameters
}
Ensemble Averaging
The ensemble hook trains multiple parameter sets (“members”) simultaneously
and averages their weight outputs, providing implicit regularisation through
diversity. Members start from different initial parameters (using structured
sampling methods) and converge to different local optima.
pool = create_pool("ensemble__momentum")
run_fingerprint["optimisation_settings"].update({
"n_ensemble_members": 4, # Number of members
"ensemble_init_method": "lhs", # Initialisation sampling method
"ensemble_init_scale": 1.0, # Perturbation scale
})
Available initialisation methods:
"lhs"— Latin Hypercube Sampling (default, good space coverage)"sobol"— Sobol quasi-random sequence (low discrepancy)"grid"— Regular grid (deterministic, evenly spaced)"gaussian"— Gaussian perturbations around initial values
The ensemble hook averages the weight outputs of all members, not the parameters. This means each member produces its own weight trajectory, and the final weights are the arithmetic mean. Gradients flow through all members during backpropagation.
Multi-Hook Chaining
Multiple hooks can be combined using the double-underscore syntax. Hooks are applied left-to-right (leftmost = highest priority in MRO):
# Ensemble + bounded weights + mean reversion channel
pool = create_pool("ensemble__bounded__mean_reversion_channel")
# Ensemble + LVR tracking + momentum
pool = create_pool("ensemble__lvr__momentum")
This is equivalent to constructing the class manually:
from quantammsim.pools.creator import create_hooked_pool_instance
from quantammsim.hooks.ensemble_averaging_hook import EnsembleAveragingHook
from quantammsim.hooks.bounded_weights_hook import BoundedWeightsHook
pool = create_hooked_pool_instance(
MeanReversionChannelPool,
BoundedWeightsHook,
EnsembleAveragingHook,
)
Dynamic Fee Hooks
Fee hooks allow pools to adjust their fees based on market conditions.
Base Dynamic Fee Hook
The dynamic_fee_base_hook provides infrastructure for volatility-adjusted fees:
from quantammsim.hooks.dynamic_fee_base_hook import DynamicFeeBaseHook
Momentum Dynamic Fee Hook
Adjusts fees based on recent price momentum:
from quantammsim.hooks.momentum_dynamic_fee_hook import MomentumDynamicFeeHook
Creating Custom Hooks
Hooks are implemented as mixin classes that override specific pool methods. The hook must appear before the base pool class in the inheritance order:
from quantammsim.pools.G3M.quantamm.momentum_pool import MomentumPool
class MyCustomHook:
"""Custom hook that modifies pool behavior."""
def some_pool_method(self, *args, **kwargs):
# Custom logic before
result = super().some_pool_method(*args, **kwargs)
# Custom logic after
return result
# Create hooked pool class
class HookedMomentumPool(MyCustomHook, MomentumPool):
pass
# Or use the creator utility
from quantammsim.pools.creator import create_hooked_pool_instance
pool = create_hooked_pool_instance(MomentumPool, MyCustomHook)
Key methods that can be overridden:
calculate_fine_weights- Post-process calculated weightscalculate_fees- Custom fee calculationpost_trade_hook- Logic after each trade
Hook Ordering
When multiple hooks are applied, they are processed right-to-left in the inheritance order. The first hook in the list has the highest priority (its methods are called first).
# Hook1's methods take precedence over Hook2's
class MultiHookedPool(Hook1, Hook2, BasePool):
pass