Crypto backtesting
Loading...
Searching...
No Matches
backtest.cxx
Go to the documentation of this file.
1#include "backtest.h"
2#include "fx/core.h"
3#include "fx/trade.h"
4#include "utils.h"
5#include <mutex>
6#include <string>
7
8/// Take a vector of files to backtest with testing params, and return a summary
9/// of trades across all files
10std::vector<trade_t> to_summary(std::span<const std::string_view> files) {
11
12 // Results container and access mutex
13 std::vector<trade_t> results;
14 auto &&results_mutex = std::mutex{};
15
16 // For each file
17 std::ranges::for_each(files, [&](auto &&csv) {
18 using namespace std::views;
19
20 // Get price data from disk
21 auto &&contents = file_read(csv);
22 auto &&series = to_series3(contents);
23
24 // Calculate all trade windows, remove non trades and
25 // fold each window into a single price
26 auto &&entries = series | slide(fx::win) | filter(fx::is_entry2) |
27 transform(fx::to_last);
28
29 // Evaluate each trade
30 for (auto &&x : entries) {
31
32 // Find the entry iterator
33 auto &&entry_it = std::ranges::find_if(
34 series, [&](auto y) { return fx::to_time(x) == fx::to_time(y); });
35
36 // Calculate index into series
37 auto &&offset = std::ranges::distance(std::cbegin(series), entry_it);
38
39 // Calculate trade window size but don't run off the end
40 auto trade_window_size =
41 std::min(std::size(series) - offset, static_cast<size_t>(fx::win));
42
43 // Create trade window by dropping everything before the entry
44 // iterator
45 auto &&trade = std::vector<std::vector<double>>{
46 std::cbegin(series) + offset,
47 std::cbegin(series) + offset + trade_window_size};
48
49 // Calculate profit
50 auto &&entry = fx::to_first(trade);
51 auto &&exit = fx::to_exit(trade);
52 auto &&profit = fx::to_profit(fx::to_spot(entry), fx::to_spot(exit));
53
54 // Calculate duration of trade
55 auto &&entry_time = fx::to_time(entry);
56 auto &&exit_time = fx::to_time(exit);
57 auto &&duration = exit_time - entry_time;
58
59 // Trim file name for reporting
60 auto &&to_token = csv | take(std::ranges::size(csv) - 4uz) | drop(12uz);
61
62 // Store results
63 std::scoped_lock lock(results_mutex);
64 results.push_back({to_token, entry_time, fx::to_spot(entry),
65 fx::to_spot(exit), profit, duration});
66 }
67 });
68
69 // Sort results
70 std::ranges::sort(
71 results, [](auto a, auto b) { return std::get<1>(a) > std::get<1>(b); });
72
73 return results;
74}
std::vector< trade_t > to_summary(std::span< const std::string_view > files)
Definition backtest.cxx:10
std::vector< std::vector< double > > to_series3(const std::string &csv)
Open a CSV file and return a vector of floating points for each row.
Definition file.cxx:90
std::string file_read(const std::string_view file_name)
Open a file a return a string of the contents.
Definition file.cxx:12
constexpr auto to_first(std::ranges::range auto &&xs)
Return the first entry in a series.
Definition core.h:19
constexpr auto to_time(std::ranges::range auto &&xs)
Get time of a data point.
Definition ohlc.h:9
constexpr auto to_last
Return the last entry in a series.
Definition core.h:25
auto to_exit
Find an exit in a series.
Definition trade.h:152
constexpr auto win
The number of prices in a trading window.
Definition constants.h:6
constexpr auto to_profit(auto &&entry, auto &&exit)
Calculate profit from a trade.
Definition core.h:59
auto is_entry2
Calculate if the final price is an entry.
Definition trade.h:232
constexpr auto to_spot
Calculate spot value, note we don't average all of the OHLC prices.
Definition trade.h:32