|
1 | | -use chrono::{Duration, Utc}; |
| 1 | +use chrono::{Duration, TimeZone, Utc, FixedOffset}; |
| 2 | +use hyperliquid_rust_sdk::{BaseUrl, InfoClient}; |
2 | 3 | use hyperliquid_backtest::prelude::*; |
3 | 4 | use std::fs::File; |
4 | 5 | use std::io::Write; |
5 | 6 |
|
6 | | -/// # Simple OHLC Data Fetching Example |
| 7 | +/// # Simple OHLC Data Fetching Example (Fixed with Working API) |
7 | 8 | /// |
8 | 9 | /// This example demonstrates how to fetch historical OHLC data from Hyperliquid API |
9 | 10 | /// for different time intervals and trading pairs. It shows: |
10 | | -/// - Basic data fetching for BTC |
| 11 | +/// - Basic data fetching for BTC using the correct SDK |
11 | 12 | /// - Custom time range specification |
12 | 13 | /// - Data validation and statistics |
13 | 14 | /// - Saving data to CSV for further analysis |
| 15 | +/// - Testing different symbols and intervals |
14 | 16 | /// |
15 | 17 | /// The example fetches 7 days of hourly data for BTC/USD and saves it to a CSV file. |
16 | 18 |
|
17 | 19 | #[tokio::main] |
18 | 20 | async fn main() -> Result<()> { |
19 | | - println!("Hyperliquid Simple Data Fetching Example"); |
20 | | - println!("=======================================\n"); |
| 21 | + println!("🚀 Hyperliquid Simple Data Fetching Example (Fixed)"); |
| 22 | + println!("==================================================\n"); |
21 | 23 |
|
22 | 24 | // Define time range for data fetching (last 7 days) |
23 | | - let end_time = Utc::now().timestamp() as u64; |
24 | | - let start_time = end_time - (7 * 24 * 3600); // 7 days of data |
| 25 | + let end_time = Utc::now(); |
| 26 | + let start_time = end_time - Duration::days(7); |
| 27 | + let start_timestamp = start_time.timestamp_millis() as u64; |
| 28 | + let end_timestamp = end_time.timestamp_millis() as u64; |
25 | 29 |
|
26 | 30 | println!("Fetching BTC/USD hourly data for the last 7 days..."); |
| 31 | + println!("Time range: {} to {}", |
| 32 | + start_time.format("%Y-%m-%d %H:%M"), |
| 33 | + end_time.format("%Y-%m-%d %H:%M")); |
| 34 | + |
| 35 | + // Initialize Hyperliquid client |
| 36 | + let info_client = InfoClient::new(None, Some(BaseUrl::Mainnet)).await?; |
27 | 37 |
|
28 | | - // Fetch BTC data using the convenience method |
29 | | - let btc_data = HyperliquidData::fetch_btc("1h", start_time, end_time).await?; |
| 38 | + // Fetch BTC data using the working SDK |
| 39 | + let candles = info_client |
| 40 | + .candles_snapshot("BTC".to_string(), "1h".to_string(), start_timestamp, end_timestamp) |
| 41 | + .await?; |
| 42 | + |
| 43 | + println!("✅ Successfully fetched {} candles!", candles.len()); |
| 44 | + |
| 45 | + if candles.is_empty() { |
| 46 | + return Err(HyperliquidBacktestError::api_error("No data received from API")); |
| 47 | + } |
| 48 | + |
| 49 | + // Convert candles to our internal format |
| 50 | + let mut datetime = Vec::new(); |
| 51 | + let mut open = Vec::new(); |
| 52 | + let mut high = Vec::new(); |
| 53 | + let mut low = Vec::new(); |
| 54 | + let mut close = Vec::new(); |
| 55 | + let mut volume = Vec::new(); |
| 56 | + |
| 57 | + for candle in &candles { |
| 58 | + let timestamp = Utc.timestamp_millis_opt(candle.time_open as i64).unwrap() |
| 59 | + .with_timezone(&FixedOffset::east_opt(0).unwrap()); |
| 60 | + |
| 61 | + datetime.push(timestamp); |
| 62 | + open.push(candle.open.parse::<f64>().unwrap_or(0.0)); |
| 63 | + high.push(candle.high.parse::<f64>().unwrap_or(0.0)); |
| 64 | + low.push(candle.low.parse::<f64>().unwrap_or(0.0)); |
| 65 | + close.push(candle.close.parse::<f64>().unwrap_or(0.0)); |
| 66 | + volume.push(candle.vlm.parse::<f64>().unwrap_or(0.0)); |
| 67 | + } |
| 68 | + |
| 69 | + // Create our internal Data struct |
| 70 | + let btc_data = HyperliquidData::with_ohlc_data( |
| 71 | + "BTC".to_string(), |
| 72 | + datetime, |
| 73 | + open, |
| 74 | + high, |
| 75 | + low, |
| 76 | + close, |
| 77 | + volume, |
| 78 | + )?; |
30 | 79 |
|
31 | 80 | // Print data statistics |
32 | 81 | println!("\nData fetched successfully!"); |
33 | | - println!("Symbol: {}", btc_data.ticker); |
| 82 | + println!("Symbol: {}", btc_data.symbol); |
34 | 83 | println!("Time range: {} to {}", |
35 | | - btc_data.datetime.first().unwrap().format("%Y-%m-%d %H:%M"), |
36 | | - btc_data.datetime.last().unwrap().format("%Y-%m-%d %H:%M")); |
| 84 | + btc_data.datetime.first().map(|d| d.format("%Y-%m-%d %H:%M").to_string()).unwrap_or_else(|| "N/A".to_string()), |
| 85 | + btc_data.datetime.last().map(|d| d.format("%Y-%m-%d %H:%M").to_string()).unwrap_or_else(|| "N/A".to_string())); |
37 | 86 | println!("Number of data points: {}", btc_data.len()); |
38 | 87 | println!("Number of funding rate points: {}", btc_data.funding_rates.len()); |
39 | 88 |
|
@@ -98,17 +147,44 @@ async fn main() -> Result<()> { |
98 | 147 | file.write_all(csv_content.as_bytes())?; |
99 | 148 | println!("Data saved to {}", csv_file); |
100 | 149 |
|
101 | | - // Demonstrate fetching data for another asset (ETH) |
102 | | - println!("\nFetching ETH/USD data for comparison..."); |
103 | | - let eth_data = HyperliquidData::fetch("ETH", "1h", start_time, end_time).await?; |
104 | | - |
105 | | - println!("ETH data fetched: {} data points", eth_data.len()); |
106 | | - |
107 | | - // Demonstrate fetching data with different time interval |
108 | | - println!("\nFetching BTC/USD data with 5-minute intervals..."); |
109 | | - let btc_5m_data = HyperliquidData::fetch_btc("5m", end_time - (24 * 3600), end_time).await?; |
110 | | - |
111 | | - println!("BTC 5-minute data fetched: {} data points for the last 24 hours", btc_5m_data.len()); |
| 150 | + // Try fetching different time intervals |
| 151 | + println!("\nFetching 5-minute data for the last 24 hours..."); |
| 152 | + let btc_5m_candles = info_client |
| 153 | + .candles_snapshot("BTC".to_string(), "5m".to_string(), end_timestamp - (24 * 3600 * 1000), end_timestamp) |
| 154 | + .await?; |
| 155 | + println!("5m data points: {}", btc_5m_candles.len()); |
| 156 | + |
| 157 | + // Try fetching ETH data |
| 158 | + println!("\nFetching ETH data for comparison..."); |
| 159 | + let eth_candles = info_client |
| 160 | + .candles_snapshot("ETH".to_string(), "1h".to_string(), start_timestamp, end_timestamp) |
| 161 | + .await?; |
| 162 | + println!("ETH data points: {}", eth_candles.len()); |
| 163 | + |
| 164 | + // Try fetching SOL data |
| 165 | + println!("\nFetching SOL data for comparison..."); |
| 166 | + let sol_candles = info_client |
| 167 | + .candles_snapshot("SOL".to_string(), "1h".to_string(), start_timestamp, end_timestamp) |
| 168 | + .await?; |
| 169 | + println!("SOL data points: {}", sol_candles.len()); |
| 170 | + |
| 171 | + // Test different intervals for BTC |
| 172 | + println!("\nTesting different intervals for BTC..."); |
| 173 | + let intervals = vec!["1m", "5m", "15m", "1h", "4h", "1d"]; |
| 174 | + |
| 175 | + for interval in intervals { |
| 176 | + println!("Testing interval: {}", interval); |
| 177 | + match info_client |
| 178 | + .candles_snapshot("BTC".to_string(), interval.to_string(), start_timestamp, end_timestamp) |
| 179 | + .await { |
| 180 | + Ok(test_candles) => { |
| 181 | + println!(" ✅ {}: {} candles", interval, test_candles.len()); |
| 182 | + } |
| 183 | + Err(e) => { |
| 184 | + println!(" ❌ {}: {}", interval, e); |
| 185 | + } |
| 186 | + } |
| 187 | + } |
112 | 188 |
|
113 | 189 | println!("\nExample completed successfully!"); |
114 | 190 |
|
|
0 commit comments