| Crates.io | slouch |
| lib.rs | slouch |
| version | 0.0.3 |
| created_at | 2025-10-17 17:54:42.208482+00 |
| updated_at | 2025-11-12 09:13:23.030146+00 |
| description | Simple OUCH 5.0 client & message types for order entry. |
| homepage | |
| repository | https://github.com/j-stach/slouch |
| max_upload_size | |
| id | 1888021 |
| size | 107,584 |
Simple OUCH 5.0 client for communication of orders to NASDAQ.
Contains strong types for order-related messages and a simple client to send and receive them.
This crate should be presumed experimental and non-functional until integration testing has been completed. If you are willing and able to assist with integration testing, please leave a response under this issue.
slouch to your Rust project (v2024 or more recent):cargo add slouch
OuchClient to handle order entry by wrapping a TCP stream that is
already logged in to an OUCH account.
When the client is created, it will attempt to query the account.
Setup will fail if an AccountQueryResponse is not received from the server.use std::net::{ SocketAddr, TcpStream };
use slouch::OuchClient;
let mut stream = TcpStream::connect(SocketAddr::new(
/* IP address */,
/* Port number */
));
// TODO: Login to your account as described during OUCH onboarding.
let mut client = OuchClient::new(stream).unwrap();
OuchResponse is an enum that can be matched to extract message values.use slouch::account_query;
use slouch::msg::OuchResponse::*;
let request = account_query!();
client.send(request).unwrap();
let response = client.recv().unwrap();
match response {
AccountQueryResponse(aqr) => {
let _time: chrono::NaiveTime = aqr.timestamp();
let _num: UserRefNum = aqr.next_user_ref_num();
let _opts: &Vec<TagValue> = aqr.options();
},
_ => {/* Do something else */}
}
OuchRequest has a macro to simplify message creation. use slouch::{ enter, types::* };
let request = enter!{
user_ref_num: client.new_user_ref_num(),
side: Side::Buy,
quantity: 69u32,
symbol: StockSymbol::from("STONKS").unwrap(),
price: Price::new(35000u64).unwrap(),
time_in_force: TimeInForce::Day,
display: Display::Visible,
capacity: Capacity::Agency,
intermarket_sweep: false,
cross_type: CrossType::Opening,
order_token: OrderToken::from("To The Moon").unwrap()
};
client.send(request).unwrap();
log crate and can be enabled through the logs feature.
An asynchronous version of the client uses tokio and can be enabled through the async feature.
By default, OuchClient is synchronous and its events are not logged.# Cargo.toml
[dependencies]
slouch = { version = "0.0.0", features = ["logs", "async"] }
OuchRequest and OuchResponse may also be used without an OuchClient.use std::net;
use slouch::{ account_query, msg::OuchResponse };
// OUCH Server port
let addr = net::SocketAddr::new(/* IP address */, /* Port number */);
let mut stream = net::TcpStream::connect(addr).unwrap();
// TODO: Login to your account as described during OUCH onboarding.
let bytes = account_query!().encode();
stream.write_all(&bytes).unwrap();
let mut buf = vec![];
let n = stream.read(&mut buf).unwrap();
let (_buf, response) = OuchResponse::parse(&self.buf[..n]).unwrap();
Development history and current tasks are tracked in TODO.md.
Developer resources:
Contributions are welcome! Submit issues and pull requests to this repository.