#trading #backtesting #investment #stock #crypto

barter

构建事件驱动实时交易与回测引擎的框架

51 个版本

0.8.15 2024 年 7 月 12 日
0.8.13 2023 年 4 月 16 日
0.8.12 2023 年 2 月 18 日
0.8.6 2022 年 12 月 3 日
0.1.0 2021 年 3 月 27 日

#backtesting 中排名 6

每月 29 次下载

MIT 许可证

310KB
6.5K SLoC

Barter

Barter 是一个开源的 Rust 框架,用于构建 事件驱动的实时交易与回测系统。通过在近似的交易引擎上对策略进行回测,您可以在算法交易中安心。它是

  • 快速:Barter 提供了一个基于高性能 Rust(in-rust-we-trust)的多线程交易引擎框架。
  • 简单:Barter 提供了一个模块化数据架构,专注于简洁性。
  • 可定制:一系列特质定义了每个 Barter 组件如何通信,提供了一个高度可扩展的交易框架。

请参阅:Barter-DataBarter-IntegrationBarter-Execution

Crates.io MIT licensed Build Status Discord chat

API 文档 | 聊天

概述

Barter 是一个开源的 Rust 框架,用于构建 事件驱动的实时交易与回测系统。它提供了一种高性能、易于定制的交易引擎,使您能够在近似于实时交易的系统中进行策略回测。该引擎可以通过向引擎的 command_tx 发送命令来控制。同样,可以使用 event_rx 监听引擎的事件(对于事件溯源很有用)。从高层次来看,它提供了一些解耦的组件,这些组件通过一系列特质进行交互

  • 数据:MarketGenerator 特质管理 MarketEvents 的生成,该事件作为系统的心跳。例如,提供了 live::MarketFeed 实现,该实现利用 Barter-Data WebSocket 集成来提供实时交易所数据(例如/交易、K线图等)。
  • 策略:SignalGenerator特性负责在分析传入的市场事件后生成信号。信号是建议性的,并发送到投资组合进行分析。
  • 投资组合:MarketUpdater、OrderGenerator和FillUpdater控制全局状态投资组合实现。投资组合在接收到策略的咨询性SignalEvents后可能会生成OrderEvents。投资组合的状态在接收到市场事件和填充事件后更新。
  • 执行:ExecutionClient特性负责在从投资组合接收到OrderEvents后生成FillEvents。例如,提供了一个模拟执行的处理器实现,用于模拟干交易或回测运行中所需的任何交易所执行行为。
  • 统计:提供夏普比率、卡尔玛比率、最大回撤等指标,用于分析交易会话的表现。单遍散度算法分析每个已关闭的头寸,并有效地计算交易摘要。
  • 交易者:能够使用自定义的数据、策略和执行实例进行交易,同时享有对全局投资组合的共享访问权限。
  • 引擎:多线程交易引擎,能够使用任意数量的交易者市场对进行交易。每个包含的交易者实例在自己的线程上运行。

示例

  • 为了简洁:不包含导入 - 请参阅 /examples 获取所需的一切!
  • 为了简单起见:
    • 引擎和交易者(s)通过硬编码的值进行配置,而不是通过配置值加载。
    • 引擎只包含一个交易者(通常您会有很多交易者,每个市场一个)。
    • 远程命令(例如/ Command::Terminate、Command::ExitPosition)不会通过其command_tx发送到引擎,这种对引擎的控制可以根据您的喜好添加(例如连接到HTTP端点)。
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Setup Logger & Load Config For Engine & Trader Instances Here

    // Create channel to distribute Commands to the Engine & it's Traders (eg/ Command::Terminate)
    let (command_tx, command_rx) = mpsc::channel(20);
    
    // Create Event channel to listen to all Engine Events in real-time
    let (event_tx, event_rx) = mpsc::unbounded_channel();
    let event_tx = EventTx::new(event_tx);
    
    // Generate unique identifier to associate an Engine's components
    let engine_id = Uuid::new_v4();
    
    // Create the Market(s) to be traded on (1-to-1 relationship with a Trader)
    let market = Market::new("binance", ("btc", "usdt", InstrumentKind::Spot));
    
    // Build global shared-state MetaPortfolio (1-to-1 relationship with an Engine)
    let portfolio = Arc::new(Mutex::new(
        MetaPortfolio::builder()
            .engine_id(engine_id)
            .markets(vec![market.clone()])
            .starting_cash(10_000.0)
            .repository(InMemoryRepository::new())
            .allocation_manager(DefaultAllocator { default_order_value: 100.0 })
            .risk_manager(DefaultRisk {})
            .statistic_config(StatisticConfig {
                starting_equity: 10_000.0,
                trading_days_per_year: 365,
                risk_free_return: 0.0,
            })
            .build_and_init()
            .expect("failed to build & initialise MetaPortfolio"),
    ));
    
    // Build Trader(s)
    let mut traders = Vec::new();
    
    // Create channel for each Trader so the Engine can distribute Commands to it
    let (trader_command_tx, trader_command_rx) = mpsc::channel(10);

    traders.push(
        Trader::builder()
            .engine_id(engine_id)
            .market(market.clone())
            .command_rx(trader_command_rx)
            .event_tx(event_tx.clone())
            .portfolio(Arc::clone(&portfolio))
            .data(historical::MarketFeed::new([test_util::market_candle].into_iter()))
            .strategy(RSIStrategy::new(StrategyConfig { rsi_period: 14 }))
            .execution(SimulatedExecution::new(ExecutionConfig {
                simulated_fees_pct: Fees {
                        exchange: 0.1,
                        slippage: 0.05,
                        network: 0.0,}
                }))
            .build()
            .expect("failed to build trader")
    );
    
    // Build Engine (1-to-many relationship with Traders)
    
    // Create HashMap<Market, trader_command_tx> so Engine can route Commands to Traders 
    let trader_command_txs = HashMap::from_iter([(market, trader_command_tx)]);
    
    let engine = Engine::builder()
        .engine_id(engine_id)
        .command_rx(command_rx)
        .portfolio(portfolio)
        .traders(traders)
        .trader_command_txs(trader_command_txs)
        .statistics_summary(TradingSummary::init(StatisticConfig {
            starting_equity: 1000.0,
            trading_days_per_year: 365,
            risk_free_return: 0.0
        }))
        .build()
        .expect("failed to build engine");
        
    // Listen to Engine Events & do something with them
    tokio::spawn(listen_to_events(event_rx)); 
        
    // --- Run Trading Session Until Remote Shutdown OR Data Feed ends naturally (ie/ backtest) ---
    engine.run().await;
}

获取帮助

首先,看看您的问题是否可以在API文档中找到。如果答案不在那里,我很乐意通过聊天来帮助您,并通过Discord尝试回答您的问题。

贡献

🎉 感谢您对改善Barter生态系统的帮助!请通过discord联系以讨论开发、新功能和未来的路线图。

除了Barter crate之外,Barter项目还维护

  • Barter-Integration:高性能、低级框架,用于构建灵活的Web集成。
  • Barter-Data:高性能且规范的WebSocket集成,用于领先的加密货币交易所 - 包含电池。
  • Barter-Execution:正在开发中,并将很快集成。

路线图

  • 集成新的"Barter-Execution"库,以提供额外的开箱即用功能,用于执行OrderEvents。
  • 构建策略实用工具,用于聚合逐笔交易和/或蜡烛图到多时间框架数据结构,并提供一个使用实用工具的多时间框架策略示例。
  • 完善MetaPortfolio分配器和风险管理系统。
  • 等等!

许可证

本项目受MIT许可证许可。

贡献

除非您明确声明,否则您提交的任何旨在包含在Barter中的贡献,均应按MIT许可证许可,不附加任何额外条款或条件。

依赖关系

~15–27MB
~403K SLoC