Skip to content

Commit

Permalink
chore(refactor): docs
Browse files Browse the repository at this point in the history
  • Loading branch information
ts0yu authored Aug 12, 2024
1 parent ec636e5 commit 7b4662a
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 36 deletions.
48 changes: 46 additions & 2 deletions src/arena.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,25 @@ use crate::{
types::{PoolManager, PoolManager::PoolKey},
};

/// Represents an [`Arena`] that can be used to run a simulation and execute strategies.
pub struct Arena {
/// The underlying Anvil execution environment.
pub env: AnvilInstance,

/// The strategies that are to be run in the simulation.
pub strategies: Vec<Box<dyn Strategy>>,

/// The pool that the strategies are to be run against, and the arbitrageur to peg.
pub pool: PoolKey,

/// The feed that provides the current, theoretical value of the pool.
pub feed: Box<dyn Feed>,

providers: HashMap<usize, AnvilProvider>,
}

impl Arena {
/// Run all strategies in the simulation with a given configuration.
pub async fn run(&mut self, config: Config) {
let admin_provider = self.providers[&0].clone();

Expand All @@ -38,29 +47,60 @@ impl Arena {
.unwrap();

for (idx, strategy) in self.strategies.iter_mut().enumerate() {
strategy.init(self.providers[&(idx + 1)].clone());
strategy.init(
self.providers[&(idx + 1)].clone(),
Signal::new(
*pool_manager.address(),
self.pool.clone(),
self.feed.current_value(),
None,
),
);
}

for step in 0..config.steps {
for (idx, strategy) in self.strategies.iter_mut().enumerate() {
strategy.process(self.providers[&(idx + 1)].clone());
strategy.process(
self.providers[&(idx + 1)].clone(),
Signal::new(
*pool_manager.address(),
self.pool.clone(),
self.feed.current_value(),
Some(step),
),
);
}

self.feed.step();
}
}
}

/// A builder for an [`Arena`] that can be used to configure the simulation.
pub struct ArenaBuilder {
/// [`Arena::env`]
pub env: AnvilInstance,

/// [`Arena::strategies`]
pub strategies: Vec<Box<dyn Strategy>>,

/// [`Arena::pool`]
pub pool: Option<PoolKey>,

/// [`Arena::feed`]
pub feed: Option<Box<dyn Feed>>,

providers: Option<HashMap<usize, AnvilProvider>>,
}

impl Default for ArenaBuilder {
fn default() -> Self {
Self::new()
}
}

impl ArenaBuilder {
/// Public constructor function for a new [`ArenaBuilder`].
pub fn new() -> Self {
ArenaBuilder {
env: Anvil::default().spawn(),
Expand All @@ -71,21 +111,25 @@ impl ArenaBuilder {
}
}

/// Add a strategy to the simulation.
pub fn with_strategy(mut self, strategy: Box<dyn Strategy>) -> Self {
self.strategies.push(strategy);
self
}

/// Set the pool that the strategies are to be run against.
pub fn with_pool(mut self, pool: PoolKey) -> Self {
self.pool = Some(pool);
self
}

/// Set the feed that provides the current, theoretical value of the pool.
pub fn with_feed(mut self, feed: Box<dyn Feed>) -> Self {
self.feed = Some(feed);
self
}

/// Build the [`Arena`] with the given configuration.
pub fn build(self) -> Arena {
let mut providers = HashMap::new();

Expand Down
3 changes: 3 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
/// Configuration for the simulation.
pub struct Config {
/// Number of steps to run the simulation for.
pub steps: usize,
}

impl Config {
/// Public constructor function for a new [`Config`].
pub fn new(steps: usize) -> Self {
Config { steps }
}
Expand Down
10 changes: 6 additions & 4 deletions src/feed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,25 @@ pub trait Feed {
}

#[derive(Debug)]
/// Implementation of an Ornstein-Uhlenbeck process using a Euler-Maruyama discretization scheme.
pub struct OrnsteinUhlenbeck {
current_value: f64,

/// Mean reversion rate
/// Mean reversion rate.
theta: f64,

/// Long-term mean
/// Long-term mean.
mu: f64,

// Volatility
/// Volatility.
sigma: f64,

// Time step
/// Time step.
dt: f64,
}

impl OrnsteinUhlenbeck {
/// Public constructor function for a new [`OrnsteinUhlenbeck`].
pub fn new(initial_value: f64, theta: f64, mu: f64, sigma: f64, dt: f64) -> Self {
OrnsteinUhlenbeck {
current_value: initial_value,
Expand Down
63 changes: 56 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
#![warn(missing_docs)]
#[doc = include_str!("../README.md")]

/// Defines the main simulation runtime.
pub mod arena;

/// Contains configuration types for the simulation.
pub mod config;

/// Contains the types for various price processes.
pub mod feed;

/// Defines the base strategy trait.
pub mod strategy;
pub mod types;

use alloy::{
network::{Ethereum, EthereumWallet},
node_bindings::{Anvil, AnvilInstance},
Expand All @@ -14,11 +24,9 @@ use alloy::{
transports::http::{Client, Http},
};

use crate::{
arena::ArenaBuilder, config::Config, feed::OrnsteinUhlenbeck, strategy::Strategy,
types::PoolManager::PoolKey,
};
use crate::types::PoolManager::PoolKey;

/// Provider type that includes all necessary fillers to execute transactions on an [`Anvil`] node.
pub type AnvilProvider = FillProvider<
JoinFill<
JoinFill<JoinFill<JoinFill<Identity, GasFiller>, NonceFiller>, ChainIdFiller>,
Expand All @@ -29,15 +37,56 @@ pub type AnvilProvider = FillProvider<
Ethereum,
>;

mod types {
use alloy_sol_macro::sol;

#[allow(missing_docs)]
sol! {
#[sol(rpc)]
#[derive(Debug)]
PoolManager,
"contracts/v4-core/out/PoolManager.sol/PoolManager.json"
}
}

/// A signal that is passed to a [`Strategy`] to provide information about the current state of the pool.
#[derive(Debug, Clone)]
pub struct Signal {
/// Address of the pool manager.
pub manager: Address,

/// Key of the pool.
pub pool: PoolKey,

/// Current theoretical value of the pool.
pub current_value: f64,

/// Current step of the simulation.
pub step: Option<usize>,
}

impl Signal {
/// Public constructor function for a new [`Signal`].
pub fn new(manager: Address, pool: PoolKey, current_value: f64, step: Option<usize>) -> Self {
Self {
manager,
pool,
current_value,
step,
}
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::{arena::ArenaBuilder, config::Config, feed::OrnsteinUhlenbeck, strategy::Strategy};

struct StrategyMock;

impl Strategy for StrategyMock {
fn init(&self, _provider: AnvilProvider) {}
fn process(&self, _provider: AnvilProvider) {}
fn init(&self, _provider: AnvilProvider, _signal: Signal) {}
fn process(&self, _provider: AnvilProvider, _signal: Signal) {}
}

#[tokio::test]
Expand Down
8 changes: 6 additions & 2 deletions src/strategy.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
use super::*;

/// Represents a strategy that can be run in an [`Arena`].
pub trait Strategy {
fn init(&self, provider: AnvilProvider);
fn process(&self, provider: AnvilProvider);
/// Initialization function for ths strategy to be run upon simulation startup.
fn init(&self, provider: AnvilProvider, signal: Signal);

/// Processing function for the strategy to be run each simulation step.
fn process(&self, provider: AnvilProvider, signal: Signal);
}
21 changes: 0 additions & 21 deletions src/types.rs

This file was deleted.

0 comments on commit 7b4662a

Please sign in to comment.