Documentation Index
Fetch the complete documentation index at: https://mintlify.com/dhir1007/nanoARB/llms.txt
Use this file to discover all available pages before exploring further.
Overview
NanoARB uses Rust’s type-safe error handling with the Result type. All errors implement the thiserror::Error trait for consistent error messages and conversions.
Error Type
The core Error enum defines all possible error conditions.
Definition
#[derive(Error, Debug, Clone)]
pub enum Error {
#[error("Invalid price: {0}")]
InvalidPrice(String),
#[error("Invalid quantity: {0}")]
InvalidQuantity(String),
#[error("Invalid order ID: {0}")]
InvalidOrderId(String),
#[error("Invalid timestamp: {0}")]
InvalidTimestamp(String),
#[error("Invalid instrument: {0}")]
InvalidInstrument(String),
#[error("Order not found: {0}")]
OrderNotFound(u64),
#[error("Insufficient liquidity at price {price} for quantity {quantity}")]
InsufficientLiquidity {
price: String,
quantity: String,
},
#[error("Risk limit exceeded: {0}")]
RiskLimitExceeded(String),
#[error("Parse error: {0}")]
ParseError(String),
#[error("Configuration error: {0}")]
ConfigError(String),
#[error("I/O error: {0}")]
IoError(String),
#[error("Serialization error: {0}")]
SerializationError(String),
#[error("Model inference error: {0}")]
ModelError(String),
#[error("Internal error: {0}")]
Internal(String),
}
Result Type
A type alias for convenience.
pub type Result<T> = std::result::Result<T, Error>;
Error Variants
InvalidPrice
Returned when a price value is invalid.
return Err(Error::InvalidPrice("negative value".to_string()));
Common causes:
- Negative prices where not allowed
- Price exceeds maximum allowed value
- Invalid price format in parsing
InvalidQuantity
Returned when a quantity value is invalid.
if qty == 0 {
return Err(Error::InvalidQuantity("quantity cannot be zero".to_string()));
}
Common causes:
- Zero quantity for orders
- Quantity exceeds maximum
- Invalid quantity format
InvalidOrderId
Returned when an order ID is invalid.
return Err(Error::InvalidOrderId("order ID must be positive".to_string()));
InvalidTimestamp
Returned when a timestamp value is invalid.
return Err(Error::InvalidTimestamp("timestamp in the future".to_string()));
Common causes:
- Timestamps in the future (when not allowed)
- Timestamps before Unix epoch (when not allowed)
- Invalid timestamp format
InvalidInstrument
Returned when an instrument identifier is invalid.
return Err(Error::InvalidInstrument(
format!("unknown instrument: {}", symbol)
));
Common causes:
- Unknown instrument symbol
- Instrument not configured
- Invalid instrument ID
OrderNotFound
Returned when an order cannot be found.
return Err(Error::OrderNotFound(order_id.value()));
Common causes:
- Attempting to cancel non-existent order
- Querying order that was never created
- Order ID typo
InsufficientLiquidity
Returned when there’s not enough liquidity to fill an order.
return Err(Error::InsufficientLiquidity {
price: format!("{}", price),
quantity: format!("{}", qty),
});
Common causes:
- Market order larger than available liquidity
- Thin order book
- Attempting to fill at specific price level with insufficient depth
RiskLimitExceeded
Returned when a risk limit is breached.
return Err(Error::RiskLimitExceeded(
format!("position {} exceeds max {}", position, max_position)
));
Common causes:
- Position limit exceeded
- Order size too large
- Drawdown limit breached
- Daily loss limit hit
ParseError
Returned when parsing fails.
return Err(Error::ParseError(
format!("failed to parse timestamp: {}", s)
));
Common causes:
- Invalid data format
- Malformed configuration
- Corrupt market data
ConfigError
Returned when configuration is invalid.
return Err(Error::ConfigError(
"missing required field 'instrument_id'".to_string()
));
Common causes:
- Missing configuration fields
- Invalid configuration values
- Conflicting configuration options
IoError
Returned when I/O operations fail.
// Automatically converted from std::io::Error
let file = File::open("data.bin")?;
Common causes:
- File not found
- Permission denied
- Disk full
- Network connection lost
SerializationError
Returned when serialization/deserialization fails.
// Automatically converted from bincode::Error or serde_json::Error
let data = bincode::serialize(&order)?;
Common causes:
- Invalid data format
- Version mismatch
- Corrupt data
ModelError
Returned when ML model inference fails.
return Err(Error::ModelError(
"model input shape mismatch".to_string()
));
Common causes:
- Invalid input shape
- Model not loaded
- Inference timeout
- GPU out of memory
Internal
Returned for unexpected internal errors.
return Err(Error::Internal(
"unexpected state: order book empty".to_string()
));
Common causes:
- Invariant violations
- Unexpected state
- Programming errors
Error Handling Patterns
Basic Error Handling
use nano_core::{Error, Result};
fn submit_order(order: Order) -> Result<OrderId> {
// Validate order
if order.quantity.is_zero() {
return Err(Error::InvalidQuantity(
"quantity cannot be zero".to_string()
));
}
// Submit order
Ok(order.id)
}
// Usage
match submit_order(order) {
Ok(order_id) => println!("Order submitted: {}", order_id),
Err(e) => eprintln!("Failed to submit order: {}", e),
}
Using the ? Operator
The ? operator propagates errors up the call stack.
fn process_fill(fill: &Fill) -> Result<()> {
let order = get_order(fill.order_id)?; // Propagates Error::OrderNotFound
update_position(order.side, fill.quantity)?;
calculate_pnl(fill)?;
Ok(())
}
Error Context
Add context to errors for better debugging.
fn load_config(path: &str) -> Result<Config> {
let contents = std::fs::read_to_string(path)
.map_err(|e| Error::IoError(
format!("failed to read config from {}: {}", path, e)
))?;
let config: Config = serde_json::from_str(&contents)
.map_err(|e| Error::ConfigError(
format!("invalid config format: {}", e)
))?;
Ok(config)
}
Handling Specific Errors
match submit_order(order) {
Ok(order_id) => {
println!("Order {} submitted", order_id);
}
Err(Error::RiskLimitExceeded(msg)) => {
eprintln!("Risk check failed: {}", msg);
// Maybe retry with smaller size
}
Err(Error::InsufficientLiquidity { price, quantity }) => {
eprintln!("Not enough liquidity at {} for {}", price, quantity);
// Maybe adjust price
}
Err(e) => {
eprintln!("Order submission failed: {}", e);
}
}
Converting Errors
Standard library errors are automatically converted.
use std::io;
use nano_core::Result;
fn read_data(path: &str) -> Result<Vec<u8>> {
// io::Error is automatically converted to Error::IoError
let data = std::fs::read(path)?;
Ok(data)
}
fn deserialize_order(data: &[u8]) -> Result<Order> {
// bincode::Error is automatically converted to Error::SerializationError
let order = bincode::deserialize(data)?;
Ok(order)
}
Logging Errors
use log::{error, warn};
fn handle_fill(fill: &Fill) -> Result<()> {
if let Err(e) = process_fill(fill) {
match e {
Error::OrderNotFound(id) => {
warn!("Order {} not found, possibly already processed", id);
}
Error::RiskLimitExceeded(ref msg) => {
error!("Risk limit exceeded: {}", msg);
// Trigger emergency procedures
trigger_kill_switch();
}
_ => {
error!("Failed to process fill: {}", e);
}
}
return Err(e);
}
Ok(())
}
Custom Error Creation
impl RiskManager {
fn check_order(&self, order: &Order, position: i64) -> Result<()> {
// Check order size
if order.quantity.value() > self.max_order_size {
return Err(Error::RiskLimitExceeded(
format!(
"Order size {} exceeds maximum {}",
order.quantity.value(),
self.max_order_size
)
));
}
// Check resulting position
let new_position = position +
(order.quantity.as_i64() * order.side.sign());
if new_position.abs() > self.max_position {
return Err(Error::RiskLimitExceeded(
format!(
"Resulting position {} would exceed maximum {}",
new_position.abs(),
self.max_position
)
));
}
Ok(())
}
}
Best Practices
1. Use Descriptive Error Messages
// Good
Err(Error::InvalidPrice(
format!("price {} exceeds maximum {}", price, MAX_PRICE)
))
// Bad
Err(Error::InvalidPrice("invalid".to_string()))
2. Include Context
// Good
Err(Error::OrderNotFound(
format!("order {} not found in active orders", order_id)
))
// Better - but OrderNotFound already takes u64
Err(Error::OrderNotFound(order_id.value()))
3. Handle Errors Appropriately
// Don't ignore errors
let _ = submit_order(order); // Bad!
// Handle or propagate
submit_order(order)?; // Propagate
// Or handle explicitly
if let Err(e) = submit_order(order) {
log::error!("Failed to submit: {}", e);
return Err(e);
}
4. Log Before Returning
fn critical_operation() -> Result<()> {
if let Err(e) = risky_operation() {
error!("Critical operation failed: {}", e);
return Err(e);
}
Ok(())
}
5. Use Result Type Consistently
// Good - consistent use of Result
fn validate_order(order: &Order) -> Result<()> { ... }
fn submit_order(order: Order) -> Result<OrderId> { ... }
// Avoid mixing Option and Result without good reason