From ab7ae89b9135ddf8bee643592a5a16d43619be0a Mon Sep 17 00:00:00 2001 From: ts0yu <120932697+ts0yu@users.noreply.github.com> Date: Thu, 15 Aug 2024 18:51:35 +0000 Subject: [PATCH] feat(refactor): arbitrageur trait --- README.md | 2 +- src/arena.rs | 37 +++++++++++++++++++++++++---------- src/engine/arbitrageur.rs | 7 +++++++ src/{ => engine}/inspector.rs | 0 src/engine/mod.rs | 2 ++ src/lib.rs | 16 ++++++++++----- 6 files changed, 48 insertions(+), 16 deletions(-) create mode 100644 src/engine/arbitrageur.rs rename src/{ => engine}/inspector.rs (100%) create mode 100644 src/engine/mod.rs diff --git a/README.md b/README.md index 4edc07d..4534da8 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ The price of the simulation's underlying pool is set via a price process that im To use Arena, the Rust programming language must be installed on your machine. This is commonly achieved using `rustup`. Arena can be added to your library or binary with -```rust +``` cargo add arena-core ``` diff --git a/src/arena.rs b/src/arena.rs index aac57e2..281f97b 100644 --- a/src/arena.rs +++ b/src/arena.rs @@ -5,8 +5,8 @@ use alloy::{primitives::U256, providers::ProviderBuilder, signers::local::Privat use super::*; use crate::{ config::Config, + engine::{arbitrageur::Arbitrageur, inspector::Inspector}, feed::Feed, - inspector::Inspector, strategy::Strategy, types::{ArenaToken, LiquidExchange, PoolManager, PoolManager::PoolKey}, }; @@ -28,6 +28,9 @@ pub struct Arena { /// The inspector that is used to evaluate the performance of the strategies. pub inspector: Box>, + /// The arbitrageur that is used to peg the pool. + pub arbitrageur: Box, + providers: HashMap, } @@ -96,10 +99,16 @@ impl Arena { } for step in 0..config.steps { + let signal = Signal::new( + *pool_manager.address(), + self.pool.clone(), + self.feed.current_value(), + Some(step), + ); + liquid_exchange .setPrice( - alloy::primitives::utils::parse_ether(&self.feed.step().to_string()) - .unwrap(), + alloy::primitives::utils::parse_ether(&self.feed.step().to_string()).unwrap(), ) .send() .await @@ -107,16 +116,13 @@ impl Arena { .watch() .await .unwrap(); - + + self.arbitrageur.arbitrage(&signal, admin_provider.clone()); + for (idx, strategy) in self.strategies.iter_mut().enumerate() { strategy.process( self.providers[&(idx + 1)].clone(), - Signal::new( - *pool_manager.address(), - self.pool.clone(), - self.feed.current_value(), - Some(step), - ), + signal.clone(), &mut self.inspector, ); } @@ -143,6 +149,9 @@ pub struct ArenaBuilder { /// [`Arena::inspector`] pub inspector: Option>>, + /// [`Arena::arbitrageur`] + pub arbitrageur: Option>, + providers: Option>, } @@ -162,6 +171,7 @@ impl ArenaBuilder { feed: None, providers: None, inspector: None, + arbitrageur: None, } } @@ -201,6 +211,12 @@ impl ArenaBuilder { self } + /// Set the inspector that is used to evaluate the performance of the strategies. + pub fn with_arbitrageur(mut self, arbitrageur: Box) -> Self { + self.arbitrageur = Some(arbitrageur); + self + } + /// Build the [`Arena`] with the given configuration. pub fn build(self) -> Arena { let mut providers = HashMap::new(); @@ -225,6 +241,7 @@ impl ArenaBuilder { pool: self.pool, feed: self.feed.unwrap(), inspector: self.inspector.unwrap(), + arbitrageur: self.arbitrageur.unwrap(), providers, } } diff --git a/src/engine/arbitrageur.rs b/src/engine/arbitrageur.rs new file mode 100644 index 0000000..d6617b9 --- /dev/null +++ b/src/engine/arbitrageur.rs @@ -0,0 +1,7 @@ +use crate::{AnvilProvider, Signal}; + +/// Generic trait allowing user defined arbitrage strategies. +pub trait Arbitrageur { + /// Perform an arbitrage based on a [`Signal`]. + fn arbitrage(&self, signal: &Signal, provider: AnvilProvider); +} diff --git a/src/inspector.rs b/src/engine/inspector.rs similarity index 100% rename from src/inspector.rs rename to src/engine/inspector.rs diff --git a/src/engine/mod.rs b/src/engine/mod.rs new file mode 100644 index 0000000..9be8227 --- /dev/null +++ b/src/engine/mod.rs @@ -0,0 +1,2 @@ +pub mod arbitrageur; +pub mod inspector; diff --git a/src/lib.rs b/src/lib.rs index 95e7e00..5c11eea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,4 @@ #![warn(missing_docs)] -#[doc = include_str!("../README.md")] /// Defines the main simulation runtime. pub mod arena; @@ -13,8 +12,7 @@ pub mod feed; /// Defines the base strategy trait. pub mod strategy; -/// Defines the [`Inspector`] trait. -pub mod inspector; +pub mod engine; use alloy::{ network::{Ethereum, EthereumWallet}, @@ -27,7 +25,7 @@ use alloy::{ transports::http::{Client, Http}, }; -use crate::{inspector::Inspector, types::PoolManager::PoolKey}; +use crate::{engine::inspector::Inspector, types::PoolManager::PoolKey}; /// Provider type that includes all necessary fillers to execute transactions on an [`Anvil`] node. pub type AnvilProvider = FillProvider< @@ -105,8 +103,15 @@ mod tests { feed::OrnsteinUhlenbeck, strategy::Strategy, }; + use crate::engine::arbitrageur::Arbitrageur; + struct StrategyMock; struct InspectorMock; + struct ArbitrageurMock; + + impl Arbitrageur for ArbitrageurMock { + fn arbitrage(&self, _signal: &Signal, _provider: AnvilProvider) {} + } impl Inspector for InspectorMock { fn inspect(&self, _step: usize) -> Option { @@ -143,8 +148,9 @@ mod tests { .with_tick_spacing(2) .with_feed(Box::new(OrnsteinUhlenbeck::new(0.1, 0.1, 0.1, 0.1, 0.1))) .with_inspector(Box::new(InspectorMock {})) + .with_arbitrageur(Box::new(ArbitrageurMock {})) .build(); - arena.run(Config::new(0)).await; + arena.run(Config::new(1)).await; } }