hyperliquid_backtest/lib.rs
1//! # Hyperliquid Backtester
2//!
3//! A comprehensive Rust library that integrates Hyperliquid trading data with the rs-backtester
4//! framework to enable sophisticated backtesting of trading strategies using real Hyperliquid
5//! market data, including perpetual futures mechanics and funding rate calculations.
6//!
7//! ## Features
8//!
9//! - 🚀 **Async Data Fetching**: Efficiently fetch historical OHLC data from Hyperliquid API
10//! - 💰 **Funding Rate Support**: Complete funding rate data and perpetual futures mechanics
11//! - 🔄 **Seamless Integration**: Drop-in replacement for rs-backtester with enhanced features
12//! - 📊 **Enhanced Reporting**: Comprehensive metrics including funding PnL and arbitrage analysis
13//! - ⚡ **High Performance**: Optimized for large datasets and complex multi-asset strategies
14//! - 🛡️ **Type Safety**: Comprehensive error handling with detailed error messages
15//! - 📈 **Advanced Strategies**: Built-in funding arbitrage and enhanced technical indicators
16//!
17//! ## API Stability
18//!
19//! This crate follows semantic versioning (SemVer):
20//! - **Major version** (0.x.y → 1.0.0): Breaking API changes
21//! - **Minor version** (0.1.x → 0.2.0): New features, backward compatible
22//! - **Patch version** (0.1.0 → 0.1.1): Bug fixes, backward compatible
23//!
24//! Current version: **0.1.0** (Pre-1.0 development phase)
25//!
26//! ### Stability Guarantees
27//!
28//! - **Public API**: All items in the [`prelude`] module are considered stable within minor versions
29//! - **Data Structures**: [`HyperliquidData`], [`HyperliquidBacktest`], and [`HyperliquidCommission`] are stable
30//! - **Error Types**: [`HyperliquidBacktestError`] variants may be added but not removed in minor versions
31//! - **Strategy Interface**: [`HyperliquidStrategy`] trait is stable for implementors
32//!
33//! ## Quick Start
34//!
35//! Add this to your `Cargo.toml`:
36//!
37//! ```toml
38//! [dependencies]
39//! hyperliquid-backtester = "0.1"
40//! tokio = { version = "1.0", features = ["full"] }
41//! ```
42//!
43//! ### Basic Backtesting Example
44//!
45//! ```rust,no_run
46//! use hyperliquid_backtest::prelude::*;
47//! use chrono::{DateTime, FixedOffset, Utc};
48//!
49//! #[tokio::main]
50//! async fn main() -> Result<(), HyperliquidBacktestError> {
51//! // Define time range (last 30 days)
52//! let end_time = Utc::now().timestamp() as u64;
53//! let start_time = end_time - (30 * 24 * 60 * 60); // 30 days ago
54//!
55//! // Fetch historical data for BTC with 1-hour intervals
56//! let data = HyperliquidData::fetch("BTC", "1h", start_time, end_time).await?;
57//!
58//! // Create a simple moving average crossover strategy
59//! let strategy = enhanced_sma_cross(10, 20, Default::default())?;
60//!
61//! // Set up backtest with $10,000 initial capital
62//! let mut backtest = HyperliquidBacktest::new(
63//! data,
64//! strategy,
65//! 10000.0,
66//! HyperliquidCommission::default(),
67//! )?;
68//!
69//! // Run backtest including funding calculations
70//! backtest.calculate_with_funding()?;
71//!
72//! // Generate comprehensive report
73//! let report = backtest.enhanced_report()?;
74//!
75//! println!("📊 Backtest Results:");
76//! println!("Total Return: {:.2}%", report.total_return * 100.0);
77//! println!("Trading PnL: ${:.2}", report.trading_pnl);
78//! println!("Funding PnL: ${:.2}", report.funding_pnl);
79//! println!("Sharpe Ratio: {:.3}", report.sharpe_ratio);
80//!
81//! Ok(())
82//! }
83//! ```
84//!
85//! ### Funding Arbitrage Strategy Example
86//!
87//! ```rust,no_run
88//! use hyperliquid_backtest::prelude::*;
89//!
90//! #[tokio::main]
91//! async fn main() -> Result<(), HyperliquidBacktestError> {
92//! let data = HyperliquidData::fetch("ETH", "1h", start_time, end_time).await?;
93//!
94//! // Create funding arbitrage strategy with 0.01% threshold
95//! let strategy = funding_arbitrage_strategy(0.0001)?;
96//!
97//! let mut backtest = HyperliquidBacktest::new(
98//! data,
99//! strategy,
100//! 50000.0, // Higher capital for arbitrage
101//! HyperliquidCommission::default(),
102//! )?;
103//!
104//! backtest.calculate_with_funding()?;
105//!
106//! // Get detailed funding analysis
107//! let funding_report = backtest.funding_report()?;
108//!
109//! println!("💰 Funding Arbitrage Results:");
110//! println!("Total Funding Received: ${:.2}", funding_report.total_funding_received);
111//! println!("Total Funding Paid: ${:.2}", funding_report.total_funding_paid);
112//! println!("Net Funding PnL: ${:.2}", funding_report.net_funding_pnl);
113//! println!("Average Funding Rate: {:.4}%", funding_report.avg_funding_rate * 100.0);
114//!
115//! Ok(())
116//! }
117//! ```
118//!
119//! ## Migration from rs-backtester
120//!
121//! This library is designed as a drop-in enhancement to rs-backtester. See the
122//! [migration guide](https://docs.rs/hyperliquid-backtester/latest/hyperliquid_backtest/migration/index.html)
123//! for detailed instructions on upgrading existing rs-backtester code.
124//!
125//! ## Error Handling
126//!
127//! All fallible operations return [`Result<T, HyperliquidBacktestError>`](Result). The error type
128//! provides detailed context and suggestions for resolution:
129//!
130//! ```rust,no_run
131//! use hyperliquid_backtest::prelude::*;
132//!
133//! match HyperliquidData::fetch("INVALID", "1h", start, end).await {
134//! Ok(data) => println!("Success!"),
135//! Err(HyperliquidBacktestError::HyperliquidApi(msg)) => {
136//! eprintln!("API Error: {}", msg);
137//! // Handle API-specific errors
138//! },
139//! Err(HyperliquidBacktestError::UnsupportedInterval(interval)) => {
140//! eprintln!("Unsupported interval: {}", interval);
141//! eprintln!("Supported intervals: {:?}", HyperliquidDataFetcher::supported_intervals());
142//! },
143//! Err(e) => eprintln!("Other error: {}", e),
144//! }
145//! ```
146
147pub mod data;
148pub mod backtest;
149pub mod strategies;
150pub mod errors;
151pub mod utils;
152pub mod indicators;
153pub mod funding_report;
154pub mod csv_export;
155pub mod migration;
156pub mod api_docs;
157pub mod trading_mode;
158pub mod trading_mode_impl;
159pub mod unified_data;
160pub mod unified_data_impl;
161pub mod paper_trading;
162pub mod real_time_data_stream;
163pub mod real_time_monitoring;
164pub mod risk_manager;
165pub mod live_trading;
166pub mod live_trading_safety;
167pub mod mode_reporting;
168
169/// Logging and debugging utilities
170pub mod logging {
171 //! Logging and debugging utilities for the hyperliquid-backtester crate.
172 //!
173 //! This module provides convenient functions for setting up structured logging
174 //! and debugging support throughout the library.
175 //!
176 //! ## Basic Usage
177 //!
178 //! ```rust
179 //! use hyperliquid_backtest::logging::init_logger;
180 //!
181 //! // Initialize with default settings (INFO level)
182 //! init_logger();
183 //!
184 //! // Or with custom log level
185 //! init_logger_with_level("debug");
186 //! ```
187 //!
188 //! ## Environment Variables
189 //!
190 //! You can control logging behavior using environment variables:
191 //!
192 //! - `RUST_LOG`: Set log level (e.g., `debug`, `info`, `warn`, `error`)
193 //! - `HYPERLIQUID_LOG_FORMAT`: Set format (`json` or `pretty`)
194 //! - `HYPERLIQUID_LOG_FILE`: Write logs to file instead of stdout
195 //!
196 //! ## Examples
197 //!
198 //! ```bash
199 //! # Enable debug logging
200 //! RUST_LOG=debug cargo run --example basic_backtest
201 //!
202 //! # Use JSON format for structured logging
203 //! RUST_LOG=info HYPERLIQUID_LOG_FORMAT=json cargo run
204 //!
205 //! # Write logs to file
206 //! RUST_LOG=info HYPERLIQUID_LOG_FILE=backtest.log cargo run
207 //! ```
208
209 use std::env;
210 use tracing_subscriber::{
211 fmt::{self, format::FmtSpan},
212 layer::SubscriberExt,
213 util::SubscriberInitExt,
214 EnvFilter,
215 };
216
217 /// Initialize the default logger with INFO level logging.
218 ///
219 /// This sets up structured logging with reasonable defaults for most use cases.
220 /// The logger will respect the `RUST_LOG` environment variable if set.
221 ///
222 /// # Examples
223 ///
224 /// ```rust
225 /// use hyperliquid_backtest::logging::init_logger;
226 ///
227 /// init_logger();
228 /// log::info!("Logger initialized successfully");
229 /// ```
230 pub fn init_logger() {
231 init_logger_with_level("info");
232 }
233
234 /// Initialize the logger with a specific log level.
235 ///
236 /// # Arguments
237 ///
238 /// * `level` - The log level to use (e.g., "debug", "info", "warn", "error")
239 ///
240 /// # Examples
241 ///
242 /// ```rust
243 /// use hyperliquid_backtest::logging::init_logger_with_level;
244 ///
245 /// init_logger_with_level("debug");
246 /// log::debug!("Debug logging enabled");
247 /// ```
248 pub fn init_logger_with_level(level: &str) {
249 let env_filter = EnvFilter::try_from_default_env()
250 .unwrap_or_else(|_| EnvFilter::new(format!("hyperliquid_backtest={}", level)));
251
252 let format = env::var("HYPERLIQUID_LOG_FORMAT").unwrap_or_else(|_| "pretty".to_string());
253 let log_file = env::var("HYPERLIQUID_LOG_FILE").ok();
254
255 let subscriber = tracing_subscriber::registry().with(env_filter);
256
257 match (format.as_str(), log_file) {
258 ("json", Some(file_path)) => {
259 let file = std::fs::OpenOptions::new()
260 .create(true)
261 .append(true)
262 .open(file_path)
263 .expect("Failed to open log file");
264
265 subscriber
266 .with(
267 fmt::layer()
268 .json()
269 .with_writer(file)
270 .with_span_events(FmtSpan::CLOSE)
271 )
272 .init();
273 }
274 ("json", None) => {
275 subscriber
276 .with(
277 fmt::layer()
278 .json()
279 .with_span_events(FmtSpan::CLOSE)
280 )
281 .init();
282 }
283 (_, Some(file_path)) => {
284 let file = std::fs::OpenOptions::new()
285 .create(true)
286 .append(true)
287 .open(file_path)
288 .expect("Failed to open log file");
289
290 subscriber
291 .with(
292 fmt::layer()
293 .pretty()
294 .with_writer(file)
295 .with_span_events(FmtSpan::CLOSE)
296 )
297 .init();
298 }
299 _ => {
300 subscriber
301 .with(
302 fmt::layer()
303 .pretty()
304 .with_span_events(FmtSpan::CLOSE)
305 )
306 .init();
307 }
308 }
309 }
310
311 /// Initialize logger for testing with reduced verbosity.
312 ///
313 /// This is useful for tests where you want to capture logs but don't want
314 /// them to interfere with test output.
315 pub fn init_test_logger() {
316 let _ = tracing_subscriber::fmt()
317 .with_test_writer()
318 .with_env_filter("hyperliquid_backtest=warn")
319 .try_init();
320 }
321
322 /// Create a tracing span for performance monitoring.
323 ///
324 /// This is useful for tracking the performance of specific operations
325 /// like data fetching or backtest calculations.
326 ///
327 /// # Arguments
328 ///
329 /// * `name` - The name of the operation being tracked
330 /// * `details` - Additional details to include in the span
331 ///
332 /// # Examples
333 ///
334 /// ```rust
335 /// use hyperliquid_backtest::logging::performance_span;
336 /// use tracing::Instrument;
337 ///
338 /// async fn fetch_data() -> Result<(), Box<dyn std::error::Error>> {
339 /// let span = performance_span("data_fetch", &[("symbol", "BTC"), ("interval", "1h")]);
340 ///
341 /// async {
342 /// // Your data fetching logic here
343 /// Ok(())
344 /// }
345 /// .instrument(span)
346 /// .await
347 /// }
348 /// ```
349 pub fn performance_span(name: &str, details: &[(&str, &str)]) -> tracing::Span {
350 let span = tracing::info_span!("performance", operation = name);
351
352 // Record additional fields if needed
353 for (key, value) in details {
354 span.record(*key, *value);
355 }
356
357 span
358 }
359}
360
361#[cfg(test)]
362mod tests {
363 pub mod backtest_tests;
364 pub mod strategies_tests;
365 pub mod indicators_tests;
366 pub mod indicators_tests_extended;
367 pub mod funding_report_tests;
368 pub mod csv_export_tests;
369 pub mod csv_export_tests_enhanced;
370 pub mod data_tests;
371 pub mod data_price_tests;
372 pub mod data_conversion_tests;
373 pub mod errors_tests;
374 pub mod commission_tests;
375 pub mod funding_payment_tests;
376 pub mod mock_data;
377 pub mod integration_tests;
378 pub mod performance_tests;
379 pub mod regression_tests;
380 pub mod trading_mode_tests;
381 pub mod unified_data_tests;
382 pub mod unified_data_impl_tests;
383 pub mod standalone_unified_data_tests;
384 pub mod risk_manager_tests;
385 pub mod advanced_risk_controls_tests;
386 pub mod live_trading_tests;
387 pub mod live_trading_safety_tests;
388 pub mod real_time_monitoring_tests;
389 pub mod trading_strategy_tests;
390 // Mode-specific test suites
391 pub mod paper_trading_tests;
392 pub mod live_trading_integration_tests;
393 pub mod strategy_consistency_tests;
394 pub mod performance_stress_tests;
395 pub mod safety_validation_tests;
396 pub mod workflow_tests;
397 pub mod standalone_position_tests;
398}
399
400// Re-export commonly used types
401pub use data::{HyperliquidData, HyperliquidDataFetcher, FundingStatistics};
402pub use backtest::{
403 HyperliquidBacktest, HyperliquidCommission, OrderType, TradingScenario,
404 CommissionTracker, CommissionStats, OrderTypeStrategy
405};
406pub use strategies::{
407 HyperliquidStrategy, TradingSignal, SignalStrength, FundingAwareConfig,
408 funding_arbitrage_strategy, enhanced_sma_cross
409};
410pub use errors::{HyperliquidBacktestError, Result};
411pub use indicators::{
412 FundingPredictionModel, FundingPredictionConfig, FundingPrediction,
413 FundingDirection, FundingVolatility, FundingMomentum, FundingCycle,
414 FundingAnomaly, FundingArbitrageOpportunity, FundingPriceCorrelation,
415 OpenInterestData, OpenInterestChange, LiquidationData, LiquidationImpact,
416 BasisIndicator, FundingRatePredictor
417};
418pub use funding_report::{
419 FundingReport, FundingDistribution, FundingRatePoint,
420 FundingDirectionStats, FundingMetricsByPeriod, FundingPeriodMetric
421};
422pub use backtest::FundingPayment;
423pub use csv_export::{
424 EnhancedCsvExport, EnhancedCsvExportExt, StrategyComparisonData
425};
426pub use trading_mode::{
427 TradingMode, TradingConfig, RiskConfig, SlippageConfig, ApiConfig,
428 TradingModeError
429};
430pub use trading_mode_impl::{
431 TradingModeManager, TradingResult
432};
433pub use unified_data::{
434 Position, OrderRequest, OrderResult, MarketData, Signal, SignalDirection,
435 OrderSide, OrderType as TradingOrderType, TimeInForce, OrderStatus,
436 TradingStrategy, OrderBookLevel, OrderBookSnapshot, Trade
437};
438pub use paper_trading::{
439 PaperTradingEngine, PaperTradingError, SimulatedOrder, PaperTradingMetrics,
440 TradeLogEntry, PaperTradingReport
441};
442pub use real_time_data_stream::{
443 RealTimeDataStream, RealTimeDataError, SubscriptionType, DataSubscription
444};
445pub use risk_manager::{
446 RiskManager, RiskError, RiskOrder, Result as RiskResult
447};
448pub use live_trading::{
449 LiveTradingEngine, LiveTradingError, LiveOrder
450};
451pub use mode_reporting::{
452 ModeReportingManager, CommonPerformanceMetrics, PaperTradingReport as ModeSpecificPaperTradingReport,
453 LiveTradingReport, RealTimePnLReport, MonitoringDashboardData, FundingImpactAnalysis,
454 RiskMetrics, ConnectionMetrics, AlertEntry, OrderSummary
455};
456pub use real_time_monitoring::{
457 MonitoringServer, MonitoringClient, MonitoringManager, MonitoringError,
458 MonitoringMessage, TradeExecutionUpdate, ConnectionStatusUpdate, ConnectionStatus,
459 PerformanceMetricsUpdate
460};
461
462/// Prelude module for convenient imports
463pub mod prelude {
464 pub use crate::data::{HyperliquidData, HyperliquidDataFetcher};
465 pub use crate::backtest::{
466 HyperliquidBacktest, HyperliquidCommission, OrderType, TradingScenario,
467 CommissionTracker, CommissionStats, OrderTypeStrategy
468 };
469 pub use crate::strategies::{
470 HyperliquidStrategy, funding_arbitrage_strategy, enhanced_sma_cross
471 };
472 pub use crate::errors::{HyperliquidBacktestError, Result};
473 pub use crate::indicators::{
474 FundingDirection, FundingPrediction, FundingRatePredictor,
475 OpenInterestData, LiquidationData, BasisIndicator,
476 calculate_funding_volatility, calculate_funding_momentum,
477 calculate_funding_arbitrage, calculate_basis_indicator
478 };
479 pub use crate::funding_report::{
480 FundingReport, FundingDistribution, FundingRatePoint,
481 FundingDirectionStats, FundingMetricsByPeriod, FundingPeriodMetric
482 };
483 pub use crate::backtest::FundingPayment;
484 pub use crate::csv_export::{
485 EnhancedCsvExport, EnhancedCsvExportExt, StrategyComparisonData
486 };
487 pub use crate::logging::{init_logger, init_logger_with_level, performance_span};
488 pub use crate::trading_mode::{
489 TradingMode, TradingModeError
490 };
491 pub use crate::trading_mode_impl::{
492 TradingModeManager, TradingResult
493 };
494 pub use crate::unified_data::{
495 Position, OrderRequest, OrderResult, MarketData, Signal, SignalDirection,
496 OrderSide, TimeInForce, OrderStatus, TradingStrategy,
497 OrderBookLevel, OrderBookSnapshot, Trade
498 };
499 pub use crate::trading_mode::{
500 TradingConfig, RiskConfig, SlippageConfig, ApiConfig
501 };
502 pub use crate::paper_trading::{
503 PaperTradingEngine, PaperTradingError, SimulatedOrder, PaperTradingMetrics,
504 TradeLogEntry, PaperTradingReport
505 };
506 pub use crate::real_time_data_stream::{
507 RealTimeDataStream, RealTimeDataError, SubscriptionType, DataSubscription
508 };
509 pub use crate::risk_manager::{
510 RiskManager, RiskError, RiskOrder, Result as RiskResult
511 };
512 pub use crate::live_trading::{
513 LiveTradingEngine, LiveTradingError, LiveOrder,
514 AlertLevel, AlertMessage, RetryPolicy, SafetyCircuitBreakerConfig
515 };
516 pub use crate::mode_reporting::{
517 ModeReportingManager, CommonPerformanceMetrics, PaperTradingReport as ModeSpecificPaperTradingReport,
518 LiveTradingReport, RealTimePnLReport, MonitoringDashboardData, FundingImpactAnalysis,
519 RiskMetrics, ConnectionMetrics, AlertEntry, OrderSummary
520 };
521 pub use crate::real_time_monitoring::{
522 MonitoringServer, MonitoringClient, MonitoringManager, MonitoringError,
523 MonitoringMessage, TradeExecutionUpdate, ConnectionStatusUpdate, ConnectionStatus,
524 PerformanceMetricsUpdate
525 };
526 pub use chrono::{DateTime, FixedOffset};
527}