matching_engine/
lib.rs

1extern crate log;
2
3use std::{env, io, process};
4use std::io::BufRead;
5use std::sync::mpsc::{Receiver, Sender};
6use std::thread::sleep;
7use std::time::Duration;
8
9use colored::Colorize;
10use log::{error, info};
11
12use crate::common::utils;
13use crate::matchers::fifo_matcher::FIFOMatcher;
14use crate::matchers::matcher::Matcher;
15use crate::matchers::prorata_matcher::ProrataMatcher;
16use crate::model::domain::OrderBook;
17
18pub mod model;
19pub mod matchers;
20pub mod formatters;
21pub mod common;
22
23
24
25
26pub struct CmdArgs {
27    pub file_path: String,
28    pub algo: String,
29}
30
31fn print_help() {
32    println!("Usage:");
33    println!("If using cargo:");
34    println!("cargo -- -h for help");
35    println!("cargo run <Enter> for starting without an orderbook or algo param");
36    println!("cargo run -- <order_file_path> <algo(FIFO|PRO>");
37    println!();
38    println!("If using executable:");
39    println!("exchange_simulator <Enter> for starting without an orderbook or algo param");
40    println!("exchange_simulator.exe -h for help");
41    println!("exchange_simulator.exe <order_file+path> <algo(FIFO|PRO>");
42    process::exit(0);
43}
44///This function sits in a loop accepting user input for matching until the user quits
45/// User inputs are added to the order book and sent to the matcher for matching
46pub fn start_user(tx: &Sender<OrderBook>, rx: &Receiver<OrderBook>, file_path: String) {
47    if file_path == "-h" {
48        print_help();
49    }
50    let input = utils::read_input(&file_path);
51    let mut ob = utils::create_order_book(input);
52    if let Err(e) = tx.send(ob) {
53        error!("Error sending file {}",e);
54    }
55    sleep(Duration::from_secs(1));
56    loop {
57        let mut order_book = match rx.recv() {
58            Ok(ob) => ob,
59            Err(e) => {
60                error!("Error receiving order book {}",e);
61                OrderBook::default()
62            }
63        };
64
65        order_book.pretty_print_self();
66        println!("Enter an order({} ) to match  or {} to quit","<id> <symbol> <qty> <price> <side(Buy|Sell)>".bold().reversed(), "q".bold().red());
67        println!("");
68        let mut line = String::new();
69        io::stdin().read_line(&mut line).unwrap();
70        if line.chars().nth(0) == Some('q') {
71            process::exit(0);
72        }
73        let order = utils::create_order_from_string(line.trim_end().to_string());
74        order_book.add_order_to_order_book(order);
75        if let Err(e) = tx.send(order_book) {
76            error!("Error sending order book {}",e);
77        };
78        sleep(Duration::from_secs(1));
79    }
80}
81
82/// creates the matcher based on the algo and starts the matcher which spins in a loop matching the order book as and when available
83/// C
84pub fn start_matcher(tx: &Sender<OrderBook>, rx: &Receiver<OrderBook>, algo: String) {
85    if algo == "PRO" {
86        let mut matcher = ProrataMatcher;
87        matcher.start(&tx, &rx);
88    } else {
89        let mut matcher = FIFOMatcher;
90        matcher.start(&tx, &rx);
91    }
92}
93
94pub fn get_cmd_args() -> Result<CmdArgs, &'static str> {
95    let mut args = env::args();
96    args.next();
97    let file_path = match args.next() {
98        Some(path) => path,
99        None => return Err("No order file provided"),
100    };
101
102    let algo = match args.next() {
103        Some(arg) => arg,
104        None => String::from("FIFO")
105    };
106
107    let cmd_args = CmdArgs {
108        file_path: file_path,
109        algo: algo,
110    };
111    Ok(cmd_args)
112}
113
114
115