2026-02-27 09:00:22 +00:00
|
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
|
pragma solidity ^0.8.19;
|
|
|
|
|
|
|
|
|
|
import { LiquidityManager } from "../../src/LiquidityManager.sol";
|
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 { OptimizerV3Push3 } from "../../src/OptimizerV3Push3.sol";
|
|
|
|
|
import { BacktestKraiken } from "./BacktestKraiken.sol";
|
|
|
|
|
import { MockToken } from "./MockToken.sol";
|
2026-02-27 09:00:22 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @notice Deployment result for the KrAIken system on the shadow pool.
|
|
|
|
|
*/
|
|
|
|
|
struct KrAIkenSystem {
|
|
|
|
|
BacktestKraiken kraiken;
|
2026-03-14 05:08:32 +00:00
|
|
|
/// @dev OptimizerV3Push3 is used as the optimizer address. Its getLiquidityParams()
|
|
|
|
|
/// uses zeroed inputs (no on-chain stake data) and returns bear-mode defaults on
|
|
|
|
|
/// every recenter. This is intentional for backtesting.
|
2026-02-27 09:00:22 +00:00
|
|
|
OptimizerV3Push3 optimizer;
|
|
|
|
|
LiquidityManager lm;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @title KrAIkenDeployer
|
|
|
|
|
* @notice Library that deploys the KrAIken protocol contracts on top of a shadow pool
|
|
|
|
|
* for backtesting purposes.
|
|
|
|
|
*
|
|
|
|
|
* Deployment order follows DeployLocal.sol:
|
|
|
|
|
* 1. Deploy OptimizerV3Push3 (no proxy — it only exposes isBullMarket(), so LM falls
|
|
|
|
|
* back to bear-mode defaults via try/catch on every recenter call).
|
|
|
|
|
* 2. Deploy LiquidityManager pointing at the shadow factory + mock WETH + BacktestKraiken.
|
|
|
|
|
* 3. Wire BacktestKraiken → LM (setLiquidityManager).
|
|
|
|
|
* 4. Set fee destination on LM.
|
|
|
|
|
* 5. Fund LM with mock WETH (initial capital).
|
|
|
|
|
*
|
|
|
|
|
* @dev All functions are `internal` so they are inlined into BacktestRunner.s.sol,
|
|
|
|
|
* keeping msg.sender consistent with the broadcaster throughout deployment.
|
|
|
|
|
*/
|
|
|
|
|
library KrAIkenDeployer {
|
|
|
|
|
uint256 internal constant DEFAULT_INITIAL_CAPITAL = 10 ether;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @notice Deploy the KrAIken system with default initial capital (10 ETH equivalent).
|
|
|
|
|
*/
|
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 shadowFactory, address mockWeth, address krkToken, address feeDestination) internal returns (KrAIkenSystem memory sys) {
|
2026-02-27 09:00:22 +00:00
|
|
|
return deploy(shadowFactory, mockWeth, krkToken, feeDestination, DEFAULT_INITIAL_CAPITAL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @notice Deploy the KrAIken system with configurable initial capital.
|
|
|
|
|
*
|
|
|
|
|
* @param shadowFactory Factory that created the shadow pool.
|
|
|
|
|
* @param mockWeth Mock WETH token address (18-decimal ERC-20, freely mintable).
|
|
|
|
|
* @param krkToken BacktestKraiken token address (setLiquidityManager not yet called).
|
|
|
|
|
* @param feeDestination Address that will receive LP fees; also used as the caller
|
|
|
|
|
* for subsequent setRecenterAccess() calls.
|
|
|
|
|
* @param initialCapital Mock WETH minted to LM so recenter() has capital to deploy.
|
|
|
|
|
*/
|
|
|
|
|
function deploy(
|
|
|
|
|
address shadowFactory,
|
|
|
|
|
address mockWeth,
|
|
|
|
|
address krkToken,
|
|
|
|
|
address feeDestination,
|
|
|
|
|
uint256 initialCapital
|
|
|
|
|
)
|
|
|
|
|
internal
|
|
|
|
|
returns (KrAIkenSystem memory sys)
|
|
|
|
|
{
|
|
|
|
|
// 1. Deploy OptimizerV3Push3.
|
2026-03-14 05:08:32 +00:00
|
|
|
// OptimizerV3Push3.getLiquidityParams() uses zeroed inputs (no stake data),
|
|
|
|
|
// so every recenter uses bear defaults — conservative and correct for a
|
|
|
|
|
// baseline backtest.
|
2026-02-27 09:00:22 +00:00
|
|
|
OptimizerV3Push3 optimizer = new OptimizerV3Push3();
|
|
|
|
|
|
|
|
|
|
// 2. Deploy LiquidityManager. It computes the pool address from factory + WETH +
|
|
|
|
|
// KRK + FEE (10 000). The shadow pool must have been created with the same
|
|
|
|
|
// factory and the same fee tier (ShadowPoolDeployer.SHADOW_FEE == 10 000).
|
|
|
|
|
LiquidityManager lm = new LiquidityManager(shadowFactory, mockWeth, krkToken, address(optimizer));
|
|
|
|
|
|
|
|
|
|
// 3. Wire BacktestKraiken → LM so the restricted mint/burn functions work.
|
|
|
|
|
BacktestKraiken(krkToken).setLiquidityManager(address(lm));
|
|
|
|
|
|
|
|
|
|
// 4. Set fee destination (required before setRecenterAccess can be called).
|
|
|
|
|
lm.setFeeDestination(feeDestination);
|
|
|
|
|
|
|
|
|
|
// 5. Fund LM with mock WETH. recenter() uses _getEthBalance() which reads
|
|
|
|
|
// weth.balanceOf(address(this)). Pre-funding avoids calling weth.deposit()
|
|
|
|
|
// (which MockToken does not implement).
|
|
|
|
|
MockToken(mockWeth).mint(address(lm), initialCapital);
|
|
|
|
|
|
|
|
|
|
sys = KrAIkenSystem({ kraiken: BacktestKraiken(krkToken), optimizer: optimizer, lm: lm });
|
|
|
|
|
}
|
|
|
|
|
}
|