nautilus_model/defi/pool_analysis/
snapshot.rs1use alloy_primitives::{U160, U256};
17use nautilus_core::UnixNanos;
18use serde::{Deserialize, Serialize};
19
20use crate::{
21 defi::{
22 data::block::BlockPosition, pool_analysis::position::PoolPosition, tick_map::tick::PoolTick,
23 },
24 identifiers::InstrumentId,
25};
26
27pub const PROTOCOL_FEE_BASIS_POINTS_DENOMINATOR: u32 = 10_000;
29
30#[cfg_attr(
36 feature = "python",
37 pyo3::pyclass(module = "nautilus_trader.model", from_py_object)
38)]
39#[cfg_attr(
40 feature = "python",
41 pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.model")
42)]
43#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
44pub struct PoolSnapshot {
45 pub instrument_id: InstrumentId,
47 pub state: PoolState,
49 pub positions: Vec<PoolPosition>,
51 pub ticks: Vec<PoolTick>,
53 pub analytics: PoolAnalytics,
55 pub block_position: BlockPosition,
57 #[serde(default)]
59 pub ts_event: UnixNanos,
60 #[serde(default)]
62 pub ts_init: UnixNanos,
63}
64
65impl PoolSnapshot {
66 #[must_use]
68 #[expect(clippy::too_many_arguments)]
69 pub fn new(
70 instrument_id: InstrumentId,
71 state: PoolState,
72 positions: Vec<PoolPosition>,
73 ticks: Vec<PoolTick>,
74 analytics: PoolAnalytics,
75 block_position: BlockPosition,
76 ts_event: UnixNanos,
77 ts_init: UnixNanos,
78 ) -> Self {
79 Self {
80 instrument_id,
81 state,
82 positions,
83 ticks,
84 analytics,
85 block_position,
86 ts_event,
87 ts_init,
88 }
89 }
90}
91
92#[cfg_attr(
98 feature = "python",
99 pyo3::pyclass(module = "nautilus_trader.model", from_py_object)
100)]
101#[cfg_attr(
102 feature = "python",
103 pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.model")
104)]
105#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
106pub struct PoolState {
107 pub current_tick: i32,
109 pub price_sqrt_ratio_x96: U160,
111 pub liquidity: u128,
113 pub protocol_fees_token0: U256,
115 pub protocol_fees_token1: U256,
117 pub fee_protocol: u8,
119 #[serde(default)]
121 pub fee_protocol0_basis_points: Option<u32>,
122 #[serde(default)]
124 pub fee_protocol1_basis_points: Option<u32>,
125 pub fee_growth_global_0: U256,
127 pub fee_growth_global_1: U256,
129}
130
131impl PoolState {
132 #[must_use]
134 pub fn new(protocol_fees_token0: U256, protocol_fees_token1: U256, fee_protocol: u8) -> Self {
135 Self {
136 current_tick: 0,
137 price_sqrt_ratio_x96: U160::ZERO,
138 liquidity: 0,
139 protocol_fees_token0,
140 protocol_fees_token1,
141 fee_protocol,
142 fee_protocol0_basis_points: None,
143 fee_protocol1_basis_points: None,
144 fee_growth_global_0: U256::ZERO,
145 fee_growth_global_1: U256::ZERO,
146 }
147 }
148
149 #[must_use]
151 pub const fn uniswap_v3_fee_protocol(&self, zero_for_one: bool) -> u8 {
152 if zero_for_one {
153 self.fee_protocol % 16
154 } else {
155 self.fee_protocol >> 4
156 }
157 }
158
159 #[must_use]
161 pub const fn fee_protocol_basis_points(&self, zero_for_one: bool) -> Option<u32> {
162 if zero_for_one {
163 self.fee_protocol0_basis_points
164 } else {
165 self.fee_protocol1_basis_points
166 }
167 }
168
169 pub fn set_uniswap_v3_fee_protocol(&mut self, fee_protocol: u8) {
171 self.fee_protocol = fee_protocol;
172 self.fee_protocol0_basis_points = None;
173 self.fee_protocol1_basis_points = None;
174 }
175
176 pub fn set_protocol_fee_basis_points(&mut self, fee_protocol0: u32, fee_protocol1: u32) {
178 self.fee_protocol = 0;
179 self.fee_protocol0_basis_points = Some(fee_protocol0);
180 self.fee_protocol1_basis_points = Some(fee_protocol1);
181 }
182}
183
184impl Default for PoolState {
185 fn default() -> Self {
186 Self {
187 current_tick: 0,
188 price_sqrt_ratio_x96: U160::ZERO,
189 liquidity: 0,
190 protocol_fees_token0: U256::ZERO,
191 protocol_fees_token1: U256::ZERO,
192 fee_protocol: 0,
193 fee_protocol0_basis_points: None,
194 fee_protocol1_basis_points: None,
195 fee_growth_global_0: U256::ZERO,
196 fee_growth_global_1: U256::ZERO,
197 }
198 }
199}
200
201#[cfg_attr(
206 feature = "python",
207 pyo3::pyclass(module = "nautilus_trader.model", from_py_object)
208)]
209#[cfg_attr(
210 feature = "python",
211 pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.model")
212)]
213#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
214pub struct PoolAnalytics {
215 pub total_amount0_deposited: U256,
217 pub total_amount1_deposited: U256,
219 pub total_amount0_collected: U256,
221 pub total_amount1_collected: U256,
223 pub total_swaps: u64,
225 pub total_mints: u64,
227 pub total_burns: u64,
229 pub total_fee_collects: u64,
231 pub total_flashes: u64,
233 pub liquidity_utilization_rate: f64,
235}
236
237impl Default for PoolAnalytics {
238 fn default() -> Self {
239 Self {
240 total_amount0_deposited: U256::ZERO,
241 total_amount1_deposited: U256::ZERO,
242 total_amount0_collected: U256::ZERO,
243 total_amount1_collected: U256::ZERO,
244 total_swaps: 0,
245 total_mints: 0,
246 total_burns: 0,
247 total_fee_collects: 0,
248 total_flashes: 0,
249 liquidity_utilization_rate: 0.0,
250 }
251 }
252}