2026-02-27 05:08:27 +00:00
|
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
|
pragma solidity ^0.8.19;
|
|
|
|
|
|
fix: Backtesting #5: Position tracking + P&L metrics (#319)
- Add PositionTracker.sol: tracks position lifecycle (open/close per
recenter), records tick ranges, liquidity, entry/exit blocks/timestamps,
token amounts (via LiquidityAmounts math), fees (proportional to
liquidity share), IL (LP exit value − HODL value at exit price), and
net P&L per position. Aggregates total fees, cumulative IL, net P&L,
rebalance count, Anchor time-in-range, and capital efficiency accumulators.
Logs with [TRACKER][TYPE] prefix; emits cumulative P&L every 500 blocks.
- Modify StrategyExecutor.sol: add IUniswapV3Pool + token0isWeth to
constructor (creates PositionTracker internally), call
tracker.notifyBlock() on every block for time-in-range, and call
tracker.recordRecenter() on each successful recenter. logSummary()
now delegates to tracker.logFinalSummary().
- Modify BacktestRunner.s.sol: pass sp.pool and token0isWeth to
StrategyExecutor constructor; log tracker address.
- forge fmt: reformat all backtesting scripts and affected src/test files
to project style (number_underscore=thousands, multiline_func_header=all).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 11:23:18 +00:00
|
|
|
import { UniswapHelpers } from "../../src/helpers/UniswapHelpers.sol";
|
2026-02-27 05:08:27 +00:00
|
|
|
import { IUniswapV3Factory } from "@uniswap-v3-core/interfaces/IUniswapV3Factory.sol";
|
|
|
|
|
import { IUniswapV3Pool } from "@uniswap-v3-core/interfaces/IUniswapV3Pool.sol";
|
|
|
|
|
|
|
|
|
|
struct ShadowPool {
|
|
|
|
|
IUniswapV3Factory factory;
|
|
|
|
|
IUniswapV3Pool pool;
|
|
|
|
|
address token0;
|
|
|
|
|
address token1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @title ShadowPoolDeployer
|
|
|
|
|
* @notice Deploys a fresh UniswapV3Factory and pool for backtesting.
|
|
|
|
|
* SHADOW_FEE = 10 000 (1%) matches the AERO/WETH pool on Base.
|
|
|
|
|
*/
|
|
|
|
|
library ShadowPoolDeployer {
|
|
|
|
|
uint24 internal constant SHADOW_FEE = 10_000;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @notice Deploy a new UniswapV3 factory + pool and initialize it.
|
|
|
|
|
* @param tokenA One of the two mock tokens (any order).
|
|
|
|
|
* @param tokenB The other mock token.
|
|
|
|
|
* @param sqrtPriceX96 Initial sqrt price (Q64.96).
|
|
|
|
|
* @return sp ShadowPool struct with factory, pool, token0, token1 addresses.
|
|
|
|
|
*/
|
fix: Backtesting #5: Position tracking + P&L metrics (#319)
- Add PositionTracker.sol: tracks position lifecycle (open/close per
recenter), records tick ranges, liquidity, entry/exit blocks/timestamps,
token amounts (via LiquidityAmounts math), fees (proportional to
liquidity share), IL (LP exit value − HODL value at exit price), and
net P&L per position. Aggregates total fees, cumulative IL, net P&L,
rebalance count, Anchor time-in-range, and capital efficiency accumulators.
Logs with [TRACKER][TYPE] prefix; emits cumulative P&L every 500 blocks.
- Modify StrategyExecutor.sol: add IUniswapV3Pool + token0isWeth to
constructor (creates PositionTracker internally), call
tracker.notifyBlock() on every block for time-in-range, and call
tracker.recordRecenter() on each successful recenter. logSummary()
now delegates to tracker.logFinalSummary().
- Modify BacktestRunner.s.sol: pass sp.pool and token0isWeth to
StrategyExecutor constructor; log tracker address.
- forge fmt: reformat all backtesting scripts and affected src/test files
to project style (number_underscore=thousands, multiline_func_header=all).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 11:23:18 +00:00
|
|
|
function deploy(address tokenA, address tokenB, uint160 sqrtPriceX96) internal returns (ShadowPool memory sp) {
|
2026-02-27 05:08:27 +00:00
|
|
|
sp.factory = UniswapHelpers.deployUniswapFactory();
|
|
|
|
|
|
|
|
|
|
address poolAddr = sp.factory.createPool(tokenA, tokenB, SHADOW_FEE);
|
|
|
|
|
sp.pool = IUniswapV3Pool(poolAddr);
|
|
|
|
|
|
|
|
|
|
sp.pool.initialize(sqrtPriceX96);
|
|
|
|
|
|
|
|
|
|
// Resolve canonical token ordering from the pool.
|
|
|
|
|
sp.token0 = sp.pool.token0();
|
|
|
|
|
sp.token1 = sp.pool.token1();
|
|
|
|
|
}
|
|
|
|
|
}
|