1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
//! Discrete event market simulation library
//!
//! Implements a discrete event simulation
//! environment ([Env]) and utilities for writing
//! discrete event market simulations.
//!
//! # Model
//!
//! In the discrete event model the state of
//! the market is updated in fixed size
//! time-steps. Inside each step agents can
//! submit updates/instructions to the
//! the simulated market, which are then processed
//! at the end of the step.
//!
//! Each simulation update performs the following
//! steps:
//!
//! - Iterate over all the agents, updating their
//!   state, and market instructions submitted to
//!   a queue.
//! - The instructions are randomly shuffled, and
//!   then processed in sequence, updating the state
//!   of the market.
//! - Record the state of the market.
//!
//! Hence agents can only observe the state of the
//! market at the end of the previous step when
//! updating, and have no guarantee of the ordering
//! of transactions.
//!
//! See [bourse_book] for details of the limit
//! order-book used in this environment.
//!
//! # Examples
//!
//! ```
//! use bourse_de::types::{Price, Side, Vol};
//! use bourse_de::agents;
//! use bourse_de::agents::Agent;
//! use bourse_de::{sim_runner, Env};
//! use rand::{RngCore, Rng};
//!
//! // Define a set of agents using built
//! // in definitions
//! #[derive(agents::Agents)]
//! struct SimAgents {
//!     pub a: agents::MomentumAgent,
//!     pub b: agents::NoiseAgent,
//! }
//!
//! // Initialise agent parameters
//! let m_params = agents::MomentumParams {
//!     tick_size: 2,
//!     p_cancel: 0.1,
//!     trade_vol: 100,
//!     decay: 1.0,
//!     demand: 5.0,
//!     scale: 0.5,
//!     order_ratio: 1.0,
//!     price_dist_mu: 0.0,
//!     price_dist_sigma: 10.0,
//! };
//!
//! let n_params = agents::NoiseAgentParams{
//!     tick_size: 2,
//!     p_limit: 0.2,
//!     p_market: 0.2,
//!     p_cancel: 0.1,
//!     trade_vol: 100,
//!     price_dist_mu: 0.0,
//!     price_dist_sigma: 1.0,
//! };
//!
//! let mut agents = SimAgents {
//!     a: agents::MomentumAgent::new(0, 10, m_params),
//!     b: agents::NoiseAgent::new(10, 20, n_params),
//! };
//!
//! // Initialise the environment and agents
//! let mut env = Env::new(0, 1, 1_000_000, true);
//!
//! // Run the simulation
//! sim_runner(&mut env, &mut agents, 101, 50, true);
//!
//! // Get history of level 2 data over the course of the simulation
//! let data = env.level_2_data();
//! ```
//!
//! # Implementing Your Own Agents
//!
//! For use in [sim_runner] simulation agents should implement the [agents::AgentSet]
//! trait. For a set of homogeneous agents (i.e. all the agents are the
//! same type) this can be implemented directly.
//!
//! For a mixture of agent types, the [agents::Agents] macro can be used
//! to automatically implement [agents::AgentSet] for a struct of agents
//! all implementing [agents::Agent]. For examples
//!
//! ```
//! use bourse_de::{Env, sim_runner};
//! use bourse_de::agents::{Agent, AgentSet, Agents};
//! use rand::RngCore;
//!
//! struct AgentTypeA{}
//!
//! impl Agent for AgentTypeA{
//!     fn update<R: RngCore>(
//!         &mut self, env: &mut bourse_de::Env, rng: &mut R
//!     ) {}
//! }
//!
//! struct AgentTypeB{}
//!
//! impl Agent for AgentTypeB{
//!     fn update<R: RngCore>(
//!         &mut self, env: &mut bourse_de::Env, rng: &mut R
//!     ) {}
//! }
//!
//! #[derive(Agents)]
//! struct SimAgents {
//!     pub a: AgentTypeA,
//!     pub b: AgentTypeB,
//! }
//!
//! let mut env = bourse_de::Env::new(0, 1, 1_000_000, true);
//! let mut agents = SimAgents{a: AgentTypeA{}, b: AgentTypeB{}};
//!
//! sim_runner(&mut env, &mut agents, 101, 50, true);
//! ```
//!
//! # Randomness
//!
//! To ensure simulations are deterministic (given a random seed)
//! random generators (that implement the [rand::RngCore] trait) are
//! passed to agents during the simulation. The [rand_distr] crate
//! can be used to sample from common distributions.
//!

pub mod agents;
mod env;
mod runner;

pub use bourse_book::{types, OrderError};
pub use env::Env;
pub use runner::sim_runner;