triangular_arbitrage_bot/src/queue.h

93 lines
4.8 KiB
C

#ifndef FUSED_QUEUE_H
#define FUSED_QUEUE_H
#include <stdint.h>
#include <stdbool.h>
#include <stdatomic.h>
#include "book.h"
#include "triangle.h"
#define MAX_SIGNAL_LEN 4096
#define Spsc_QUEUE_DEPTH 1024
/* Single price+size level in an order book snapshot */
typedef struct {
double price; /* price at this level */
double size; /* available size at this level */
} book_level_t;
/* Snapshot of one leg's order book included in a signal */
typedef struct {
char symbol[SYMBOL_NAME_LEN]; /* trading pair symbol name */
int64_t ts_ms; /* book timestamp (milliseconds) */
book_level_t bids[MAX_BOOK_LEVELS]; /* bid levels (top of book) */
book_level_t asks[MAX_BOOK_LEVELS]; /* ask levels (top of book) */
uint8_t bid_count; /* number of valid bid levels */
uint8_t ask_count; /* number of valid ask levels */
} signal_book_t;
/* One leg of a triangular arbitrage signal */
typedef struct {
char symbol[SYMBOL_NAME_LEN]; /* trading pair symbol */
char input_currency[CURRENCY_NAME_LEN]; /* currency being traded in */
char output_currency[CURRENCY_NAME_LEN]; /* currency being traded out */
char fee_currency[CURRENCY_NAME_LEN]; /* currency used to pay fees */
double fee_rate; /* fee rate for this leg */
double exchange_rate; /* computed exchange rate for the leg */
char side[5]; /* trade side: "buy" or "sell" */
char order_param[32]; /* order parameter string for the executor */
double quote_volume; /* notional quote volume for the leg */
double base_increment; /* base asset lot size step */
double quote_increment; /* quote asset lot size step */
double base_min_size; /* minimum base asset order size */
} signal_leg_t;
/* Collection of up to 3 legs comprising a triangular signal */
typedef struct {
uint8_t leg_count; /* number of legs (typically 3) */
signal_leg_t legs[3]; /* the individual leg descriptors */
} signal_legs_t;
/* Entry describing one triangular arbitrage opportunity */
typedef struct {
char triangle_key[CURRENCY_NAME_LEN * 3 + 4]; /* unique triangle identifier e.g. "BTC-ETH-USDT" */
char primary_quote[CURRENCY_NAME_LEN]; /* primary quote currency of the triangle */
double predicted_bps; /* predicted profit in basis points */
char max_volume[32]; /* max trade volume as string */
double starting_volume; /* recommended starting volume */
bool live; /* whether this entry is from live (vs simulated) data */
int64_t ts_ms; /* signal generation timestamp */
int64_t book_ts_ms; /* reference order book timestamp */
int64_t t_sock_arrive_ms; /* timestamp when bytes arrived at SSL_read */
int64_t t_arrive_ms; /* arrival timestamp at evaluator (post-parse) */
int64_t t_eval_ms; /* evaluation completion timestamp */
uint8_t book_count; /* number of books used (typically 3) */
signal_book_t books[3]; /* order book snapshots for each leg */
signal_legs_t legs; /* leg descriptors for execution */
} signal_entry_t;
/* Lock-free single-producer single-consumer queue for signal entries */
typedef struct {
signal_entry_t *buffer; /* ring buffer of entries */
_Atomic uint32_t head; /* consumer read index (atomic) */
_Atomic uint32_t tail; /* producer write index (atomic) */
int eventfd; /* eventfd for waking consumer */
uint32_t depth; /* capacity of the ring buffer */
uint32_t dropped; /* count of dropped entries due to full queue */
} spsc_queue_t;
/* Initialise an SPSC queue backed by a wakeup eventfd */
int spsc_init(spsc_queue_t *q, int wakeup_fd);
/* Destroy an SPSC queue and free its buffer */
void spsc_destroy(spsc_queue_t *q);
/* Push an entry into the queue (non-blocking); returns false if full */
bool spsc_push(spsc_queue_t *q, const signal_entry_t *entry);
/* Pop an entry from the queue (non-blocking); returns false if empty */
bool spsc_pop(spsc_queue_t *q, signal_entry_t *entry);
/* Returns true if the queue is empty */
bool spsc_empty(const spsc_queue_t *q);
/* Returns the number of entries currently in the queue */
uint32_t spsc_count(const spsc_queue_t *q);
#endif