# TLI (Terminal Line Interface) Usage Guide Welcome to the Foxhunt TLI usage guide. This document provides comprehensive information on how to use the TLI client library to interact with the Foxhunt High-Frequency Trading system. ## Table of Contents 1. [Quick Start](#quick-start) 2. [Installation](#installation) 3. [Basic Usage](#basic-usage) 4. [Configuration](#configuration) 5. [API Reference](#api-reference) 6. [Examples](#examples) 7. [Testing](#testing) 8. [Performance](#performance) 9. [Troubleshooting](#troubleshooting) 10. [Best Practices](#best-practices) ## Quick Start ```rust use tli::prelude::*; use tli::TliClient; #[tokio::main] async fn main() -> TliResult<()> { // Create and connect to TLI client let mut client = TliClient::new(); client.connect().await?; // Check system health let health = client.check_health().await?; println!("System status: {:?}", health); // Disconnect when done client.disconnect().await; Ok(()) } ``` ## Installation Add TLI to your `Cargo.toml`: ```toml [dependencies] tli = { path = "../tli" } # Local development # or when published: # tli = "0.1.0" # Required async runtime tokio = { version = "1.0", features = ["full"] } # For logging (recommended) tracing = "0.1" tracing-subscriber = "0.3" ``` ## Basic Usage ### Creating a Client ```rust use tli::{TliClient, ServiceEndpoints}; // Default endpoints (from environment variables or defaults) let client = TliClient::new(); // Custom endpoints let endpoints = ServiceEndpoints { trading_engine: "http://localhost:50052".to_string(), risk_management: "http://localhost:50053".to_string(), ml_signals: "http://localhost:50054".to_string(), market_data: "http://localhost:50055".to_string(), health_check: "http://localhost:50056".to_string(), }; let client = TliClient::with_endpoints(endpoints); ``` ### Connecting to Services ```rust let mut client = TliClient::new(); // Connect to all services client.connect().await?; // Check connection status let health_status = client.check_health().await?; for status in health_status { println!("{}: {} ({})", status.service, status.status, status.endpoint); } ``` ### Order Management ```rust use tli::proto::trading::*; // Submit an order let order_request = SubmitOrderRequest { symbol: "AAPL".to_string(), side: OrderSide::Buy as i32, order_type: OrderType::Market as i32, quantity: 100.0, price: Some(150.0), }; let trading_client = client.trading()?; let response = trading_client .submit_order(tonic::Request::new(order_request)) .await?; println!("Order submitted: {}", response.into_inner().order_id); // List orders let list_request = ListOrdersRequest { symbol: "".to_string(), // All symbols limit: Some(10), }; let response = trading_client .list_orders(tonic::Request::new(list_request)) .await?; for order in response.into_inner().orders { println!("Order: {} - {} {} @ ${}", order.order_id, order.symbol, order.quantity, order.price); } ``` ### Real-time Streaming ```rust use tokio_stream::StreamExt; // Start order updates stream let request = StreamOrderUpdatesRequest {}; let response = trading_client .stream_order_updates(tonic::Request::new(request)) .await?; let mut stream = response.into_inner(); // Process updates while let Some(update) = stream.next().await { match update { Ok(order_update) => { println!("Order update: {} - Status: {}", order_update.order_id, order_update.status); } Err(e) => { eprintln!("Stream error: {}", e); break; } } } ``` ### Configuration Management ```rust // Get configuration let config_client = client.config()?; let get_request = GetConfigRequest { key: "max_order_size".to_string(), }; let response = config_client .get_config(tonic::Request::new(get_request)) .await?; if let Some(config) = response.into_inner().config { println!("Config: {} = {}", config.key, config.value); } // Set configuration let set_request = SetConfigRequest { key: "trading_enabled".to_string(), value: "true".to_string(), config_type: "boolean".to_string(), description: "Enable trading operations".to_string(), }; let response = config_client .set_config(tonic::Request::new(set_request)) .await?; println!("Config updated: {}", response.into_inner().message); ``` ### Monitoring and Metrics ```rust // Get system status let monitoring_client = client.monitoring()?; let status_request = GetSystemStatusRequest {}; let response = monitoring_client .get_system_status(tonic::Request::new(status_request)) .await?; for service in response.into_inner().services { println!("Service: {} - Status: {}", service.name, service.status); } // Get metrics let metrics_request = GetMetricsRequest { metric_names: vec![ "latency_p99".to_string(), "orders_per_second".to_string(), ], }; let response = monitoring_client .get_metrics(tonic::Request::new(metrics_request)) .await?; for metric in response.into_inner().metrics { println!("Metric: {} = {} {}", metric.name, metric.value, metric.unit); } ``` ## Configuration ### Environment Variables TLI can be configured using environment variables: ```bash # Service endpoints export FOXHUNT_TRADING_ENGINE_URL="http://localhost:50052" export FOXHUNT_RISK_MANAGEMENT_URL="http://localhost:50053" export FOXHUNT_ML_SIGNALS_URL="http://localhost:50054" export FOXHUNT_MARKET_DATA_URL="http://localhost:50055" export FOXHUNT_HEALTH_CHECK_URL="http://localhost:50056" # Logging export RUST_LOG="info" # Testing export TLI_ENABLE_RT_TESTS="true" ``` ### Connection Timeouts ```rust use std::time::Duration; use tonic::transport::Endpoint; // Custom timeout configuration (when building endpoints manually) let channel = Endpoint::from_shared("http://localhost:50052")? .timeout(Duration::from_secs(10)) .connect_timeout(Duration::from_secs(5)) .connect() .await?; ``` ## API Reference ### Core Types ```rust // Re-exported from the prelude use tli::prelude::*; // Main client pub struct TliClient { /* ... */ } // Service endpoints configuration pub struct ServiceEndpoints { pub trading_engine: String, pub risk_management: String, pub ml_signals: String, pub market_data: String, pub health_check: String, } // Error types pub enum TliError { Connection(String), InvalidRequest(String), InvalidSymbol(String), NotConnected(String), } pub type TliResult = Result; ``` ### Client Methods ```rust impl TliClient { // Creation pub fn new() -> Self; pub fn with_endpoints(endpoints: ServiceEndpoints) -> Self; // Connection management pub async fn connect(&mut self) -> TliResult<()>; pub async fn disconnect(&mut self); pub async fn check_health(&mut self) -> TliResult>; // Service access pub fn trading(&mut self) -> TliResult<&mut TradingServiceClient>; pub fn monitoring(&mut self) -> TliResult<&mut MonitoringServiceClient>; pub fn config(&mut self) -> TliResult<&mut ConfigServiceClient>; } ``` ### Utility Functions ```rust // Timestamp conversions pub fn unix_nanos_to_system_time(nanos: i64) -> SystemTime; pub fn system_time_to_unix_nanos(time: SystemTime) -> i64; pub fn current_unix_nanos() -> i64; // Validation pub fn validate_symbol(symbol: &str) -> TliResult<()>; pub fn validate_quantity(quantity: f64) -> TliResult<()>; pub fn validate_price(price: f64) -> TliResult<()>; // Type conversions pub fn order_side_to_string(side: OrderSide) -> &'static str; pub fn string_to_order_side(side: &str) -> TliResult; pub fn order_type_to_string(order_type: OrderType) -> &'static str; pub fn string_to_order_type(order_type: &str) -> TliResult; ``` ## Examples ### Basic Dashboard Run the basic dashboard example: ```bash # Basic dashboard with default settings cargo run --example basic_dashboard # Custom configuration cargo run --example basic_dashboard custom # Connection test only cargo run --example basic_dashboard test ``` Features: - Real-time system status display - Order and position counts - Automatic reconnection - Terminal-based UI ### Configuration Management Run the configuration management example: ```bash # Basic configuration operations cargo run --example config_management basic # Configuration validation demo cargo run --example config_management validation # Search and filtering cargo run --example config_management search # Interactive editor cargo run --example config_management interactive ``` Features: - Configuration CRUD operations - Validation with custom rules - Category-based organization - Search and filtering - Sensitive data masking ### Real-time Streaming Run the streaming example: ```bash # Basic streaming (requires running services) cargo run --example real_time_streaming basic # High-frequency data handling cargo run --example real_time_streaming highfreq # Error handling and recovery cargo run --example real_time_streaming errors # Backpressure handling cargo run --example real_time_streaming backpressure ``` Features: - Multiple concurrent streams - High-frequency data processing - Error handling and recovery - Backpressure management - Real-time aggregation ## Testing ### Running Tests ```bash # Unit tests cargo test # Integration tests cargo test --test integration # Property-based tests cargo test --features proptest # With real-time tests (requires services) TLI_ENABLE_RT_TESTS=true cargo test ``` ### Mock Server Testing ```bash # Start mock servers for testing cargo test --test integration -- --nocapture # Test with specific mock port TEST_MOCK_PORT=51000 cargo test ``` ### Property-Based Testing The TLI library includes property-based tests using `proptest`: ```rust proptest! { #[test] fn test_timestamp_conversion_property(timestamp in 0i64..i64::MAX/2) { let system_time = unix_nanos_to_system_time(timestamp); let converted = system_time_to_unix_nanos(system_time); prop_assert!((converted - timestamp).abs() < 1000); } } ``` ## Performance ### Benchmarking Run performance benchmarks: ```bash # All benchmarks cargo bench # Specific benchmark suites cargo bench --bench configuration_benchmarks cargo bench --bench client_performance cargo bench --bench serialization_benchmarks # With HTML reports cargo bench -- --output-format html ``` ### Performance Characteristics Based on benchmarks, TLI provides: - **Timestamp conversions**: < 100ns per operation - **Validation operations**: < 50ns per validation - **Type conversions**: < 10ns per conversion - **Protobuf serialization**: ~1-10μs depending on message size - **JSON serialization**: ~5-50μs depending on message size ### Optimization Tips 1. **Reuse clients**: Create TLI clients once and reuse them 2. **Batch operations**: Use streaming for high-frequency data 3. **Connection pooling**: Share connections across multiple operations 4. **Async programming**: Use `tokio::spawn` for concurrent operations 5. **Buffer sizing**: Tune channel buffer sizes for your workload ```rust // Good: Reuse client let mut client = TliClient::new(); client.connect().await?; for _ in 0..1000 { let _ = client.check_health().await?; } // Better: Batch operations let health_checks = (0..1000).map(|_| client.check_health()); let results = futures::future::join_all(health_checks).await; ``` ## Troubleshooting ### Common Issues #### Connection Refused ``` Error: Connection(Connection refused) ``` **Solution**: Ensure Foxhunt services are running and accessible: ```bash # Check if services are running curl http://localhost:50052/health netstat -ln | grep 50052 # Check environment variables echo $FOXHUNT_TRADING_ENGINE_URL ``` #### Service Not Connected ``` Error: NotConnected(Trading service not connected) ``` **Solution**: Call `connect()` before using services: ```rust let mut client = TliClient::new(); client.connect().await?; // Required before using services let trading_client = client.trading()?; ``` #### Invalid Symbol ``` Error: InvalidSymbol(Symbol contains invalid characters) ``` **Solution**: Use valid symbol format: ```rust // Valid symbols validate_symbol("AAPL")?; // ✓ validate_symbol("BTC.USD")?; // ✓ validate_symbol("EUR-USD")?; // ✓ // Invalid symbols validate_symbol("BTC/USD")?; // ✗ - slash not allowed validate_symbol("")?; // ✗ - empty not allowed ``` #### Timeout Errors ``` Error: Connection(Request timeout) ``` **Solution**: Increase timeouts or check network connectivity: ```rust // Custom timeout configuration let endpoints = ServiceEndpoints { trading_engine: "http://slow-server:50052".to_string(), // ... other endpoints }; let client = TliClient::with_endpoints(endpoints); ``` ### Debug Logging Enable debug logging for troubleshooting: ```bash # Enable debug logs export RUST_LOG=debug cargo run --example basic_dashboard # Trace-level logging (very verbose) export RUST_LOG=trace cargo run --example basic_dashboard ``` ```rust // In code tracing_subscriber::fmt() .with_max_level(tracing::Level::DEBUG) .init(); ``` ### Performance Issues If experiencing performance issues: 1. **Check network latency**: ```bash ping trading-engine-host traceroute trading-engine-host ``` 2. **Monitor resource usage**: ```bash # CPU and memory usage top -p $(pgrep your-app) # Network connections ss -tuln | grep :50052 ``` 3. **Profile your application**: ```bash # Use perf for profiling perf record -g cargo run --release --example basic_dashboard perf report ``` ## Best Practices ### Error Handling Always handle errors appropriately: ```rust // Good: Proper error handling match client.check_health().await { Ok(health) => { // Process health status for status in health { if status.status.contains("ERROR") { warn!("Service {} has issues: {}", status.service, status.status); } } } Err(TliError::Connection(msg)) => { error!("Connection failed: {}", msg); // Implement retry logic } Err(TliError::NotConnected(msg)) => { warn!("Not connected: {}", msg); // Attempt reconnection } Err(e) => { error!("Unexpected error: {}", e); } } ``` ### Resource Management Properly manage connections and resources: ```rust // Good: Explicit disconnection { let mut client = TliClient::new(); client.connect().await?; // Use client... client.disconnect().await; // Explicit cleanup } // Better: Use RAII pattern struct TradingSession { client: TliClient, } impl TradingSession { async fn new() -> TliResult { let mut client = TliClient::new(); client.connect().await?; Ok(Self { client }) } } impl Drop for TradingSession { fn drop(&mut self) { // Note: async drop not available, use explicit cleanup // or spawn a task for async cleanup } } ``` ### Concurrent Operations Use async properly for concurrent operations: ```rust // Good: Concurrent health checks for multiple clients let clients = vec![client1, client2, client3]; let health_checks = clients.iter_mut() .map(|client| client.check_health()); let results = futures::future::join_all(health_checks).await; // Better: Use spawn for truly parallel operations let tasks: Vec<_> = clients.into_iter() .map(|mut client| tokio::spawn(async move { client.check_health().await })) .collect(); let results = futures::future::join_all(tasks).await; ``` ### Validation Always validate input data: ```rust // Validate before submitting orders fn validate_order_request(request: &SubmitOrderRequest) -> TliResult<()> { validate_symbol(&request.symbol)?; validate_quantity(request.quantity)?; if let Some(price) = request.price { validate_price(price)?; } Ok(()) } // Use in order submission validate_order_request(&order_request)?; let response = trading_client.submit_order(tonic::Request::new(order_request)).await?; ``` ### Configuration Management Use environment-specific configuration: ```rust // Environment-aware configuration fn get_endpoints_for_env() -> ServiceEndpoints { match std::env::var("ENVIRONMENT").as_deref() { Ok("production") => ServiceEndpoints { trading_engine: "https://prod-trading.company.com".to_string(), // ... production endpoints }, Ok("staging") => ServiceEndpoints { trading_engine: "https://staging-trading.company.com".to_string(), // ... staging endpoints }, _ => ServiceEndpoints::default(), // Development defaults } } ``` ### Monitoring and Observability Implement proper monitoring: ```rust use tracing::{info, warn, error, instrument}; #[instrument] async fn submit_order_with_monitoring( client: &mut TliClient, request: SubmitOrderRequest, ) -> TliResult { let start = std::time::Instant::now(); match client.trading()?.submit_order(tonic::Request::new(request)).await { Ok(response) => { let elapsed = start.elapsed(); info!("Order submitted successfully in {:?}", elapsed); Ok(response.into_inner().order_id) } Err(e) => { let elapsed = start.elapsed(); error!("Order submission failed after {:?}: {}", elapsed, e); Err(TliError::Connection(e.to_string())) } } } ``` --- ## Additional Resources - [TLI API Documentation](https://docs.rs/tli) (when published) - [Foxhunt System Documentation](../docs/) - [gRPC Documentation](https://grpc.io/docs/) - [Tokio Documentation](https://tokio.rs/) - [Tracing Documentation](https://tracing.rs/) ## Support For support and questions: 1. Check the [troubleshooting section](#troubleshooting) 2. Review the [examples](#examples) 3. Run the test suite to verify your setup 4. Check the logs with debug logging enabled ## Contributing When contributing to TLI: 1. Run the full test suite: `cargo test` 2. Run benchmarks: `cargo bench` 3. Check code formatting: `cargo fmt` 4. Run clippy: `cargo clippy` 5. Update documentation as needed --- *Last updated: 2025-01-21*