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}