DEV Community

JustinCampos454
JustinCampos454

Posted on

Backtesting AMM Liquidity Strategies with amm-strategy-backtester

If you work with DeFi, you eventually run into a difficult question:

How do I know whether an AMM liquidity strategy actually works?

Providing liquidity to an AMM is very different from simply buying and holding an asset.

An LP position can earn trading fees, but it can also suffer from impermanent loss, price movements, rebalancing costs, and other forms of execution risk.

That makes historical testing particularly useful.

One interesting JavaScript/Node.js project in this area is amm-strategy-backtester, a package designed around the idea of testing AMM liquidity strategies programmatically.

Why AMM strategies need a different kind of backtest

A traditional trading strategy might be as simple as:

if price > moving average:
    buy

if price < moving average:
    sell
Enter fullscreen mode Exit fullscreen mode

An AMM liquidity strategy has a different lifecycle:

Deposit liquidity
       ↓
Price changes
       ↓
Trades occur
       ↓
LP earns fees
       ↓
Token composition changes
       ↓
Strategy decides whether to rebalance
       ↓
Withdraw or continue providing liquidity
Enter fullscreen mode Exit fullscreen mode

The important part is that an LP position is path dependent.

Two markets can finish at exactly the same final price but produce very different LP results because the price may have taken completely different paths to get there.

That is one reason AMM strategy backtesting is interesting.

What is amm-strategy-backtester?

The npm package is intended to provide a programmatic way to experiment with AMM liquidity strategies rather than manually calculating LP performance from historical data.

amm-strategy-backtester on npm

The broader concept is straightforward:

  1. Provide historical market data.
  2. Define an LP strategy.
  3. Simulate how the strategy behaves.
  4. Track the resulting portfolio.
  5. Compare the result with alternative strategies or benchmarks.

For developers, this is useful because the strategy can become code instead of a spreadsheet.

That makes it possible to experiment with different rules and repeat the same experiment consistently.

The simplest AMM strategy

Imagine starting with:

$10,000
Enter fullscreen mode Exit fullscreen mode

You could create a baseline strategy:

Deposit liquidity
↓
Never rebalance
↓
Hold until the end of the test
Enter fullscreen mode Exit fullscreen mode

This gives you a baseline against which more sophisticated strategies can be compared.

For example:

Strategy A: Buy and hold

Strategy B: Static LP

Strategy C: Periodic rebalancing

Strategy D: Volatility-based rebalancing

Strategy E: Dynamic liquidity ranges
Enter fullscreen mode Exit fullscreen mode

The goal isn't necessarily to find the strategy with the highest backtest return.

The goal is to understand why each strategy performs differently.

Fees vs. impermanent loss

One of the most important concepts when evaluating an AMM LP strategy is the relationship between fees and impermanent loss.

Suppose an LP earns:

Trading fees:       +$1,500
Impermanent loss:   -$900
Other costs:        -$200
--------------------------------
Net effect:         +$400
Enter fullscreen mode Exit fullscreen mode

Looking only at the fee number would give you the wrong impression.

A strategy that generates $1,500 in fees isn't necessarily better than a strategy generating $1,000.

The relevant question is:

What was the total portfolio outcome after accounting for everything?

This is where backtesting becomes valuable.

Why rebalancing matters

Consider a concentrated liquidity strategy.

You start with a price range:

Lower bound: $1,800
Upper bound: $2,200
Enter fullscreen mode Exit fullscreen mode

If the market moves from:

$2,000 → $2,100 → $2,200 → $2,400
Enter fullscreen mode Exit fullscreen mode

your position may eventually move out of the active range.

At that point, your strategy has a decision to make.

Should it:

1. Do nothing?
2. Withdraw liquidity?
3. Move the range?
4. Create a new position?
5. Wait for the market to return?
Enter fullscreen mode Exit fullscreen mode

Each decision produces a different result.

A backtester lets you turn these decisions into explicit rules and evaluate them against historical conditions.

A strategy is just a set of rules

One of the things I like about approaching AMM strategies from a software perspective is that the strategy can be expressed as a deterministic function.

Conceptually:

function strategy(state) {
  if (state.price > state.upperRange) {
    return "REBALANCE";
  }

  if (state.price < state.lowerRange) {
    return "REBALANCE";
  }

  return "HOLD";
}
Enter fullscreen mode Exit fullscreen mode

You can then make the rules considerably more sophisticated.

For example:

function strategy(state) {
  if (state.volatility > HIGH_VOLATILITY) {
    return "WIDEN_RANGE";
  }

  if (state.price > state.upperRange) {
    return "MOVE_RANGE_UP";
  }

  if (state.price < state.lowerRange) {
    return "MOVE_RANGE_DOWN";
  }

  return "HOLD";
}
Enter fullscreen mode Exit fullscreen mode

The backtesting engine becomes the environment in which those rules can be evaluated.

Don't optimize only for returns

A common mistake in backtesting is to search for the configuration with the highest return.

Imagine testing 100 strategies and discovering this:

Strategy #73
Return: +247%
Enter fullscreen mode Exit fullscreen mode

That looks fantastic.

But then you discover:

Maximum drawdown: -82%
Number of rebalances: 1,842
Transaction costs: extremely high
Enter fullscreen mode Exit fullscreen mode

The strategy might not be useful in practice.

For AMM strategies, I would look at several dimensions:

  • Total return
  • Net P&L
  • Maximum drawdown
  • Fees earned
  • Impermanent loss
  • Number of rebalances
  • Time spent out of range
  • Capital efficiency
  • Gas/transaction costs
  • Performance across different market regimes

The best strategy isn't necessarily the one with the largest number in the return column.

Test different market regimes

A strategy that works during a sideways market may behave very differently during a strong trend.

For example:

Market regime       Strategy behavior
--------------------------------------
Sideways             Potentially favorable
Slow uptrend         Needs investigation
Strong uptrend       Range may become inactive
Slow downtrend       Needs investigation
Sharp crash          Potentially significant loss
High volatility      Frequent rebalancing
Enter fullscreen mode Exit fullscreen mode

This is why a good AMM backtest shouldn't rely on a single historical period.

Test multiple periods.

Test multiple assets.

Test multiple volatility environments.

And, ideally, keep some data completely outside the optimization process for out-of-sample validation.

Backtesting isn't the same as predicting

This distinction is important.

A backtest answers:

"What would this set of rules have done under these historical assumptions?"

It does not answer:

"What will happen next?"

A strategy can produce an excellent historical equity curve and still fail in live trading.

Potential reasons include:

  • Overfitting
  • Look-ahead bias
  • Poor historical data
  • Unrealistic execution assumptions
  • Slippage
  • Gas costs
  • Liquidity changes
  • Timing differences
  • Market regime changes

The more realistic the simulator, the more useful the result becomes.

There is active research specifically around backtesting concentrated-liquidity market makers on Uniswap V3, which highlights how specialized the problem is compared with ordinary trading backtests.

Why JavaScript is interesting for this

A lot of quantitative research is done in Python, but JavaScript/TypeScript has a useful place in DeFi development.

The ecosystem is already heavily connected to:

Node.js
TypeScript
Ethereum tooling
RPC providers
DEX APIs
Web3 libraries
Enter fullscreen mode Exit fullscreen mode

That means you can potentially keep strategy research closer to the code used by your actual application or trading infrastructure.

For example:

Historical data
      ↓
Backtest engine
      ↓
Strategy
      ↓
Performance metrics
      ↓
Visualization
      ↓
Live strategy
Enter fullscreen mode Exit fullscreen mode

The long-term goal shouldn't necessarily be:

"I built a profitable backtest."

It should be:

"I built a strategy whose assumptions I understand and can progressively validate against real execution."

What I would add to a serious AMM backtester

If you're building on top of an AMM backtesting project, there are several areas worth paying attention to.

1. Real swap-level data

Candle data can be convenient, but AMMs operate through swaps.

For higher-fidelity simulation, historical swap events and pool state can become extremely important.

2. Execution costs

A strategy that rebalances every few minutes may look great before costs.

After gas and execution costs, the result could be completely different.

3. Slippage

Large LP positions shouldn't necessarily assume perfect execution.

The simulator should model the relationship between trade size, pool liquidity, and execution price.

4. Concentrated liquidity

For Uniswap V3-style strategies, price ranges and ticks introduce another layer of complexity.

A realistic simulator needs to understand what happens when price moves through those ranges.

5. Out-of-sample testing

Don't optimize and evaluate on exactly the same data.

A better workflow is:

Historical data
      ↓
Training / optimization period
      ↓
Strategy selection
      ↓
Out-of-sample period
      ↓
Robustness analysis
Enter fullscreen mode Exit fullscreen mode

6. Monte Carlo and stress testing

Historical data represents only one path.

Stress testing can help answer questions such as:

What if volatility doubles?

What if price crashes 40%?

What if fees fall?

What if rebalancing costs increase?

What if the market trends continuously?
Enter fullscreen mode Exit fullscreen mode

These questions are often more useful than another decimal place of historical return.

A practical research workflow

If I were experimenting with amm-strategy-backtester, I'd structure the research process like this:

Step 1
Choose an AMM and trading pair

        ↓

Step 2
Collect historical data

        ↓

Step 3
Create a simple buy-and-hold benchmark

        ↓

Step 4
Create a static LP benchmark

        ↓

Step 5
Implement one active strategy

        ↓

Step 6
Run the same period across all strategies

        ↓

Step 7
Measure fees, P&L, IL and drawdown

        ↓

Step 8
Add realistic costs

        ↓

Step 9
Test different market regimes

        ↓

Step 10
Validate using out-of-sample data
Enter fullscreen mode Exit fullscreen mode

This approach is much more informative than immediately trying to build a complicated "AI-powered" LP strategy.

Start simple.

Establish a baseline.

Then add complexity one variable at a time.

Final thoughts

AMM liquidity provision is an interesting software problem because it sits at the intersection of:

DeFi
+
Market microstructure
+
Quantitative research
+
Software engineering
Enter fullscreen mode Exit fullscreen mode

A project such as amm-strategy-backtester is useful because it encourages developers to treat liquidity provision as something that can be defined, simulated, measured, and iterated on.

But the important lesson is that a backtest is only as good as its assumptions.

If your simulator ignores execution costs, liquidity changes, slippage, timing, or other important parts of the market, a beautiful equity curve may tell you very little.

The real objective should therefore be:

Build the most honest simulation you can, not the most profitable-looking one.

And once the simulation is trustworthy, you can start asking the much more interesting questions:

Which LP strategy is robust?

Which market conditions does it survive?

How much of the return comes from fees versus directional exposure?

And does the strategy still work when the assumptions become less favorable?

That's where AMM backtesting becomes more than a coding exercise — it becomes a serious quantitative research tool.

Top comments (0)