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 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322
//! # Barter
//! [`Barter`] is an open-source Rust framework for building **event-driven live-trading & backtesting systems**.
//! Algorithmic trade with the peace of mind that comes from knowing your strategies have been
//! backtested with a near-identical trading Engine.
//! It is:
//! * **Fast**: Barter provides a multi-threaded trading Engine framework built in high-performance Rust (in-rust-we-trust).
//! * **Easy**: Barter provides a modularised data architecture that focuses on simplicity.
//! * **Customisable**: A set of traits define how every Barter component communicates, providing a highly extensible
//! framework for trading.
//!
//! See [`Readme`].
//!
//! ## Overview
//! Barter is an open-source Rust framework for building **event-driven live-trading & backtesting systems**. It provides
//! a high-performance, easy to customise, trading Engine that enables backtesting strategies on a near-identical system
//! to live trading. The Engine can be **controlled by issuing Commands** over the Engine's command_tx. Similarly,
//! the **Engine's Events can be listened to using the event_rx** (useful for event-sourcing). At a high level,
//! it provides several de-coupled components that interact via a set of traits:
//! * **Data**: Continuer & MarketGenerator traits govern the generation of a MarketEvents data feed that acts as the system
//! heartbeat. For example, a LiveCandleHandler implementation is provided utilising [`Barter-Data`]'s WebSocket functionality to
//! provide a live market Candle data feed to the system.
//! * **Strategy**: The SignalGenerator trait governs potential generation of SignalEvents after analysing incoming
//! MarketEvents. SignalEvents are advisory signals sent to the Portfolio for analysis.
//! * **Portfolio**: MarketUpdater, OrderGenerator, and FillUpdater govern global state Portfolio implementations. A
//! Portfolio may generate OrderEvents after receiving advisory SignalEvents from a Strategy. The Portfolio's state
//! updates after receiving MarketEvents and FillEvents.
//! * **Execution**: The FillGenerator trait governs the generation of FillEvents after receiving OrderEvents from the
//! Portfolio. For example, a SimulatedExecution handler implementation is provided for simulating any exchange execution
//! behaviour required in dry-trading or backtesting runs.
//! * **Statistic**: Provides metrics such as Sharpe Ratio, Calmar Ratio, and Max Drawdown to analyse trading session
//! performance. One-pass dispersion algorithms analyse each closed Position and efficiently calculates a trading summary.
//! * **Trader**: Capable of trading a single market pair using a customisable selection of it's own Data, Strategy &
//! Execution instances, as well as shared access to a global Portfolio.
//! * **Engine**: Multi-threaded trading Engine capable of trading with an arbitrary number of Trader market pairs. Each
//! contained Trader instance operates on its own thread.
//!
//! [`Barter`]: https://gitlab.com/open-source-keir/financial-modelling/trading/barter-rs
//! [`Barter-Data`]: https://crates.io/crates/barter-data
//! [`Readme`]: https://crates.io/crates/barter
//!
//! ## Getting Started
//! ### Data Handler
//! ```
//!
//!
//! use barter::data::{Feed, historical, MarketGenerator};
//! use barter_data::test_util::market_trade;
//! use barter_integration::model::Side;
//!
//! let mut data = historical::MarketFeed::new([market_trade(Side::Buy)].into_iter());
//!
//! loop {
//! let market_event = match data.generate() {
//! Feed::Next(market_event) => market_event,
//! Feed::Finished => break,
//! Feed::Unhealthy => continue,
//! };
//! }
//! ```
//!
//! ### Strategy
//! ```
//! use barter::{
//! strategy::{SignalGenerator, example::{Config as StrategyConfig, RSIStrategy}},
//! };
//! use barter_data::{
//! test_util,
//! model::{MarketEvent }
//! };
//! use barter_integration::model::Side;
//!
//! let config = StrategyConfig {
//! rsi_period: 14,
//! };
//!
//! let mut strategy = RSIStrategy::new(config);
//!
//! let market_event = test_util::market_trade(Side::Buy);
//!
//! let signal_event = strategy.generate_signal(&market_event);
//! ```
//!
//! ### Portfolio
//! ```
//! use barter::{
//! portfolio::{
//! MarketUpdater, OrderGenerator, FillUpdater,
//! portfolio::{PortfolioLego, MetaPortfolio},
//! repository::in_memory::InMemoryRepository,
//! allocator::DefaultAllocator,
//! risk::DefaultRisk,
//! },
//! statistic::summary::{
//! pnl::PnLReturnSummary,
//! trading::{Config as StatisticConfig, TradingSummary},
//! },
//! event::Event,
//! test_util,
//! };
//! use barter_integration::model::{Market, InstrumentKind};
//! use std::marker::PhantomData;
//! use uuid::Uuid;
//!
//! let components = PortfolioLego {
//! engine_id: Uuid::new_v4(),
//! markets: vec![Market::new("binance", ("btc", "usdt", InstrumentKind::Spot))],
//! repository: InMemoryRepository::new(),
//! allocator: DefaultAllocator{ default_order_value: 100.0 },
//! risk: DefaultRisk{},
//! starting_cash: 10000.0,
//! statistic_config: StatisticConfig {
//! starting_equity: 10000.0 ,
//! trading_days_per_year: 365,
//! risk_free_return: 0.0
//! },
//! _statistic_marker: PhantomData::<TradingSummary>::default()
//! };
//!
//! let mut portfolio = MetaPortfolio::init(components).unwrap();
//!
//! let some_event = Event::OrderNew(test_util::order_event());
//!
//! match some_event {
//! Event::Market(market) => {
//! portfolio.update_from_market(&market);
//! }
//! Event::Signal(signal) => {
//! portfolio.generate_order(&signal);
//! }
//! Event::SignalForceExit(signal) => {
//! portfolio.generate_exit_order(signal);
//! }
//! Event::Fill(fill) => {
//! portfolio.update_from_fill(&fill);
//! }
//! _ => {}
//! }
//! ```
//!
//! ### Execution
//! ```
//! use barter::{
//! test_util,
//! portfolio::OrderEvent,
//! execution::{
//! simulated::{Config as ExecutionConfig, SimulatedExecution},
//! Fees, ExecutionClient,
//! }
//! };
//!
//! let config = ExecutionConfig {
//! simulated_fees_pct: Fees {
//! exchange: 0.1,
//! slippage: 0.05, // Simulated slippage modelled as a Fee
//! network: 0.0,
//! }
//! };
//!
//! let mut execution = SimulatedExecution::new(config);
//!
//! let order_event = test_util::order_event();
//!
//! let fill_event = execution.generate_fill(&order_event);
//! ```
//!
//! ### Statistic
//! ```
//! use barter::{
//! test_util,
//! portfolio::position::Position,
//! statistic::summary::{
//! trading::{Config as StatisticConfig, TradingSummary},
//! Initialiser, PositionSummariser, TableBuilder
//! }
//! };
//!
//! // Do some automated trading with barter components that generates a vector of closed Positions
//! let positions = vec![test_util::position(), test_util::position()];
//!
//! let config = StatisticConfig {
//! starting_equity: 10000.0,
//! trading_days_per_year: 253,
//! risk_free_return: 0.5,
//! };
//!
//! let mut trading_summary = TradingSummary::init(config);
//!
//! trading_summary.generate_summary(&positions);
//!
//! trading_summary
//! .table("Total")
//! .printstd();
//! ```
//!
//! ### Engine & Traders
//! [See Readme Engine Example](https://crates.io/crates/barter#example)
#![warn(
unused,
missing_debug_implementations,
missing_copy_implementations,
rust_2018_idioms,
// missing_docs
)]
/// Defines a MarketEvent, and provides the Continuer and MarketGenerator traits for
/// handling the generation of them. Contains implementations such as the (tick-by_tick)
/// LiveTradeHandler, and HistoricalCandleHandler that generates a market feed and acts as the
/// system heartbeat.
pub mod data;
/// Defines a SignalEvent and SignalForceExit, as well as the SignalGenerator trait for handling the
/// generation of them. Contains an example RSIStrategy implementation that analyses a MarketEvent
/// and may generate a new advisory SignalEvent to be analysed by the Portfolio OrderGenerator.
pub mod strategy;
/// Defines useful data structures such as an OrderEvent and Position. The Portfolio must
/// interact with MarketEvents, SignalEvents, OrderEvents, and FillEvents. The useful traits
/// MarketUpdater, OrderGenerator, & FillUpdater are provided that define the interactions
/// with these events. Contains a MetaPortfolio implementation that persists state in a
/// generic Repository. This also contains example implementations of an OrderAllocator &
/// OrderEvaluator, which help the Portfolio make decisions on whether to generate OrderEvents and
/// of what size.
pub mod portfolio;
/// Defines a FillEvent, and provides a useful trait FillGenerator for handling the generation
/// of them. Contains an example SimulatedExecution implementation that simulates live broker
/// execution.
pub mod execution;
/// Defines an Event enum that contains variants that are vital to the trading event loop
/// (eg/ MarketEvent). Other variants communicate work done by the system (eg/ FillEvent), as well
/// as changes in system state (eg/ PositionUpdate).
pub mod event;
/// Defines various iterative statistical methods that can be used to calculate trading performance
/// metrics in one-pass. A trading performance summary implementation has been provided containing
/// several key metrics such as Sharpe Ratio, Calmar Ratio, and Max Drawdown.
pub mod statistic;
/// Multi-threaded trading Engine capable of trading with an arbitrary number market pairs. Contains
/// a Trader for each Market pair that consists of it's own Data, Strategy &
/// Execution components, as well as shared access to a global Portfolio.
pub mod engine;
#[macro_use]
extern crate prettytable;
pub mod test_util {
use crate::{
data::MarketMeta,
execution::{Fees, FillEvent},
portfolio::{position::Position, OrderEvent, OrderType},
strategy::{Decision, Signal},
};
pub use barter_data::test_util::{market_candle, market_trade};
use barter_integration::model::{Exchange, Instrument, InstrumentKind, Side};
use chrono::Utc;
/// Build a [`Signal`].
pub fn signal() -> Signal {
Signal {
time: Utc::now(),
exchange: Exchange::from("binance"),
instrument: Instrument::from(("btc", "usdt", InstrumentKind::Spot)),
signals: Default::default(),
market_meta: Default::default(),
}
}
/// Build an [`OrderEvent`] to buy 1.0 contract.
pub fn order_event() -> OrderEvent {
OrderEvent {
time: Utc::now(),
exchange: Exchange::from("binance"),
instrument: Instrument::from(("eth", "usdt", InstrumentKind::Spot)),
market_meta: MarketMeta::default(),
decision: Decision::default(),
quantity: 1.0,
order_type: OrderType::default(),
}
}
/// Build a [`FillEvent`] for a single bought contract.
pub fn fill_event() -> FillEvent {
FillEvent {
time: Utc::now(),
exchange: Exchange::from("binance"),
instrument: Instrument::from(("eth", "usdt", InstrumentKind::Spot)),
market_meta: Default::default(),
decision: Decision::default(),
quantity: 1.0,
fill_value_gross: 100.0,
fees: Fees::default(),
}
}
/// Build a [`Position`].
pub fn position() -> Position {
Position {
position_id: "engine_id_trader_{}_{}_position".to_owned(),
exchange: Exchange::from("binance"),
instrument: Instrument::from(("eth", "usdt", InstrumentKind::Spot)),
meta: Default::default(),
side: Side::Buy,
quantity: 1.0,
enter_fees: Default::default(),
enter_fees_total: 0.0,
enter_avg_price_gross: 100.0,
enter_value_gross: 100.0,
exit_fees: Default::default(),
exit_fees_total: 0.0,
exit_avg_price_gross: 0.0,
exit_value_gross: 0.0,
current_symbol_price: 100.0,
current_value_gross: 100.0,
unrealised_profit_loss: 0.0,
realised_profit_loss: 0.0,
}
}
}