{"id":17946502,"url":"https://github.com/janrockdev/rust-exchange","last_synced_at":"2025-08-12T22:36:50.812Z","repository":{"id":259673075,"uuid":"879053338","full_name":"janrockdev/rust-exchange","owner":"janrockdev","description":"Rust Exchange Sandpit in Rust with gRPC","archived":false,"fork":false,"pushed_at":"2025-07-19T15:28:03.000Z","size":403,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-19T19:21:00.949Z","etag":null,"topics":["rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"cc-by-sa-4.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/janrockdev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-10-26T20:50:15.000Z","updated_at":"2024-10-31T21:15:28.000Z","dependencies_parsed_at":"2025-02-09T03:30:21.019Z","dependency_job_id":"3a523c87-f046-4d43-a2e7-5da8a07c74a1","html_url":"https://github.com/janrockdev/rust-exchange","commit_stats":null,"previous_names":["janrockdev/rust-exchange"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/janrockdev/rust-exchange","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janrockdev%2Frust-exchange","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janrockdev%2Frust-exchange/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janrockdev%2Frust-exchange/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janrockdev%2Frust-exchange/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/janrockdev","download_url":"https://codeload.github.com/janrockdev/rust-exchange/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janrockdev%2Frust-exchange/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270148077,"owners_count":24535693,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-12T02:00:09.011Z","response_time":80,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["rust"],"created_at":"2024-10-29T07:05:54.011Z","updated_at":"2025-08-12T22:36:50.674Z","avatar_url":"https://github.com/janrockdev.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Rust Exchange Sandpit in Rust with gRPC\n\n[![Rust](https://github.com/janrockdev/rust-exchange/actions/workflows/rust.yml/badge.svg)](https://github.com/janrockdev/rust-exchange/actions/workflows/rust.yml)\n\n## Description\nThis simple Rust Exchange provides an example of implementation of a cryptocurrency orderbook with live connectivity to real crypto exchange. It has also option to run in --offline mode and use predefined orderbook to support testing and e.g., UI build. It supports real-time order matching for market and limit orders. Designed for performance and scalability, this project leverages Rust's memory safety and concurrency features to ensure high reliability and low latency. Key features include:\n\nFinal version will:\n- Order Matching Engine: Handles various order types (limit, market) with high precision and speed from gRPC client CLI.\n- Real-time Updates: Ensures immediate reflection of order book changes and market data.\n- Concurrency: Utilizes Rust's async capabilities to process multiple transactions simultaneously.\n- Ideal for developers looking to build high-performance trading systems and applications in the cryptocurrency space.\n\nCurrent version:\n- gRPC-based server\n    - with periodic orderbook update from Kraken exchange using public API\n    - orderbook data stored in in-memory cache with persistency to a disk\n    - trade matching engine with logic to process market and limit order only (stop/cancel in progress)\n- gRPC-based client\n    - with sections for:\n        - price updates\n        - orderbook preview\n        - trade execution\n        - tradebook preview (in progress)\n        - support to tradebook per trader (in progress)\n\n## Extended version (private repo) with real-time dashboard\n\n![dashboard](https://github.com/janrockdev/rust-exchange/blob/main/dashboard.png)\n\n## TODO (backlog)\n- [ ] review ordering for limit orders\n- [ ] aggregation of orders by price for preview (remove id, ts)\n- [ ] more tests\n- [ ] profiling \u003e\u003e perf + flamegraph / tokio-console/TSan\n- [ ] performance test \u003e\u003e criterion/wrk(http)\n- [x] add all to Github Actions (CI/CD)\n\n## Configuration\n\nConfiguration in config.yaml file (root folder / example):\n```\nkraken:\n  symbols: [\"XETHZUSD\", \"SUIUSD\", \"XXBTZUSD\"] # pair to collect\n  persist: \"data\" # path to persist orderbook + trade snapshots for testing purpose\n  offline: [\"data/offline/XXBTZUSD_order_book.csv\", \"data/offline/XETHZUSD_order_book.csv\", \"data/offline/SUIUSD_order_book.csv\"] # path for offline testing orderbooks\n```\n\n## Tests\n```shell\nexport RUST_LOG=debug\ncargo test -- --nocapture\n```\n\n### Demo\n```shell\n# 1) run sever in offline mode\nexport RUST_LOG=debug\ncargo run --bin server -- --offline\n\n# output\nOffline mode enabled: Loading order books from CSV files.\n[2024-10-23T20:20:15Z INFO  server] Loaded order for XXBTZUSD: Price: 65303.20000, Volume: 0.001, Side: ask, ID: aebe5fde-5a35-4d82-8f54-18963ff07bc4, Timestamp: 2024-06-18T14:54:27.946288646+00:00\n[2024-10-23T20:20:15Z INFO  server] Loaded order for XXBTZUSD: Price: 65296.70000, Volume: 0.375, Side: ask, ID: 4c578c60-753e-43a9-9a60-6cc8895e9704, Timestamp: 2024-06-18T14:54:27.946288646+00:00\n[2024-10-23T20:20:15Z INFO  server] Loaded order for XXBTZUSD: Price: 65294.50000, Volume: 1.500, Side: ask, ID: 6f715879-5ac1-4201-912a-88c021a7b69b, Timestamp: 2024-06-18T14:54:27.946288646+00:00\n[2024-10-23T20:20:15Z INFO  server] Loaded order for XXBTZUSD: Price: 65290.60000, Volume: 0.004, Side: ask, ID: 752ff333-d5b4-44ef-a008-6881ccd17f2c, Timestamp: 2024-06-18T14:54:27.946288646+00:00\n[2024-10-23T20:20:15Z INFO  server] Loaded order for XXBTZUSD: Price: 65290.10000, Volume: 15.633, Side: ask, ID: ec7739a5-b43f-45ec-9aed-b314641bc7e9, Timestamp: 2024-06-18T14:54:27.946288646+00:00\n[2024-10-23T20:20:15Z INFO  server] Loaded order for XXBTZUSD: Price: 65290.00000, Volume: 0.040, Side: bid, ID: f6dc7cfd-f985-4d3b-883b-ca8936f682c2, Timestamp: 2024-06-18T14:54:27.946288646+00:00\n[2024-10-23T20:20:15Z INFO  server] Loaded order for XXBTZUSD: Price: 65279.40000, Volume: 0.082, Side: bid, ID: d67d153c-b0fc-405a-bd5e-113b53cb54ce, Timestamp: 2024-06-18T14:54:27.946288646+00:00\n[2024-10-23T20:20:15Z INFO  server] Loaded order for XXBTZUSD: Price: 65279.30000, Volume: 0.001, Side: bid, ID: 925e5f92-dfda-47bd-94d2-33b824da8b17, Timestamp: 2024-06-18T14:54:27.946288646+00:00\n[2024-10-23T20:20:15Z INFO  server] Loaded order for XXBTZUSD: Price: 65249.90000, Volume: 0.375, Side: bid, ID: 094c50c4-48eb-4e9a-ae30-1cff6849218e, Timestamp: 2024-06-18T14:54:27.946288646+00:00\n[2024-10-23T20:20:15Z INFO  server] Loaded order for XXBTZUSD: Price: 65238.60000, Volume: 0.008, Side: bid, ID: 01c979ef-2a50-4ddd-b612-db7c75174ab4, Timestamp: 2024-06-18T14:54:27.946288646+00:00\n\n# 2) run client with trade\ncargo run --bin client market-order XXBTZUSD 1.4 buy market 0.0 Rock\n\n# output\nProcessing order for trader: Rock\nOrderbook status before processing trade: ----\nPrice: 65303.20000, Volume: 0.001, Side: ask, ID: aebe5fde-5a35-4d82-8f54-18963ff07bc4, Timestamp: 2024-06-18T14:54:27.946288646+00:00\nPrice: 65296.70000, Volume: 0.375, Side: ask, ID: 4c578c60-753e-43a9-9a60-6cc8895e9704, Timestamp: 2024-06-18T14:54:27.946288646+00:00\nPrice: 65294.50000, Volume: 1.500, Side: ask, ID: 6f715879-5ac1-4201-912a-88c021a7b69b, Timestamp: 2024-06-18T14:54:27.946288646+00:00\nPrice: 65290.60000, Volume: 0.004, Side: ask, ID: 752ff333-d5b4-44ef-a008-6881ccd17f2c, Timestamp: 2024-06-18T14:54:27.946288646+00:00\nPrice: 65290.10000, Volume: 15.633, Side: ask, ID: ec7739a5-b43f-45ec-9aed-b314641bc7e9, Timestamp: 2024-06-18T14:54:27.946288646+00:00\nPrice: 65290.00000, Volume: 0.040, Side: bid, ID: f6dc7cfd-f985-4d3b-883b-ca8936f682c2, Timestamp: 2024-06-18T14:54:27.946288646+00:00\nPrice: 65279.40000, Volume: 0.082, Side: bid, ID: d67d153c-b0fc-405a-bd5e-113b53cb54ce, Timestamp: 2024-06-18T14:54:27.946288646+00:00\nPrice: 65279.30000, Volume: 0.001, Side: bid, ID: 925e5f92-dfda-47bd-94d2-33b824da8b17, Timestamp: 2024-06-18T14:54:27.946288646+00:00\nPrice: 65249.90000, Volume: 0.375, Side: bid, ID: 094c50c4-48eb-4e9a-ae30-1cff6849218e, Timestamp: 2024-06-18T14:54:27.946288646+00:00\nPrice: 65238.60000, Volume: 0.008, Side: bid, ID: 01c979ef-2a50-4ddd-b612-db7c75174ab4, Timestamp: 2024-06-18T14:54:27.946288646+00:00\n----------------------------------------------\n\nMatched order: price: 65290.1, volume: 15.633, side: ask, timestamp: 2024-06-18T14:54:27.946288646+00:00, order_type: limit, id: ec7739a5-b43f-45ec-9aed-b314641bc7e9\nOrder partially matched, remaining volume updated: Order { id: ec7739a5-b43f-45ec-9aed-b314641bc7e9, price: OrderedFloat(65290.1), volume: OrderedFloat(14.232999999999999), side: \"ask\", timestamp: \"2024-06-18T14:54:27.946288646+00:00\", order_type: \"limit\" }\n\nOrderbook status after processing trade: -----\nPrice: 65303.20000, Volume: 0.001, Side: ask, ID: aebe5fde-5a35-4d82-8f54-18963ff07bc4, Timestamp: 2024-06-18T14:54:27.946288646+00:00\nPrice: 65296.70000, Volume: 0.375, Side: ask, ID: 4c578c60-753e-43a9-9a60-6cc8895e9704, Timestamp: 2024-06-18T14:54:27.946288646+00:00\nPrice: 65294.50000, Volume: 1.500, Side: ask, ID: 6f715879-5ac1-4201-912a-88c021a7b69b, Timestamp: 2024-06-18T14:54:27.946288646+00:00\nPrice: 65290.60000, Volume: 0.004, Side: ask, ID: 752ff333-d5b4-44ef-a008-6881ccd17f2c, Timestamp: 2024-06-18T14:54:27.946288646+00:00\nPrice: 65290.10000, Volume: 14.233, Side: ask, ID: ec7739a5-b43f-45ec-9aed-b314641bc7e9, Timestamp: 2024-06-18T14:54:27.946288646+00:00\nPrice: 65290.00000, Volume: 0.040, Side: bid, ID: f6dc7cfd-f985-4d3b-883b-ca8936f682c2, Timestamp: 2024-06-18T14:54:27.946288646+00:00\nPrice: 65279.40000, Volume: 0.082, Side: bid, ID: d67d153c-b0fc-405a-bd5e-113b53cb54ce, Timestamp: 2024-06-18T14:54:27.946288646+00:00\nPrice: 65279.30000, Volume: 0.001, Side: bid, ID: 925e5f92-dfda-47bd-94d2-33b824da8b17, Timestamp: 2024-06-18T14:54:27.946288646+00:00\nPrice: 65249.90000, Volume: 0.375, Side: bid, ID: 094c50c4-48eb-4e9a-ae30-1cff6849218e, Timestamp: 2024-06-18T14:54:27.946288646+00:00\nPrice: 65238.60000, Volume: 0.008, Side: bid, ID: 01c979ef-2a50-4ddd-b612-db7c75174ab4, Timestamp: 2024-06-18T14:54:27.946288646+00:00\n----------------------------------------------\n```\n\n## Build\n```shell\ncargo build --release\n```\n\n## Run (development)\n\n### Server (development)\n\nRun server in offline mode with orderbooks from snapshots for development:\n```shell\n# server\nexport RUST_LOG=debug\ncargo run --bin server -- --offline\n```\n\n### Server (development)\n```shell\n# set the right level of logging\nexport RUST_LOG=info\ncargo run --bin server\n```\n\n### Client (development)\n```shell\n# set the right level of logging\nexport RUST_LOG=info\ncargo run --bin client market-order XXBTZUSD 1.4 buy market 0.0 Rock\ncargo run --bin client market-order XXBTZUSD 1.4 sell market 0.0 Rock\ncargo run --bin client market-order XXBTZUSD 1.4 buy limit 65248.0 Rock\ncargo run --bin client market-order XXBTZUSD 1.4 sell limit 65248.0 Rock\n```\n\n```shell\n# trader's trades\ncargo run --bin client retrieve-trades Rock\n# example\nTrades for trader Rock:\nID: e006b2dd-1183-44f3-9231-62b6ea969c0f, Pair: XXBTZUSD, Side: buy, Price: 65290.09, Volume: 16, Timestamp: 2024-06-19T21:12:07.214014409+00:00, Id: e006b2dd-1183-44f3-9231-62b6ea969c0f, Status: new\nID: bc59817c-acb3-4b6d-a91c-5dae967bbcc7, Pair: XXBTZUSD, Side: ask, Price: 65290.1, Volume: 15.633, Timestamp: 2024-06-19T21:12:07.214395802+00:00, Id: bc59817c-acb3-4b6d-a91c-5dae967bbcc7, Status: filled\nID: c8e3d3da-5d4c-479b-84bb-b1ad5dd66c47, Pair: XXBTZUSD, Side: ask, Price: 65290.6, Volume: 0.004, Timestamp: 2024-06-19T21:12:07.214430880+00:00, Id: c8e3d3da-5d4c-479b-84bb-b1ad5dd66c47, Status: filled\nID: 4b80e237-5db6-4e96-b677-98b32574716b, Pair: XXBTZUSD, Side: ask, Price: 65294.5, Volume: 1.1369999999999991, Timestamp: 2024-06-19T21:12:07.214461156+00:00, Id: 4b80e237-5db6-4e96-b677-98b32574716b, Status: partially_filled\n\n```\n\n## Architeture decisions\n- HashMap performance is O(1), while BTreeMap performance is O(log N), however we have just 2 keys and doing a lot insert/delete/lookup where HashMap should be better.\n- Ordered_float crate in Rust that provides a way to handle f64 and f32 floating-point numbers with total ordering. The standard f64 and f32 types in Rust do not implement the Ord trait because floating-point numbers do not have a total order due to the presence of special values like NaN (Not a Number). OrderedFloat solves this problem by providing a total order for floating-point numbers.\n\n## Notes\n\n### Trade status\n- New: The order has been received by the exchange but has not yet been processed or entered into the order book.\n- Pending: The order is under review or awaiting certain conditions before it can be entered into the order book.\n- Open: The order is active and has been entered into the order book. It is waiting to be matched with a counter order.\n- Partially Filled: Part of the order has been matched and executed, but the entire order is not yet fully completed. The remaining portion remains open in the order book.\n- Filled: The entire order has been matched and executed. There is no remaining quantity left in the order.\n- Canceled: The order has been canceled by the trader or broker and will not be executed. This can happen before the order is fully or partially filled.\n- Rejected: The order has been rejected by the exchange, possibly due to insufficient funds, incorrect order details, or violation of trading rules.\n- Expired: The order has expired based on the time conditions set (e.g., good for day orders that are not filled by the end of the trading day).\n- Pending Cancel: A cancellation request has been submitted for the order, but it has not yet been confirmed or processed.\n- Pending Replace: A modification request has been submitted for the order (e.g., change in quantity or price), but it has not yet been confirmed or processed.\n\n### Trade Status Flow\nNew -\u003e Pending -\u003e Open \nOpen -\u003e Partially Filled -\u003e Filled\nOpen -\u003e Canceled\nPending -\u003e Rejected\nOpen -\u003e Expired\n\n### Generic Archicture\n\n```mermaid\nflowchart LR\n    Trader --\u003e Broker\n    Broker --\u003e Order_Transmission\n    Order_Transmission --\u003e Exchange\n    Exchange \u003c--\u003e Account_Management\n    Exchange \u003c--\u003e Tradebook\n    Exchange \u003c--\u003e Orderbook\n    Exchange \u003c--\u003e Marching_Engine\n    Exchange \u003c--\u003e Clearing\n    Clearing \u003c--\u003e Settlement\n```\n\n### Code Base:\n#### Client:\n```mermaid\nsequenceDiagram\n    participant Trader\n    participant CLI\n    participant OrderBookClient\n    participant OrderBookService\n\n    Trader-\u003e\u003eCLI: Execute Trading-CLI command\n    CLI-\u003e\u003eCLI: Parse command-line arguments\n\n    alt MarketOrder\n        CLI-\u003e\u003eOrderBookClient: connect(\"http://[::1]:50051\")\n        OrderBookClient-\u003e\u003eCLI: Connected to Server\n        CLI-\u003e\u003eOrderBookClient: place_market_order(OrderRequest)\n        OrderBookClient-\u003e\u003eOrderBookService: Forward OrderRequest\n        OrderBookService-\u003e\u003eOrderBookClient: OrderResponse\n        OrderBookClient-\u003e\u003eCLI: Order Response\n\n    else RetrieveTrades\n        CLI-\u003e\u003eOrderBookClient: connect(\"http://[::1]:50051\")\n        OrderBookClient-\u003e\u003eCLI: Connected to Server\n        CLI-\u003e\u003eOrderBookClient: get_trade_book(TradeBookRequest)\n        OrderBookClient-\u003e\u003eOrderBookService: Forward TradeBookRequest\n        OrderBookService-\u003e\u003eOrderBookClient: TradeBookResponse\n        OrderBookClient-\u003e\u003eCLI: Trade Book Response\n        CLI-\u003e\u003eTrader: Display trades for trader\n    end\n\n```\n\n#### Server:\n```mermaid\nsequenceDiagram\n    participant Trader\n    participant CLI\n    participant OrderBookService\n    participant OrderBookClient\n    participant OrderBookServer\n    participant OrderBookAPI\n    participant TradeBook\n    \n    Trader-\u003e\u003eCLI: Execute command\n    CLI-\u003e\u003eOrderBookClient: Send OrderRequest\n    OrderBookClient-\u003e\u003eOrderBookService: Forward OrderRequest\n    OrderBookService-\u003e\u003eOrderBook: Place order in OrderBook\n    OrderBookService-\u003e\u003eTradeBook: Record trade with status \"new\"\n    \n    alt MarketOrder\n        OrderBookService-\u003e\u003eOrderBook: Match and execute orders\n        OrderBook-\u003e\u003eTradeBook: Update trade status to \"filled\" or \"partially_filled\"\n    end\n\n    alt Retrieve OrderBook\n        CLI-\u003e\u003eOrderBookClient: Send OrderBookRequest\n        OrderBookClient-\u003e\u003eOrderBookService: Forward OrderBookRequest\n        OrderBookService-\u003e\u003eOrderBook: Fetch orders\n        OrderBook-\u003e\u003eOrderBookService: Return OrderBookResponse\n        OrderBookService-\u003e\u003eOrderBookClient: Return OrderBookResponse\n        OrderBookClient-\u003e\u003eCLI: Display OrderBookResponse\n    end\n\n    alt Retrieve TradeBook\n        CLI-\u003e\u003eOrderBookClient: Send TradeBookRequest\n        OrderBookClient-\u003e\u003eOrderBookService: Forward TradeBookRequest\n        OrderBookService-\u003e\u003eTradeBook: Fetch trades\n        TradeBook-\u003e\u003eOrderBookService: Return TradeBookResponse\n        OrderBookService-\u003e\u003eOrderBookClient: Return TradeBookResponse\n        OrderBookClient-\u003e\u003eCLI: Display TradeBookResponse\n    end\n\n    loop Update OrderBooks\n        OrderBookService-\u003e\u003eOrderBookAPI: Fetch order books\n        OrderBookAPI-\u003e\u003eOrderBookService: Return updated order books\n        OrderBookService-\u003e\u003eOrderBook: Update order books\n    end\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjanrockdev%2Frust-exchange","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjanrockdev%2Frust-exchange","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjanrockdev%2Frust-exchange/lists"}