Price Scenarios
Price Scenarios primitives project an LP position’s value at a hypothetical price change from the current pool state. Three primitives, one per protocol family: Uniswap V2/V3, Balancer (2-asset weighted), Stableswap (2-asset).
These are paper projections — no settlement-swap impact. Use them to answer “if ETH drops 30% from here, what’s my position worth?”
All primitives in the Agentic Primitives section follow the same contract: stateless construction, computation at .apply(), typed dataclass return.
from defipy.twin import MockProvider, StateTwinBuilder
provider = MockProvider()builder = StateTwinBuilder()
lp_v2 = builder.build(provider.snapshot("eth_dai_v2"))lp_bal = builder.build(provider.snapshot("eth_dai_balancer_50_50"))lp_sts = builder.build(provider.snapshot("usdc_dai_stableswap_A10"))SimulatePriceMove
Section titled “SimulatePriceMove”Purpose. Project a Uniswap V2/V3 LP position’s value at a hypothetical price change.
Signature.
SimulatePriceMove().apply( lp, price_change_pct, position_size_lp, lwr_tick=None, upr_tick=None,) -> PriceMoveScenarioprice_change_pct is a fraction (-0.30 = 30% drop), bounded by > -1.0. position_size_lp is in LP-token units; the result is scale-invariant in this size, so use any positive value. fee_projection is always None in v1 (no fee modeling). Numeraire is token0.
from defipy import SimulatePriceMove
# What happens to a 10,000 LP-share position if ETH drops 30%?result = SimulatePriceMove().apply( lp_v2, price_change_pct = -0.30, position_size_lp = 10000.0,)print(f"new_price_ratio: {result.new_price_ratio:.6f}")print(f"new_value: {result.new_value:.4f}")print(f"il_at_new_price: {result.il_at_new_price:.6f}")print(f"value_change_pct: {result.value_change_pct:.6f}")print(f"fee_projection: {result.fee_projection}")SimulateBalancerPriceMove
Section titled “SimulateBalancerPriceMove”Purpose. Same projection adapted to a 2-asset Balancer weighted pool. The IL formula uses base/opp weights (not just the price ratio).
Signature.
SimulateBalancerPriceMove().apply(lp, price_change_pct, lp_init_amt) -> BalancerPriceMoveScenarioNumeraire is opp-token units. Raises ValueError if lp is not a BalancerExchange or pool is N>2 (propagated from BalancerImpLoss).
from defipy import SimulateBalancerPriceMove
result = SimulateBalancerPriceMove().apply( lp_bal, price_change_pct = -0.30, lp_init_amt = 100.0,)print(f"base / opp: {result.base_tkn_name} / {result.opp_tkn_name}")print(f"base_weight: {result.base_weight}")print(f"new_price_ratio: {result.new_price_ratio:.6f}")print(f"new_value: {result.new_value:.4f}")print(f"il_at_new_price: {result.il_at_new_price:.6f}")print(f"value_change_pct: {result.value_change_pct:.6f}")SimulateStableswapPriceMove
Section titled “SimulateStableswapPriceMove”Purpose. Project a 2-asset stableswap LP position’s value at a hypothetical depeg. High A makes small price deviations costly.
Signature.
SimulateStableswapPriceMove().apply(lp, price_change_pct, lp_init_amt) -> StableswapPriceMoveScenarioUse small moves — stableswap is depeg-sensitive. Catches DepegUnreachableError: if the projected alpha is unreachable, new_value / il_at_new_price / value_change_pct come back as None (token_names, A, new_price_ratio still populated). At-peg short-circuit returns IL=0 exactly.
from defipy import SimulateStableswapPriceMove
# Stableswap is sensitive — model a 5% depeg.result = SimulateStableswapPriceMove().apply( lp_sts, price_change_pct = -0.05, lp_init_amt = 100.0,)print(f"token_names: {result.token_names}")print(f"A: {result.A}")print(f"new_price_ratio: {result.new_price_ratio:.6f}")print(f"new_value: {result.new_value}")print(f"il_at_new_price: {result.il_at_new_price}")print(f"value_change_pct: {result.value_change_pct}")Protocol coverage
Section titled “Protocol coverage”| Protocol | Supported | Notes |
|---|---|---|
| Uniswap V2 | ✅ | SimulatePriceMove — closed-form V2 IL |
| Uniswap V3 | ✅ | SimulatePriceMove with lwr_tick/upr_tick for range-aware IL |
| Balancer | ✅ | SimulateBalancerPriceMove — 2-asset only |
| Stableswap | ✅ | SimulateStableswapPriceMove — 2-asset only; unreachable-alpha returns None for value fields |
MCP tool exposure
Section titled “MCP tool exposure”All three primitives are surfaced as MCP tools in the curated set of 10:
SimulatePriceMoveSimulateBalancerPriceMoveSimulateStableswapPriceMove
Price-scenario questions (“what if ETH drops?”) are highest-traffic agent queries, so all three protocol variants are exposed directly rather than left to the LLM to compose.