Break-Even
Break-Even primitives answer “when am I made whole?” — find the price at which fees offset IL, or the holding period at which fee income compensates current IL drag.
Two primitives: - FindBreakEvenPrice — both alpha values where accumulated fees exactly offset IL - FindBreakEvenTime — linear projection of how long until current fees catch up to current IL
All primitives in the Agentic Primitives section follow the same contract: stateless construction, computation at .apply(), typed dataclass return.
Setup
[1]:
from defipy.twin import MockProvider, StateTwinBuilder
provider = MockProvider()
builder = StateTwinBuilder()
lp_v2 = builder.build(provider.snapshot("eth_dai_v2"))
FindBreakEvenPrice
Purpose. Find both alphas (price ratios vs entry) where accumulated fee_income exactly offsets impermanent loss. Useful for setting alert thresholds.
Signature.
FindBreakEvenPrice().apply(
lp, lp_init_amt, fee_income,
lwr_tick=None, upr_tick=None,
) -> BreakEvenAlphas
V2/V3 supported (V3 via the range-scale factor). When fees are large enough that sqrt(f_scaled) >= 1, the upside break-even is None and upside_hedged=True (downside still exists for f > 0). Zero fee_income returns the degenerate case (both alphas = 1.0). Prices are in token1/token0.
[2]:
from defipy import FindBreakEvenPrice
result = FindBreakEvenPrice().apply(
lp_v2,
lp_init_amt = 10000.0,
fee_income = 50.0, # 50 ETH of accumulated fees
)
[3]:
print(f"break_even_alpha_down: {result.break_even_alpha_down:.6f}")
print(f"break_even_alpha_up: {result.break_even_alpha_up:.6f}")
print(f"break_even_price_down: {result.break_even_price_down:.4f}")
print(f"break_even_price_up: {result.break_even_price_up:.4f}")
print(f"fee_to_entry_ratio: {result.fee_to_entry_ratio:.6f}")
print(f"upside_hedged: {result.upside_hedged}")
break_even_alpha_down: 0.667907
break_even_alpha_up: 1.658962
break_even_price_down: 66.7907
break_even_price_up: 165.8962
fee_to_entry_ratio: 0.050000
upside_hedged: False
FindBreakEvenTime
Purpose. Estimate days (and blocks) until fee income compensates current IL drag at the current fee accrual rate. Simple linear projection; no rate uncertainty modeling.
Signature.
FindBreakEvenTime(blocks_per_day=7200).apply(
lp, lp_init_amt, entry_x_amt, entry_y_amt,
holding_period_days,
lwr_tick=None, upr_tick=None,
) -> BreakEvenTime
V2/V3 only (delegates to AnalyzePosition). diagnosis ∈ {"already_broken_even", "no_il_drag", "no_fee_income", "projected"}. The "no_fee_income" branch sets days_to_break_even and blocks_to_break_even to None.
[4]:
from defipy import FindBreakEvenTime
# ETH up 25% from entry, 30 days held — same scenario as the position-analysis pilot.
result = FindBreakEvenTime().apply(
lp_v2,
lp_init_amt = 10000.0,
entry_x_amt = 1000.0,
entry_y_amt = 80000.0,
holding_period_days = 30.0,
)
[5]:
print(f"current_il_drag: {result.current_il_drag:.4f}")
print(f"fee_income_to_date: {result.fee_income_to_date:.4f}")
print(f"fee_rate_per_day: {result.fee_rate_per_day:.4f}")
print(f"days_to_break_even: {result.days_to_break_even}")
print(f"blocks_to_break_even: {result.blocks_to_break_even}")
print(f"already_broken_even: {result.already_broken_even}")
print(f"diagnosis: {result.diagnosis}")
current_il_drag: 11.1456
fee_income_to_date: 211.1456
fee_rate_per_day: 7.0382
days_to_break_even: 0.0
blocks_to_break_even: 0
already_broken_even: True
diagnosis: already_broken_even
Protocol coverage
MCP tool exposure
Neither primitive is in the curated 10. Break-even questions are downstream of position-analysis — agents typically derive break-even thresholds LLM-side after running AnalyzePosition. The category exists for the explicit request “give me the break-even price” without requiring the LLM to derive it.