1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
//! Example demonstrating how to submit multiple market orders and monitor order updates.
//!
//! This example connects to TWS/IB Gateway, starts a background thread to monitor order updates,
//! then submits a series of buy and sell orders for AAPL stock with 1 second delays between orders.
//!
//! The `submit_order` method is used to send orders, while `order_update_stream`
//! provides real-time updates about all orders including:
//! - Order status changes
//! - Execution/fill notifications
//! - Commission reports
//! - System messages
use ibapi::{contracts::ContractBuilder, prelude::*};
use std::sync::Arc;
use std::thread;
use std::time::Duration;
fn main() -> Result<(), Box<dyn std::error::Error>> {
env_logger::init();
let symbol = "AAPL";
let client = Arc::new(Client::connect("127.0.0.1:4002", 100).expect("connection failed"));
println!("Connected {client:?}");
// Start background thread to monitor order updates
let monitor_client = client.clone();
let _monitor_handle = thread::spawn(move || {
println!("Starting order monitoring thread...");
match monitor_client.order_update_stream() {
Ok(stream) => {
for update in stream {
match update {
OrderUpdate::OrderStatus(status) => {
println!(
"[Monitor] Order {} Status: {} - Filled: {}/{}",
status.order_id, status.status, status.filled, status.remaining
);
}
OrderUpdate::OpenOrder(open_order) => {
println!(
"[Monitor] Open Order {}: {} {} shares of {} @ {}",
open_order.order_id,
open_order.order.action,
open_order.order.total_quantity,
open_order.contract.symbol,
open_order.order.order_type
);
}
OrderUpdate::ExecutionData(execution) => {
println!(
"[Monitor] Execution: {} {} shares @ {} on {}",
execution.execution.side, execution.execution.shares, execution.execution.price, execution.execution.exchange
);
}
OrderUpdate::CommissionReport(report) => {
println!("[Monitor] Commission: ${} for execution {}", report.commission, report.execution_id);
}
OrderUpdate::Message(message) => {
println!("[Monitor] Message: {}", message.message);
}
}
}
}
Err(e) => {
eprintln!("Error creating order update stream: {}", e);
}
}
});
// Give the monitoring thread time to start
thread::sleep(Duration::from_millis(100));
let contract = ContractBuilder::stock(symbol, "SMART", "USD").build().expect("invalid contract");
// Place a series of buy and sell orders
let order_quantities = vec![
(Action::Buy, 100.0),
(Action::Sell, 50.0),
(Action::Buy, 75.0),
(Action::Sell, 100.0),
(Action::Buy, 25.0),
];
for (i, (action, quantity)) in order_quantities.iter().enumerate() {
let order_id = client.next_order_id();
let order = order_builder::market_order(action.clone(), *quantity);
println!(
"\n[Main] Placing order #{} (ID: {}) - {} {} shares of {}",
i + 1,
order_id,
action,
quantity,
symbol
);
match client.submit_order(order_id, &contract, &order) {
Ok(_) => println!("[Main] Order {} submitted successfully", order_id),
Err(e) => eprintln!("[Main] Failed to submit order {}: {}", order_id, e),
}
// Wait 1 second between orders
if i < order_quantities.len() - 1 {
println!("[Main] Waiting 1 second before next order...");
thread::sleep(Duration::from_secs(1));
}
}
println!("\n[Main] All orders submitted. Waiting for order updates...");
// Wait a bit for final order updates to come through
thread::sleep(Duration::from_secs(10));
println!("[Main] Shutting down...");
// Note: In a real application, you would want a more graceful shutdown mechanism
// The monitoring thread will end when the main thread exits
Ok(())
}