Skip to content

Commit

Permalink
Merge pull request #18 from primitivefinance/refactor-template
Browse files Browse the repository at this point in the history
simplified template
  • Loading branch information
0xJepsen authored Nov 12, 2023
2 parents 053a0fb + a0a1fcb commit ab6f4c6
Show file tree
Hide file tree
Showing 12 changed files with 112 additions and 335 deletions.
Empty file added analysis/prices/output.json
Empty file.
4 changes: 2 additions & 2 deletions src/agents/block_admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ impl BlockAdmin {
///
/// # Arguments
/// * [`Environment`] - The environment containing blockchain node information.
/// * [`SimulationConfig<Fixed>`] - The simulation configuration providing block timestep size.
/// * [`SimulationConfig`] - The simulation configuration providing block timestep size.
///
/// # Returns
/// * [`Result<Self>`] - A result containing the new BlockAdmin or an error.
pub async fn new(environment: &Environment, config: &SimulationConfig<Fixed>) -> Result<Self> {
pub async fn new(environment: &Environment, config: &SimulationConfig) -> Result<Self> {
let client = RevmMiddleware::new(environment, "block_admin".into())?;
let timestep_size = config.block.timestep_size;
let block_number = client.get_block_number().await?.as_u64();
Expand Down
2 changes: 0 additions & 2 deletions src/agents/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ pub mod token_admin;

use std::marker::{Send, Sync};

use crate::settings::parameters::Fixed;

/// Universal agent methods for interacting with the simulation environment or
/// loop.
/// Agents are expected to be both [`Send`] and [`Sync`].
Expand Down
16 changes: 8 additions & 8 deletions src/agents/price_changer.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::agents::*;
use crate::settings::{parameters::GBMParameters, SimulationConfig};
use crate::settings::{GBMParameters, SimulationConfig};
use arbiter_core::bindings::liquid_exchange::LiquidExchange;
use arbiter_core::environment::Environment;
use arbiter_core::math::{float_to_wad, GeometricBrownianMotion, StochasticProcess, Trajectories};
Expand Down Expand Up @@ -29,15 +29,15 @@ impl PriceChanger {
pub async fn new(
environment: &Environment,
token_admin: &token_admin::TokenAdmin,
config: &SimulationConfig<Fixed>,
config: &SimulationConfig,
) -> Result<Self> {
let client = RevmMiddleware::new(environment, "price_changer".into())?;
let liquid_exchange = LiquidExchange::deploy(
client,
(
token_admin.arbx.address(),
token_admin.arby.address(),
float_to_wad(config.trajectory.initial_price.0),
float_to_wad(config.trajectory.initial_price),
),
)?
.send()
Expand All @@ -54,11 +54,11 @@ impl PriceChanger {
let trajectory_params = &config.trajectory;
let trajectory = match trajectory_params.process.as_str() {
"gbm" => {
let GBMParameters { drift, volatility } = config.gbm.unwrap();
GeometricBrownianMotion::new(drift.0, volatility.0).seedable_euler_maruyama(
trajectory_params.initial_price.0,
trajectory_params.t_0.0,
trajectory_params.t_n.0,
let GBMParameters { drift, volatility } = config.gbm;
GeometricBrownianMotion::new(drift, volatility).seedable_euler_maruyama(
trajectory_params.initial_price,
trajectory_params.t_0,
trajectory_params.t_n,
trajectory_params.num_steps,
1,
false,
Expand Down
22 changes: 6 additions & 16 deletions src/config/counter.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
simulation = "Counter"
output_directory = "analysis/counter"
output_file_name = "output"

[trajectory]
# The type of price process to use.
Expand All @@ -11,28 +12,17 @@ seed = 10
# The number of distinct paths to use
num_paths = 10
# The initial price of the asset.
[trajectory.initial_price]
fixed = 1.0
initial_price = 1.0
# The start time of the process.
[trajectory.t_0]
fixed = 0.0
t_0 = 0.0
# The end time of the process.
[trajectory.t_n]
fixed = 10.0
t_n = 10.0

[gbm]
# The drift of the process.
[gbm.drift]
fixed = 0.0
# start = -1.0
# end = 1.0
# steps = 11
drift = 0.0
# The volatility of the process.
[gbm.volatility]
# start = 0.1
# end = 1.0
# steps = 10
fixed = 0.5
volatility = 0.5

[block]
timestep_size = 15
22 changes: 6 additions & 16 deletions src/config/gbm.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
simulation = "SimulatedPricePath"
output_directory = "analysis/prices"
output_file_name = "output"

[trajectory]
# The type of price process to use.
Expand All @@ -11,28 +12,17 @@ seed = 10
# The number of distinct paths to use
num_paths = 10
# The initial price of the asset.
[trajectory.initial_price]
fixed = 1.0
initial_price = 1.0
# The start time of the process.
[trajectory.t_0]
fixed = 0.0
t_0 = 0.0
# The end time of the process.
[trajectory.t_n]
fixed = 10.0
t_n = 10.0

[gbm]
# The drift of the process.
[gbm.drift]
fixed = 0.0
# start = -1.0
# end = 1.0
# steps = 11
drift = 0.0
# The volatility of the process.
[gbm.volatility]
# start = 0.1
# end = 1.0
# steps = 10
fixed = 0.5
volatility = 0.5

[block]
timestep_size = 15
28 changes: 24 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use std::time::Instant;
use std::{
fs::{self, DirEntry},
time::Instant,
};

use anyhow::Result;
use clap::{ArgAction, CommandFactory, Parser, Subcommand};
Expand Down Expand Up @@ -29,7 +32,7 @@ struct Args {
enum Commands {
/// Represents the `Bind` subcommand.
Simulate {
#[clap(index = 1, default_value = "src/config/gbm.toml")]
#[clap(index = 1, default_value = "src/config/")]
config_path: String,
},
}
Expand All @@ -47,7 +50,7 @@ enum Commands {
/// $ cargo run simulate [path_to_config]
/// ```
///
/// By default, if no configuration path is provided, it will read from "src/config/gbm.toml".
/// By default, if no configuration path is provided, it will read from "src/config/".
///
/// These simulations are performed in Arbiter's in memory revm instance and with the exposed RevmMiddleware.
fn main() -> Result<()> {
Expand All @@ -58,11 +61,28 @@ fn main() -> Result<()> {
println!("Reading from config path: {}", config_path);
let start = Instant::now();
// This is the entry point for the simulation
simulations::batch(config_path)?;
let files = read_toml_files(config_path)?;
println!("files: {:?}", files);
simulations::batch(files)?;
let duration = start.elapsed();
println!("Total duration of simulations: {:?}", duration);
}
None => Args::command().print_long_help()?,
}
Ok(())
}

// Function to read .toml files from a directory and return their paths
fn read_toml_files(dir: &str) -> Result<Vec<String>, std::io::Error> {
let paths = fs::read_dir(dir)?
.filter_map(Result::ok)
.filter(is_toml_file)
.map(|entry| entry.path().to_string_lossy().into_owned())
.collect();
Ok(paths)
}

// Helper function to check if a DirEntry is a .toml file
fn is_toml_file(entry: &DirEntry) -> bool {
entry.path().extension().map_or(false, |ext| ext == "toml")
}
107 changes: 51 additions & 56 deletions src/settings/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
pub mod parameters;

use parameters::*;

use crate::simulations::SimulationType;
use config::{Config, ConfigError};
use serde::{Deserialize, Serialize};
Expand All @@ -11,82 +7,81 @@ use serde::{Deserialize, Serialize};
/// This struct holds all the necessary parameters and configurations needed to run a simulation.
/// It encompasses several sub-configurations such as `TrajectoryParameters` and `GBMParameters`.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SimulationConfig<P: Parameterized<f64>> {
pub struct SimulationConfig {
/// The type of simulation to run, defined by an enum `SimulationType`.
pub simulation: SimulationType,

/// Maximum number of parallel simulations to run.
pub max_parallel: Option<usize>,

/// Directory where the simulation output will be stored.
pub output_directory: String,

/// Name of the file where the simulation results will be written.
pub output_file_name: Option<String>,
pub output_file_name: String,

/// Parameters specific to the trajectory of the simulation.
pub trajectory: TrajectoryParameters<P>,
pub trajectory: TrajectoryParameters,

/// Parameters specific to the Geometric Brownian Motion (GBM) if applicable.
pub gbm: Option<GBMParameters<P>>,
pub gbm: GBMParameters,

/// Parameters related to block configurations.
pub block: BlockParameters,
}

impl SimulationConfig<Meta> {
impl SimulationConfig {
/// Creates a new `SimulationConfig` instance from a configuration file.
///
/// Reads the specified configuration file and deserializes it into a `SimulationConfig` object.
/// The `config_path` is the path to the configuration file in question.
pub fn new(config_path: &str) -> Result<Self, ConfigError> {
pub fn new(config_path: String) -> Result<Self, ConfigError> {
let s = Config::builder()
.add_source(config::File::with_name(config_path))
.add_source(config::File::with_name(&config_path))
.build()?;
s.try_deserialize()
}
}

impl Parameterized<SimulationConfig<Fixed>> for SimulationConfig<Meta> {
/// Generates a list of `SimulationConfig` instances with fixed parameters.
///
/// This method is responsible for taking the meta parameters defined in the configuration,
/// generating the actual fixed parameters, and creating a list of complete `SimulationConfig` instances.
fn generate(&self) -> Vec<SimulationConfig<Fixed>> {
let mut result = vec![];
let trajectories = self.trajectory.generate();

let gbms = self
.gbm
.as_ref()
.map(|gbm| gbm.generate())
.unwrap_or_default();

if gbms.is_empty() {
panic!("You must supply either a gbm configuration.");
}

for trajectory in &trajectories {
for gbm in &gbms {
let output_directory = self.output_directory.clone()
+ "/gbm_drift="
+ &gbm.drift.0.to_string()
+ "_vol="
+ &gbm.volatility.0.to_string();
let output_file_name =
format!("trajectory={}", trajectory.output_tag.clone().unwrap());
result.push(SimulationConfig {
simulation: self.simulation,
max_parallel: None,
output_directory,
output_file_name: Some(output_file_name),
trajectory: trajectory.clone(),
gbm: Some(*gbm),
block: self.block,
});
}
}

result
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
pub struct BlockParameters {
pub timestep_size: u64,
}

/// Defines parameters for a trajectory in the simulation.
///
/// Contains information like initial price, start and end times,
/// and number of steps and paths in the simulation.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TrajectoryParameters {
/// The name.
pub process: String,

/// The initial price of the asset.
pub initial_price: f64,

/// The start time of the process.
pub t_0: f64,

/// The end time of the process.
pub t_n: f64,

/// The number of steps in the process.
pub num_steps: usize,

/// The number of paths in the process.
pub num_paths: usize,

/// The seed for the process.
pub seed: u64,

/// The tag for the output file.
pub output_tag: Option<String>,
}

/// Contains the parameters for the Geometric Brownian Motion (GBM) process.
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
pub struct GBMParameters {
// The drift of the process.
pub drift: f64,

// The volatility of the process.
pub volatility: f64,
}
Loading

0 comments on commit ab6f4c6

Please sign in to comment.