Expand description
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.
Getting Started
Data Handler
use barter::{data::{Feed, historical, MarketGenerator}, test_util};
use barter_integration::model::Side;
let mut data = historical::MarketFeed::new([test_util::market_event_trade(Side::Buy)].into_iter());
loop {
let market_event = match data.next() {
Feed::Next(market_event) => market_event,
Feed::Finished => break,
Feed::Unhealthy => continue,
};
}
Strategy
use barter::{
strategy::{SignalGenerator, example::{Config as StrategyConfig, RSIStrategy}},
test_util,
};
use barter_integration::model::Side;
let config = StrategyConfig {
rsi_period: 14,
};
let mut strategy = RSIStrategy::new(config);
let market_event = test_util::market_event_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, instrument::kind::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
Modules
- 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.
- 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.
- 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).
- 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.
- 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.
- 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.
- 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.