fix: use double-precision timestamps for sub-millisecond signal timing
This commit is contained in:
parent
17aac4b4ef
commit
60257f068f
|
|
@ -21,10 +21,10 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
static inline int64_t now_ms(void) {
|
static double now_ms(void) {
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
clock_gettime(CLOCK_REALTIME, &ts);
|
clock_gettime(CLOCK_REALTIME, &ts);
|
||||||
return (int64_t)ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
|
return (double)ts.tv_sec * 1000.0 + (double)ts.tv_nsec / 1000000.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Copied from executor.c for paper-trade simulation ── */
|
/* ── Copied from executor.c for paper-trade simulation ── */
|
||||||
|
|
@ -54,7 +54,7 @@ void evaluator_init(evaluator_t *ev, const triangle_set_t *triangles,
|
||||||
ev->stats.best_triangle_key[0] = '\0';
|
ev->stats.best_triangle_key[0] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
bool evaluate_symbol(evaluator_t *ev, uint16_t symbol_idx, int64_t t_sock_arrive_ms, int64_t t_arrive_ms) {
|
bool evaluate_symbol(evaluator_t *ev, uint16_t symbol_idx, int64_t t_sock_arrive_ms, double t_arrive_ms) {
|
||||||
const triangle_set_t *tris = ev->triangles;
|
const triangle_set_t *tris = ev->triangles;
|
||||||
const order_book_t *books = ev->books;
|
const order_book_t *books = ev->books;
|
||||||
const config_t *cfg = ev->cfg;
|
const config_t *cfg = ev->cfg;
|
||||||
|
|
@ -79,7 +79,7 @@ bool evaluate_symbol(evaluator_t *ev, uint16_t symbol_idx, int64_t t_sock_arrive
|
||||||
uint32_t *tri_flat = tris->tri_flat;
|
uint32_t *tri_flat = tris->tri_flat;
|
||||||
if (!tri_flat) return false;
|
if (!tri_flat) return false;
|
||||||
|
|
||||||
static int64_t last_status_ms = 0;
|
static double last_status_ms = 0.0;
|
||||||
|
|
||||||
for (uint32_t j = 0; j < count; j++) {
|
for (uint32_t j = 0; j < count; j++) {
|
||||||
uint32_t i = tri_flat[offset + j];
|
uint32_t i = tri_flat[offset + j];
|
||||||
|
|
@ -161,7 +161,7 @@ bool evaluate_symbol(evaluator_t *ev, uint16_t symbol_idx, int64_t t_sock_arrive
|
||||||
}
|
}
|
||||||
if (net_bps < ev->stats.worst_net_bps) ev->stats.worst_net_bps = net_bps;
|
if (net_bps < ev->stats.worst_net_bps) ev->stats.worst_net_bps = net_bps;
|
||||||
|
|
||||||
int64_t now = now_ms();
|
double now = now_ms();
|
||||||
if (now - last_status_ms >= 30000) {
|
if (now - last_status_ms >= 30000) {
|
||||||
last_status_ms = now;
|
last_status_ms = now;
|
||||||
log_write_screen("[STATUS] evals=%lu signals=%lu "
|
log_write_screen("[STATUS] evals=%lu signals=%lu "
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ typedef struct {
|
||||||
uint64_t triangles_skipped; /* count of triangles skipped for other reasons */
|
uint64_t triangles_skipped; /* count of triangles skipped for other reasons */
|
||||||
double best_net_bps; /* best net profit seen (basis points) */
|
double best_net_bps; /* best net profit seen (basis points) */
|
||||||
double worst_net_bps; /* worst net profit seen (basis points) */
|
double worst_net_bps; /* worst net profit seen (basis points) */
|
||||||
int64_t last_eval_ts_ms; /* timestamp of last evaluation (milliseconds) */
|
double last_eval_ts_ms; /* timestamp of last evaluation (milliseconds) */
|
||||||
char best_triangle_key[48]; /* triangle key that produced best_net_bps */
|
char best_triangle_key[48]; /* triangle key that produced best_net_bps */
|
||||||
} eval_stats_t;
|
} eval_stats_t;
|
||||||
|
|
||||||
|
|
@ -37,6 +37,6 @@ void evaluator_init(evaluator_t *ev, const triangle_set_t *triangles,
|
||||||
executor_slot_t *slots, int n_slots, bool kcs_discount);
|
executor_slot_t *slots, int n_slots, bool kcs_discount);
|
||||||
|
|
||||||
/* Evaluate all triangles involving the given symbol; returns true if a signal was fired */
|
/* Evaluate all triangles involving the given symbol; returns true if a signal was fired */
|
||||||
bool evaluate_symbol(evaluator_t *ev, uint16_t symbol_idx, int64_t t_sock_arrive_ms, int64_t t_arrive_ms);
|
bool evaluate_symbol(evaluator_t *ev, uint16_t symbol_idx, int64_t t_sock_arrive_ms, double t_arrive_ms);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -178,10 +178,10 @@ void executor_execute_triangle(executor_thread_t *et,
|
||||||
double exec_start_mono = now_mono_ms();
|
double exec_start_mono = now_mono_ms();
|
||||||
double leg_timings[6] = {0}; /* leg0_order, leg0_fill, leg1_order, leg1_fill, leg2_order, leg2_fill */
|
double leg_timings[6] = {0}; /* leg0_order, leg0_fill, leg1_order, leg1_fill, leg2_order, leg2_fill */
|
||||||
snprintf(corr_id, sizeof(corr_id), "%08x%08x%08x%08x",
|
snprintf(corr_id, sizeof(corr_id), "%08x%08x%08x%08x",
|
||||||
(unsigned)(uintptr_t)&sig->legs.legs[0] ^ (unsigned)sig->ts_ms,
|
(unsigned)(uintptr_t)&sig->legs.legs[0] ^ (unsigned)(uint64_t)sig->ts_ms,
|
||||||
(unsigned)sig->ts_ms ^ (unsigned)sig->book_ts_ms,
|
(unsigned)(uint64_t)sig->ts_ms ^ (unsigned)sig->book_ts_ms,
|
||||||
(unsigned)sig->predicted_bps,
|
(unsigned)sig->predicted_bps,
|
||||||
(unsigned)sig->t_arrive_ms);
|
(unsigned)(uint64_t)sig->t_arrive_ms);
|
||||||
|
|
||||||
double leg_output[3] = {0};
|
double leg_output[3] = {0};
|
||||||
double fills[3][6] = {{0}}; /* leg, output, avg_price, fee, input_vol, latency_ms */
|
double fills[3][6] = {{0}}; /* leg, output, avg_price, fee, input_vol, latency_ms */
|
||||||
|
|
@ -410,13 +410,13 @@ void executor_execute_triangle(executor_thread_t *et,
|
||||||
/* ── Build timing string (t0 = book_update_arrived = 0.0ms) ── */
|
/* ── Build timing string (t0 = book_update_arrived = 0.0ms) ── */
|
||||||
char timings_str[512] = "";
|
char timings_str[512] = "";
|
||||||
int tp = 0;
|
int tp = 0;
|
||||||
int64_t book_base = sig->t_arrive_ms;
|
double book_base = sig->t_arrive_ms;
|
||||||
|
|
||||||
if (book_base > 0) {
|
if (book_base > 0) {
|
||||||
if (sig->book_ts_ms > 0)
|
if (sig->book_ts_ms > 0)
|
||||||
tp += snprintf(timings_str + tp, sizeof(timings_str) - tp,
|
tp += snprintf(timings_str + tp, sizeof(timings_str) - tp,
|
||||||
"t-1_snapshot=%.3fms ",
|
"t-1_snapshot=%.3fms ",
|
||||||
(double)((int64_t)sig->book_ts_ms - book_base));
|
sig->book_ts_ms - book_base);
|
||||||
|
|
||||||
tp += snprintf(timings_str + tp, sizeof(timings_str) - tp,
|
tp += snprintf(timings_str + tp, sizeof(timings_str) - tp,
|
||||||
"t0_arrival=0.0ms ");
|
"t0_arrival=0.0ms ");
|
||||||
|
|
@ -424,9 +424,9 @@ void executor_execute_triangle(executor_thread_t *et,
|
||||||
if (sig->ts_ms > 0)
|
if (sig->ts_ms > 0)
|
||||||
tp += snprintf(timings_str + tp, sizeof(timings_str) - tp,
|
tp += snprintf(timings_str + tp, sizeof(timings_str) - tp,
|
||||||
"t1_signal=%.3fms ",
|
"t1_signal=%.3fms ",
|
||||||
(double)((int64_t)sig->ts_ms - book_base));
|
sig->ts_ms - book_base);
|
||||||
|
|
||||||
double sig_recv = (double)(exec_start_rt - book_base);
|
double sig_recv = exec_start_rt - book_base;
|
||||||
for (int l = 0; l < 3; l++) {
|
for (int l = 0; l < 3; l++) {
|
||||||
double o = leg_timings[l * 2];
|
double o = leg_timings[l * 2];
|
||||||
double f = leg_timings[l * 2 + 1];
|
double f = leg_timings[l * 2 + 1];
|
||||||
|
|
|
||||||
|
|
@ -98,11 +98,11 @@ typedef struct {
|
||||||
char max_volume[32];
|
char max_volume[32];
|
||||||
double starting_volume;
|
double starting_volume;
|
||||||
bool live;
|
bool live;
|
||||||
int64_t ts_ms;
|
double ts_ms;
|
||||||
int64_t book_ts_ms;
|
int64_t book_ts_ms;
|
||||||
int64_t t_sock_arrive_ms;
|
int64_t t_sock_arrive_ms;
|
||||||
int64_t t_arrive_ms;
|
double t_arrive_ms;
|
||||||
int64_t t_eval_ms;
|
double t_eval_ms;
|
||||||
uint8_t book_count;
|
uint8_t book_count;
|
||||||
signal_book_t books[3];
|
signal_book_t books[3];
|
||||||
signal_legs_t legs;
|
signal_legs_t legs;
|
||||||
|
|
|
||||||
|
|
@ -42,10 +42,10 @@ uint64_t ws_client_now_ms(void) {
|
||||||
return now_ms_impl();
|
return now_ms_impl();
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t now_realtime_ms(void) {
|
static double now_realtime_ms(void) {
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
clock_gettime(CLOCK_REALTIME, &ts);
|
clock_gettime(CLOCK_REALTIME, &ts);
|
||||||
return (uint64_t)ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
|
return (double)ts.tv_sec * 1000.0 + (double)ts.tv_nsec / 1000000.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset a WebSocket connection to its initial disconnected state, freeing
|
/* Reset a WebSocket connection to its initial disconnected state, freeing
|
||||||
|
|
@ -955,7 +955,7 @@ int ws_client_read(ws_client_t *client, uint32_t conn_idx) {
|
||||||
|
|
||||||
/* Flush: evaluate all symbols updated in this burst */
|
/* Flush: evaluate all symbols updated in this burst */
|
||||||
if (dirty_count > 0) {
|
if (dirty_count > 0) {
|
||||||
int64_t t_arrive = (int64_t)now_realtime_ms();
|
double t_arrive = now_realtime_ms();
|
||||||
for (uint32_t d = 0; d < dirty_count; d++) {
|
for (uint32_t d = 0; d < dirty_count; d++) {
|
||||||
evaluate_symbol(client->evaluator, dirty[d],
|
evaluate_symbol(client->evaluator, dirty[d],
|
||||||
conn->t_sock_arrive_ms, t_arrive);
|
conn->t_sock_arrive_ms, t_arrive);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue