Repository navigation
Expand file tree
/
Copy pathtimestamp_migration_example.rs
More file actions
342 lines (294 loc) · 11 KB
/
Copy pathtimestamp_migration_example.rs
File metadata and controls
342 lines (294 loc) · 11 KB
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
//! Timestamp Migration Example
//!
//! This example demonstrates how to migrate from the old u64 timestamp API
//! to the new standardized i64 timestamp API in CCXT Rust.
//!
//! # Usage
//!
//! ```bash
//! cargo run --example timestamp_migration_example
//! ```
#![allow(deprecated)]
use ccxt_core::{
prelude::*,
time::{TimestampConversion, TimestampUtils},
};
use ccxt_exchanges::binance::Binance;
use rust_decimal_macros::dec;
use std::env;
#[tokio::main]
async fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
println!("=== Timestamp Migration Example ===\n");
// Initialize exchange
let config = ExchangeConfig {
api_key: env::var("BINANCE_API_KEY")
.ok()
.map(ccxt_core::SecretString::new),
secret: env::var("BINANCE_API_SECRET")
.ok()
.map(ccxt_core::SecretString::new),
sandbox: false,
..Default::default()
};
let exchange = Binance::new(config)?;
// Example 1: Basic timestamp creation and usage
example_timestamp_creation().await?;
// Example 2: Data structure creation with i64 timestamps
example_data_structures().await?;
// Example 3: OHLCV fetching migration
example_ohlcv_migration(&exchange).await?;
// Example 4: Trade fetching migration
example_trades_migration(&exchange).await?;
// Example 5: Conversion utilities
example_conversion_utilities().await?;
// Example 6: Error handling
example_error_handling().await?;
println!("\n=== Migration Example Complete ===");
Ok(())
}
/// Example 1: Basic timestamp creation and usage
async fn example_timestamp_creation() -> std::result::Result<(), Box<dyn std::error::Error>> {
println!("📅 Example 1: Timestamp Creation");
println!("--------------------------------");
// OLD WAY (deprecated - don't do this)
#[allow(clippy::cast_possible_truncation)]
let _old_timestamp = chrono::Utc::now().timestamp_millis() as u64;
println!("❌ Old way: casting to u64 (deprecated)");
// NEW WAY (recommended)
let new_timestamp: i64 = chrono::Utc::now().timestamp_millis();
println!("✅ New way: using i64 directly");
println!(" Current timestamp: {} ms", new_timestamp);
// Using timestamp utilities
let util_timestamp = TimestampUtils::now_ms();
println!("✅ Using utilities: {} ms", util_timestamp);
// Formatting timestamps
let formatted = TimestampUtils::format_iso8601(new_timestamp);
println!(" Formatted: {:?}", formatted);
println!();
Ok(())
}
/// Example 2: Data structure creation with i64 timestamps
async fn example_data_structures() -> std::result::Result<(), Box<dyn std::error::Error>> {
println!("🏗️ Example 2: Data Structures");
println!("------------------------------");
let timestamp: i64 = chrono::Utc::now().timestamp_millis();
// Create ticker with i64 timestamp
let ticker = Ticker::new("BTC/USDT".to_string(), timestamp);
println!("✅ Ticker created with i64 timestamp: {}", ticker.timestamp);
// Create order book with i64 timestamp
let orderbook = OrderBook::new("BTC/USDT".to_string(), timestamp);
println!(
"✅ OrderBook created with i64 timestamp: {}",
orderbook.timestamp
);
// Create trade with i64 timestamp
let trade = Trade::new(
"BTC/USDT".to_string(),
OrderSide::Buy,
dec!(50000.0).into(),
dec!(0.1).into(),
timestamp,
);
println!("✅ Trade created with i64 timestamp: {}", trade.timestamp);
// Create OHLCV with i64 timestamp
let ohlcv = Ohlcv::new(
timestamp,
dec!(49000.0).into(), // open
dec!(51000.0).into(), // high
dec!(48500.0).into(), // low
dec!(50000.0).into(), // close
dec!(1234.5).into(), // volume
);
println!("✅ OHLCV created with i64 timestamp: {}", ohlcv.timestamp);
println!();
Ok(())
}
/// Example 3: OHLCV fetching migration
async fn example_ohlcv_migration(
exchange: &Binance,
) -> std::result::Result<(), Box<dyn std::error::Error>> {
println!("📊 Example 3: OHLCV Fetching Migration");
println!("--------------------------------------");
// OLD WAY (deprecated - still works but shows warnings)
println!("❌ Old way (deprecated):");
println!(" // This would show deprecation warnings:");
println!(
" // exchange.fetch_ohlcv_u64(\"BTC/USDT\", Timeframe::H1, Some(timestamp_u64), Some(100), None)"
);
// NEW WAY 1: Basic method
println!("✅ New way 1: Basic method");
match exchange
.fetch_ohlcv("BTC/USDT", "1h", None, Some(5), None)
.await
{
Ok(candles) => {
println!(" Fetched {} candles using basic method", candles.len());
if let Some(first) = candles.first() {
println!(" First candle timestamp: {}", first.timestamp);
}
}
Err(e) => println!(" Error: {}", e),
}
// NEW WAY 2: Parameter-based method (recommended for complex queries)
println!("✅ New way 2: Parameter-based method");
let since: i64 = chrono::Utc::now().timestamp_millis() - (24 * 60 * 60 * 1000); // 24 hours ago
match exchange
.fetch_ohlcv("BTC/USDT", "1h", Some(since), Some(10), None)
.await
{
Ok(candles) => {
println!(
" Fetched {} candles using parameter method",
candles.len()
);
if let Some(first) = candles.first() {
println!(" First candle timestamp: {}", first.timestamp);
println!(" Since parameter (i64): {}", since);
}
}
Err(e) => println!(" Error: {}", e),
}
println!();
Ok(())
}
/// Example 4: Trade fetching migration
async fn example_trades_migration(
exchange: &Binance,
) -> std::result::Result<(), Box<dyn std::error::Error>> {
println!("💱 Example 4: Trade Fetching Migration");
println!("--------------------------------------");
// OLD WAY (this signature no longer exists)
println!("❌ Old way (no longer available):");
println!(" // exchange.fetch_trades(\"BTC/USDT\", Some(5)) // This signature is gone");
// NEW WAY 1: Basic trades (no parameters)
println!("✅ New way 1: Basic trades");
match exchange.fetch_trades("BTC/USDT", None).await {
Ok(trades) => {
println!(" Fetched {} trades using basic method", trades.len());
}
Err(e) => println!(" Error: {}", e),
}
// NEW WAY 2: With limit only
println!("✅ New way 2: With limit");
match exchange.fetch_trades("BTC/USDT", Some(5)).await {
Ok(trades) => {
println!(" Fetched {} trades with limit", trades.len());
}
Err(e) => println!(" Error: {}", e),
}
// NEW WAY 3: With timestamp filtering (i64)
println!("✅ New way 3: With timestamp filtering");
let since: i64 = chrono::Utc::now().timestamp_millis() - (60 * 60 * 1000); // 1 hour ago
// Note: The Binance implementation doesn't have fetch_trades_with_limit method
// Instead, we use the regular fetch_trades method with limit parameter
println!(" Note: Using fetch_trades with limit parameter");
match exchange.fetch_trades("BTC/USDT", Some(10)).await {
Ok(trades) => {
println!(" Fetched {} trades with timestamp filter", trades.len());
println!(" Since parameter (i64): {}", since);
}
Err(e) => println!(" Error: {}", e),
}
println!();
Ok(())
}
/// Example 5: Conversion utilities
#[allow(deprecated)] // Demonstrating deprecated conversion functions
async fn example_conversion_utilities() -> std::result::Result<(), Box<dyn std::error::Error>> {
println!("🔄 Example 5: Conversion Utilities");
println!("----------------------------------");
// Convert u64 to i64
let u64_timestamp = 1609459200000u64; // January 1, 2021
match TimestampUtils::u64_to_i64(u64_timestamp) {
Ok(i64_timestamp) => {
println!(
"✅ u64 to i64 conversion: {} -> {}",
u64_timestamp, i64_timestamp
);
}
Err(e) => println!("❌ Conversion error: {}", e),
}
// Convert Option<u64> to Option<i64>
let u64_option = Some(1609459200000u64);
match u64_option.to_i64() {
Ok(i64_option) => {
println!(
"✅ Option<u64> to Option<i64>: {:?} -> {:?}",
u64_option, i64_option
);
}
Err(e) => println!("❌ Conversion error: {}", e),
}
// Validate timestamp
let timestamp = 1609459200000i64;
match TimestampUtils::validate_timestamp(timestamp) {
Ok(validated) => {
println!("✅ Timestamp validation: {} is valid", validated);
}
Err(e) => println!("❌ Validation error: {}", e),
}
// Parse timestamp from string
match TimestampUtils::parse_timestamp("1609459200000") {
Ok(parsed) => {
println!("✅ String parsing: '1609459200000' -> {}", parsed);
}
Err(e) => println!("❌ Parse error: {}", e),
}
// Time conversions
let seconds = 1609459200i64;
let milliseconds = TimestampUtils::seconds_to_ms(seconds);
let back_to_seconds = TimestampUtils::ms_to_seconds(milliseconds);
println!(
"✅ Time conversions: {}s -> {}ms -> {}s",
seconds, milliseconds, back_to_seconds
);
println!();
Ok(())
}
/// Example 6: Error handling
#[allow(deprecated)] // Demonstrating error handling with deprecated conversion functions
async fn example_error_handling() -> std::result::Result<(), Box<dyn std::error::Error>> {
println!("⚠️ Example 6: Error Handling");
println!("-----------------------------");
// Test timestamp overflow (u64 to i64)
let large_u64 = u64::MAX;
match TimestampUtils::u64_to_i64(large_u64) {
Ok(converted) => {
println!("Unexpected success: {}", converted);
}
Err(e) => {
println!("✅ Correctly caught overflow: {}", e);
}
}
// Test timestamp underflow (i64 to u64)
let negative_i64 = -1000i64;
match TimestampUtils::i64_to_u64(negative_i64) {
Ok(converted) => {
println!("Unexpected success: {}", converted);
}
Err(e) => {
println!("✅ Correctly caught underflow: {}", e);
}
}
// Test invalid timestamp range
let invalid_timestamp = -1i64;
match TimestampUtils::validate_timestamp(invalid_timestamp) {
Ok(validated) => {
println!("Unexpected success: {}", validated);
}
Err(e) => {
println!("✅ Correctly caught invalid range: {}", e);
}
}
// Test invalid string parsing
match TimestampUtils::parse_timestamp("not_a_number") {
Ok(parsed) => {
println!("Unexpected success: {}", parsed);
}
Err(e) => {
println!("✅ Correctly caught parse error: {}", e);
}
}
println!();
Ok(())
}