WU Trading Library 0.2.0
A backtesting and trading strategy library
Loading...
Searching...
No Matches
runner.c
Go to the documentation of this file.
1#include <stdlib.h>
2#include <stdio.h>
3#include <string.h>
4#include "wu.h"
5
6static bool validate_input_type(WU_DataType reader_type, WU_DataType expected_type) {
7 if (reader_type == expected_type) {
8 return true;
9 }
10 if (reader_type == WU_DATA_TYPE_CANDLE && expected_type == WU_DATA_TYPE_SINGLE_VALUE) {
11 return true;
12 }
13 if (reader_type == WU_DATA_TYPE_TRADE && expected_type == WU_DATA_TYPE_SINGLE_VALUE) {
14 return true;
15 }
16 return false;
17}
18
19static WU_DataType get_reader_data_type(WU_Reader reader) {
20 WU_CsvReader csv = (WU_CsvReader)reader;
21 if (csv) {
22 return csv->data_type;
23 }
25}
26
27static void run_backtest(WU_Runner runner, bool verbose) {
28 if (!runner) return;
29 WU_Portfolio portfolio = runner->portfolio;
30 WU_Strategy strategy = runner->strategy;
31 void** input_buffers = malloc(sizeof(void*) * runner->num_readers);
32 WU_Single* converted = malloc(sizeof(WU_Single) * runner->num_readers);
33 if (!input_buffers || !converted) {
34 fprintf(stderr, "Error: Failed to allocate input buffers\n");
35 free(input_buffers);
36 free(converted);
37 return;
38 }
39 if (verbose) {
40 printf("Starting backtest with %d input(s)...\n", runner->num_readers);
41 }
42 int iteration = 0;
43 while (true) {
44 bool all_valid = true;
45 for (int i = 0; i < runner->num_readers; i++) {
46 void* data = wu_reader_next(runner->readers[i]);
47 if (!data) {
48 all_valid = false;
49 break;
50 }
51 WU_DataType actual_type = ((WU_Candle*)data)->data_type;
52 WU_DataType expected_type = strategy->input_types[i];
53 if (actual_type == WU_DATA_TYPE_CANDLE &&
54 expected_type == WU_DATA_TYPE_SINGLE_VALUE) {
55 converted[i] = wu_candle_to_single_value((WU_Candle*)data);
56 input_buffers[i] = &converted[i];
57 }
58 else if (actual_type == WU_DATA_TYPE_TRADE &&
59 expected_type == WU_DATA_TYPE_SINGLE_VALUE) {
60 converted[i] = wu_trade_to_single_value((WU_Trade*)data);
61 input_buffers[i] = &converted[i];
62 }
63 else if (actual_type == expected_type) {
64 input_buffers[i] = data;
65 }
66 else {
67 fprintf(stderr, "Error at iteration %d: Input %d has type %d but strategy expects type %d\n",
68 iteration, i, actual_type, expected_type);
69 all_valid = false;
70 break;
71 }
72 }
73 if (!all_valid) {
74 break;
75 }
76 wu_strategy_update(strategy, (const void**)input_buffers);
77 wu_portfolio_update(portfolio, strategy->signal_buffer);
78 if (verbose && iteration % 100 == 0) {
79 printf("Iteration %d | Signals: %d | Value: %.2f | P&L: %.2f\n",
80 iteration,
81 strategy->num_outputs,
82 wu_portfolio_value(portfolio),
83 wu_portfolio_pnl(portfolio));
84 }
85
86 iteration++;
87 }
88 if (verbose) {
89 printf("Backtest completed after %d iterations\n", iteration);
90 }
91 free(input_buffers);
92 free(converted);
93}
94
95WU_Runner wu_runner_new(
96 WU_Portfolio portfolio,
97 WU_Strategy strategy,
98 WU_Reader readers[]
99) {
100 if (!portfolio || !strategy || !readers) {
101 fprintf(stderr, "Error: NULL argument passed to wu_runner_new\n");
102 return NULL;
103 }
104 int num_readers = wu_strategy_num_inputs(strategy);
105 for (int i = 0; i < num_readers; i++) {
106 if (!readers[i]) {
107 fprintf(stderr, "Error: Reader %d is NULL\n", i);
108 return NULL;
109 }
110 WU_DataType reader_type = get_reader_data_type(readers[i]);
111 WU_DataType expected_type = strategy->input_types[i];
112 if (!validate_input_type(reader_type, expected_type)) {
113 fprintf(stderr, "Error: Reader %d produces type %d but strategy expects type %d\n",
114 i, reader_type, expected_type);
115 return NULL;
116 }
117 }
118 WU_Runner runner = malloc(sizeof(struct WU_Runner_));
119 if (!runner) {
120 fprintf(stderr, "Error: Failed to allocate runner\n");
121 return NULL;
122 }
123 runner->readers = malloc(sizeof(WU_Reader) * num_readers);
124 if (!runner->readers) {
125 fprintf(stderr, "Error: Failed to allocate reader array\n");
126 free(runner);
127 return NULL;
128 }
129 memcpy(runner->readers, readers, sizeof(WU_Reader) * num_readers);
130 runner->portfolio = portfolio;
131 runner->strategy = strategy;
132 runner->num_readers = num_readers;
133 runner->run = run_backtest;
134 return runner;
135}
136
137void wu_runner_free(WU_Runner runner) {
138 if (!runner) return;
139 wu_portfolio_delete(runner->portfolio);
140 wu_strategy_delete(runner->strategy);
141 for (int i = 0; i < runner->num_readers; i++) {
142 wu_reader_delete(runner->readers[i]);
143 }
144 free(runner->readers);
145 free(runner);
146}
#define wu_trade_to_single_value(trade)
Definition data.h:69
#define wu_candle_to_single_value(candle)
Definition data.h:66
#define wu_portfolio_update(portfolio, signals)
The update macro allows you to update the portfolio with new signals.
Definition portfolios.h:28
#define wu_portfolio_delete(portfolio)
Frees the resources associated with the portfolio.
Definition portfolios.h:52
#define wu_portfolio_value(portfolio)
Calculates the current value of the portfolio.
Definition portfolios.h:37
#define wu_portfolio_pnl(portfolio)
Calculates the profit and loss (PnL) of the portfolio.
Definition portfolios.h:45
#define wu_reader_delete(reader)
Definition readers.h:25
#define wu_reader_next(reader)
Definition readers.h:21
void wu_runner_free(WU_Runner runner)
Definition runner.c:137
static bool validate_input_type(WU_DataType reader_type, WU_DataType expected_type)
Definition runner.c:6
static WU_DataType get_reader_data_type(WU_Reader reader)
Definition runner.c:19
static void run_backtest(WU_Runner runner, bool verbose)
Definition runner.c:27
WU_Runner wu_runner_new(WU_Portfolio portfolio, WU_Strategy strategy, WU_Reader readers[])
Creates a new runner with multiple readers.
Definition runner.c:95
#define wu_strategy_delete(strategy)
Definition strategies.h:24
#define wu_strategy_num_inputs(strategy)
Definition strategies.h:29
#define wu_strategy_update(strategy, inputs)
Definition strategies.h:21
WU_Candle represents an aggregated data point to represent how prices moved within a specific time pe...
Definition data.h:15
WU_Runner is a backtest runner that processes data from multiple readers, updates a strategy,...
Definition runners.h:32
WU_Single represents a single value with a timestamp, which can be a price, an indicator value,...
Definition data.h:47
WU_Trade represents a single trade in the market, including the timestamp, price, volume,...
Definition data.h:32
WU_DataType
WU_DataType represents the type of input data, which can be a candle, a trade, or a single value.
Definition types.h:24
@ WU_DATA_TYPE_TRADE
Definition types.h:26
@ WU_DATA_TYPE_SINGLE_VALUE
Definition types.h:27
@ WU_DATA_TYPE_CANDLE
Definition types.h:25