Skip to content

Commit 6255233

Browse files
authored
Merge pull request #2 from xsa-dev/examples-startup
Examples startup
2 parents 92fec65 + fb3431f commit 6255233

6 files changed

Lines changed: 483 additions & 41 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ serde_json = "1.0"
7070

7171
# Error handling
7272
thiserror = "1.0"
73+
anyhow = "1.0"
7374

7475
# CSV handling
7576
csv = "1.3"

examples/basic_backtest.rs

Lines changed: 77 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,27 @@
1-
use chrono::Utc;
1+
use chrono::{Duration, TimeZone, Utc, FixedOffset};
2+
use hyperliquid_rust_sdk::{BaseUrl, InfoClient};
23
use hyperliquid_backtest::prelude::*;
34

4-
/// # Basic Backtest Example
5+
/// # Basic Backtest Example (Fixed with Working API)
56
///
67
/// This example demonstrates how to run a simple backtest using the Hyperliquid backtester.
78
/// It shows:
89
/// - Setting up logging for debugging and monitoring
9-
/// - Fetching historical data from Hyperliquid API
10+
/// - Fetching historical data from Hyperliquid API using the correct SDK
1011
/// - Creating a basic SMA crossover strategy
1112
/// - Configuring backtest parameters with realistic commission rates
1213
/// - Running the backtest with funding rates enabled
1314
/// - Analyzing and reporting comprehensive results
1415
/// - Comparing performance with and without funding rates
1516
/// - Exporting results to CSV for further analysis
1617
///
17-
/// The example uses a 10/30 SMA crossover strategy on BTC/USD data over the last 90 days.
18+
/// The example uses a 10/30 SMA crossover strategy on BTC/USD data over the last 30 days.
19+
///
20+
/// ## Supported Symbols
21+
///
22+
/// Based on Hyperliquid API testing, the following symbols work:
23+
/// - BTC, ETH, SOL, AVAX, ATOM (all return data)
24+
/// - All intervals: 1m, 5m, 15m, 1h, 4h, 1d
1825
///
1926
/// ## Usage
2027
///
@@ -40,20 +47,69 @@ async fn main() -> Result<()> {
4047

4148
log::info!("Starting Hyperliquid Basic Backtest Example");
4249

43-
println!("🚀 Hyperliquid Basic Backtest Example");
44-
println!("=====================================\n");
50+
println!("🚀 Hyperliquid Basic Backtest Example (Fixed)");
51+
println!("============================================\n");
4552

46-
// Fetch historical data for BTC with funding rates
47-
let end_time = Utc::now().timestamp() as u64;
48-
let start_time = end_time - (90 * 24 * 3600); // 90 days of data
49-
50-
println!("Fetching BTC/USD data for the last 90 days...");
51-
let data = HyperliquidData::fetch("BTC", "1h", start_time, end_time).await?;
53+
// Define time range for data fetching (last 30 days for faster testing)
54+
let end_time = Utc::now();
55+
let start_time = end_time - Duration::days(30);
56+
let start_timestamp = start_time.timestamp_millis() as u64;
57+
let end_timestamp = end_time.timestamp_millis() as u64;
58+
59+
println!("Fetching BTC/USD data for the last 30 days...");
60+
println!("Time range: {} to {}",
61+
start_time.format("%Y-%m-%d %H:%M"),
62+
end_time.format("%Y-%m-%d %H:%M"));
63+
64+
// Initialize Hyperliquid client
65+
let info_client = InfoClient::new(None, Some(BaseUrl::Mainnet)).await?;
5266

53-
println!("Data fetched: {} data points from {} to {}\n",
67+
// Fetch OHLCV data using the working SDK
68+
let candles = info_client
69+
.candles_snapshot("BTC".to_string(), "1h".to_string(), start_timestamp, end_timestamp)
70+
.await?;
71+
72+
println!("✅ Successfully fetched {} candles!", candles.len());
73+
74+
if candles.is_empty() {
75+
return Err(HyperliquidBacktestError::api_error("No data received from API"));
76+
}
77+
78+
// Convert candles to our internal format
79+
let mut datetime = Vec::new();
80+
let mut open = Vec::new();
81+
let mut high = Vec::new();
82+
let mut low = Vec::new();
83+
let mut close = Vec::new();
84+
let mut volume = Vec::new();
85+
86+
for candle in &candles {
87+
let timestamp = Utc.timestamp_millis_opt(candle.time_open as i64).unwrap()
88+
.with_timezone(&FixedOffset::east_opt(0).unwrap());
89+
90+
datetime.push(timestamp);
91+
open.push(candle.open.parse::<f64>().unwrap_or(0.0));
92+
high.push(candle.high.parse::<f64>().unwrap_or(0.0));
93+
low.push(candle.low.parse::<f64>().unwrap_or(0.0));
94+
close.push(candle.close.parse::<f64>().unwrap_or(0.0));
95+
volume.push(candle.vlm.parse::<f64>().unwrap_or(0.0));
96+
}
97+
98+
// Create our internal Data struct
99+
let data = HyperliquidData::with_ohlc_data(
100+
"BTC".to_string(),
101+
datetime,
102+
open,
103+
high,
104+
low,
105+
close,
106+
volume,
107+
)?;
108+
109+
println!("Data converted: {} data points from {} to {}\n",
54110
data.len(),
55-
data.datetime.first().unwrap().format("%Y-%m-%d %H:%M"),
56-
data.datetime.last().unwrap().format("%Y-%m-%d %H:%M"));
111+
data.datetime.first().map(|d| d.format("%Y-%m-%d %H:%M").to_string()).unwrap_or_else(|| "N/A".to_string()),
112+
data.datetime.last().map(|d| d.format("%Y-%m-%d %H:%M").to_string()).unwrap_or_else(|| "N/A".to_string()));
57113

58114
// Create a simple SMA crossover strategy using the enhanced_sma_cross function
59115
println!("Setting up SMA crossover strategy (10/30)...");
@@ -78,8 +134,11 @@ async fn main() -> Result<()> {
78134
initial_capital,
79135
commission.clone(),
80136
);
137+
138+
// Initialize the base backtest first
139+
backtest.initialize_base_backtest()?;
81140

82-
// Run backtest with funding rates
141+
// Then calculate with funding rates
83142
backtest.calculate_with_funding()?;
84143

85144
// Get enhanced report
@@ -141,7 +200,8 @@ async fn main() -> Result<()> {
141200
initial_capital,
142201
commission_no_funding,
143202
);
144-
203+
204+
backtest_no_funding.initialize_base_backtest()?;
145205
backtest_no_funding.calculate_with_funding()?;
146206

147207
let report_no_funding = backtest_no_funding.enhanced_report()?;

examples/simple_data_fetching.rs

Lines changed: 99 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,88 @@
1-
use chrono::{Duration, Utc};
1+
use chrono::{Duration, TimeZone, Utc, FixedOffset};
2+
use hyperliquid_rust_sdk::{BaseUrl, InfoClient};
23
use hyperliquid_backtest::prelude::*;
34
use std::fs::File;
45
use std::io::Write;
56

6-
/// # Simple OHLC Data Fetching Example
7+
/// # Simple OHLC Data Fetching Example (Fixed with Working API)
78
///
89
/// This example demonstrates how to fetch historical OHLC data from Hyperliquid API
910
/// 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
1112
/// - Custom time range specification
1213
/// - Data validation and statistics
1314
/// - Saving data to CSV for further analysis
15+
/// - Testing different symbols and intervals
1416
///
1517
/// The example fetches 7 days of hourly data for BTC/USD and saves it to a CSV file.
1618
1719
#[tokio::main]
1820
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");
2123

2224
// 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;
2529

2630
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?;
2737

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+
)?;
3079

3180
// Print data statistics
3281
println!("\nData fetched successfully!");
33-
println!("Symbol: {}", btc_data.ticker);
82+
println!("Symbol: {}", btc_data.symbol);
3483
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()));
3786
println!("Number of data points: {}", btc_data.len());
3887
println!("Number of funding rate points: {}", btc_data.funding_rates.len());
3988

@@ -98,17 +147,44 @@ async fn main() -> Result<()> {
98147
file.write_all(csv_content.as_bytes())?;
99148
println!("Data saved to {}", csv_file);
100149

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+
}
112188

113189
println!("\nExample completed successfully!");
114190

0 commit comments

Comments
 (0)