gmsol_model/market/
position_impact.rs1use num_traits::{CheckedSub, FromPrimitive, Zero};
2
3use crate::{
4 action::distribute_position_impact::DistributePositionImpact,
5 params::{position::PositionImpactDistributionParams, PriceImpactParams},
6 Balance, BaseMarket, BaseMarketMut, Pool,
7};
8
9pub trait PositionImpactMarket<const DECIMALS: u8>: BaseMarket<DECIMALS> {
11 fn position_impact_pool(&self) -> crate::Result<&Self::Pool>;
13
14 fn position_impact_params(&self) -> crate::Result<PriceImpactParams<Self::Num>>;
16
17 fn position_impact_distribution_params(
19 &self,
20 ) -> crate::Result<PositionImpactDistributionParams<Self::Num>>;
21
22 fn passed_in_seconds_for_position_impact_distribution(&self) -> crate::Result<u64>;
24}
25
26pub trait PositionImpactMarketMut<const DECIMALS: u8>:
28 BaseMarketMut<DECIMALS> + PositionImpactMarket<DECIMALS>
29{
30 fn position_impact_pool_mut(&mut self) -> crate::Result<&mut Self::Pool>;
34
35 fn just_passed_in_seconds_for_position_impact_distribution(&mut self) -> crate::Result<u64>;
37}
38
39impl<M: PositionImpactMarket<DECIMALS>, const DECIMALS: u8> PositionImpactMarket<DECIMALS>
40 for &mut M
41{
42 fn position_impact_pool(&self) -> crate::Result<&Self::Pool> {
43 (**self).position_impact_pool()
44 }
45
46 fn position_impact_params(&self) -> crate::Result<PriceImpactParams<Self::Num>> {
47 (**self).position_impact_params()
48 }
49
50 fn position_impact_distribution_params(
51 &self,
52 ) -> crate::Result<PositionImpactDistributionParams<Self::Num>> {
53 (**self).position_impact_distribution_params()
54 }
55
56 fn passed_in_seconds_for_position_impact_distribution(&self) -> crate::Result<u64> {
57 (**self).passed_in_seconds_for_position_impact_distribution()
58 }
59}
60
61impl<M: PositionImpactMarketMut<DECIMALS>, const DECIMALS: u8> PositionImpactMarketMut<DECIMALS>
62 for &mut M
63{
64 fn position_impact_pool_mut(&mut self) -> crate::Result<&mut Self::Pool> {
65 (**self).position_impact_pool_mut()
66 }
67
68 fn just_passed_in_seconds_for_position_impact_distribution(&mut self) -> crate::Result<u64> {
69 (**self).just_passed_in_seconds_for_position_impact_distribution()
70 }
71}
72
73pub trait PositionImpactMarketExt<const DECIMALS: u8>: PositionImpactMarket<DECIMALS> {
75 #[inline]
77 fn position_impact_pool_amount(&self) -> crate::Result<Self::Num> {
78 self.position_impact_pool()?.long_amount()
79 }
80
81 fn pending_position_impact_pool_distribution_amount(
83 &self,
84 duration_in_secs: u64,
85 ) -> crate::Result<(Self::Num, Self::Num)> {
86 use crate::utils;
87
88 let current_amount = self.position_impact_pool_amount()?;
89 let params = self.position_impact_distribution_params()?;
90 let min_position_impact_pool_amount = params.min_position_impact_pool_amount();
91 if params.distribute_factor().is_zero()
92 || current_amount <= *min_position_impact_pool_amount
93 {
94 return Ok((Zero::zero(), current_amount));
95 }
96 let max_distribution_amount = current_amount
97 .checked_sub(min_position_impact_pool_amount)
98 .ok_or(crate::Error::Computation(
99 "calculating max distribution amount",
100 ))?;
101
102 let duration_value = Self::Num::from_u64(duration_in_secs).ok_or(crate::Error::Convert)?;
103 let mut distribution_amount =
104 utils::apply_factor(&duration_value, params.distribute_factor())
105 .ok_or(crate::Error::Computation("calculating distribution amount"))?;
106 if distribution_amount > max_distribution_amount {
107 distribution_amount = max_distribution_amount;
108 }
109 let next_amount =
110 current_amount
111 .checked_sub(&distribution_amount)
112 .ok_or(crate::Error::Computation(
113 "calculating next position impact amount",
114 ))?;
115 Ok((distribution_amount, next_amount))
116 }
117}
118
119impl<M: PositionImpactMarket<DECIMALS> + ?Sized, const DECIMALS: u8>
120 PositionImpactMarketExt<DECIMALS> for M
121{
122}
123
124pub trait PositionImpactMarketMutExt<const DECIMALS: u8>:
126 PositionImpactMarketMut<DECIMALS>
127{
128 fn apply_delta_to_position_impact_pool(&mut self, delta: &Self::Signed) -> crate::Result<()> {
130 self.position_impact_pool_mut()?
131 .apply_delta_to_long_amount(delta)
132 }
133
134 fn distribute_position_impact(
136 &mut self,
137 ) -> crate::Result<DistributePositionImpact<&mut Self, DECIMALS>>
138 where
139 Self: Sized,
140 {
141 Ok(DistributePositionImpact::from(self))
142 }
143}
144
145impl<M: PositionImpactMarketMut<DECIMALS> + ?Sized, const DECIMALS: u8>
146 PositionImpactMarketMutExt<DECIMALS> for M
147{
148}