-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: async arbitrageur trait, improvements to DefaultArbitrageur
- Loading branch information
Showing
5 changed files
with
120 additions
and
6 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,86 @@ | ||
use crate::{AnvilProvider, Signal}; | ||
use async_trait::async_trait; | ||
use rug::{ops::Pow, Float}; | ||
|
||
use crate::{types::Fetcher, AnvilProvider, Signal}; | ||
|
||
/// Generic trait allowing user defined arbitrage strategies. | ||
#[async_trait] | ||
pub trait Arbitrageur { | ||
/// Perform an arbitrage based on a [`Signal`]. | ||
fn arbitrage(&self, signal: &Signal, provider: AnvilProvider); | ||
async fn arbitrage(&self, signal: &Signal, provider: AnvilProvider); | ||
} | ||
|
||
/// Default implementation of an [`Arbitrageur`] that uses the closed-form optimal swap amount to determine the optimal arbitrage. | ||
pub struct DefaultArbitrageur; | ||
|
||
#[async_trait] | ||
impl Arbitrageur for DefaultArbitrageur { | ||
async fn arbitrage(&self, signal: &Signal, provider: AnvilProvider) { | ||
let base = Float::with_val(53, 1.0001); | ||
let price = Float::with_val(53, signal.current_value); | ||
|
||
let target_tick = price.log10() / base.log10(); | ||
let current_tick = Float::with_val(53, signal.tick); | ||
|
||
let (start, end) = if current_tick < target_tick { | ||
(current_tick, target_tick) | ||
} else { | ||
(target_tick, current_tick) | ||
}; | ||
|
||
let (a, b) = self | ||
.get_tick_range_liquidity( | ||
signal, | ||
provider, | ||
start.to_i32_saturating().unwrap(), | ||
end.to_i32_saturating().unwrap(), | ||
) | ||
.await; | ||
} | ||
} | ||
|
||
impl DefaultArbitrageur { | ||
async fn get_tick_range_liquidity( | ||
&self, | ||
signal: &Signal, | ||
provider: AnvilProvider, | ||
start: i32, | ||
end: i32, | ||
) -> (Float, Float) { | ||
let fetcher = Fetcher::new(signal.fetcher, provider); | ||
|
||
let mut liquidity_a = Float::with_val(53, 0); | ||
let mut liquidity_b = Float::with_val(53, 0); | ||
|
||
for tick in start..end { | ||
let pool_id = fetcher | ||
.toId(signal.pool.clone().into()) | ||
.call() | ||
.await | ||
.unwrap() | ||
.poolId; | ||
|
||
let tick_info = fetcher | ||
.getTickInfo(signal.manager, pool_id, tick) | ||
.call() | ||
.await | ||
.unwrap(); | ||
let sqrt_price = Float::with_val(53, Float::with_val(53, 1.0001).pow(tick / 2)); | ||
|
||
let tick_liquidity = Float::with_val(53, tick_info.liquidityNet); | ||
|
||
liquidity_a += tick_liquidity.clone() / sqrt_price.clone(); | ||
liquidity_b += tick_liquidity * sqrt_price; | ||
} | ||
|
||
(liquidity_a, liquidity_b) | ||
} | ||
} | ||
|
||
/// No-op implementation of an [`Arbitrageur`] for custom usecases. | ||
pub struct EmptyArbitrageur; | ||
|
||
#[async_trait] | ||
impl Arbitrageur for EmptyArbitrageur { | ||
fn arbitrage(&self, _signal: &Signal, _provider: AnvilProvider) {} | ||
async fn arbitrage(&self, _signal: &Signal, _provider: AnvilProvider) {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters