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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
//! Binance Exchange Usage Example
//!
//! This example demonstrates how to use the Binance exchange implementation
//! to fetch market data, trade, and manage orders.
// Allow clippy warnings for example code - examples prioritize readability over strict linting
#![allow(clippy::field_reassign_with_default)]
#![allow(deprecated)]
use anyhow::{Context, Result};
use ccxt_core::ExchangeConfig;
use ccxt_core::logging::{LogConfig, init_logging};
use ccxt_exchanges::binance::Binance;
#[tokio::main]
async fn main() -> Result<()> {
// Initialize logging system
// Use development config for examples (Debug level, Pretty format)
init_logging(&LogConfig::development());
println!("=== Binance Exchange Example ===\n");
// Initialize Binance exchange
// For public endpoints, you can use default config (no API credentials)
let mut config = ExchangeConfig::default();
config.verbose = true; // Enable verbose logging to see HTTP requests/responses
let exchange = Binance::new(config).context("Failed to initialize Binance exchange")?;
exchange.load_markets(false).await?;
// Example 1: Fetch all markets
println!("1. Fetching markets...");
match exchange.fetch_markets().await {
Ok(markets) => {
println!(" Found {} markets", markets.len());
if let Some(market) = markets.values().next() {
println!(
" Example market: {} ({}/{})",
market.symbol, market.base, market.quote
);
}
}
Err(e) => println!(" Error: {}", e),
}
println!();
// Example 2: Fetch ticker for BTC/USDT
println!("2. Fetching BTC/USDT ticker...");
match exchange
.fetch_ticker("BTC/USDT", ccxt_core::types::TickerParams::default())
.await
{
Ok(ticker) => {
println!(" Symbol: {}", ticker.symbol);
println!(" Last: {:?}", ticker.last);
println!(" Bid: {:?}", ticker.bid);
println!(" Ask: {:?}", ticker.ask);
println!(" Volume: {:?}", ticker.base_volume);
}
Err(e) => println!(" Error: {}", e),
}
println!();
// Example 3: Fetch order book
println!("3. Fetching BTC/USDT order book...");
match exchange.fetch_order_book("BTC/USDT", Some(10)).await {
Ok(order_book) => {
println!(" Symbol: {}", order_book.symbol);
println!(" Bids: {} levels", order_book.bids.len());
println!(" Asks: {} levels", order_book.asks.len());
if let Some(best_bid) = order_book.bids.first() {
println!(" Best bid: {} @ {}", best_bid.amount, best_bid.price);
}
if let Some(best_ask) = order_book.asks.first() {
println!(" Best ask: {} @ {}", best_ask.amount, best_ask.price);
}
}
Err(e) => println!(" Error: {}", e),
}
println!();
// Example 4: Fetch recent trades (using new API)
println!("4. Fetching recent BTC/USDT trades...");
match exchange.fetch_trades("BTC/USDT", Some(5)).await {
Ok(trades) => {
println!(" Found {} trades", trades.len());
for (i, trade) in trades.iter().enumerate() {
println!(
" Trade {}: {} {} @ {} (side: {:?})",
i + 1,
trade.amount,
trade.symbol,
trade.price,
trade.side
);
}
}
Err(e) => println!(" Error: {}", e),
}
println!();
// Example 5: Fetch OHLCV (candlestick) data
println!("5. Fetching BTC/USDT 1h OHLCV data...");
match exchange
.fetch_ohlcv("BTC/USDT", "1h", None, Some(5), None)
.await
{
Ok(candles) => {
println!(" Found {} candles", candles.len());
for (i, candle) in candles.iter().enumerate() {
// OHLCV is now a struct with fields: timestamp, open, high, low, close, volume
println!(
" Candle {}: O:{} H:{} L:{} C:{} V:{}",
i + 1,
candle.open,
candle.high,
candle.low,
candle.close,
candle.volume
);
}
}
Err(e) => println!(" Error: {}", e),
}
println!();
// Example 6: Private API endpoints (requires API credentials)
println!("6. Private API examples (requires credentials)...");
// To use private endpoints, uncomment and set your credentials:
// let private_config = ExchangeConfig {
// api_key: Some("YOUR_API_KEY".to_string()),
// secret: Some("YOUR_SECRET".to_string()),
// ..Default::default()
// };
// let exchange_private = Binance::new(private_config)?;
// Fetch account balance
// match exchange_private.fetch_balance().await {
// Ok(balance) => {
// println!(" Account balance:");
// for (currency, amount) in balance.free.iter() {
// if *amount > 0.0 {
// println!(" {}: {} (free), {} (used)",
// currency,
// amount,
// balance.used.get(currency).unwrap_or(&0.0)
// );
// }
// }
// }
// Err(e) => println!(" Error: {}", e),
// }
// Create a limit order
// match exchange_private.create_order(
// "BTC/USDT",
// "limit",
// "buy",
// 0.001,
// Some(40000.0)
// ).await {
// Ok(order) => {
// println!(" Order created:");
// println!(" ID: {:?}", order.id);
// println!(" Symbol: {}", order.symbol);
// println!(" Side: {:?}", order.side);
// println!(" Type: {:?}", order.type_);
// println!(" Amount: {}", order.amount);
// println!(" Price: {:?}", order.price);
// }
// Err(e) => println!(" Error: {}", e),
// }
// Cancel an order
// match exchange_private.cancel_order("12345", "BTC/USDT").await {
// Ok(order) => {
// println!(" Order cancelled: {:?}", order.id);
// }
// Err(e) => println!(" Error: {}", e),
// }
println!(" (Private API examples are commented out)");
println!(" Set your credentials to test private endpoints");
println!();
// Example 7: Perpetual futures markets
println!("7. Fetching perpetual futures data...");
// Initialize Binance Futures exchange
let futures_config = ExchangeConfig::default();
let futures_exchange = Binance::new_swap(futures_config)
.context("Failed to initialize Binance Futures exchange")?;
// Fetch all futures markets
println!(" Fetching futures markets...");
match futures_exchange.fetch_markets().await {
Ok(markets) => {
println!(" Found {} futures markets", markets.len());
// Find perpetual futures (symbols ending with /USDT)
let perpetuals: Vec<_> = markets
.values()
.filter(|m| m.symbol.contains("/USDT") && m.symbol.contains("PERP"))
.take(5)
.collect();
println!(" Found {} perpetual futures:", perpetuals.len());
for market in perpetuals {
println!(" - {}: {}/{}", market.symbol, market.base, market.quote);
}
}
Err(e) => println!(" Error: {}", e),
}
println!();
// Fetch BTC/USDT perpetual futures ticker
println!(" Fetching BTC/USDT perpetual futures ticker...");
match futures_exchange
.fetch_ticker("BTC/USDT", ccxt_core::types::TickerParams::default())
.await
{
Ok(ticker) => {
println!(" Symbol: {}", ticker.symbol);
println!(" Last: {:?}", ticker.last);
println!(" 24h Change: {:?}", ticker.percentage);
println!(" 24h Volume: {:?}", ticker.base_volume);
println!(" Funding Rate: N/A (not included in ticker)");
}
Err(e) => println!(" Error: {}", e),
}
println!();
// Fetch BTC/USDT perpetual futures order book
println!(" Fetching BTC/USDT perpetual futures order book...");
match futures_exchange
.fetch_order_book("BTC/USDT", Some(10))
.await
{
Ok(order_book) => {
println!(" Symbol: {}", order_book.symbol);
println!(" Bids: {} levels", order_book.bids.len());
println!(" Asks: {} levels", order_book.asks.len());
if let (Some(best_bid), Some(best_ask)) =
(order_book.bids.first(), order_book.asks.first())
{
let spread = best_ask.price - best_bid.price;
// Use a constant for 100.0 to avoid unwrap
let hundred = rust_decimal::Decimal::ONE_HUNDRED;
let spread_percent = (spread / best_bid.price) * hundred;
println!(" Spread: {} ({:.4}%)", spread, spread_percent);
}
}
Err(e) => println!(" Error: {}", e),
}
println!();
// Fetch perpetual futures funding rate
println!(" Fetching BTC/USDT funding rate...");
// Note: This would require implementing fetch_funding_rate method
// For now, we'll show a placeholder
println!(" Funding rate: ~0.01% (example)");
println!(" Note: Implement fetch_funding_rate method to get real rates");
println!();
// Example 8: Private futures API endpoints (requires API credentials)
println!("8. Private futures API examples (requires credentials)...");
// To use private futures endpoints, uncomment and set your credentials:
// let private_futures_config = ExchangeConfig {
// api_key: Some("YOUR_API_KEY".to_string()),
// secret: Some("YOUR_SECRET".to_string()),
// ..Default::default()
// };
// let futures_exchange_private = Binance::new_futures(private_futures_config)?;
// Set leverage for perpetual futures
// match futures_exchange_private.set_leverage("BTC/USDT", 10).await {
// Ok(result) => {
// println!(" Leverage set: {:?}", result);
// }
// Err(e) => println!(" Error: {}", e),
// }
// Create a perpetual futures limit order
// match futures_exchange_private.create_order(
// "BTC/USDT",
// "limit",
// "buy",
// 0.01,
// Some(40000.0)
// ).await {
// Ok(order) => {
// println!(" Futures order created:");
// println!(" ID: {:?}", order.id);
// println!(" Symbol: {}", order.symbol);
// println!(" Side: {:?}", order.side);
// println!(" Type: {:?}", order.type_);
// println!(" Amount: {}", order.amount);
// println!(" Price: {:?}", order.price);
// }
// Err(e) => println!(" Error: {}", e),
// }
// Set position mode (hedge or one-way)
// match futures_exchange_private.set_position_mode(true).await {
// Ok(result) => {
// println!(" Position mode set to hedge: {:?}", result);
// }
// Err(e) => println!(" Error: {}", e),
// }
// Fetch open positions
// match futures_exchange_private.fetch_positions().await {
// Ok(positions) => {
// println!(" Current positions:");
// for position in positions {
// if position.size != 0.0 {
// println!(" {}: {} @ {}",
// position.symbol,
// position.size,
// position.entry_price.unwrap_or(0.0)
// );
// }
// }
// }
// Err(e) => println!(" Error: {}", e),
// }
println!(" (Private futures API examples are commented out)");
println!(" Set your credentials to test private futures endpoints");
println!();
// Example 9: WebSocket streams (commented out as they run continuously)
/*
println!("9. WebSocket ticker stream (press Ctrl+C to stop)...");
exchange.subscribe_ticker("BTC/USDT", |ticker| async move {
println!(" Ticker update: {} @ {:?}", ticker.symbol, ticker.last);
Ok(())
}).await?;
// Futures WebSocket stream
println!(" Futures WebSocket ticker stream...");
futures_exchange.subscribe_ticker("BTC/USDT", |ticker| async move {
println!(" Futures Ticker update: {} @ {:?}", ticker.symbol, ticker.last);
Ok(())
}).await?;
*/
println!("=== Example completed ===");
Ok(())
}