Skip to content

Commit

Permalink
feat(algo): add backtest_on_all_seen_data method and related enhancem…
Browse files Browse the repository at this point in the history
…ents

- Implemented `backtest_on_all_seen_data` in `Algorithm` to perform comprehensive backtesting on all available data, including detailed logging with `instrument`.
- Updated `TestData` to set default accuracy to `0.5` when no trades are present, improving metric reliability.
- Enhanced logging in `main.rs` by replacing `eprintln!` with `tracing::error` for better log management.
- Adjusted the loop range for `depth` in `run` from `1..75` to `1..60` to optimize performance and reduce unnecessary iterations.
- Added `test_algo_on_all_data` in `tests/algorithm.rs` to validate the new backtesting functionality and ensure algorithm reliability.

This commit enhances the backtesting capabilities of the algorithm, improves logging practices, and includes necessary tests to maintain code quality.
  • Loading branch information
noahbclarkson committed Nov 19, 2024
1 parent af561c5 commit 36c9406
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 4 deletions.
26 changes: 26 additions & 0 deletions src/algorithm/algo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,32 @@ impl Algorithm {
Ok(result)
}

#[instrument(skip(dataset, config, self))]
pub fn backtest_on_all_seen_data(
&self,
dataset: &IntervalData,
config: &KryptoConfig,
) -> Result<AlgorithmResult, KryptoError> {
debug!("Running backtest on all seen data");

// Prepare the dataset using existing settings
let (features, _, candles) = Self::prepare_dataset(dataset, &self.settings);

// Use the trained PLS model to make predictions on all features
let predictions = predict(&self.pls, &features);

// Create TestData with the predictions and candles
let test_data = TestData::new(predictions, candles.clone(), config)?;

// Evaluate performance metrics
let monthly_return = test_data.monthly_return;
let accuracy = test_data.accuracy;

let result = AlgorithmResult::new(monthly_return, accuracy);
info!("Backtest on all seen data result: {}", result);
Ok(result)
}

#[instrument(skip(dataset))]
fn prepare_dataset(
dataset: &IntervalData,
Expand Down
2 changes: 1 addition & 1 deletion src/algorithm/test_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ impl TestData {
let accuracy = if total_trades > 0 {
inner.correct as f64 / total_trades as f64
} else {
0.0
0.5
};
let monthly_return = if months > 0.0 && inner.cash.is_finite() && inner.cash > 0.0 && inner.cash_history.len() > 1 {
(inner.cash / 1000.0).powf(1.0 / months) - 1.0
Expand Down
6 changes: 3 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ use krypto::{
error::KryptoError,
logging::setup_tracing,
};
use tracing::info;
use tracing::{error, info};

pub fn main() {
let (_, file_guard) = setup_tracing(Some("logs")).expect("Failed to set up tracing");
let result = run();
if let Err(e) = result {
eprintln!("Error: {:?}", e);
error!("Error: {:?}", e);
}
drop(file_guard);
}
Expand Down Expand Up @@ -41,7 +41,7 @@ fn run() -> Result<(), KryptoError> {
for symbol in interval_data.keys() {
info!("Symbol: {}", symbol);
for n in 1..50 {
for depth in 1..75 {
for depth in 1..60 {
if n >= depth * TECHNICAL_COUNT {
continue;
}
Expand Down
20 changes: 20 additions & 0 deletions tests/algorithm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,23 @@ fn test_algorithm() {
}
}
}

#[test]
fn test_algo_on_all_data() {
let config = KryptoConfig {
start_date: "2019-01-01".to_string(),
symbols: vec!["BTCUSDT".to_string(), "ETHUSDT".to_string(), "BNBUSDT".to_string()],
intervals: vec![Interval::TwoHours],
..Default::default()
};
let (dataset, _gaurds) = setup_default_data("algo_on_all_unseen_data", Some(config.clone()));
info!("Shape: {:?}", dataset.shape());
let interval = dataset.keys().next().unwrap();
let interval_data = dataset.get(interval).unwrap();
let symbol = interval_data.keys().next().unwrap();
let settings = AlgorithmSettings::new(10, 18, symbol);
let result = Algorithm::load(interval_data, settings, &config).unwrap();
info!("Algorithm Loaded Successfully");
let algo_result = result.backtest_on_all_seen_data(interval_data, &config).unwrap();
info!("Algorithm Result: {}", algo_result);
}

0 comments on commit 36c9406

Please sign in to comment.