Skip to main content

nautilus_model/defi/pool_analysis/
snapshot.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2026 Nautech Systems Pty Ltd. All rights reserved.
3//  https://nautechsystems.io
4//
5//  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6//  You may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16use alloy_primitives::{U160, U256};
17use serde::{Deserialize, Serialize};
18
19use crate::{
20    defi::{
21        data::block::BlockPosition, pool_analysis::position::PoolPosition, tick_map::tick::PoolTick,
22    },
23    identifiers::InstrumentId,
24};
25
26/// Complete snapshot of a liquidity pool's state at a specific point in time.
27///
28/// `PoolSnapshot` provides a self-contained representation of a pool's
29/// entire state, bundling together the global state variables, all liquidity positions,
30/// and the complete tick distribution.
31#[cfg_attr(
32    feature = "python",
33    pyo3::pyclass(module = "nautilus_trader.core.nautilus_pyo3.model", from_py_object)
34)]
35#[cfg_attr(
36    feature = "python",
37    pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.model")
38)]
39#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
40pub struct PoolSnapshot {
41    /// The instrument ID of the pool this snapshot represents.
42    pub instrument_id: InstrumentId,
43    /// Global pool state including price, tick, fees, and cumulative flows.
44    pub state: PoolState,
45    /// All liquidity positions in the pool.
46    pub positions: Vec<PoolPosition>,
47    /// Complete tick distribution across the pool's price range.
48    pub ticks: Vec<PoolTick>,
49    /// Analytics counters for the pool.
50    pub analytics: PoolAnalytics,
51    /// Block position where this snapshot was taken.
52    pub block_position: BlockPosition,
53}
54
55impl PoolSnapshot {
56    /// Creates a new `PoolSnapshot` with the specified parameters.
57    #[must_use]
58    pub fn new(
59        instrument_id: InstrumentId,
60        state: PoolState,
61        positions: Vec<PoolPosition>,
62        ticks: Vec<PoolTick>,
63        analytics: PoolAnalytics,
64        block_position: BlockPosition,
65    ) -> Self {
66        Self {
67            instrument_id,
68            state,
69            positions,
70            ticks,
71            analytics,
72            block_position,
73        }
74    }
75}
76
77/// Global state snapshot of a liquidity pool at a specific point in time.
78///
79/// `PoolState` encapsulates the core global variables that define a UniswapV3-style
80/// AMM pool's current state. This includes the current price position, cumulative
81/// deposit/withdrawal flows, and protocol fee configuration.
82#[cfg_attr(
83    feature = "python",
84    pyo3::pyclass(module = "nautilus_trader.core.nautilus_pyo3.model", from_py_object)
85)]
86#[cfg_attr(
87    feature = "python",
88    pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.model")
89)]
90#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
91pub struct PoolState {
92    /// Current tick position of the pool price.
93    pub current_tick: i32,
94    /// Current sqrt price ratio as Q64.96 fixed point number.
95    pub price_sqrt_ratio_x96: U160,
96    /// Current active liquidity in the pool.
97    pub liquidity: u128,
98    /// Accumulated protocol fees in token0 units.
99    pub protocol_fees_token0: U256,
100    /// Accumulated protocol fees in token1 units.
101    pub protocol_fees_token1: U256,
102    /// Protocol fee packed: lower 4 bits for token0, upper 4 bits for token1.
103    pub fee_protocol: u8,
104    /// Global fee growth for token0 as Q128.128 fixed-point number.
105    pub fee_growth_global_0: U256,
106    /// Global fee growth for token1 as Q128.128 fixed-point number.
107    pub fee_growth_global_1: U256,
108}
109
110impl PoolState {
111    /// Creates a new `PoolState` with the specified parameters.
112    #[must_use]
113    pub fn new(protocol_fees_token0: U256, protocol_fees_token1: U256, fee_protocol: u8) -> Self {
114        Self {
115            current_tick: 0,
116            price_sqrt_ratio_x96: U160::ZERO,
117            liquidity: 0,
118            protocol_fees_token0,
119            protocol_fees_token1,
120            fee_protocol,
121            fee_growth_global_0: U256::ZERO,
122            fee_growth_global_1: U256::ZERO,
123        }
124    }
125}
126
127impl Default for PoolState {
128    fn default() -> Self {
129        Self {
130            current_tick: 0,
131            price_sqrt_ratio_x96: U160::ZERO,
132            liquidity: 0,
133            protocol_fees_token0: U256::ZERO,
134            protocol_fees_token1: U256::ZERO,
135            fee_protocol: 0,
136            fee_growth_global_0: U256::ZERO,
137            fee_growth_global_1: U256::ZERO,
138        }
139    }
140}
141
142/// Analytics counters and metrics for pool operations.
143///
144/// It tracks cumulative statistics about pool activity, including
145/// deposit and collection flows, event counts, and performance metrics for debugging.
146#[cfg_attr(
147    feature = "python",
148    pyo3::pyclass(module = "nautilus_trader.core.nautilus_pyo3.model", from_py_object)
149)]
150#[cfg_attr(
151    feature = "python",
152    pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.model")
153)]
154#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
155pub struct PoolAnalytics {
156    /// Total amount of token0 deposited through mints.
157    pub total_amount0_deposited: U256,
158    /// Total amount of token1 deposited through mints.
159    pub total_amount1_deposited: U256,
160    /// Total amount of token0 collected
161    pub total_amount0_collected: U256,
162    /// Total amount of token1 collected.
163    pub total_amount1_collected: U256,
164    /// Total number of swap events processed.
165    pub total_swaps: u64,
166    /// Total number of mint events processed.
167    pub total_mints: u64,
168    /// Total number of burn events processed.
169    pub total_burns: u64,
170    /// Total number of fee collection events processed.
171    pub total_fee_collects: u64,
172    /// Total number of flash events processed.
173    pub total_flashes: u64,
174    /// Liquidity utilization rate (active liquidity / total liquidity)
175    pub liquidity_utilization_rate: f64,
176}
177
178impl Default for PoolAnalytics {
179    fn default() -> Self {
180        Self {
181            total_amount0_deposited: U256::ZERO,
182            total_amount1_deposited: U256::ZERO,
183            total_amount0_collected: U256::ZERO,
184            total_amount1_collected: U256::ZERO,
185            total_swaps: 0,
186            total_mints: 0,
187            total_burns: 0,
188            total_fee_collects: 0,
189            total_flashes: 0,
190            liquidity_utilization_rate: 0.0,
191        }
192    }
193}