├── .gitignore ├── .travis.yml ├── GNUmakefile ├── Makefile.am ├── README.md ├── build-aux ├── Makefile.am ├── yuck-coru.c.m4 ├── yuck-coru.h.m4 ├── yuck-scmver.c ├── yuck-scmver.h ├── yuck-scmver.m4 ├── yuck.am ├── yuck.c ├── yuck.m4 ├── yuck.man.m4 ├── yuck.mk └── yuck.yuck ├── clob.pc.in ├── configure.ac ├── m4 ├── sxe-compiler.m4 ├── sxe-dfp754.m4 ├── sxe-linker.m4 └── yuck.m4 ├── src ├── Makefile.am ├── btree.c ├── btree.h ├── btree_val.h ├── clob.c ├── clob.h ├── clob_type.h.in ├── clob_val.h ├── cloe.c ├── cloe.yuck ├── dfp754_d32.c ├── dfp754_d32.h ├── dfp754_d64.c ├── dfp754_d64.h ├── mmod-auction.c ├── mmod-auction.h ├── mmod-fok.c ├── mmod-fok.h ├── mmod-ioc.c ├── mmod-ioc.h ├── mmod-pdo.c ├── mmod-pdo.h ├── nifty.h ├── plqu.c ├── plqu.h ├── plqu_val.h ├── quos.c ├── quos.h ├── unxs.c ├── unxs.h ├── version.c.in └── version.h ├── test ├── Makefile.am ├── btree_01.c ├── btree_02.c ├── clob_01.c ├── clob_02.c ├── clob_03.c ├── clob_04.c ├── clob_05.c ├── clob_06.c ├── clob_07.c ├── clob_stress_01.c ├── clob_stress_02.c ├── clob_stress_03.c ├── clob_stress_04.c ├── clob_stress_05.c ├── clob_stress_06.c ├── clob_stress_07.c ├── clob_stress_08.c ├── cloe_01.c ├── cloe_02.c ├── cloe_03.c ├── cloe_04.c ├── cloe_05.c ├── cloe_06.c ├── cloe_07.c ├── cloe_08.c ├── cloe_09.c ├── cloe_10.c ├── cloe_11.c ├── cloe_12.c ├── cloe_13.c ├── cloe_14.c ├── cloe_15.c ├── mmod_auction_xetra_01.c ├── mmod_auction_xetra_02.c ├── mmod_auction_xetra_03.c ├── mmod_auction_xetra_04.c ├── mmod_auction_xetra_05.c ├── mmod_auction_xetra_06.c ├── mmod_auction_xetra_07.c ├── mmod_auction_xetra_08.c ├── mmod_auction_xetra_09.c ├── mmod_fill_or_kill_01.c ├── mmod_fill_or_kill_02.c ├── mmod_fill_or_kill_03.c ├── mmod_immediate_or_cancel_01.c ├── mmod_price_discovery_01.c ├── plqu_01.c ├── unxs_order_01.c ├── unxs_order_02.c ├── unxs_order_03.c ├── unxs_order_04.c ├── unxs_order_05.c ├── unxs_order_06.c ├── unxs_order_07.c ├── unxs_order_11.c ├── unxs_order_12.c ├── unxs_order_13.c ├── unxs_order_14.c ├── unxs_order_15.c ├── unxs_order_16.c ├── unxs_order_17.c ├── unxs_order_18.c ├── unxs_order_19.c ├── unxs_order_20.c ├── unxs_xetra_01.c ├── unxs_xetra_02.c ├── unxs_xetra_03.c ├── unxs_xetra_04.c ├── unxs_xetra_05.c ├── unxs_xetra_06.c ├── unxs_xetra_07.c ├── unxs_xetra_08.c └── unxs_xetra_09.c └── version.mk.in /.gitignore: -------------------------------------------------------------------------------- 1 | aclocal.m4 2 | autom4te.cache 3 | configure 4 | ltmain.sh 5 | m4/libtool.m4 6 | m4/lt*.m4 7 | Makefile.in 8 | config.guess 9 | config.sub 10 | install-sh 11 | missing 12 | src/config.h.in 13 | *~ 14 | =build*/ 15 | build/ 16 | depcomp 17 | ++* 18 | Makefile 19 | .version 20 | config.log 21 | config.status 22 | libtool 23 | *.o 24 | config.h 25 | stamp-h1 26 | .deps 27 | .libs 28 | test-driver 29 | compile 30 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | 3 | os: 4 | - linux 5 | 6 | compiler: 7 | - gcc 8 | 9 | before_script: 10 | - autoreconf -vfi 11 | 12 | script: 13 | - ./configure || { cat config.log; false; } 14 | - make 15 | - make check 16 | || { cat test/test-suite.log; false; } 17 | - make distcheck 18 | || { cat clob-*/_build/test/test-suite.log; false; } 19 | 20 | notifications: 21 | email: 22 | - devel@fresse.org 23 | -------------------------------------------------------------------------------- /GNUmakefile: -------------------------------------------------------------------------------- 1 | # This GNUmakefile is used only if you run GNU Make. 2 | 3 | # If the user runs GNU make but has not yet run ./configure, 4 | # give them a diagnostic. 5 | _gl-Makefile := $(wildcard [M]akefile) 6 | ifneq ($(_gl-Makefile),) 7 | 8 | _dist-target_p ?= $(filter-out %clean, $(filter dist%,$(MAKECMDGOALS))) 9 | 10 | include Makefile 11 | 12 | # update the included makefile snippet which sets VERSION variables 13 | version.mk: .version version.mk.in FORCE 14 | -$(AM_V_GEN) \ 15 | if test "$(MAKECMDGOALS)" != "am--refresh"; then \ 16 | $(MAKE) -C "$(top_builddir)/build-aux" $(MAKECMDGOALS); \ 17 | PATH="$(top_builddir)/build-aux:$${PATH}" \ 18 | yuck scmver --ignore-noscm -o $@ --reference $^; \ 19 | if test $$? -eq 3 -a -n "$(_dist-target_p)"; then \ 20 | exec $(MAKE) $(MAKECMDGOALS); \ 21 | fi; \ 22 | fi 23 | 24 | else 25 | 26 | .DEFAULT_GOAL := abort-due-to-no-makefile 27 | $(MAKECMDGOALS): abort-due-to-no-makefile 28 | 29 | abort-due-to-no-makefile: 30 | @echo There seems to be no Makefile in this directory. 1>&2 31 | @echo "You must run ./configure before running 'make'." 1>&2 32 | exit 1 33 | 34 | endif 35 | 36 | .PHONY: FORCE 37 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | include $(top_builddir)/version.mk 2 | 3 | LANG = C 4 | LC_ALL = C 5 | 6 | ACLOCAL_AMFLAGS = -I m4 7 | 8 | SUBDIRS = 9 | EXTRA_DIST = $(DISTCLEANFILES) $(doc_DATA) 10 | DISTCLEANFILES = 11 | CLEANFILES = 12 | doc_DATA = 13 | 14 | pkgconfigdir = @libdir@/pkgconfig 15 | pkgconfig_DATA = 16 | pkgconfig_DATA += clob.pc 17 | DISTCLEANFILES += $(pkgconfig_DATA) 18 | EXTRA_DIST += clob.pc.in 19 | 20 | SUBDIRS += build-aux 21 | SUBDIRS += src 22 | SUBDIRS += test 23 | 24 | DISTCLEANFILES += version.mk 25 | DISTCLEANFILES += .version 26 | EXTRA_DIST += version.mk.in 27 | 28 | ## make sure .version is read-only in the dist 29 | dist-hook: 30 | chmod ugo-w $(distdir)/.version 31 | 32 | clob.pc: .version clob.pc.in 33 | $(AM_V_GEN) PATH="$(top_builddir)/build-aux:$${PATH}" \ 34 | yuck$(EXEEXT) scmver -n \ 35 | --reference .version $(srcdir)/clob.pc.in | \ 36 | $(SHELL) "$(builddir)/config.status" --file=- > $@ 37 | 38 | ## Makefile.am ends here 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | clob 2 | ==== 3 | 4 | A central limit order book designed to support several market models 5 | (uncrossing schemes). Emphasis is on high throughput. 6 | 7 | 8 | Red tape 9 | -------- 10 | 11 | - licensed under [BSD3c][1] 12 | - dependencies: POSIX system, C11 compiler with DFP754 decimal support 13 | 14 | 15 | Features 16 | -------- 17 | 18 | - b+tree based central limit order book 19 | - pluggable uncrossing schemes 20 | - market models: auction, continuous trading 21 | - IEEE-754 decimals 22 | - handles ~360 auctions with 10000 orders each per second 23 | - handles ~6M orders per second in continuous trading mode 24 | - thrice the performance when `double` is used instead of `_Decimal64` 25 | 26 | 27 | Motivation 28 | ---------- 29 | 30 | In academia, we want to study crossed books and the orders that caused 31 | them, or gain insight on the effects of walls of stop orders on 32 | liquidity, or simply study new order types or schemes of uncrossing. 33 | 34 | Off-the-shelf products are mostly unsuitable for academic studies. 35 | 36 | Not only do they often lack support for a batch mode, they also tightly 37 | couple their order book implementation and uncrossing scheme, a bundle 38 | known as *matching engine*, that allows orders or trades to cut corners 39 | under the label of latency or high performance. 40 | 41 | In many cases, it is impossible to extend the functionality of a 42 | matching engine, e.g. to implement the semantics of mid-point orders or 43 | stop orders, or dark liquidity, etc. Nearly all attempts end up in 44 | changing the existing implementation considerably, or, worse, putting a 45 | second implementation to the side of the existing one with no synergy 46 | between them. 47 | 48 | This prompted us to write `clob`, a simple matching engine that's 49 | flexible enough to serve our studies. 50 | 51 | 52 | Patterns 53 | -------- 54 | 55 | A book for continuous auctions: 56 | 57 | while (1) { 58 | next = next_auction(); 59 | 60 | do { 61 | clob_ord_t ord = read_order(); 62 | clob_oid_t oid = clob_add(book, ord); 63 | send_confirmation(oid); 64 | } while (time(NULL) < next); 65 | 66 | mmod_auc_t A = mmod_auction(book); 67 | unxs_auction(book, A.prc, A.qty); 68 | send_executions(book); 69 | } 70 | 71 | Routines `next_auction`, `read_order`, `send_confirmation` and 72 | `send_executions` would have to be written. 73 | 74 | A book for continuous trading: 75 | 76 | while (1) { 77 | clob_ord_t ord = read_order(); 78 | 79 | /* see if order crosses book */ 80 | ord = unxs_order(book, ord); 81 | 82 | if (ord.qty.dis + ord.qty.hid > 0.dd) { 83 | /* put remainder of order into book */ 84 | clob_oid_t oid = clob_add(book, ord); 85 | send_confirmation(oid); 86 | } 87 | 88 | send_executions(book); 89 | send_quotes(book); 90 | } 91 | 92 | where additionally `send_quotes` would have to be written to 93 | disseminate updated quotes. Continuous trading and continuous auction 94 | can freely be mixed as well. 95 | 96 | [1]: http://opensource.org/licenses/BSD-3-Clause 97 | -------------------------------------------------------------------------------- /build-aux/Makefile.am: -------------------------------------------------------------------------------- 1 | LANG = C 2 | LC_ALL = C 3 | 4 | AM_CFLAGS = $(EXTRA_CFLAGS) 5 | 6 | noinst_PROGRAMS = 7 | BUILT_SOURCES = 8 | EXTRA_DIST = 9 | DISTCLEANFILES = 10 | 11 | if !HAVE_YUCK 12 | include yuck.am 13 | endif !HAVE_YUCK 14 | 15 | ## Makefile.am ends here 16 | -------------------------------------------------------------------------------- /build-aux/yuck-coru.h.m4: -------------------------------------------------------------------------------- 1 | /* -*- c -*- */ 2 | changequote`'changequote([,])dnl 3 | changecom([#])dnl 4 | #if !defined INCLUDED_yuck_h_ 5 | #define INCLUDED_yuck_h_ 6 | 7 | #include 8 | 9 | #define YUCK_OPTARG_NONE ((void*)0x1U) 10 | 11 | enum yuck_cmds_e { 12 | pushdef([last], yuck_cmd())pushdef([first], defn([last]))[]dnl 13 | /* value used when no command was specified */ 14 | first = 0U, 15 | 16 | /* actual commands */ 17 | foreachq([cmd], yuck_cmds(), [define([last], yuck_cmd(defn([cmd])))[]last, 18 | ]) 19 | /* convenience identifiers */ 20 | YUCK_NOCMD = first, 21 | YUCK_NCMDS = last 22 | popdef([last])popdef([first])[]dnl 23 | }; 24 | 25 | define([yuck_slot_predecl], [dnl 26 | yuck_iftype([$1], [$2], 27 | [arg,mul], [size_t ]yuck_canon([$1], [$2])[_nargs], 28 | [arg,mul,opt], [size_t ]yuck_canon([$1], [$2])[_nargs], 29 | )dnl 30 | ])dnl 31 | 32 | define([yuck_slot_decl], [dnl 33 | pushdef([pre], [yuck_slot_predecl([$1], [$2])])dnl 34 | pushdef([ident], [yuck_slot_identifier([$1], [$2])])dnl 35 | yuck_iftype([$1], [$2], 36 | [flag], [unsigned int ident;], 37 | [arg], [char *ident;], 38 | [arg,opt], [char *ident;], 39 | [arg,mul], [pre; char **ident;], 40 | [arg,mul,opt], [pre; char **ident;], 41 | [auto], [/* $1 is handled automatically */])dnl 42 | popdef([pre])dnl 43 | popdef([ident])dnl 44 | ])dnl 45 | 46 | ifelse(yuck_cmds(), [], [dnl 47 | typedef struct yuck_s yuck_t; 48 | ], [dnl 49 | typedef union yuck_u yuck_t; 50 | ])dnl 51 | 52 | foreachq([cmd], yuck_cmds(), [ 53 | /* convenience structure for `cmd' */ 54 | struct yuck_cmd_[]defn([cmd])[]_s { 55 | enum yuck_cmds_e [cmd]; 56 | 57 | /* left-over arguments, the command string is never a part of this */ 58 | size_t nargs; 59 | char **args; 60 | foreachq([slot], yuck_idents(), [ 61 | yuck_slot_decl(defn([slot]))[]dnl 62 | ]) 63 | foreachq([slot], yuck_idents(defn([cmd])), [ 64 | yuck_slot_decl(defn([slot]), defn([cmd]))[]dnl 65 | ]) 66 | }; 67 | ]) 68 | 69 | ifelse(yuck_cmds(), [], [dnl 70 | /* generic struct */ 71 | struct yuck_s { 72 | enum yuck_cmds_e cmd; 73 | 74 | /* left-over arguments, 75 | * the command string is never a part of this */ 76 | size_t nargs; 77 | char **args; 78 | 79 | /* slots common to all commands */ 80 | foreachq([slot], yuck_idents(), [ 81 | yuck_slot_decl(defn([slot]))[]dnl 82 | ]) 83 | }; 84 | ], [dnl else 85 | union yuck_u { 86 | /* generic struct */ 87 | struct { 88 | enum yuck_cmds_e cmd; 89 | 90 | /* left-over arguments, 91 | * the command string is never a part of this */ 92 | size_t nargs; 93 | char **args; 94 | 95 | /* slots common to all commands */ 96 | foreachq([slot], yuck_idents(), [dnl 97 | yuck_slot_decl(defn([slot])) 98 | ])dnl 99 | }; 100 | 101 | /* depending on CMD at most one of the following structs is filled in 102 | * if CMD is YUCK_NONE no slots of this union must be accessed */ 103 | foreachq([cmd], yuck_cmds(), [dnl 104 | struct yuck_cmd_[]defn([cmd])[]_s defn([cmd]); 105 | ])dnl 106 | }; 107 | ]) 108 | 109 | pushdef([DECLF], ifdef([YUCK_HEADER], [extern], [static]))[]dnl 110 | DECLF __attribute__((nonnull(1))) int 111 | yuck_parse(yuck_t*, int argc, char *argv[[]]); 112 | DECLF __attribute__((nonnull(1))) void yuck_free(yuck_t*); 113 | 114 | DECLF __attribute__((nonnull(1))) void yuck_auto_help(const yuck_t*); 115 | DECLF __attribute__((nonnull(1))) void yuck_auto_usage(const yuck_t*); 116 | DECLF __attribute__((nonnull(1))) void yuck_auto_version(const yuck_t*); 117 | 118 | /* some hooks */ 119 | #if defined yuck_post_help 120 | DECLF __attribute__((nonnull(1))) void yuck_post_help(const yuck_t*); 121 | #endif /* yuck_post_help */ 122 | 123 | #if defined yuck_post_usage 124 | DECLF __attribute__((nonnull(1))) void yuck_post_usage(const yuck_t*); 125 | #endif /* yuck_post_usage */ 126 | 127 | #if defined yuck_post_version 128 | DECLF __attribute__((nonnull(1))) void yuck_post_version(const yuck_t*); 129 | #endif /* yuck_post_version */ 130 | popdef([DECLF])[]dnl 131 | 132 | #endif /* INCLUDED_yuck_h_ */ 133 | changequote`'dnl 134 | -------------------------------------------------------------------------------- /build-aux/yuck-scmver.h: -------------------------------------------------------------------------------- 1 | /*** yuck-version.h -- snarf versions off project cwds 2 | * 3 | * Copyright (C) 2013-2019 Sebastian Freundt 4 | * 5 | * Author: Sebastian Freundt 6 | * 7 | * This file is part of yuck. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 16 | * 2. Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 20 | * 3. Neither the name of the author nor the names of any contributors 21 | * may be used to endorse or promote products derived from this 22 | * software without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 34 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | * 36 | ***/ 37 | #if !defined INCLUDED_yuck_version_h_ 38 | #define INCLUDED_yuck_version_h_ 39 | 40 | #include "stdlib.h" 41 | 42 | typedef const struct yuck_version_s *yuck_version_t; 43 | 44 | typedef enum { 45 | YUCK_SCM_ERROR = -1, 46 | YUCK_SCM_TARBALL, 47 | YUCK_SCM_GIT, 48 | YUCK_SCM_BZR, 49 | YUCK_SCM_HG, 50 | } yuck_scm_t; 51 | 52 | struct yuck_version_s { 53 | yuck_scm_t scm; 54 | unsigned int dirty:1U; 55 | char vtag[16U]; 56 | unsigned int dist; 57 | /* up to 28bits of revision id (hash for git), 58 | * the lower 4bits denote the length */ 59 | unsigned int rvsn; 60 | }; 61 | 62 | extern const char *const yscm_strs[]; 63 | 64 | 65 | /* public api */ 66 | /** 67 | * Determine SCM version of file(s) in PATH. */ 68 | extern int yuck_version(struct yuck_version_s *restrict v, const char *path); 69 | 70 | /** 71 | * Read a reference file FN and return scm version information. */ 72 | extern int yuck_version_read(struct yuck_version_s *restrict, const char *fn); 73 | 74 | /** 75 | * Write scm version information in V to reference file FN. */ 76 | extern int yuck_version_write(const char *fn, const struct yuck_version_s *v); 77 | 78 | /** 79 | * Write scm version into buffer. */ 80 | extern ssize_t yuck_version_write_fd(int fd, const struct yuck_version_s *v); 81 | 82 | /** 83 | * Compare two version objects, return <0 if V1 < V2, >0 if V1 > V2 and 84 | * 0 if V1 and V2 are considered equal. */ 85 | extern int yuck_version_cmp(yuck_version_t v1, yuck_version_t v2); 86 | 87 | #endif /* INCLUDED_yuck_version_h_ */ 88 | -------------------------------------------------------------------------------- /build-aux/yuck-scmver.m4: -------------------------------------------------------------------------------- 1 | changequote`'changequote([,])dnl 2 | divert([-1]) 3 | changecom([##]) 4 | 5 | ## we used to define YUCK_SCMVER_VERSION in m4 terms here 6 | ## however in C it's so much easier to come by with the same thing 7 | ## so we reserve this file for future (m4-based) goodness 8 | 9 | divert[]dnl 10 | changequote()dnl 11 | -------------------------------------------------------------------------------- /build-aux/yuck.am: -------------------------------------------------------------------------------- 1 | ## automake rules for yuck 2 | ## set the following variables in the including Makefile.am beforehand 3 | ## noinst_PROGRAMS 4 | ## BUILT_SOURCES 5 | ## EXTRA_DIST 6 | ## DISTCLEANFILES 7 | 8 | yuck_CPPFLAGS = -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -D_BSD_SOURCE 9 | yuck_CPPFLAGS += -D_ALL_SOURCE 10 | yuck_CPPFLAGS += -D_DARWIN_C_SOURCE 11 | yuck_CPPFLAGS += -D_NETBSD_SOURCE 12 | 13 | noinst_PROGRAMS += yuck-bootstrap 14 | yuck_bootstrap_SOURCES = yuck.c 15 | yuck_bootstrap_CPPFLAGS = $(yuck_CPPFLAGS) 16 | yuck_bootstrap_CPPFLAGS += -DBOOTSTRAP 17 | yuck_bootstrap_CPPFLAGS += -DWITH_SCMVER 18 | 19 | noinst_PROGRAMS += yuck 20 | yuck_SOURCES = yuck.c yuck.yuck 21 | yuck_SOURCES += yuck-scmver.c yuck-scmver.h yuck-scmver.m4 22 | yuck_SOURCES += yuck.m4 23 | yuck_SOURCES += yuck-coru.c.m4 yuck-coru.h.m4 24 | yuck_SOURCES += yuck.man.m4 25 | yuck_CPPFLAGS += -DYUCK_TEMPLATE_PATH='"$(abs_srcdir)"' 26 | yuck_CPPFLAGS += -DWITH_SCMVER 27 | BUILT_SOURCES += yuck.yucc 28 | 29 | ## aix make wants all prereq's to exist 30 | EXTRA_DIST += yuck.m4i 31 | EXTRA_DIST += yuck.yucc 32 | 33 | DISTCLEANFILES += yuck.m4i yuck.yucc 34 | 35 | ## also include custom Makefile recipes 36 | include $(srcdir)/yuck.mk 37 | -------------------------------------------------------------------------------- /build-aux/yuck.man.m4: -------------------------------------------------------------------------------- 1 | .\" auto generated by yuck -*- nroff -*- 2 | changequote`'changequote([,])dnl 3 | ifdef([YUCK_VERSION], [], [dnl else (!YUCK_VERSION) 4 | ifdef([YUCK_SCMVER_VERSION], [dnl then 5 | define([YUCK_VERSION], [YUCK_SCMVER_VERSION])[]dnl 6 | ], [dnl else (!YUCK_SCMVER_VERSION) 7 | define([YUCK_VERSION], [unknown])dnl 8 | ])dnl 9 | ])dnl 10 | define([ucase], [translit([$1], [abcdefghijklmnopqrstuvwxyz], [ABCDEFGHIJKLMNOPQRSTUVWXYZ])])dnl 11 | ifdef([YUCK_PKG_STR], [], [define([YUCK_PKG_STR], [YUCK_UMB_STR])])dnl 12 | .TH ucase(YUCK_UMB_STR) "1" "YUCK_MAN_DATE" "YUCK_PKG_STR YUCK_VERSION" "User Commands" 13 | .SH NAME 14 | pushdef([umb_desc], [yuck_first_line(yuck_umb_desc())])dnl 15 | pushdef([alt_desc], [manual page for YUCK_PKG_STR YUCK_VERSION])dnl 16 | YUCK_UMB_STR - first_nonnil(umb_desc, alt_desc) 17 | popdef([umb_desc])dnl 18 | popdef([alt_desc])dnl 19 | .SH SYNOPSIS 20 | .B YUCK_UMB_STR 21 | [[\fIOPTION\fR]]...[ ]dnl 22 | ifelse(yuck_cmds(), [], [], [\fICOMMAND\fR]) 23 | []dnl 24 | yuck_esc(dnl 25 | yuck_esc(dnl 26 | yuck_esc(dnl 27 | yuck_esc(dnl 28 | yuck_esc(translit(defn([YUCK_UMB_POSARG]), [[]], []), 29 | [ -], [\fR -]), 30 | [ ], [ \fI]), 31 | [], [\fR\fI]), 32 | [], [\fR]), 33 | [...], [\fR...]) 34 | .SH DESCRIPTION 35 | yuck_umb_desc() 36 | ifelse(yuck_cmds(), [], [], [dnl 37 | 38 | .PP 39 | \fICOMMAND\fR may be one of: 40 | foreachq([__CMD__], yuck_cmds(), [dnl 41 | .TP 42 | .B yuck_cmd_string(__CMD__) 43 | . 44 | yuck_cmd_desc(__CMD__) 45 | ])dnl 46 | ])dnl 47 | 48 | .PP 49 | define([yuck_man_option], [dnl 50 | pushdef([lhs], [yuck_option_help_lhs([$1], [$2])])dnl 51 | yuck_esc(dnl 52 | yuck_esc(dnl 53 | yuck_esc(dnl 54 | yuck_esc(dnl 55 | yuck_esc(dnl 56 | yuck_esc(dnl 57 | yuck_esc(lhs, 58 | [,], [\fR,]), 59 | [ -], [ \fB-]), 60 | [], [\fR]), 61 | [=], [\fR=]), 62 | [=], [=\fI]), 63 | [], [\fR]), 64 | [...], [\fR...])dnl 65 | popdef([lhs])dnl 66 | ]) 67 | Recognized \fIOPTION\fRs: 68 | foreachq([__IDN__], yuck_idents(), [dnl 69 | .TP 70 | .B yuck_man_option(defn([__IDN__]), []) 71 | yuck_option_desc(defn([__IDN__]), []) 72 | ])dnl 73 | dnl 74 | ifelse(yuck_cmds(), [], [], [dnl 75 | .SH COMMANDS 76 | ])dnl 77 | foreachq([__CMD__], yuck_cmds(), [ 78 | .P 79 | .B YUCK_UMB_STR yuck_cmd_string(__CMD__) 80 | [[\fIOPTION\fR]]... 81 | yuck_esc(dnl 82 | yuck_esc(dnl 83 | yuck_esc(dnl 84 | yuck_esc(dnl 85 | yuck_esc(translit(yuck_cmd_posarg(__CMD__), [[]], []), 86 | [ -], [\fR -]), 87 | [ ], [ \fI]), 88 | [], [\fR\fI]), 89 | [], [\fR]), 90 | [...], [\fR...]) 91 | .br 92 | yuck_cmd_desc(C) 93 | .P 94 | \fIOPTION\fRs specific to the \fB[]yuck_cmd_string(__CMD__)\fR command: 95 | foreachq([__IDN__], yuck_idents(__CMD__), [dnl 96 | .TP 97 | .B yuck_option_help_lhs(defn([__IDN__]), defn([__CMD__])) 98 | yuck_option_desc(defn([__IDN__]), defn([__CMD__])) 99 | ])dnl 100 | ])dnl 101 | foreachq([__INC__], defn([YUCK_INCLUDES]), [dnl 102 | include(__INC__) 103 | ]) 104 | ifdef([YUCK_NFO_STR], [ 105 | .SH "SEE ALSO" 106 | The full documentation for 107 | .B YUCK_UMB_STR 108 | is maintained as a Texinfo manual. If the 109 | .B info 110 | and 111 | .B YUCK_UMB_STR 112 | programs are properly installed at your site, the command 113 | .IP 114 | .B info ifelse(YUCK_NFO_STR, YUCK_UMB_STR, [YUCK_NFO_STR], [(YUCK_NFO_STR)YUCK_UMB_STR]) 115 | .PP 116 | should give you access to the complete manual. 117 | ])dnl 118 | .\" yuck.m4man ends here 119 | changequote`'dnl 120 | -------------------------------------------------------------------------------- /build-aux/yuck.mk: -------------------------------------------------------------------------------- 1 | ## bootstrapping rules, made for inclusion in your own Makefiles 2 | yuck.m4i: yuck.yuck 3 | $(MAKE) $(AM_MAKEFLAGS) yuck-bootstrap 4 | $(AM_V_GEN) $(builddir)/yuck-bootstrap$(EXEEXT) $(srcdir)/yuck.yuck > $@ \ 5 | || { rm -f -- $@; false; } 6 | 7 | yuck.yucc: yuck.m4i yuck.m4 yuck-coru.h.m4 yuck-coru.c.m4 8 | $(AM_V_GEN) $(M4) $(srcdir)/yuck.m4 yuck.m4i \ 9 | $(srcdir)/yuck-coru.h.m4 $(srcdir)/yuck-coru.c.m4 | \ 10 | tr '\002\003\016\017' '[]()' > $@ \ 11 | || { rm -f -- $@; false; } 12 | -------------------------------------------------------------------------------- /build-aux/yuck.yuck: -------------------------------------------------------------------------------- 1 | Usage: yuck COMMAND [ARG]... 2 | 3 | Generate command line option parsers for umbrella commands. 4 | 5 | -k, --keep Keep intermediary files. 6 | -o, --output=FILE Output goes into FILE instead of stdout. 7 | 8 | 9 | ## Usages of the single commands 10 | Usage: yuck [OPTION]... gen [FILE]... 11 | 12 | Generate a parser from definitions in FILE, or stdin if omitted. 13 | 14 | -H, --header=FILE Also generate a header file. 15 | --no-auto-flags Do not add auto flags (--help, --version). 16 | --no-auto-help Do not add auto --help flag 17 | --no-auto-version Do not add auto --version flag 18 | --no-auto-actions Do not automatically handle auto flags. 19 | --version=VERSION Hardwire version number. 20 | --custom=FILE Include custom macros from FILE. 21 | -p, --preserve Preserve indentation and newlines. 22 | 23 | 24 | ## GENMAN 25 | Usage: yuck [OPTION]... genman [FILE]... 26 | 27 | Generate a man page from definitions in FILE, or stdin if omitted. 28 | 29 | --version-string=STRING Hardwire version number as STRING. 30 | --version-file=FILE Hardwire version number from FILE. 31 | --package=STRING Use package STRING instead of umbrella. 32 | -i, --include=FILE... Include sections from FILE 33 | --info-page[=NAME] Include reference to Texinfo manual. 34 | 35 | 36 | ## GENDSL 37 | Usage: yuck gendsl [FILE]... 38 | 39 | Generate the intermediary description of definitions from FILE, or stdin 40 | if omitted. 41 | 42 | --no-auto-flags Do not add auto flags (--help, --version). 43 | --no-auto-help Do not add auto --help flag 44 | --no-auto-version Do not add auto --version flag 45 | --no-auto-actions Do not automatically handle auto flags. 46 | --version=VERSION Hardwire version number. 47 | -p, --preserve Preserve indentation and newlines. 48 | 49 | 50 | ## VER 51 | Usage: yuck scmver [PATH] 52 | 53 | Guess version number for SCM controlled PATH. 54 | If PATH is a file run a transformation. 55 | If PATH is a directory just output the version number. 56 | 57 | Transformations are done through the m4 processor: 58 | YUCK_SCMVER_VTAG will expand to the tag name. 59 | YUCK_SCMVER_SCM will expand to the name of the SCM used. 60 | YUCK_SCMVER_DIST will expand to the distance, that is the number of 61 | commits since the last tag. 62 | YUCK_SCMVER_RVSN will expand to the current commit number. 63 | YUCK_SCMVER_FLAG_DIRTY is set for changes in the source tree that have 64 | not yet been committed. 65 | 66 | Definitions in the template yuck-scmver.m4 are prepended, and by 67 | default this defines the YUCK_SCMVER_VERSION macro that expands to the 68 | full version number. 69 | 70 | 71 | -v, --verbose Print additional information on stderr. 72 | --reference=FILE Store version reference in FILE and don't touch 73 | the output file if nothing has changed. 74 | -f, --force Force operation even if the current scm version 75 | coincides with the reference version. 76 | -n, --use-reference Use version number provided in the reference 77 | file instead of determining it. 78 | --ignore-noscm Don't treat no scm as error. 79 | 80 | 81 | Usage: yuck config 82 | 83 | Output config values for yuck. 84 | 85 | --m4 Print m4 value used during yuck build. 86 | -------------------------------------------------------------------------------- /clob.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | includedir=@includedir@ 4 | headerdir=@headerdir@ 5 | libdir=@libdir@ 6 | datadir=@datarootdir@ 7 | dfp754_CFLAGS=@dfp754_CFLAGS@ 8 | dfp754_LIBS=@dfp754_LIBS@ 9 | 10 | Name: @PACKAGE_NAME@ 11 | Description: Simple limit order book and matching engine. 12 | Version: YUCK_SCMVER_VERSION 13 | Libs: -L${libdir} -lclob ${dfp754_LIBS} 14 | Cflags: -I${includedir} ${dfp754_CFLAGS} 15 | 16 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | dnl ------------------------------------------------------------------------- 2 | dnl Autoconf startup. 3 | dnl ------------------------------------------------------------------------- 4 | 5 | AC_PREREQ([2.63]) 6 | AC_INIT([clob], [0.1.0], [freundt@ga-group.nl]) 7 | AC_CONFIG_AUX_DIR([build-aux]) 8 | AC_CONFIG_HEADERS([src/config.h src/clob_type.h]) 9 | AC_CONFIG_MACRO_DIR([m4]) 10 | 11 | dnl ------------------------------------------------------------------------- 12 | dnl Local copyright notices. 13 | dnl ------------------------------------------------------------------------- 14 | 15 | AC_COPYRIGHT([dnl 16 | #### Configuration script for clob 17 | #### Copyright (C) 2010-2022 Sebastian Freundt 18 | 19 | ### Don't edit this script! 20 | ### This script was automatically generated by the `autoconf' program 21 | ### from the file `./configure.ac'. 22 | ### To rebuild it, execute the command 23 | ### autoreconf 24 | ]) 25 | 26 | AM_INIT_AUTOMAKE([foreign parallel-tests dist-xz color-tests]) 27 | m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) 28 | 29 | ## the build chain 30 | AC_PROG_CC([icc cc gcc]) 31 | SXE_CHECK_CC([gnu11 gnu99]) 32 | SXE_CHECK_CFLAGS 33 | AC_CHECK_TOOLS([AR], [xiar ar], [false]) 34 | AC_C_BIGENDIAN 35 | AC_PROG_RANLIB 36 | 37 | ## check if yuck is globally available 38 | AX_CHECK_YUCK 39 | AX_YUCK_SCMVER([version.mk]) 40 | AC_CONFIG_LINKS([GNUmakefile:GNUmakefile]) 41 | 42 | ## check for decimals 43 | SXE_CHECK_DFP754 44 | if test "${sxe_cv_feat_dfp754_arith_flavour}" != "unknown"; then 45 | have_decimal="yes" 46 | else 47 | have_decimal="no" 48 | fi 49 | 50 | ## check for price/quantity types 51 | AC_ARG_WITH([decimal], [ 52 | AS_HELP_STRING([--without-decimal], [Use _Decimal64 for prices and quantities instead of IEEE-754 _Float64. Default: yes, if dfp754 support is found.])], 53 | [with_decimal="${withval}"], [with_decimal="${have_decimal}"]) 54 | if test "${with_decimal}" = "yes"; then 55 | AC_DEFINE([WITH_DECIMAL], [1], [Whether to use dfp754 price/quantity type]) 56 | CLOB_TYPE="_Decimal64" 57 | CLOB_NAN="((${CLOB_TYPE})__builtin_nan(\"\"))" 58 | CLOB_ISNAN="isnand64" 59 | else 60 | CLOB_TYPE="double" 61 | CLOB_NAN="(__builtin_nan(\"\"))" 62 | CLOB_ISNAN="isnan" 63 | fi 64 | AC_DEFINE_UNQUOTED([CLOB_TYPE], [${CLOB_TYPE}], [C spelling of price/quantity type]) 65 | AC_DEFINE_UNQUOTED([CLOB_NAN], [${CLOB_NAN}], [C spelling of price/quantity nan value]) 66 | AC_DEFINE_UNQUOTED([CLOB_ISNAN], [${CLOB_ISNAN}], [C spelling of price/quantity nan predicate]) 67 | AC_SUBST([CLOB_TYPE]) 68 | AC_SUBST([CLOB_NAN]) 69 | AC_SUBST([CLOB_ISNAN]) 70 | AM_CONDITIONAL([WITH_DECIMAL], [test "${with_decimal}" = "yes"]) 71 | 72 | ## output 73 | AC_CONFIG_FILES([Makefile]) 74 | AC_CONFIG_FILES([build-aux/Makefile]) 75 | AC_CONFIG_FILES([src/Makefile]) 76 | AC_CONFIG_FILES([test/Makefile]) 77 | AC_OUTPUT 78 | 79 | echo 80 | echo 81 | echo "Build summary" 82 | echo "=============" 83 | echo 84 | echo "Everything will be built" 85 | echo 86 | 87 | ## configure ends here 88 | dnl configure.ac ends here 89 | -------------------------------------------------------------------------------- /m4/sxe-linker.m4: -------------------------------------------------------------------------------- 1 | dnl linker.m4 --- linker magic 2 | dnl 3 | dnl Copyright (C) 2005 - 2012 Sebastian Freundt 4 | dnl Copyright (c) 2005 Steven G. Johnson 5 | dnl Copyright (c) 2005 Matteo Frigo 6 | dnl 7 | dnl Author: Sebastian Freundt 8 | dnl 9 | dnl Redistribution and use in source and binary forms, with or without 10 | dnl modification, are permitted provided that the following conditions 11 | dnl are met: 12 | dnl 13 | dnl 1. Redistributions of source code must retain the above copyright 14 | dnl notice, this list of conditions and the following disclaimer. 15 | dnl 16 | dnl 2. Redistributions in binary form must reproduce the above copyright 17 | dnl notice, this list of conditions and the following disclaimer in the 18 | dnl documentation and/or other materials provided with the distribution. 19 | dnl 20 | dnl 3. Neither the name of the author nor the names of any contributors 21 | dnl may be used to endorse or promote products derived from this 22 | dnl software without specific prior written permission. 23 | dnl 24 | dnl THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 25 | dnl IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | dnl WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | dnl DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 | dnl FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 | dnl CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 | dnl SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31 | dnl BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 | dnl WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33 | dnl OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 34 | dnl IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | dnl 36 | dnl This file is part of SXEmacs. 37 | 38 | AC_DEFUN([SXE_CHECK_LINKER_FLAGS], [dnl 39 | dnl just like SXE_CHECK_COMPILER_FLAGS but calls the linker 40 | dnl SXE_CHECK_LINKER_FLAGS(, , , 41 | dnl ) 42 | AC_REQUIRE([SXE_CHECK_COMPILER_XFLAG]) 43 | 44 | AC_MSG_CHECKING([whether linker accepts $1]) 45 | 46 | dnl Some hackery here since AC_CACHE_VAL can't handle a non-literal varname: 47 | AC_LANG_WERROR([on]) 48 | AS_LITERAL_IF([$1], [ 49 | AC_CACHE_VAL(AS_TR_SH(sxe_cv_[]_AC_LANG_ABBREV[]_flags_$1), [ 50 | sxe_save_FLAGS=$[]_AC_LANG_PREFIX[]FLAGS 51 | _AC_LANG_PREFIX[]FLAGS="$4 ${XFLAG} $1" 52 | AC_LINK_IFELSE([AC_LANG_PROGRAM()], 53 | AS_TR_SH(sxe_cv_[]_AC_LANG_ABBREV[]_flags_$1)="yes", 54 | AS_TR_SH(sxe_cv_[]_AC_LANG_ABBREV[]_flags_$1)="no") 55 | _AC_LANG_PREFIX[]FLAGS=$sxe_save_FLAGS])], [ 56 | sxe_save_FLAGS=$[]_AC_LANG_PREFIX[]FLAGS 57 | _AC_LANG_PREFIX[]FLAGS="$4 ${XFLAG} $1" 58 | AC_LINK_IFELSE([AC_LANG_PROGRAM()], 59 | eval AS_TR_SH(sxe_cv_[]_AC_LANG_ABBREV[]_flags_$1)="yes", 60 | eval AS_TR_SH(sxe_cv_[]_AC_LANG_ABBREV[]_flags_$1)="no") 61 | _AC_LANG_PREFIX[]FLAGS=$sxe_save_FLAGS]) 62 | eval sxe_check_linker_flags=$AS_TR_SH(sxe_cv_[]_AC_LANG_ABBREV[]_flags_$1) 63 | AC_LANG_WERROR([off]) 64 | 65 | AC_MSG_RESULT([$sxe_check_linker_flags]) 66 | if test "$sxe_check_linker_flags" = "yes"; then 67 | m4_default([$2], :) 68 | else 69 | m4_default([$3], :) 70 | fi 71 | ])dnl SXE_CHECK_LINKER_FLAGS 72 | 73 | 74 | AC_DEFUN([SXE_CHECK_LD_ZFLAG], [dnl 75 | pushdef([LD_ZFLAG], [$1]) 76 | pushdef([cv_zflag], [sxe_cv_ld__z_]translit(LD_ZFLAG,[-.=],[___])) 77 | 78 | SXE_CHECK_LINKER_FLAGS([-z ]LD_ZFLAG[]) 79 | 80 | dnl Use the check that actually calls the compiler/linker to examine the flags 81 | dnl AC_CACHE_CHECK([whether linker supports -z ]LD_ZFLAG[], 82 | dnl []cv_zflag[], [_SXE_CHECK_LD_ZFLAG(LD_ZFLAG)]) 83 | 84 | popdef([cv_zflag]) 85 | popdef([LD_ZFLAG]) 86 | ])dnl SXE_CHECK_LD_ZFLAG 87 | 88 | AC_DEFUN([_SXE_CHECK_LD_ZFLAG], [dnl 89 | ## arg1 is the flag to check for 90 | pushdef([LD_ZFLAG], [$1]) 91 | pushdef([cv_zflag], [sxe_cv_ld__z_]translit(LD_ZFLAG,[-.=],[___])) 92 | 93 | if test "$GCC" = "yes"; then 94 | if test "($CC -Xlinker --help 2>&1 | \ 95 | grep \"-z []LD_ZFLAG[]\" > /dev/null 2>&1 ) "; then 96 | cv_zflag="yes" 97 | else 98 | cv_zflag="no" 99 | fi 100 | elif test -n "$LD"; then 101 | if test "($LD --help 2>&1 | \ 102 | grep \"-z []LD_ZFLAG[]\" > /dev/null 2>&1 )"; then 103 | cv_zflag="yes" 104 | else 105 | cv_zflag="no" 106 | fi 107 | else 108 | cv_zflag="no" 109 | fi 110 | 111 | popdef([cv_zflag]) 112 | popdef([LD_ZFLAG]) 113 | ])dnl _SXE_CHECK_LD_ZFLAG 114 | 115 | AC_DEFUN([SXE_LD_EXPORT_DYNAMIC], [dnl 116 | SXE_CHECK_LINKER_FLAGS([-export-dynamic], [ 117 | LD_EXPORT_DYNAMIC="-export-dynamic" 118 | ]) 119 | 120 | AC_SUBST([LD_EXPORT_DYNAMIC]) 121 | ])dnl SXE_LD_EXPORT_DYNAMIC 122 | 123 | AC_DEFUN([SXE_CHECK_LDFLAGS], [dnl 124 | AC_REQUIRE([SXE_CHECK_COMPILER_XFLAG]) 125 | 126 | ## relocation 127 | SXE_CHECK_LD_ZFLAG([combreloc]) 128 | SXE_CHECK_LD_ZFLAG([nocombreloc]) 129 | ## symbols 130 | SXE_CHECK_LD_ZFLAG([defs]) 131 | SXE_CHECK_LD_ZFLAG([muldefs]) 132 | ## search paths 133 | SXE_CHECK_LD_ZFLAG([nodefaultlib]) 134 | ## binding policy 135 | SXE_CHECK_LD_ZFLAG([lazy]) 136 | SXE_CHECK_LD_ZFLAG([now]) 137 | 138 | SXE_LD_EXPORT_DYNAMIC 139 | 140 | LDFLAGS="${ldflags} ${ac_cv_env_LDFLAGS_value}" 141 | AC_MSG_CHECKING([for preferred LDFLAGS]) 142 | AC_MSG_RESULT([${LDFLAGS}]) 143 | 144 | AC_MSG_NOTICE([ 145 | If you wish to ADD your own flags you want to stop here and rerun the 146 | configure script like so: 147 | configure LDFLAGS= 148 | 149 | You can always override the determined LDFLAGS, partially or totally, 150 | using 151 | make -C LDFLAGS= [target] 152 | or 153 | make LDFLAGS= [target] 154 | respectively 155 | 156 | NOTE: -C option is not available on all systems 157 | ]) 158 | ])dnl SXE_CHECK_LDFLAGS 159 | 160 | AC_DEFUN([SXE_PREPEND_LINKER_FLAG], [dnl 161 | ## a convenience function to add such linker flags to variables 162 | ## arg1 is the flag to add (must include -z if applicable) 163 | ## arg2 is the variable whither to prepend 164 | pushdef([FLAG], [$1]) 165 | pushdef([__FLAG], [-Wl,]patsubst([$1], [ ], [[,]])) 166 | pushdef([VAR], [$2]) 167 | 168 | []VAR[]="[]__FLAG[] $[]VAR[]" 169 | if test "$extra_verbose" = "yes"; then 170 | echo " Prepending linker flag \"[]__FLAG[]\" to \$[]VAR[]" 171 | fi 172 | 173 | popdef([VAR]) 174 | popdef([__FLAG]) 175 | popdef([FLAG]) 176 | ])dnl SXE_PREPEND_LINKER_FLAG 177 | 178 | dnl sxe-linker.m4 ends here 179 | -------------------------------------------------------------------------------- /m4/yuck.m4: -------------------------------------------------------------------------------- 1 | dnl yuck.m4 --- yuck goodies 2 | dnl 3 | dnl Copyright (C) 2013-2016 Sebastian Freundt 4 | dnl 5 | dnl Author: Sebastian Freundt 6 | dnl 7 | dnl Redistribution and use in source and binary forms, with or without 8 | dnl modification, are permitted provided that the following conditions 9 | dnl are met: 10 | dnl 11 | dnl 1. Redistributions of source code must retain the above copyright 12 | dnl notice, this list of conditions and the following disclaimer. 13 | dnl 14 | dnl 2. Redistributions in binary form must reproduce the above copyright 15 | dnl notice, this list of conditions and the following disclaimer in the 16 | dnl documentation and/or other materials provided with the distribution. 17 | dnl 18 | dnl 3. Neither the name of the author nor the names of any contributors 19 | dnl may be used to endorse or promote products derived from this 20 | dnl software without specific prior written permission. 21 | dnl 22 | dnl THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 23 | dnl IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | dnl WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | dnl DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 | dnl FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | dnl CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | dnl SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 29 | dnl BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 30 | dnl WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 31 | dnl OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 32 | dnl IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | dnl 34 | dnl This file is part of yuck. 35 | 36 | AC_DEFUN([AX_CHECK_M4_BUFFERS], [dnl 37 | AC_MSG_CHECKING([for m4 with sufficient capabilities]) 38 | 39 | AC_ARG_VAR([M4], [full path to the m4 tool]) 40 | probe_M4="${M4-m4}" 41 | if ${probe_M4} >/dev/null 2>&1 \ 42 | -Dx='y y y y y y y y y y y y y y y y' \ 43 | -Dy='z z z z z z z z z z z z z z z z' \ 44 | -Dz='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0' <<'EOF' 45 | [define(`foo', x)] 46 | EOF 47 | then 48 | ## ah well done 49 | AC_MSG_RESULT([${probe_M4}]) 50 | M4="${probe_M4}" 51 | else 52 | ## check if a little buffer massage solves the problem 53 | probe_M4="${M4-m4} -B16384" 54 | if ${probe_M4} >/dev/null 2>&1 \ 55 | -Dx='y y y y y y y y y y y y y y y y' \ 56 | -Dy='z z z z z z z z z z z z z z z z' \ 57 | -Dz='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0' <<'EOF' 58 | [define(`foo', x)] 59 | EOF 60 | then 61 | ## very well then, let's use -B 62 | AC_MSG_RESULT([${probe_M4}]) 63 | M4="${probe_M4}" 64 | else 65 | AC_MSG_WARN([m4 on this machine might suffer from big buffers.]) 66 | M4="${M4-m4}" 67 | fi 68 | fi 69 | 70 | AC_DEFINE_UNQUOTED([YUCK_M4], ["${M4}"], [m4 value used for yuck build]) 71 | ])dnl AX_CHECK_M4_BUFFERS 72 | 73 | AC_DEFUN([AX_CHECK_YUCK], [dnl 74 | AC_ARG_WITH([included-yuck], [dnl 75 | AS_HELP_STRING([--with-included-yuck], [ 76 | Use included copy of the yuck command line parser generator 77 | instead of the system-wide one.])], [with_included_yuck="${withval}"], [with_included_yuck="$1"]) 78 | 79 | AC_REQUIRE([AX_CHECK_M4_BUFFERS]) 80 | if test "${with_included_yuck}" = "no"; then 81 | AC_PATH_PROG([YUCK], [yuck]) 82 | AC_ARG_VAR([YUCK], [full path to the yuck tool]) 83 | 84 | if test -n "${YUCK}"; then 85 | ## see what m4 they used back then 86 | YUCK_M4=`${YUCK} config --m4 2>/dev/null` 87 | M4="${YUCK_M4-$M4}" 88 | fi 89 | else 90 | AC_MSG_CHECKING([for yuck]) 91 | AC_MSG_RESULT([using included]) 92 | fi 93 | AM_CONDITIONAL([HAVE_YUCK], [dnl 94 | test "${with_included_yuck}" = "no" -a -n "${YUCK}"]) 95 | 96 | ## further requirement is either getline() or fgetln() 97 | AC_CHECK_FUNCS([getline]) 98 | AC_CHECK_FUNCS([fgetln]) 99 | ])dnl AX_CHECK_YUCK 100 | 101 | AC_DEFUN([AX_YUCK_SCMVER], [dnl 102 | ## initially generate version.mk and yuck.version here 103 | ## because only GNU make can do this at make time 104 | pushdef([vfile], [$1]) 105 | 106 | AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) 107 | AC_LANG_PUSH([C]) 108 | AC_PROG_CC_C99 109 | ## use our yuck-scmver tool 110 | AC_MSG_CHECKING([for stipulated version files]) 111 | save_CPPFLAGS="${CPPFLAGS}" 112 | CPPFLAGS="-I${srcdir}/src -I${ac_aux_dir} ${CPPFLAGS}" 113 | AC_RUN_IFELSE([AC_LANG_SOURCE([[ 114 | #define CONFIGURE 115 | #define _XOPEN_SOURCE 600 116 | #define VERSION_FILE "${srcdir}/.version" 117 | #include "yuck-scmver.c" 118 | ]])], [STIP_VERSION=`./conftest$EXEEXT`], [AC_MSG_RESULT([none])], [dnl 119 | AC_MSG_RESULT([impossible, cross-compiling]) 120 | if test -f "[]vfile[]" -o \ 121 | -f "${srcdir}/[]vfile[]" -o \ 122 | -f "${srcdir}/.version"; then 123 | AC_MSG_NOTICE([ 124 | Files that (possibly) mandate versions have been detected. 125 | These are `]vfile[' or `${srcdir}/]vfile[' or `${srcdir}/.version'. 126 | However, their contents cannot be automatically checked for integrity 127 | due to building for a platform other than the current one 128 | (cross-compiling). 129 | 130 | I will proceed with the most conservative guess for the stipulated 131 | version, which is `${VERSION}'. 132 | 133 | If that appears to be wrong, or needs overriding, please edit the 134 | aforementioned files manually. 135 | 136 | Also note, even though this project comes with all the tools to 137 | perform a successful bootstrap for any of the files above, should 138 | they go out of date or be deleted, they don't support cross-builds. 139 | ]) 140 | fi 141 | ]) 142 | CPPFLAGS="${save_CPPFLAGS}" 143 | AC_LANG_POP([C]) 144 | 145 | if test -n "${STIP_VERSION}"; then 146 | VERSION="${STIP_VERSION}" 147 | fi 148 | ## also massage version.mk file 149 | if test -f "[]vfile[]" -a ! -w "[]vfile[]"; then 150 | : 151 | elif test -f "${srcdir}/[]vfile[]"; then 152 | ## make sure it's in the builddir as well 153 | cp -p "${srcdir}/[]vfile[]" "[]vfile[]" 2>/dev/null 154 | elif test -f "${srcdir}/[]vfile[].in"; then 155 | ${M4-m4} -DYUCK_SCMVER_VERSION="${VERSION}" \ 156 | "${srcdir}/[]vfile[].in" > "[]vfile[]" 157 | else 158 | echo "VERSION = ${VERSION}" > "[]vfile[]" 159 | fi 160 | ## make sure .version is generated (for version.mk target in GNUmakefile) 161 | if test -f "${srcdir}/.version"; then 162 | cp -p "${srcdir}/.version" ".version" 2>/dev/null 163 | else 164 | echo "v${VERSION}" > ".version" 2>/dev/null 165 | fi 166 | 167 | popdef([vfile]) 168 | ])dnl AX_YUCK_SCMVER 169 | 170 | dnl yuck.m4 ends here 171 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | ### Makefile.am 2 | include $(top_builddir)/version.mk 3 | 4 | AM_CFLAGS = $(EXTRA_CFLAGS) 5 | AM_CPPFLAGS = -D_POSIX_C_SOURCE=201001L -D_XOPEN_SOURCE=700 -D_BSD_SOURCE 6 | AM_CPPFLAGS += -D_HAVE_VERSION_H 7 | AM_LDFLAGS = $(XCCLDFLAGS) 8 | 9 | bin_PROGRAMS = 10 | noinst_PROGRAMS = 11 | lib_LIBRARIES = 12 | noinst_LIBRARIES = 13 | noinst_HEADERS = 14 | BUILT_SOURCES = 15 | EXTRA_DIST = $(BUILT_SOURCES) 16 | CLEANFILES = 17 | SUFFIXES = 18 | 19 | CLEANFILES += version.c 20 | EXTRA_DIST += version.c.in 21 | 22 | lib_LIBRARIES += libclob.a 23 | libclob_a_SOURCES = 24 | if WITH_DECIMAL 25 | libclob_a_SOURCES += dfp754_d32.c dfp754_d32.h 26 | libclob_a_SOURCES += dfp754_d64.c dfp754_d64.h 27 | endif 28 | libclob_a_SOURCES += btree.c btree.h btree_val.h 29 | libclob_a_SOURCES += plqu.c plqu.h plqu_val.h 30 | libclob_a_SOURCES += clob.c clob.h clob_val.h 31 | libclob_a_SOURCES += clob_type.h 32 | libclob_a_SOURCES += unxs.c unxs.h 33 | libclob_a_SOURCES += mmod-auction.c mmod-auction.h 34 | libclob_a_SOURCES += mmod-fok.c mmod-fok.h 35 | libclob_a_SOURCES += mmod-ioc.c mmod-ioc.h 36 | libclob_a_SOURCES += mmod-pdo.c mmod-pdo.h 37 | libclob_a_SOURCES += quos.c quos.h 38 | libclob_a_SOURCES += nifty.h 39 | libclob_a_CPPFLAGS = $(AM_CPPFLAGS) 40 | libclob_a_LIBADD = 41 | if WITH_DECIMAL 42 | libclob_a_CPPFLAGS += $(dfp754_CFLAGS) 43 | libclob_a_LIBADD += $(dfp754_LIBS) 44 | endif 45 | 46 | pkginclude_HEADERS = 47 | pkginclude_HEADERS += clob.h clob_val.h 48 | pkginclude_HEADERS += unxs.h 49 | pkginclude_HEADERS += mmod-auction.h 50 | pkginclude_HEADERS += mmod-fok.h 51 | pkginclude_HEADERS += mmod-ioc.h 52 | pkginclude_HEADERS += mmod-pdo.h 53 | pkginclude_HEADERS += quos.h 54 | 55 | bin_PROGRAMS += cloe 56 | cloe_SOURCES = cloe.c cloe.yuck 57 | cloe_CPPFLAGS = $(AM_CPPFLAGS) 58 | cloe_LDFLAGS = $(AM_LDFLAGS) 59 | if WITH_DECIMAL 60 | cloe_CPPFLAGS += $(dfp754_CFLAGS) 61 | cloe_LDFLAGS += $(dfp754_LIBS) 62 | endif 63 | cloe_LDADD = libclob.a 64 | BUILT_SOURCES += cloe.yucc 65 | 66 | 67 | ## version rules 68 | version.c: $(srcdir)/version.c.in $(top_builddir)/.version 69 | $(AM_V_GEN) PATH="$(top_builddir)/build-aux:$${PATH}" \ 70 | yuck$(EXEEXT) scmver --ignore-noscm --force -o $@ \ 71 | --use-reference --reference $(top_builddir)/.version \ 72 | $(srcdir)/version.c.in 73 | 74 | ## yuck rule 75 | SUFFIXES += .yuck 76 | SUFFIXES += .yucc 77 | .yuck.yucc: 78 | $(AM_V_GEN) PATH=$(top_builddir)/build-aux:"$${PATH}" \ 79 | yuck$(EXEEXT) gen -o $@ $< 80 | 81 | ## Create preprocessor output (debugging purposes only) 82 | .c.i: 83 | $(COMPILE) -E -o $@ $< 84 | 85 | ## Create assembler output (debugging purposes only) 86 | .c.s: 87 | $(COMPILE) -S -c $(AM_CFLAGS) $< 88 | -------------------------------------------------------------------------------- /src/btree.h: -------------------------------------------------------------------------------- 1 | /*** btree.h -- simple b+tree impl 2 | * 3 | * Copyright (C) 2016-2022 Sebastian Freundt 4 | * 5 | * Author: Sebastian Freundt 6 | * 7 | * This file is part of clob. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 16 | * 2. Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 20 | * 3. Neither the name of the author nor the names of any contributors 21 | * may be used to endorse or promote products derived from this 22 | * software without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 34 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | * 36 | **/ 37 | #if !defined INCLUDED_btree_h_ 38 | #define INCLUDED_btree_h_ 39 | #include 40 | #include 41 | /* defines btree_key_t and btree_val_t, hopefully */ 42 | #include "btree_val.h" 43 | 44 | typedef struct btree_s *btree_t; 45 | 46 | typedef struct { 47 | btree_t t; 48 | size_t i; 49 | btree_key_t k; 50 | btree_val_t *v; 51 | } btree_iter_t; 52 | 53 | 54 | extern btree_t make_btree(bool descp); 55 | extern void free_btree(btree_t); 56 | 57 | extern btree_val_t *btree_get(btree_t, btree_key_t); 58 | extern btree_val_t *btree_put(btree_t, btree_key_t); 59 | extern btree_val_t btree_rem(btree_t, btree_key_t); 60 | extern btree_val_t *btree_top(btree_t, btree_key_t*); 61 | 62 | extern bool btree_iter_next(btree_iter_t*); 63 | 64 | #endif /* INCLUDED_btree_h_ */ 65 | -------------------------------------------------------------------------------- /src/btree_val.h: -------------------------------------------------------------------------------- 1 | /*** btree_val.h -- values and keys of btrees ***/ 2 | #if !defined INCLUDED_btree_val_h_ 3 | #define INCLUDED_btree_val_h_ 4 | #include 5 | #include "clob_val.h" 6 | #include "plqu.h" 7 | 8 | /* keys are prices */ 9 | typedef px_t btree_key_t; 10 | 11 | /* values are plqu's and a plqu_val_t for the sum */ 12 | typedef struct { 13 | plqu_t q; 14 | qty_t sum; 15 | } btree_val_t; 16 | 17 | #define btree_val_nil ((btree_val_t){0U}) 18 | 19 | static inline bool 20 | btree_val_nil_p(btree_val_t v) 21 | { 22 | return v.q == 0U; 23 | } 24 | 25 | static inline void 26 | free_btree_val(btree_val_t v) 27 | { 28 | free_plqu(v.q); 29 | return; 30 | } 31 | 32 | #endif /* INCLUDED_btree_val_h_ */ 33 | -------------------------------------------------------------------------------- /src/clob.h: -------------------------------------------------------------------------------- 1 | /*** clob.h -- central limit order book 2 | * 3 | * Copyright (C) 2016-2022 Sebastian Freundt 4 | * 5 | * Author: Sebastian Freundt 6 | * 7 | * This file is part of clob. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 16 | * 2. Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 20 | * 3. Neither the name of the author nor the names of any contributors 21 | * may be used to endorse or promote products derived from this 22 | * software without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 34 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | * 36 | **/ 37 | #if !defined INCLUDED_clob_h_ 38 | #define INCLUDED_clob_h_ 39 | #include 40 | #include 41 | #include 42 | #include "clob_val.h" 43 | 44 | typedef size_t clob_qid_t; 45 | 46 | typedef enum { 47 | CLOB_TYPE_LMT, 48 | CLOB_TYPE_MKT, 49 | } clob_type_t; 50 | 51 | typedef enum { 52 | CLOB_SIDE_ASK = 0U, 53 | CLOB_SIDE_SHORT = CLOB_SIDE_ASK, 54 | CLOB_SIDE_SELLER = CLOB_SIDE_ASK, 55 | CLOB_SIDE_MAKER = CLOB_SIDE_ASK, 56 | CLOB_SIDE_RECEIVER = CLOB_SIDE_ASK, 57 | CLOB_SIDE_BID = 1U, 58 | CLOB_SIDE_LONG = CLOB_SIDE_BID, 59 | CLOB_SIDE_BUYER = CLOB_SIDE_BID, 60 | CLOB_SIDE_TAKER = CLOB_SIDE_BID, 61 | CLOB_SIDE_PAYER = CLOB_SIDE_BID, 62 | NCLOB_SIDES, 63 | } clob_side_t; 64 | 65 | typedef struct { 66 | uintptr_t lmt[NCLOB_SIDES]; 67 | uintptr_t mkt[NCLOB_SIDES]; 68 | struct quos_s *quo; 69 | struct unxs_s *exe; 70 | } clob_t; 71 | 72 | typedef struct { 73 | clob_type_t typ; 74 | clob_side_t sid; 75 | qty_t qty; 76 | union { 77 | /* limit price for limit orders */ 78 | px_t lmt; 79 | /* max slippage for market orders */ 80 | px_t slp; 81 | }; 82 | px_t stp; 83 | uintptr_t usr; 84 | } clob_ord_t; 85 | 86 | typedef struct { 87 | clob_type_t typ; 88 | clob_side_t sid; 89 | px_t prc; 90 | clob_qid_t qid; 91 | uintptr_t usr; 92 | } clob_oid_t; 93 | 94 | /* aggregated iterator */ 95 | typedef struct { 96 | clob_type_t typ; 97 | clob_side_t sid; 98 | uintptr_t private; 99 | size_t i; 100 | px_t p; 101 | qty_t q; 102 | } clob_aggiter_t; 103 | 104 | /* disaggregated iterator */ 105 | typedef struct { 106 | clob_type_t typ; 107 | clob_side_t sid; 108 | uintptr_t private1; 109 | size_t i; 110 | uintptr_t private2; 111 | size_t j; 112 | qty_t q; 113 | metr_t tim; 114 | uintptr_t usr; 115 | px_t p; 116 | } clob_disiter_t; 117 | 118 | 119 | /** 120 | * Instantiate central limit order book. 121 | * DESCP indicates whether to sort descendingly. */ 122 | extern clob_t make_clob(void); 123 | 124 | /** 125 | * Deinstantiate clob object and free associated resources. */ 126 | extern void free_clob(clob_t); 127 | 128 | /** 129 | * Add order to clob_t object and return an order id object. 130 | * If a quote-stream is attached any touched price levels will 131 | * be published there. */ 132 | extern clob_oid_t clob_add(clob_t, clob_ord_t); 133 | 134 | /** 135 | * Delete order from clob_t object. 136 | * If a quote-stream is attached any touched price levels will 137 | * be published there. */ 138 | extern int clob_del(clob_t, clob_oid_t); 139 | 140 | /** 141 | * Return mid point price. */ 142 | extern px_t clob_mid(clob_t); 143 | 144 | /** 145 | * Advance the iterator, return true if filled, false otherwise. */ 146 | extern bool clob_aggiter_next(clob_aggiter_t*); 147 | 148 | /** 149 | * Advance the iterator, return true if filled, false otherwise. */ 150 | extern bool clob_disiter_next(clob_disiter_t*); 151 | 152 | /** 153 | * Obtain current quantities of oid. */ 154 | extern qty_t clob_oid_get_qty(clob_t, clob_oid_t); 155 | 156 | /** 157 | * Obtain metronome of oid. */ 158 | extern metr_t clob_oid_get_tim(clob_t, clob_oid_t); 159 | 160 | /* for debugging purposes */ 161 | extern void clob_prnt(clob_t c); 162 | 163 | 164 | /* convenience */ 165 | static inline __attribute__((pure, const)) clob_side_t 166 | clob_contra_side(clob_side_t s) 167 | { 168 | return (clob_side_t)((unsigned int)s ^ 1U); 169 | } 170 | 171 | static inline __attribute__((pure, const)) clob_aggiter_t 172 | clob_aggiter(clob_t c, clob_type_t typ, clob_side_t sid) 173 | { 174 | return (clob_aggiter_t){typ, sid, c.lmt[typ * NCLOB_SIDES + sid]}; 175 | } 176 | 177 | static inline __attribute__((pure, const)) clob_disiter_t 178 | clob_disiter(clob_t c, clob_type_t typ, clob_side_t sid) 179 | { 180 | return (clob_disiter_t){typ, sid, c.lmt[typ * NCLOB_SIDES + sid]}; 181 | } 182 | 183 | #endif /* INCLUDED_clob_h_ */ 184 | -------------------------------------------------------------------------------- /src/clob_type.h.in: -------------------------------------------------------------------------------- 1 | /*** clob_type.h -- floating point implementation 2 | * 3 | * Copyright (C) 2016-2022 Sebastian Freundt 4 | * 5 | * Author: Sebastian Freundt 6 | * 7 | * This file is part of clob. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 16 | * 2. Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 20 | * 3. Neither the name of the author nor the names of any contributors 21 | * may be used to endorse or promote products derived from this 22 | * software without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 34 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | * 36 | **/ 37 | #if !defined INCLUDED_clob_type_h_ 38 | #define INCLUDED_clob_type_h_ 39 | 40 | #undef HAVE_DFP754_H 41 | #undef HAVE_DFP_STDLIB_H 42 | #undef HAVE_DECIMAL_H 43 | #if defined HAVE_DFP754_H 44 | # include 45 | #elif defined HAVE_DFP_STDLIB_H 46 | # include 47 | #elif defined HAVE_DECIMAL_H 48 | # include 49 | #endif /* DFP754_H || HAVE_DFP_STDLIB_H || HAVE_DECIMAL_H */ 50 | 51 | #undef CLOB_TYPE 52 | typedef CLOB_TYPE px_t; 53 | typedef CLOB_TYPE qx_t; 54 | 55 | #undef CLOB_NAN 56 | #define NANPX CLOB_NAN 57 | #define NANQX CLOB_NAN 58 | 59 | #undef CLOB_ISNAN 60 | #define isnanpx CLOB_ISNAN 61 | #define isnanqx CLOB_ISNAN 62 | 63 | #undef WITH_DECIMAL 64 | 65 | #endif /* INCLUDED_clob_type_h_ */ 66 | -------------------------------------------------------------------------------- /src/clob_val.h: -------------------------------------------------------------------------------- 1 | /*** clob_val.h -- basic types 2 | * 3 | * Copyright (C) 2016-2022 Sebastian Freundt 4 | * 5 | * Author: Sebastian Freundt 6 | * 7 | * This file is part of clob. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 16 | * 2. Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 20 | * 3. Neither the name of the author nor the names of any contributors 21 | * may be used to endorse or promote products derived from this 22 | * software without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 34 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | * 36 | **/ 37 | #if !defined INCLUDED_clob_val_h_ 38 | #define INCLUDED_clob_val_h_ 39 | #include 40 | #include "clob_type.h" 41 | 42 | /* metronome type */ 43 | typedef size_t metr_t; 44 | 45 | typedef struct { 46 | /** display quantity */ 47 | qx_t dis; 48 | /** hidden quantity */ 49 | qx_t hid; 50 | } qty_t; 51 | 52 | #define qty0 ((qty_t){0.dd, 0.dd}) 53 | 54 | 55 | static inline __attribute__((pure, const)) qx_t 56 | qty(qty_t v) 57 | { 58 | return v.dis + v.hid; 59 | } 60 | 61 | static inline __attribute__((pure, const)) qty_t 62 | qty_add(qty_t v1, qty_t v2) 63 | { 64 | return (qty_t){v1.dis + v2.dis, v1.hid + v2.hid}; 65 | } 66 | 67 | static inline __attribute__((pure, const)) qty_t 68 | qty_sub(qty_t v1, qty_t v2) 69 | { 70 | return (qty_t){v1.dis - v2.dis, v1.hid - v2.hid}; 71 | } 72 | 73 | static inline __attribute__((pure, const)) qty_t 74 | qty_exe(qty_t v, qx_t q) 75 | { 76 | /* V is executed against quantity Q, use up hidden liquidity of V first */ 77 | qx_t nuh = v.hid <= q ? v.hid : q; 78 | qx_t nuv = v.hid <= q ? q - v.hid : 0.dd; 79 | return (qty_t){v.dis - nuv, v.hid - nuh}; 80 | } 81 | 82 | #endif /* INCLUDED_clob_val_h_ */ 83 | -------------------------------------------------------------------------------- /src/cloe.c: -------------------------------------------------------------------------------- 1 | /*** cloe.c -- clob executor engine 2 | * 3 | * Copyright (C) 2016-2022 Sebastian Freundt 4 | * 5 | * Author: Sebastian Freundt 6 | * 7 | * This file is part of clob. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 16 | * 2. Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 20 | * 3. Neither the name of the author nor the names of any contributors 21 | * may be used to endorse or promote products derived from this 22 | * software without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 34 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | * 36 | **/ 37 | #if defined HAVE_CONFIG_H 38 | # include "config.h" 39 | #endif /* HAVE_CONFIG_H */ 40 | #include 41 | #include 42 | #include 43 | #if defined WITH_DECIMAL 44 | # include "dfp754_d64.h" 45 | #else 46 | # include 47 | #endif 48 | #include "clob.h" 49 | #include "unxs.h" 50 | #include "quos.h" 51 | #include "mmod-auction.h" 52 | #include "nifty.h" 53 | 54 | #if defined WITH_DECIMAL 55 | #define strtoqx strtod64 56 | #define strtopx strtod64 57 | #define qxtostr d64tostr 58 | #define pxtostr d64tostr 59 | #else 60 | #define strtoqx strtod 61 | #define strtopx strtod 62 | #define qxtostr dtostr 63 | #define pxtostr dtostr 64 | #endif 65 | 66 | #define CLOB_TYPE_AUC ((clob_type_t)0x10U) 67 | 68 | static FILE *traout, *quoout; 69 | 70 | 71 | #if !defined WITH_DECIMAL 72 | #include 73 | static int dtostr(char *restrict buf, size_t bsz, double d) 74 | { 75 | return snprintf(buf, bsz, "%f", d); 76 | } 77 | #endif /* WITH_DECIMAL */ 78 | 79 | 80 | static clob_ord_t 81 | push_beef(const char *ln, size_t lz) 82 | { 83 | /* simple order protocol 84 | * BUY/LONG \t Q [\t P] 85 | * SELL/SHORT \t Q [\t P] */ 86 | clob_ord_t o; 87 | char *on; 88 | 89 | if (UNLIKELY(!lz)) { 90 | goto bork; 91 | } 92 | switch (ln[0U]) { 93 | case 'F'/*INISH AUCTION*/: 94 | case 'f'/*inish auction*/: 95 | return (clob_ord_t){CLOB_TYPE_AUC}; 96 | case 'B'/*UY*/: 97 | case 'L'/*ONG*/: 98 | case 'b'/*uy*/: 99 | case 'l'/*ong*/: 100 | o.sid = CLOB_SIDE_BID; 101 | break; 102 | case 'S'/*ELL|HORT*/: 103 | case 's'/*ell|hort*/: 104 | o.sid = CLOB_SIDE_ASK; 105 | break; 106 | default: 107 | goto bork; 108 | } 109 | with (const char *x = strchr(ln, '\t')) { 110 | if (UNLIKELY(x == NULL)) { 111 | goto bork; 112 | } 113 | /* otherwise */ 114 | lz -= x + 1U - ln; 115 | ln = x + 1U; 116 | } 117 | /* read quantity */ 118 | o.qty.hid = 0.dd; 119 | o.qty.dis = strtoqx(ln, &on); 120 | if (LIKELY(*on > ' ')) { 121 | /* nope */ 122 | goto bork; 123 | } else if (*on++ == '\t') { 124 | o.lmt = strtopx(on, &on); 125 | if (*on > ' ') { 126 | goto bork; 127 | } 128 | o.typ = CLOB_TYPE_LMT; 129 | } else { 130 | o.typ = CLOB_TYPE_MKT; 131 | } 132 | return o; 133 | bork: 134 | return (clob_ord_t){(clob_type_t)-1}; 135 | } 136 | 137 | static void 138 | send_beef(unxs_exe_t x) 139 | { 140 | char buf[256U]; 141 | size_t len = (memcpy(buf, "TRA\t", 4U), 4U); 142 | 143 | len += qxtostr(buf + len, sizeof(buf) - len, x.qty); 144 | buf[len++] = '\t'; 145 | len += qxtostr(buf + len, sizeof(buf) - len, x.prc); 146 | buf[len++] = '\n'; 147 | fwrite(buf, 1, len, stdout); 148 | return; 149 | } 150 | 151 | static void 152 | send_cake(quos_msg_t m) 153 | { 154 | char buf[256U]; 155 | size_t len = 0U; 156 | 157 | buf[len++] = (char)('A' + m.sid); 158 | buf[len++] = '2'; 159 | buf[len++] = '\t'; 160 | len += pxtostr(buf + len, sizeof(buf) - len, m.prc); 161 | buf[len++] = '\t'; 162 | len += qxtostr(buf + len, sizeof(buf) - len, m.new); 163 | buf[len++] = '\n'; 164 | fwrite(buf, 1, len, quoout); 165 | return; 166 | } 167 | 168 | 169 | #include "cloe.yucc" 170 | 171 | int 172 | main(int argc, char *argv[]) 173 | { 174 | static yuck_t argi[1U]; 175 | int rc = 0; 176 | clob_t c; 177 | 178 | if (yuck_parse(argi, argc, argv) < 0) { 179 | rc = 1; 180 | goto out; 181 | } 182 | 183 | /* get going then */ 184 | c = make_clob(); 185 | switch (argi->cmd) { 186 | default: 187 | c.exe = make_unxs(MODE_BI); 188 | /* open the quote channel */ 189 | if ((quoout = fdopen(3, "w+")) != NULL) { 190 | c.quo = make_quos(); 191 | } 192 | break; 193 | case CLOE_CMD_AUCTION: 194 | c.exe = make_unxs(MODE_SC); 195 | break; 196 | } 197 | 198 | /* open the trade channel */ 199 | traout = stdout; 200 | 201 | /* read orders from stdin */ 202 | switch (argi->cmd) { 203 | char *line; 204 | size_t llen; 205 | ssize_t nrd; 206 | 207 | default: 208 | /* default mode is continuous trading */ 209 | line = NULL, llen = 0U; 210 | while ((nrd = getline(&line, &llen, stdin)) > 0) { 211 | clob_ord_t o = push_beef(line, nrd); 212 | 213 | if (UNLIKELY(o.typ > CLOB_TYPE_AUC)) { 214 | fputs("Error: unreadable line\n", stderr); 215 | continue; 216 | } else if (UNLIKELY(o.typ == CLOB_TYPE_AUC)) { 217 | /* just ignore auctions */ 218 | continue; 219 | } 220 | /* otherwise hand him to continuous trading */ 221 | unxs_order(c, o, NANPX); 222 | /* print trades at the very least */ 223 | for (size_t i = 0U; i < c.exe->n; i++) { 224 | send_beef(c.exe->x[i]); 225 | } 226 | unxs_clr(c.exe); 227 | if (quoout != NULL) { 228 | quos_t q = c.quo; 229 | for (size_t i = 0U; i < q->n; i++) { 230 | send_cake(q->m[i]); 231 | } 232 | quos_clr(q); 233 | } 234 | } 235 | free(line); 236 | break; 237 | 238 | case CLOE_CMD_AUCTION: 239 | /* auction mode, read until we see FINISH AUCTION */ 240 | line = NULL, llen = 0U, nrd = 1; 241 | while (nrd > 0) { 242 | mmod_auc_t a; 243 | 244 | while ((nrd = getline(&line, &llen, stdin)) > 0) { 245 | clob_ord_t o = push_beef(line, nrd); 246 | 247 | if (UNLIKELY(o.typ > CLOB_TYPE_AUC)) { 248 | fputs("Error: unreadable line\n", stderr); 249 | continue; 250 | } else if (o.typ == CLOB_TYPE_AUC) { 251 | /* auction him */ 252 | break; 253 | } 254 | /* otherwise track him in the book */ 255 | clob_add(c, o); 256 | /* calculate theoretical auction price */ 257 | a = mmod_auction(c); 258 | } 259 | /* auction him */ 260 | unxs_auction(c, a.prc, a.qty); 261 | /* print trades at the very least */ 262 | for (size_t i = 0U; i < c.exe->n; i++) { 263 | send_beef(c.exe->x[i]); 264 | } 265 | unxs_clr(c.exe); 266 | } 267 | free(line); 268 | break; 269 | } 270 | 271 | /* close quotes channel */ 272 | if (quoout != NULL) { 273 | fclose(quoout); 274 | free_quos(c.quo); 275 | } 276 | if (traout != NULL) { 277 | fclose(traout); 278 | } 279 | free_unxs(c.exe); 280 | free_clob(c); 281 | 282 | out: 283 | yuck_free(argi); 284 | return rc; 285 | } 286 | -------------------------------------------------------------------------------- /src/cloe.yuck: -------------------------------------------------------------------------------- 1 | Usage: cloe 2 | 3 | Run the clob engine (in continuous trading mode). 4 | 5 | 6 | Usage: cloe auction 7 | 8 | Run the clob engine in auction mode. 9 | -------------------------------------------------------------------------------- /src/dfp754_d32.h: -------------------------------------------------------------------------------- 1 | /*** dfp754_d32.h -- _Decimal32 goodness 2 | * 3 | * Copyright (C) 2013-2022 Sebastian Freundt 4 | * 5 | * Author: Sebastian Freundt 6 | * 7 | * This file is part of dfp754. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 16 | * 2. Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 20 | * 3. Neither the name of the author nor the names of any contributors 21 | * may be used to endorse or promote products derived from this 22 | * software without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 34 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | * 36 | ***/ 37 | #if !defined INCLUDED_dfp754_d32_h_ 38 | #define INCLUDED_dfp754_d32_h_ 39 | 40 | #if defined HAVE_CONFIG_H 41 | # include "config.h" 42 | #endif /* HAVE_CONFIG_H */ 43 | #include 44 | #include 45 | 46 | #define NAND32_U (0x7c000000U) 47 | #define INFD32_U (0x78000000U) 48 | 49 | #if !defined __DEC32_MOST_POSITIVE__ 50 | # define __DEC32_MOST_POSITIVE__ (__DEC32_MAX__) 51 | #endif /* !__DEC32_MOST_POSITIVE__ */ 52 | #if !defined __DEC32_MOST_NEGATIVE__ 53 | # define __DEC32_MOST_NEGATIVE__ (-__DEC32_MOST_POSITIVE__) 54 | #endif /* !__DEC32_MOST_NEGATIVE__ */ 55 | 56 | typedef struct { 57 | uint_least32_t mant; 58 | int expo; 59 | int sign; 60 | } bcd32_t; 61 | 62 | 63 | extern _Decimal32 strtod32(const char*, char**); 64 | 65 | #if defined HAVE_DFP754_BID_LITERALS || defined HAVE_DFP754_DPD_LITERALS 66 | extern int d32tostr(char *restrict buf, size_t bsz, _Decimal32); 67 | 68 | /** 69 | * Round X to the quantum of R. */ 70 | extern _Decimal32 quantized32(_Decimal32 x, _Decimal32 r); 71 | 72 | /** 73 | * Return X*10^N. */ 74 | extern _Decimal32 scalbnd32(_Decimal32 x, int n); 75 | #endif /* !HAVE_DFP754_*_LITERALS */ 76 | 77 | /* non-standard stuff */ 78 | /** 79 | * Decompose x. */ 80 | extern bcd32_t decompd32(_Decimal32 x); 81 | 82 | 83 | inline __attribute__((pure, const)) uint32_t bits32(_Decimal32 x); 84 | inline __attribute__((pure, const)) _Decimal32 bobs32(uint32_t u); 85 | inline __attribute__((pure, const)) int quantexpd32(_Decimal32 x); 86 | #if !defined HAVE_NAND32 87 | inline __attribute__((pure, const)) _Decimal32 nand32(char *__tagp); 88 | #endif /* !HAVE_NAND32 */ 89 | #if !defined HAVE_ISNAND32 90 | # define isnand32 __builtin_isnand32 91 | #endif /* !HAVE_ISNAND32 */ 92 | 93 | inline __attribute__((pure, const)) uint32_t 94 | bits32(_Decimal32 x) 95 | { 96 | return (union {_Decimal32 x; uint32_t u;}){x}.u; 97 | } 98 | 99 | inline __attribute__((pure, const)) _Decimal32 100 | bobs32(uint32_t u) 101 | { 102 | return (union {uint32_t u; _Decimal32 x;}){u}.x; 103 | } 104 | 105 | #if defined HAVE_DFP754_BID_LITERALS 106 | inline __attribute__((pure, const)) int quantexpbid32(_Decimal32 x); 107 | inline __attribute__((pure, const)) int 108 | quantexpbid32(_Decimal32 x) 109 | { 110 | register uint32_t b = bits32(x); 111 | register int tmp; 112 | 113 | if (b == 0U) { 114 | return 0; 115 | } else if ((b & 0x60000000U) != 0x60000000U) { 116 | tmp = (b >> 23U); 117 | } else { 118 | /* exponent starts 2 bits to the left */ 119 | tmp = (b >> 21U); 120 | } 121 | return (tmp & 0xffU) - 101; 122 | } 123 | #elif defined HAVE_DFP754_DPD_LITERALS 124 | inline __attribute__((pure, const)) int quantexpdpd32(_Decimal32 x); 125 | inline __attribute__((pure, const)) int 126 | quantexpdpd32(_Decimal32 x) 127 | { 128 | register uint32_t b = bits32(x); 129 | register int tmp; 130 | 131 | b >>= 20U; 132 | if (b == 0U) { 133 | return 0; 134 | } else if ((b & 0b11000000000U) != 0b11000000000U) { 135 | tmp = ((b & 0b11000000000U) >> 3U) | (b & 0b111111U); 136 | } else { 137 | /* exponent starts 2 bits to the left */ 138 | tmp = ((b & 0b00110000000U) >> 1U) | (b & 0b111111U); 139 | } 140 | return tmp - 101; 141 | } 142 | #endif /* HAVE_DFP754_DPD_LITERALS || HAVE_DFP754_BID_LITERALS */ 143 | 144 | #if defined HAVE_DFP754_BID_LITERALS || defined HAVE_DFP754_DPD_LITERALS 145 | inline __attribute__((pure, const)) int 146 | quantexpd32(_Decimal32 x) 147 | { 148 | #if defined HAVE_DFP754_BID_LITERALS 149 | return quantexpbid32(x); 150 | #elif defined HAVE_DFP754_DPD_LITERALS 151 | return quantexpdpd32(x); 152 | #endif /* HAVE_DFP754_*_LITERALS */ 153 | } 154 | #endif /* !HAVE_DFP754_*_LITERALS */ 155 | 156 | #if defined HAVE_BUILTIN_NAND32 157 | # define NAND32 __builtin_nand32("") 158 | #elif defined HAVE_BUILTIN_NAN_FOR_NAND32 159 | # define NAND32 ((_Decimal32)__builtin_nan("")) 160 | #else 161 | # define NAND32 ((union {uint32_t u; _Decimal32 x;}){NAND32_U}.x) 162 | #endif 163 | #if defined HAVE_BUILTIN_INFD32 164 | # define INFD32 __builtin_infd32() 165 | #elif defined HAVE_BUILTIN_INF_FOR_INFD32 166 | # define INFD32 ((_Decimal32)__builtin_inf()) 167 | #else 168 | # define INFD32 (((union {uint32_t u; _Decimal32 x;}){INFD32_U}).x) 169 | #endif 170 | 171 | #if !defined HAVE_NAND32 172 | inline __attribute__((pure, const)) _Decimal32 173 | nand32(char *__tagp __attribute__((unused))) 174 | { 175 | return NAND32; 176 | } 177 | #endif /* !HAVE_NAND32 */ 178 | 179 | #if !defined HAVE_INFD32 180 | inline __attribute__((pure, const)) _Decimal32 181 | infd32(void) 182 | { 183 | return INFD32; 184 | } 185 | #endif /* !HAVE_INFD32 */ 186 | 187 | #endif /* INCLUDED_dfp754_d32_h_ */ 188 | -------------------------------------------------------------------------------- /src/dfp754_d64.h: -------------------------------------------------------------------------------- 1 | /*** dfp754_d64.h -- _Decimal64 goodness 2 | * 3 | * Copyright (C) 2013-2022 Sebastian Freundt 4 | * 5 | * Author: Sebastian Freundt 6 | * 7 | * This file is part of dfp754. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 16 | * 2. Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 20 | * 3. Neither the name of the author nor the names of any contributors 21 | * may be used to endorse or promote products derived from this 22 | * software without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 34 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | * 36 | ***/ 37 | #if !defined INCLUDED_dfp754_d64_h_ 38 | #define INCLUDED_dfp754_d64_h_ 39 | 40 | #if defined HAVE_CONFIG_H 41 | # include "config.h" 42 | #endif /* HAVE_CONFIG_H */ 43 | #include 44 | #include 45 | 46 | #define NAND64_U (0x7c00000000000000U) 47 | #define INFD64_U (0x7800000000000000U) 48 | 49 | #if !defined __DEC64_MOST_POSITIVE__ 50 | # define __DEC64_MOST_POSITIVE__ (__DEC64_MAX__) 51 | #endif /* !__DEC64_MOST_POSITIVE__ */ 52 | #if !defined __DEC64_MOST_NEGATIVE__ 53 | # define __DEC64_MOST_NEGATIVE__ (-__DEC64_MOST_POSITIVE__) 54 | #endif /* !__DEC64_MOST_NEGATIVE__ */ 55 | 56 | typedef struct { 57 | uint_least64_t mant; 58 | int expo; 59 | int sign; 60 | } bcd64_t; 61 | 62 | 63 | extern _Decimal64 strtod64(const char*, char**); 64 | 65 | #if defined HAVE_DFP754_BID_LITERALS || defined HAVE_DFP754_DPD_LITERALS 66 | extern int d64tostr(char *restrict buf, size_t bsz, _Decimal64); 67 | 68 | /** 69 | * Round X to the quantum of R. */ 70 | extern _Decimal64 quantized64(_Decimal64 x, _Decimal64 r); 71 | 72 | /** 73 | * Return X*10^N. */ 74 | extern _Decimal64 scalbnd64(_Decimal64 x, int n); 75 | #endif /* !HAVE_DFP754_*_LITERALS */ 76 | 77 | /* non-standard stuff */ 78 | /** 79 | * Decompose x. */ 80 | extern bcd64_t decompd64(_Decimal64 x); 81 | 82 | 83 | inline __attribute__((pure, const)) uint64_t bits64(_Decimal64 x); 84 | inline __attribute__((pure, const)) _Decimal64 bobs64(uint64_t u); 85 | inline __attribute__((pure, const)) int quantexpd64(_Decimal64 x); 86 | #if !defined HAVE_NAND64 87 | inline __attribute__((pure, const)) _Decimal64 nand64(char *__tagp); 88 | #endif /* !HAVE_NAND64 */ 89 | #if !defined HAVE_ISNAND64 90 | # define isnand64 __builtin_isnand64 91 | #endif /* !HAVE_ISNAND64 */ 92 | 93 | inline __attribute__((pure, const)) uint64_t 94 | bits64(_Decimal64 x) 95 | { 96 | return (union {_Decimal64 x; uint64_t u;}){x}.u; 97 | } 98 | 99 | inline __attribute__((pure, const)) _Decimal64 100 | bobs64(uint64_t u) 101 | { 102 | return (union {uint64_t u; _Decimal64 x;}){u}.x; 103 | } 104 | 105 | #if defined HAVE_DFP754_BID_LITERALS 106 | inline __attribute__((pure, const)) int quantexpbid64(_Decimal64 x); 107 | inline __attribute__((pure, const)) int 108 | quantexpbid64(_Decimal64 x) 109 | { 110 | register uint64_t b = bits64(x); 111 | register int tmp; 112 | 113 | if (b == 0U) { 114 | return 0; 115 | } else if ((b & 0x6000000000000000ULL) != 0x6000000000000000ULL) { 116 | tmp = (b >> 53U); 117 | } else { 118 | /* exponent starts 2 bits to the left */ 119 | tmp = (b >> 51U); 120 | } 121 | return (tmp & 0x3ffU) - 398; 122 | } 123 | #elif defined HAVE_DFP754_DPD_LITERALS 124 | inline __attribute__((pure, const)) int quantexpdpd64(_Decimal64 x); 125 | inline __attribute__((pure, const)) int 126 | quantexpdpd64(_Decimal64 x) 127 | { 128 | register uint64_t b = bits64(x); 129 | register int tmp; 130 | 131 | b >>= 50U; 132 | if (b == 0U) { 133 | return 0; 134 | } else if ((b & 0b1100000000000ULL) != 0b1100000000000ULL) { 135 | tmp = ((b & 0b1100000000000ULL) >> 3U) | (b & 0b11111111ULL); 136 | } else { 137 | /* exponent starts 2 bits to the left */ 138 | tmp = ((b & 0b001100000000ULL) >> 1U) | (b & 0b11111111ULL); 139 | } 140 | return tmp - 398; 141 | } 142 | #endif /* HAVE_DFP754_DPD_LITERALS || HAVE_DFP754_BID_LITERALS */ 143 | 144 | #if defined HAVE_DFP754_BID_LITERALS || defined HAVE_DFP754_DPD_LITERALS 145 | inline __attribute__((pure, const)) int 146 | quantexpd64(_Decimal64 x) 147 | { 148 | #if defined HAVE_DFP754_BID_LITERALS 149 | return quantexpbid64(x); 150 | #elif defined HAVE_DFP754_DPD_LITERALS 151 | return quantexpdpd64(x); 152 | #endif /* HAVE_DFP754_*_LITERALS */ 153 | } 154 | #endif /* !HAVE_DFP754_*_LITERALS */ 155 | 156 | #if defined HAVE_BUILTIN_NAND64 157 | # define NAND64 __builtin_nand64("") 158 | #elif defined HAVE_BUILTIN_NAN_FOR_NAND64 159 | # define NAND64 ((_Decimal64)__builtin_nan("")) 160 | #else 161 | # define NAND64 ((union {uint64_t u; _Decimal64 x;}){NAND64_U}.x) 162 | #endif 163 | #if defined HAVE_BUILTIN_INFD64 164 | # define INFD64 __builtin_infd64() 165 | #elif defined HAVE_BUILTIN_INF_FOR_INFD64 166 | # define INFD64 ((_Decimal64)__builtin_inf()) 167 | #else 168 | # define INFD64 (((union {uint64_t u; _Decimal64 x;}){INFD64_U}).x) 169 | #endif 170 | 171 | #if !defined HAVE_NAND64 172 | inline __attribute__((pure, const)) _Decimal64 173 | nand64(char *__tagp __attribute__((unused))) 174 | { 175 | return NAND64; 176 | } 177 | #endif /* !HAVE_NAND64 */ 178 | 179 | #if !defined HAVE_INFD64 180 | inline __attribute__((pure, const)) _Decimal64 181 | infd64(void) 182 | { 183 | return INFD64; 184 | } 185 | #endif /* !HAVE_INFD64 */ 186 | 187 | #endif /* INCLUDED_dfp754_d64_h_ */ 188 | -------------------------------------------------------------------------------- /src/mmod-auction.c: -------------------------------------------------------------------------------- 1 | /*** mmod-auction.c -- auction market model 2 | * 3 | * Copyright (C) 2016-2022 Sebastian Freundt 4 | * 5 | * Author: Sebastian Freundt 6 | * 7 | * This file is part of clob. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 16 | * 2. Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 20 | * 3. Neither the name of the author nor the names of any contributors 21 | * may be used to endorse or promote products derived from this 22 | * software without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 34 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | * 36 | **/ 37 | #if defined HAVE_CONFIG_H 38 | # include "config.h" 39 | #endif /* HAVE_CONFIG_H */ 40 | #include 41 | #include 42 | #if defined WITH_DECIMAL 43 | # include 44 | #else 45 | # include 46 | #endif 47 | #include "btree.h" 48 | #include "btree_val.h" 49 | #include "plqu.h" 50 | #include "plqu_val.h" 51 | #include "clob.h" 52 | #include "clob_val.h" 53 | #include "mmod-auction.h" 54 | #include "nifty.h" 55 | 56 | #if defined WITH_DECIMAL 57 | # define MAXQX INFD64 58 | # define MINQX -INFD64 59 | # define fabsqx fabsd64 60 | # define quantizepx quantized64 61 | 62 | #if !defined HAVE_DFP754_H && !defined HAVE_DFP_STDLIB_H && !defined HAVE_DECIMAL_H 63 | static inline __attribute__((pure, const)) _Decimal64 64 | fabsd64(_Decimal64 x) 65 | { 66 | return x >= 0.dd ? x : -x; 67 | } 68 | #endif 69 | #else /* !WITH_DECIMAL */ 70 | # define MAXQX INFINITY 71 | # define MINQX -INFINITY 72 | # define fabsqx fabs 73 | # define quantizepx(x, y) (x) 74 | #endif 75 | 76 | /* auction helper */ 77 | static px_t besp; 78 | static px_t besn; 79 | static qx_t besq; 80 | static qx_t bimb; 81 | 82 | /* temporary store of bids to do traversals in the opposite direction */ 83 | static px_t *bids; 84 | static qx_t *bszs; 85 | static size_t bidz; 86 | 87 | 88 | static qx_t 89 | plqu_qx(plqu_t q) 90 | { 91 | qty_t sum = qty0; 92 | for (plqu_iter_t i = {.q = q}; plqu_iter_next(&i);) { 93 | sum = qty_add(sum, i.v.qty); 94 | } 95 | return qty(sum); 96 | } 97 | 98 | static void 99 | _init(void) 100 | { 101 | besq = 0.dd; 102 | bimb = MAXQX; 103 | besn = 1.dd; 104 | } 105 | 106 | static void 107 | _push(px_t p, qx_t b, qx_t a) 108 | { 109 | qx_t tmp = min(b, a); 110 | qx_t imb = b - a; 111 | 112 | if (tmp > besq) { 113 | bang: 114 | besp = p; 115 | besq = tmp; 116 | bimb = imb; 117 | besn = 1.dd; 118 | } else if (tmp == besq) { 119 | /* see who's got less hang */ 120 | qx_t aimb = fabsqx(imb); 121 | qx_t abimb = fabsqx(bimb); 122 | 123 | if (aimb < abimb) { 124 | goto bang; 125 | } else if (aimb == abimb) { 126 | if (imb == 0.dd || -imb == bimb) { 127 | /* add up for meaning */ 128 | besp += p; 129 | besq = tmp; 130 | bimb = 0.dd; 131 | besn += 1.dd; 132 | } else if (imb > 0.dd) { 133 | goto bang; 134 | } 135 | } 136 | } 137 | return; 138 | } 139 | 140 | static mmod_auc_t 141 | _mmod_unwind(btree_iter_t i, clob_side_t is, qx_t m) 142 | { 143 | /* helper routine for markets with limit orders on only one side 144 | * unwind orders of at most M quantities from I 145 | * this is the obvious unwind operation as would be done in 146 | * continuous trading, however we won't touch the book 147 | * the iterator is assumed to have stepped already 148 | * IS is the side of I. */ 149 | qx_t iq = 0.dd; 150 | px_t ik; 151 | 152 | do { 153 | /* keep track of auction price because we mustn't 154 | * access the iterator after he's run out of steam 155 | * (and invalidates its key slot along the way) */ 156 | ik = i.k; 157 | iq += qty(i.v->sum); 158 | } while (iq < m && btree_iter_next(&i)); 159 | return (mmod_auc_t){ik, min(iq, m), (iq - m) * (!is ? -1.dd : 1.dd)}; 160 | } 161 | 162 | 163 | mmod_auc_t 164 | mmod_auction(clob_t c) 165 | { 166 | /* here we line up the cumsum of bid quantities against the 167 | * cumsum of ask quantities, like xetra we stop at the edge 168 | * points of the overlap 169 | * it would look like this 170 | * 171 | * sum(bq) bq p aq sum(aq) 172 | * x x M 173 | * x x P x x 174 | * x x P x 175 | * P x x 176 | * P x 177 | * M x x 178 | * 179 | * Obviously because there's no way to traverse the btree 180 | * backwards we have to temporarily write one of bids and 181 | * asks into an array and traverse that one backwards 182 | * with the opposite side traversing forwards. 183 | * 184 | * At each point we check for the highest turnover, and 185 | * if there's no improvement on turnover for the lowest 186 | * imbalance. */ 187 | btree_iter_t aski, bidi; 188 | bool askp, bidp; 189 | px_t ask, bid; 190 | qx_t asz, bsz; 191 | 192 | aski = (btree_iter_t){.t = (btree_t)c.lmt[CLOB_SIDE_ASK]}; 193 | bidi = (btree_iter_t){.t = (btree_t)c.lmt[CLOB_SIDE_BID]}; 194 | askp = btree_iter_next(&aski); 195 | bidp = btree_iter_next(&bidi); 196 | if (UNLIKELY(!askp && !bidp)) { 197 | /* no bids nor asks */ 198 | return (mmod_auc_t){NANPX}; 199 | } 200 | 201 | /* track overlap region */ 202 | ask = aski.k; 203 | bid = bidi.k; 204 | 205 | asz = plqu_qx((plqu_t)c.mkt[CLOB_SIDE_SHORT]); 206 | bsz = plqu_qx((plqu_t)c.mkt[CLOB_SIDE_LONG]); 207 | 208 | /* see if there's an overlap */ 209 | if (0) { 210 | ; 211 | } else if (!bidp) { 212 | /* unwind bid market against asks */ 213 | return _mmod_unwind(aski, CLOB_SIDE_ASK, bsz); 214 | } else if (!askp) { 215 | /* unwind ask market against bids */ 216 | return _mmod_unwind(bidi, CLOB_SIDE_BID, asz); 217 | } else if (LIKELY(ask > bid && asz <= 0.dd && bsz <= 0.dd)) { 218 | /* no overlap */ 219 | return (mmod_auc_t){NANPX}; 220 | } 221 | 222 | /* determine cum vol and keep track of levels */ 223 | size_t bi = 0U; 224 | qx_t mb = bsz; 225 | 226 | do { 227 | if (UNLIKELY(++bi >= bidz)) { 228 | /* running out of bid space, resize */ 229 | size_t nuz = (bidz * 2U) ?: 256U; 230 | bids = realloc(bids, nuz * sizeof(*bids)); 231 | bszs = realloc(bszs, nuz * sizeof(*bszs)); 232 | bidz = nuz; 233 | } 234 | bids[bi] = bidi.k; 235 | bsz += qty(bidi.v->sum); 236 | bszs[bi] = bsz; 237 | } while (btree_iter_next(&bidi) && bidi.k >= ask); 238 | /* set very first element */ 239 | bids[0U] = bids[1U]; 240 | bszs[0U] = mb; 241 | 242 | /* now cumulate asks and calculate execution */ 243 | size_t ai = bi; 244 | 245 | _init(); 246 | 247 | do { 248 | for (; ai > 0U && aski.k > bids[ai]; ai--) { 249 | _push(bids[ai], bszs[ai], asz); 250 | } 251 | 252 | asz += qty(aski.v->sum); 253 | 254 | _push(aski.k, bszs[ai], asz); 255 | 256 | /* prevent double push in the next iteration */ 257 | ai -= ai > 0U && bids[ai] == aski.k; 258 | } while (btree_iter_next(&aski) && aski.k <= bid); 259 | 260 | if (ai) { 261 | do { 262 | _push(bids[ai], bszs[ai], asz); 263 | } while (--ai && aski.k > bids[ai]); 264 | } 265 | 266 | besp = quantizepx(besp / besn, besp); 267 | return (mmod_auc_t){besp, besq, bimb}; 268 | } 269 | 270 | /* mmod-auction.c ends here */ 271 | -------------------------------------------------------------------------------- /src/mmod-auction.h: -------------------------------------------------------------------------------- 1 | /*** mmod-auction.h -- auction market model 2 | * 3 | * Copyright (C) 2016-2022 Sebastian Freundt 4 | * 5 | * Author: Sebastian Freundt 6 | * 7 | * This file is part of clob. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 16 | * 2. Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 20 | * 3. Neither the name of the author nor the names of any contributors 21 | * may be used to endorse or promote products derived from this 22 | * software without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 34 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | * 36 | **/ 37 | #if !defined INCLUDED_mmod_auction_h_ 38 | #define INCLUDED_mmod_auction_h_ 39 | #include 40 | #include "clob.h" 41 | #include "clob_val.h" 42 | 43 | typedef struct { 44 | /** theo auction price */ 45 | px_t prc; 46 | /** theo auction volume */ 47 | qx_t qty; 48 | /** market imbalance */ 49 | qx_t imb; 50 | } mmod_auc_t; 51 | 52 | /** 53 | * Determine the market in the book using the auction model. */ 54 | extern mmod_auc_t mmod_auction(clob_t c); 55 | 56 | #endif /* INCLUDED_mmod_auction_h_ */ 57 | -------------------------------------------------------------------------------- /src/mmod-fok.c: -------------------------------------------------------------------------------- 1 | /*** mmod-fok.c -- decide on FOK orders 2 | * 3 | * Copyright (C) 2016-2022 Sebastian Freundt 4 | * 5 | * Author: Sebastian Freundt 6 | * 7 | * This file is part of clob. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 16 | * 2. Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 20 | * 3. Neither the name of the author nor the names of any contributors 21 | * may be used to endorse or promote products derived from this 22 | * software without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 34 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | * 36 | **/ 37 | #if defined HAVE_CONFIG_H 38 | # include "config.h" 39 | #endif /* HAVE_CONFIG_H */ 40 | #include 41 | #include 42 | #if defined WITH_DECIMAL 43 | # include 44 | #endif 45 | #include "btree.h" 46 | #include "btree_val.h" 47 | #include "plqu.h" 48 | #include "plqu_val.h" 49 | #include "clob.h" 50 | #include "clob_val.h" 51 | #include "mmod-fok.h" 52 | #include "nifty.h" 53 | 54 | 55 | static inline __attribute__((const, pure)) px_t 56 | sign_side(px_t p, clob_side_t s) 57 | { 58 | /* negate ask prices, leave bid prices */ 59 | return s == CLOB_SIDE_ASK ? -p : p; 60 | } 61 | 62 | static void 63 | _fok(clob_ord_t *restrict o, plqu_t q) 64 | { 65 | /* return the quantity taken off of Q */ 66 | plqu_iter_t qi = {.q = q}; 67 | qx_t oq = qty(o->qty); 68 | 69 | for (; plqu_iter_next(&qi) && oq > 0.dd; oq = qty(o->qty)) { 70 | qx_t mq = qty(qi.v.qty); 71 | 72 | if (mq <= oq) { 73 | /* full maker ~ partial taker */ 74 | o->qty = qty_exe(o->qty, mq); 75 | } else { 76 | /* let everyone know there's nothing left */ 77 | o->qty = qty0; 78 | break; 79 | } 80 | } 81 | return; 82 | } 83 | 84 | 85 | int 86 | mmod_fok(clob_t c, clob_ord_t o) 87 | { 88 | const clob_side_t contra = clob_contra_side(o.sid); 89 | 90 | switch (o.typ) { 91 | btree_iter_t ti; 92 | bool lmtp; 93 | 94 | case CLOB_TYPE_LMT: 95 | /* execute against contra market first, then contra limit */ 96 | ti = (btree_iter_t){.t = (btree_t)c.lmt[contra]}; 97 | lmtp = btree_iter_next(&ti); 98 | goto marketable; 99 | 100 | case CLOB_TYPE_MKT: 101 | /* execute against contra market first, then contra limit */ 102 | ti = (btree_iter_t){.t = (btree_t)c.lmt[contra]}; 103 | if (LIKELY((lmtp = btree_iter_next(&ti)))) { 104 | /* aaah, reference price, use to imply a limit */ 105 | o.lmt = ti.k + sign_side(o.slp, o.sid); 106 | } else { 107 | /* no price means no execution */ 108 | goto kill; 109 | } 110 | goto marketable; 111 | 112 | marketable: 113 | /* get markets ready */ 114 | _fok(&o, c.mkt[contra]); 115 | more: 116 | if (qty(o.qty) <= 0.dd) { 117 | goto fill; 118 | } else if (!lmtp) { 119 | goto kill; 120 | } else if (o.sid == CLOB_SIDE_ASK && ti.k < o.lmt) { 121 | /* we need an improvement over R */ 122 | goto kill; 123 | } else if (o.sid == CLOB_SIDE_BID && ti.k > o.lmt) { 124 | /* not an improvement */ 125 | goto kill; 126 | } 127 | /* otherwise dive into limits */ 128 | _fok(&o, ti.v->q); 129 | /* climb up/down the ladder */ 130 | lmtp = btree_iter_next(&ti); 131 | goto more; 132 | } 133 | fill: 134 | /* filled */ 135 | return 1; 136 | 137 | kill: 138 | /* killed */ 139 | return 0; 140 | } 141 | 142 | /* mmod-fok.c ends here */ 143 | -------------------------------------------------------------------------------- /src/mmod-fok.h: -------------------------------------------------------------------------------- 1 | /*** mmod-fok.h -- decide on FOK orders 2 | * 3 | * Copyright (C) 2016-2022 Sebastian Freundt 4 | * 5 | * Author: Sebastian Freundt 6 | * 7 | * This file is part of clob. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 16 | * 2. Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 20 | * 3. Neither the name of the author nor the names of any contributors 21 | * may be used to endorse or promote products derived from this 22 | * software without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 34 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | * 36 | **/ 37 | #if !defined INCLUDED_mmod_fok_h_ 38 | #define INCLUDED_mmod_fok_h_ 39 | #include 40 | #include "clob.h" 41 | 42 | /** 43 | * Determine whether order O can be filled immediately. */ 44 | extern int mmod_fok(clob_t c, clob_ord_t o); 45 | 46 | #endif /* INCLUDED_mmod_fok_h_ */ 47 | -------------------------------------------------------------------------------- /src/mmod-ioc.c: -------------------------------------------------------------------------------- 1 | /*** mmod-ioc.c -- decide on IOC orders 2 | * 3 | * Copyright (C) 2016-2022 Sebastian Freundt 4 | * 5 | * Author: Sebastian Freundt 6 | * 7 | * This file is part of clob. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 16 | * 2. Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 20 | * 3. Neither the name of the author nor the names of any contributors 21 | * may be used to endorse or promote products derived from this 22 | * software without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 34 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | * 36 | **/ 37 | #if defined HAVE_CONFIG_H 38 | # include "config.h" 39 | #endif /* HAVE_CONFIG_H */ 40 | #include 41 | #include 42 | #if defined WITH_DECIMAL 43 | # include 44 | #endif 45 | #include "btree.h" 46 | #include "btree_val.h" 47 | #include "plqu.h" 48 | #include "plqu_val.h" 49 | #include "clob.h" 50 | #include "clob_val.h" 51 | #include "mmod-ioc.h" 52 | #include "nifty.h" 53 | 54 | 55 | static inline __attribute__((const, pure)) px_t 56 | sign_side(px_t p, clob_side_t s) 57 | { 58 | /* negate ask prices, leave bid prices */ 59 | return s == CLOB_SIDE_ASK ? -p : p; 60 | } 61 | 62 | 63 | int 64 | mmod_ioc(clob_t c, clob_ord_t o) 65 | { 66 | const clob_side_t contra = clob_contra_side(o.sid); 67 | 68 | switch (o.typ) { 69 | btree_iter_t ti; 70 | plqu_iter_t qi; 71 | bool lmtp; 72 | 73 | case CLOB_TYPE_LMT: 74 | qi = (plqu_iter_t){.q = c.mkt[contra]}; 75 | if (plqu_iter_next(&qi)) { 76 | /* anything goes against a market order */ 77 | break; 78 | } 79 | /* otherwise prep for some serious limit checking */ 80 | ti = (btree_iter_t){.t = (btree_t)c.lmt[contra]}; 81 | lmtp = btree_iter_next(&ti); 82 | goto marketable; 83 | 84 | case CLOB_TYPE_MKT: 85 | /* execute against contra market first, then contra limit */ 86 | ti = (btree_iter_t){.t = (btree_t)c.lmt[contra]}; 87 | if (LIKELY((lmtp = btree_iter_next(&ti)))) { 88 | /* aaah, reference price, use to imply a limit */ 89 | o.lmt = ti.k + sign_side(o.slp, o.sid); 90 | } else { 91 | /* no price means no execution */ 92 | goto kill; 93 | } 94 | goto marketable; 95 | 96 | marketable: 97 | /* get markets ready */ 98 | if (!lmtp) { 99 | goto kill; 100 | } else if (o.sid == CLOB_SIDE_ASK && ti.k < o.lmt) { 101 | /* we need an improvement over R */ 102 | goto kill; 103 | } else if (o.sid == CLOB_SIDE_BID && ti.k > o.lmt) { 104 | /* not an improvement */ 105 | goto kill; 106 | } 107 | /* otherwise there would be at least some sort of fill */ 108 | break; 109 | } 110 | /* filled */ 111 | return 1; 112 | 113 | kill: 114 | /* killed */ 115 | return 0; 116 | } 117 | 118 | /* mmod-ioc.c ends here */ 119 | -------------------------------------------------------------------------------- /src/mmod-ioc.h: -------------------------------------------------------------------------------- 1 | /*** mmod-ioc.h -- decide on IOC orders 2 | * 3 | * Copyright (C) 2016-2022 Sebastian Freundt 4 | * 5 | * Author: Sebastian Freundt 6 | * 7 | * This file is part of clob. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 16 | * 2. Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 20 | * 3. Neither the name of the author nor the names of any contributors 21 | * may be used to endorse or promote products derived from this 22 | * software without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 34 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | * 36 | **/ 37 | #if !defined INCLUDED_mmod_ioc_h_ 38 | #define INCLUDED_mmod_ioc_h_ 39 | #include 40 | #include "clob.h" 41 | 42 | /** 43 | * Determine whether order O can be filled immediately. */ 44 | extern int mmod_ioc(clob_t c, clob_ord_t o); 45 | 46 | #endif /* INCLUDED_mmod_ioc_h_ */ 47 | -------------------------------------------------------------------------------- /src/mmod-pdo.c: -------------------------------------------------------------------------------- 1 | /*** mmod-pdo.c -- price discovery orders 2 | * 3 | * Copyright (C) 2016-2022 Sebastian Freundt 4 | * 5 | * Author: Sebastian Freundt 6 | * 7 | * This file is part of clob. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 16 | * 2. Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 20 | * 3. Neither the name of the author nor the names of any contributors 21 | * may be used to endorse or promote products derived from this 22 | * software without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 34 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | * 36 | **/ 37 | #if defined HAVE_CONFIG_H 38 | # include "config.h" 39 | #endif /* HAVE_CONFIG_H */ 40 | #include 41 | #include 42 | #if defined WITH_DECIMAL 43 | # include 44 | #endif 45 | #include "btree.h" 46 | #include "btree_val.h" 47 | #include "plqu.h" 48 | #include "plqu_val.h" 49 | #include "clob.h" 50 | #include "clob_val.h" 51 | #include "mmod-pdo.h" 52 | #include "nifty.h" 53 | 54 | 55 | static inline __attribute__((const, pure)) px_t 56 | sign_side(px_t p, clob_side_t s) 57 | { 58 | /* negate ask prices, leave bid prices */ 59 | return s == CLOB_SIDE_ASK ? -p : p; 60 | } 61 | 62 | static qx_t 63 | _pdo(clob_ord_t *restrict o, plqu_t q) 64 | { 65 | /* return the quantity taken off of Q */ 66 | plqu_iter_t qi = {.q = q}; 67 | qx_t oq = qty(o->qty); 68 | qx_t r = 0.dd; 69 | 70 | for (; plqu_iter_next(&qi) && oq > 0.dd; oq = qty(o->qty)) { 71 | qx_t mq = qty(qi.v.qty); 72 | 73 | if (mq <= oq) { 74 | /* full maker ~ partial taker */ 75 | o->qty = qty_exe(o->qty, mq); 76 | /* add maker quantity to result */ 77 | r += mq; 78 | } else { 79 | /* partial maker ~ full taker */ 80 | r += oq; 81 | /* let everyone know there's nothing left */ 82 | o->qty = qty0; 83 | break; 84 | } 85 | } 86 | return r; 87 | } 88 | 89 | 90 | mmod_pdo_t 91 | mmod_pdo(clob_t c, clob_ord_t o) 92 | { 93 | const clob_side_t contra = clob_contra_side(o.sid); 94 | mmod_pdo_t a = {.base = 0.dd, .term = 0.dd}; 95 | 96 | switch (o.typ) { 97 | btree_iter_t ti; 98 | bool lmtp; 99 | px_t r; 100 | 101 | case CLOB_TYPE_LMT: 102 | /* execute against contra market first, then contra limit */ 103 | ti = (btree_iter_t){.t = (btree_t)c.lmt[contra]}; 104 | if (LIKELY((lmtp = btree_iter_next(&ti)))) { 105 | /* market orders act like pegs 106 | * so find out about the top bid/ask */ 107 | switch (o.sid) { 108 | case CLOB_SIDE_ASK: 109 | r = max(o.lmt, ti.k); 110 | break; 111 | case CLOB_SIDE_BID: 112 | r = min(o.lmt, ti.k); 113 | break; 114 | } 115 | } else { 116 | /* can't execute against NAN reference price */ 117 | r = o.lmt; 118 | } 119 | goto marketable; 120 | 121 | case CLOB_TYPE_MKT: 122 | /* execute against contra market first, then contra limit */ 123 | ti = (btree_iter_t){.t = (btree_t)c.lmt[contra]}; 124 | if (LIKELY((lmtp = btree_iter_next(&ti)))) { 125 | /* aaah, reference price we need not */ 126 | r = ti.k; 127 | } else { 128 | /* can't execute against NAN reference price */ 129 | break; 130 | } 131 | /* turn slippage into absolute limit price 132 | * only if slippage is a normal */ 133 | o.lmt = r + sign_side(o.slp, o.sid); 134 | goto marketable; 135 | 136 | marketable: 137 | /* get markets ready */ 138 | a.base = _pdo(&o, c.mkt[contra]); 139 | a.term = a.base * r; 140 | more: 141 | if (qty(o.qty) <= 0.dd) { 142 | /* filled */ 143 | break; 144 | } else if (!lmtp) { 145 | /* no more limit orders */ 146 | break; 147 | } else if (o.sid == CLOB_SIDE_ASK && ti.k < o.lmt) { 148 | /* we need a price improvement */ 149 | break; 150 | } else if (o.sid == CLOB_SIDE_BID && ti.k > o.lmt) { 151 | /* not an improvement */ 152 | break; 153 | } 154 | /* otherwise dive into limits */ 155 | with (qx_t q = _pdo(&o, ti.v->q)) { 156 | /* maintain the sum */ 157 | a.base += q; 158 | a.term += q * ti.k; 159 | lmtp = btree_iter_next(&ti); 160 | } 161 | goto more; 162 | } 163 | /* remainder goes back to requester */ 164 | return a; 165 | } 166 | 167 | /* mmod-pdo.c ends here */ 168 | -------------------------------------------------------------------------------- /src/mmod-pdo.h: -------------------------------------------------------------------------------- 1 | /*** mmod-pdo.h -- price discovery order 2 | * 3 | * Copyright (C) 2016-2022 Sebastian Freundt 4 | * 5 | * Author: Sebastian Freundt 6 | * 7 | * This file is part of clob. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 16 | * 2. Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 20 | * 3. Neither the name of the author nor the names of any contributors 21 | * may be used to endorse or promote products derived from this 22 | * software without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 34 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | * 36 | **/ 37 | #if !defined INCLUDED_mmod_pdo_h_ 38 | #define INCLUDED_mmod_pdo_h_ 39 | #include 40 | #include "clob.h" 41 | 42 | typedef struct { 43 | /** quantity in base units */ 44 | qx_t base; 45 | /** quantity times price aggregate */ 46 | qx_t term; 47 | } mmod_pdo_t; 48 | 49 | /** 50 | * Obtain a price discovery from order O. */ 51 | extern mmod_pdo_t mmod_pdo(clob_t c, clob_ord_t o); 52 | 53 | #endif /* INCLUDED_mmod_pdo_h_ */ 54 | -------------------------------------------------------------------------------- /src/nifty.h: -------------------------------------------------------------------------------- 1 | /*** nifty.h -- generally handy macroes 2 | * 3 | * Copyright (C) 2009-2022 Sebastian Freundt 4 | * 5 | * Author: Sebastian Freundt 6 | * 7 | * This file is part of clob. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 16 | * 2. Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 20 | * 3. Neither the name of the author nor the names of any contributors 21 | * may be used to endorse or promote products derived from this 22 | * software without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 34 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | * 36 | ***/ 37 | #if !defined INCLUDED_nifty_h_ 38 | #define INCLUDED_nifty_h_ 39 | 40 | #if !defined LIKELY 41 | # define LIKELY(_x) __builtin_expect((_x), 1) 42 | #endif /* !LIKELY */ 43 | #if !defined UNLIKELY 44 | # define UNLIKELY(_x) __builtin_expect((_x), 0) 45 | #endif /* UNLIKELY */ 46 | 47 | #if !defined UNUSED 48 | # define UNUSED(_x) _x __attribute__((unused)) 49 | #endif /* !UNUSED */ 50 | 51 | #if !defined ALGN 52 | # define ALGN(_x, to) _x __attribute__((aligned(to))) 53 | #endif /* !ALGN */ 54 | 55 | #if !defined countof 56 | # define countof(x) (sizeof(x) / sizeof(*x)) 57 | #endif /* !countof */ 58 | 59 | #if !defined strlenof 60 | # define strlenof(lit) (sizeof(lit) - 1U) 61 | #endif /* !strlenof */ 62 | 63 | #define _paste(x, y) x ## y 64 | #define paste(x, y) _paste(x, y) 65 | 66 | #if !defined with 67 | # define with(args...) \ 68 | for (args, *paste(__ep, __LINE__) = (void*)1; \ 69 | paste(__ep, __LINE__); paste(__ep, __LINE__)= 0) 70 | #endif /* !with */ 71 | 72 | #if !defined if_with 73 | # define if_with(init, args...) \ 74 | for (init, *paste(__ep, __LINE__) = (void*)1; \ 75 | paste(__ep, __LINE__) && (args); paste(__ep, __LINE__)= 0) 76 | #endif /* !if_with */ 77 | 78 | #define once \ 79 | static int paste(__, __LINE__); \ 80 | if (!paste(__, __LINE__)++) 81 | #define but_first \ 82 | static int paste(__, __LINE__); \ 83 | if (paste(__, __LINE__)++) 84 | 85 | #define save_errno \ 86 | for (int paste(__er, __LINE__) = errno, paste(__ep, __LINE__) = 1; \ 87 | paste(__ep, __LINE__); \ 88 | errno = paste(__er, __LINE__), paste(__ep, __LINE__) = 0) 89 | 90 | static inline void* 91 | deconst(const void *cp) 92 | { 93 | union { 94 | const void *c; 95 | void *p; 96 | } tmp = {cp}; 97 | return tmp.p; 98 | } 99 | 100 | #define max(x, y) ((x) >= (y) ? (x) : (y)) 101 | #define min(x, y) ((x) <= (y) ? (x) : (y)) 102 | 103 | #endif /* INCLUDED_nifty_h_ */ 104 | -------------------------------------------------------------------------------- /src/plqu.c: -------------------------------------------------------------------------------- 1 | /*** plqu.c -- price level queue 2 | * 3 | * Copyright (C) 2016-2022 Sebastian Freundt 4 | * 5 | * Author: Sebastian Freundt 6 | * 7 | * This file is part of clob. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 16 | * 2. Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 20 | * 3. Neither the name of the author nor the names of any contributors 21 | * may be used to endorse or promote products derived from this 22 | * software without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 34 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | * 36 | **/ 37 | #if defined HAVE_CONFIG_H 38 | # include "config.h" 39 | #endif /* HAVE_CONFIG_H */ 40 | #include 41 | #include 42 | #include 43 | #include "plqu.h" 44 | #include "plqu_val.h" 45 | #include "nifty.h" 46 | 47 | #define PLQU_INIZ (8U) 48 | 49 | struct plqu_s { 50 | /* always a 2-power or a 2-power - 1U if in use */ 51 | size_t z; 52 | plqu_val_t *a; 53 | size_t head; 54 | size_t tail; 55 | }; 56 | 57 | static struct plqu_s _pool[256U], *pool = _pool; 58 | static size_t zpool = countof(_pool); 59 | /* number of plqus in use */ 60 | static size_t npool; 61 | /* lowest returned plqu */ 62 | static size_t ipool; 63 | 64 | #define Q pool[q] 65 | 66 | 67 | plqu_t 68 | make_plqu(void) 69 | { 70 | if (UNLIKELY(npool >= zpool)) { 71 | /* resize */ 72 | size_t nuz = zpool * 2U; 73 | if (UNLIKELY(pool == _pool)) { 74 | pool = malloc(nuz * sizeof(*pool)); 75 | memcpy(pool, _pool, zpool * sizeof(*_pool)); 76 | memset(pool + zpool, 0, zpool * sizeof(*_pool)); 77 | } else { 78 | pool = realloc(pool, nuz * sizeof(*pool)); 79 | memset(pool + zpool, 0, zpool * sizeof(*_pool)); 80 | } 81 | zpool = nuz; 82 | } 83 | for (; ipool < zpool && pool[ipool].z & 1U; ipool++); 84 | /* mark in use */ 85 | pool[ipool].z--; 86 | /* keep track of used pools */ 87 | npool++; 88 | return ipool + 1U; 89 | } 90 | 91 | void 92 | free_plqu(plqu_t q) 93 | { 94 | q--; 95 | Q.head = 0U; 96 | Q.tail = 0U; 97 | /* mark free */ 98 | Q.z++; 99 | npool--; 100 | ipool = q < ipool ? q : ipool;; 101 | return; 102 | } 103 | 104 | plqu_val_t 105 | plqu_get(plqu_t q, plqu_qid_t i) 106 | { 107 | q--; 108 | if (UNLIKELY(!(i > Q.head && i <= Q.tail))) { 109 | return plqu_val_nil; 110 | } 111 | const size_t slot = (i - 1U) & Q.z; 112 | return Q.a[slot]; 113 | } 114 | 115 | int 116 | plqu_put(plqu_t q, plqu_qid_t i, plqu_val_t v) 117 | { 118 | q--; 119 | if (UNLIKELY(!(i > Q.head && i <= Q.tail))) { 120 | return -1; 121 | } 122 | const size_t slot = (i - 1U) & Q.z; 123 | Q.a[slot] = v; 124 | return 0; 125 | } 126 | 127 | plqu_qid_t 128 | plqu_add(plqu_t q, plqu_val_t v) 129 | { 130 | q--; 131 | if (UNLIKELY(Q.tail - Q.head >= (Q.z + 1U))) { 132 | /* resize him */ 133 | const size_t nuz = ((Q.z + 1U) * 2U) ?: PLQU_INIZ; 134 | void *tmp = realloc(Q.a, nuz * sizeof(*Q.a)); 135 | if (UNLIKELY(tmp == NULL)) { 136 | return 0ULL; 137 | } 138 | /* otherwise resize */ 139 | Q.a = tmp; 140 | /* head is either in the current range or the next range modulo 141 | * the new size, move tail or head respectively 142 | * to make things easy (and branchless) we simply clone the 143 | * whole array */ 144 | memcpy(Q.a + (Q.z + 1U), Q.a, (Q.z + 1U) * sizeof(*Q.a)); 145 | /* keep track of size */ 146 | Q.z = nuz - 1U; 147 | } 148 | Q.a[Q.tail++ & Q.z] = v; 149 | return Q.tail; 150 | } 151 | 152 | plqu_val_t 153 | plqu_top(plqu_t q) 154 | { 155 | plqu_val_t r; 156 | 157 | q--; 158 | if (LIKELY(Q.head < Q.tail)) { 159 | r = Q.a[Q.head & Q.z]; 160 | } else { 161 | r = plqu_val_nil; 162 | } 163 | return r; 164 | } 165 | 166 | plqu_val_t 167 | plqu_pop(plqu_t q) 168 | { 169 | plqu_val_t r; 170 | 171 | q--; 172 | if (LIKELY(Q.head < Q.tail)) { 173 | const size_t slot = Q.head++ & Q.z; 174 | r = Q.a[slot]; 175 | } else { 176 | r = plqu_val_nil; 177 | } 178 | return r; 179 | } 180 | 181 | 182 | bool 183 | plqu_iter_next(plqu_iter_t *iter) 184 | { 185 | plqu_t q = iter->q; 186 | 187 | if (UNLIKELY(q-- == 0U)) { 188 | return false; 189 | } else if (UNLIKELY(iter->i < Q.head)) { 190 | iter->i = Q.head; 191 | } 192 | while (iter->i < Q.tail) { 193 | const size_t slot = (iter->i++) & Q.z; 194 | if (LIKELY(!plqu_val_nil_p(Q.a[slot]))) { 195 | /* good one */ 196 | iter->v = Q.a[slot]; 197 | return true; 198 | } 199 | } 200 | /* set iter past tail */ 201 | iter->i = Q.tail + 1U; 202 | return false; 203 | } 204 | 205 | plqu_qid_t 206 | plqu_iter_qid(plqu_iter_t iter) 207 | { 208 | plqu_qid_t cand = iter.i; 209 | plqu_t q = iter.q - 1U; 210 | return cand <= Q.tail ? cand : 0ULL; 211 | } 212 | 213 | int 214 | plqu_iter_put(plqu_iter_t iter, plqu_val_t v) 215 | { 216 | plqu_t q = iter.q; 217 | 218 | if (UNLIKELY(q-- == 0U)) { 219 | ; 220 | } else if (UNLIKELY(!iter.i || iter.i > Q.tail)) { 221 | ; 222 | } else { 223 | return plqu_put(iter.q, iter.i, v); 224 | } 225 | return -1; 226 | } 227 | 228 | int 229 | plqu_iter_set_top(plqu_iter_t iter) 230 | { 231 | plqu_t q = iter.q; 232 | 233 | if (UNLIKELY(q-- == 0U)) { 234 | return -1; 235 | } else if (UNLIKELY(!iter.i)) { 236 | return -1; 237 | } 238 | /* otherwise index becomes head */ 239 | Q.head = iter.i - 1U; 240 | return 0; 241 | } 242 | 243 | /* plqu.c ends here */ 244 | -------------------------------------------------------------------------------- /src/plqu.h: -------------------------------------------------------------------------------- 1 | /*** plqu.h -- price level queue 2 | * 3 | * Copyright (C) 2016-2022 Sebastian Freundt 4 | * 5 | * Author: Sebastian Freundt 6 | * 7 | * This file is part of clob. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 16 | * 2. Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 20 | * 3. Neither the name of the author nor the names of any contributors 21 | * may be used to endorse or promote products derived from this 22 | * software without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 34 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | * 36 | **/ 37 | #if !defined INCLUDED_plqu_h_ 38 | #define INCLUDED_plqu_h_ 39 | #include 40 | #include 41 | #include 42 | /* defines plqu_val_t, hopefully */ 43 | #include "plqu_val.h" 44 | 45 | typedef uintptr_t plqu_qid_t; 46 | typedef uintptr_t plqu_t; 47 | 48 | typedef struct { 49 | plqu_t q; 50 | size_t i; 51 | plqu_val_t v; 52 | } plqu_iter_t; 53 | 54 | 55 | extern plqu_t make_plqu(void); 56 | extern void free_plqu(plqu_t); 57 | 58 | extern plqu_val_t plqu_get(plqu_t, plqu_qid_t); 59 | extern int plqu_put(plqu_t, plqu_qid_t, plqu_val_t); 60 | extern plqu_qid_t plqu_add(plqu_t, plqu_val_t); 61 | extern plqu_val_t plqu_top(plqu_t); 62 | extern plqu_val_t plqu_pop(plqu_t); 63 | 64 | extern bool plqu_iter_next(plqu_iter_t*); 65 | extern plqu_qid_t plqu_iter_qid(plqu_iter_t); 66 | extern int plqu_iter_put(plqu_iter_t, plqu_val_t); 67 | extern int plqu_iter_set_top(plqu_iter_t); 68 | 69 | #endif /* INCLUDED_plqu_h_ */ 70 | -------------------------------------------------------------------------------- /src/plqu_val.h: -------------------------------------------------------------------------------- 1 | /*** plqu_val.h -- values of price level queues ***/ 2 | #if !defined INCLUDED_plqu_val_h_ 3 | #define INCLUDED_plqu_val_h_ 4 | #include 5 | #include 6 | #include "clob_val.h" 7 | 8 | /* order bits essential for execution */ 9 | typedef struct { 10 | /** quantity */ 11 | qty_t qty; 12 | /** metronome stamp, strictly increasing */ 13 | metr_t tim; 14 | /** user data */ 15 | uintptr_t usr; 16 | } plqu_val_t; 17 | 18 | #define plqu_val_nil ((plqu_val_t){.tim = 0U}) 19 | 20 | static inline bool 21 | plqu_val_nil_p(plqu_val_t v) 22 | { 23 | return v.tim == 0U; 24 | } 25 | 26 | #endif /* INCLUDED_plqu_h_ */ 27 | -------------------------------------------------------------------------------- /src/quos.c: -------------------------------------------------------------------------------- 1 | /*** quos.c -- quote stream attachment to central limit order book 2 | * 3 | * Copyright (C) 2016-2022 Sebastian Freundt 4 | * 5 | * Author: Sebastian Freundt 6 | * 7 | * This file is part of clob. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 16 | * 2. Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 20 | * 3. Neither the name of the author nor the names of any contributors 21 | * may be used to endorse or promote products derived from this 22 | * software without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 34 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | * 36 | **/ 37 | #if defined HAVE_CONFIG_H 38 | # include "config.h" 39 | #endif /* HAVE_CONFIG_H */ 40 | #include "quos.h" 41 | #include "nifty.h" 42 | 43 | #define QUOS_INIZ (8U) 44 | 45 | struct _quos_s { 46 | size_t n; 47 | quos_msg_t *a; 48 | size_t z; 49 | }; 50 | 51 | 52 | quos_t 53 | make_quos(void) 54 | { 55 | struct _quos_s *r = malloc(sizeof(*r)); 56 | r->n = 0U; 57 | r->a = malloc(QUOS_INIZ * sizeof(*r->a)); 58 | r->z = QUOS_INIZ; 59 | return (quos_t)r; 60 | } 61 | 62 | void 63 | free_quos(quos_t q) 64 | { 65 | struct _quos_s *_q = (struct _quos_s*)q; 66 | if (LIKELY(_q->a != NULL)) { 67 | free(_q->a); 68 | } 69 | free(q); 70 | return; 71 | } 72 | 73 | int 74 | quos_add(quos_t q, quos_msg_t m) 75 | { 76 | struct _quos_s *_q = (struct _quos_s*)q; 77 | if (UNLIKELY(_q->n >= _q->z)) { 78 | /* resize him */ 79 | const size_t nuz = _q->z * 2U; 80 | void *tmp = realloc(_q->a, nuz * sizeof(*_q->a)); 81 | if (UNLIKELY(tmp == NULL)) { 82 | return -1; 83 | } 84 | /* otherwise assign */ 85 | _q->a = tmp; 86 | _q->z = nuz; 87 | } 88 | _q->a[_q->n++] = m; 89 | return 0; 90 | } 91 | 92 | int 93 | quos_clr(quos_t q) 94 | { 95 | struct _quos_s *_q = (struct _quos_s*)q; 96 | _q->n = 0U; 97 | return 0; 98 | } 99 | 100 | /* quos.c ends here*/ 101 | -------------------------------------------------------------------------------- /src/quos.h: -------------------------------------------------------------------------------- 1 | /*** quos.h -- quote stream attachment to central limit order book 2 | * 3 | * Copyright (C) 2016-2022 Sebastian Freundt 4 | * 5 | * Author: Sebastian Freundt 6 | * 7 | * This file is part of clob. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 16 | * 2. Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 20 | * 3. Neither the name of the author nor the names of any contributors 21 | * may be used to endorse or promote products derived from this 22 | * software without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 34 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | * 36 | **/ 37 | #if !defined INCLUDED_quos_h_ 38 | #define INCLUDED_quos_h_ 39 | #include "clob.h" 40 | #include "clob_val.h" 41 | 42 | typedef struct { 43 | clob_side_t sid; 44 | px_t prc; 45 | qx_t new; 46 | } quos_msg_t; 47 | 48 | typedef struct quos_s { 49 | const size_t n; 50 | const quos_msg_t *m; 51 | } *quos_t; 52 | 53 | 54 | extern quos_t make_quos(void); 55 | 56 | extern void free_quos(quos_t); 57 | 58 | extern int quos_add(quos_t, quos_msg_t); 59 | 60 | extern int quos_clr(quos_t); 61 | 62 | #endif /* INCLUDED_quos_h_ */ 63 | -------------------------------------------------------------------------------- /src/unxs.h: -------------------------------------------------------------------------------- 1 | /*** unxs.h -- uncrossing schemes 2 | * 3 | * Copyright (C) 2016-2022 Sebastian Freundt 4 | * 5 | * Author: Sebastian Freundt 6 | * 7 | * This file is part of clob. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 16 | * 2. Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 20 | * 3. Neither the name of the author nor the names of any contributors 21 | * may be used to endorse or promote products derived from this 22 | * software without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 31 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 32 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 33 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 34 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | * 36 | **/ 37 | #if !defined INCLUDED_unxs_h_ 38 | #define INCLUDED_unxs_h_ 39 | #include 40 | #include "clob.h" 41 | #include "clob_val.h" 42 | 43 | typedef enum { 44 | /** don't keep track of parties */ 45 | MODE_NO = 0U, 46 | /** uncross with a single contra firm */ 47 | MODE_SC = 1U, 48 | /** uncross bilaterally */ 49 | MODE_BI = 2U, 50 | } unxs_mode_t; 51 | 52 | typedef struct { 53 | px_t prc; 54 | qx_t qty; 55 | } unxs_exe_t; 56 | 57 | typedef struct { 58 | qx_t base; 59 | qx_t term; 60 | } unxs_exa_t; 61 | 62 | typedef struct unxs_s { 63 | /** mode used for uncrossing */ 64 | const unxs_mode_t m; 65 | /** number of executions */ 66 | const size_t n; 67 | /** executions */ 68 | const unxs_exe_t *x; 69 | /** sides of executions from the maker point of view */ 70 | const uint_fast8_t *s; 71 | /** orders taking part in this match, (unxs_mode_t)M times N */ 72 | const clob_oid_t *o; 73 | /** remaining quantities, same dimension as O */ 74 | const qty_t *q; 75 | } *unxs_t; 76 | 77 | 78 | /** 79 | * Instantiate an uncrossing stream using uncrossing mode M. */ 80 | extern unxs_t make_unxs(unxs_mode_t); 81 | 82 | /** 83 | * Free resources associated with uncrossing stream. */ 84 | extern void free_unxs(unxs_t); 85 | 86 | /** 87 | * Clear execution stream. */ 88 | extern int unxs_clr(unxs_t); 89 | 90 | /** 91 | * Try crossing order O with book C at reference price R. 92 | * Executions will be tracked in C's exe-list. 93 | * The remainder of the order is returned. */ 94 | extern clob_ord_t 95 | unxs_order(clob_t c, clob_ord_t o, px_t r); 96 | 97 | /** 98 | * Uncross the book C at price P for a quantity of at most Q 99 | * and assuming a single contra firm. */ 100 | extern void 101 | unxs_auction(clob_t c, px_t p, qx_t q); 102 | 103 | 104 | /* convenience */ 105 | static inline __attribute__((pure, const)) unxs_exa_t 106 | unxs_exa(unxs_exe_t x, clob_side_t s) 107 | { 108 | switch (s) { 109 | case CLOB_SIDE_SELLER: 110 | /* maker is a seller */ 111 | return (unxs_exa_t){-x.qty, x.prc * x.qty}; 112 | case CLOB_SIDE_BUYER: 113 | /* maker is a buyer */ 114 | return (unxs_exa_t){x.qty, -x.prc * x.qty}; 115 | default: 116 | break; 117 | } 118 | return (unxs_exa_t){}; 119 | } 120 | 121 | #endif /* INCLUDED_unxs_h_ */ 122 | -------------------------------------------------------------------------------- /src/version.c.in: -------------------------------------------------------------------------------- 1 | /* -*- c -*- */ 2 | #include "version.h" 3 | 4 | const char _version_string[] = "YUCK_SCMVER_VERSION"; 5 | -------------------------------------------------------------------------------- /src/version.h: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDED_version_h_ 2 | #define INCLUDED_version_h_ 3 | 4 | extern const char _version_string[]; 5 | #define package_version _version_string 6 | 7 | #endif /* INCLUDED_version_h_ */ 8 | -------------------------------------------------------------------------------- /test/Makefile.am: -------------------------------------------------------------------------------- 1 | # Help the Developers and yourself. Just use the C locale and settings 2 | # for the compilation. They can still be overriden by make LANG= 3 | # but that is general a not very good idea 4 | include $(top_builddir)/version.mk 5 | 6 | LANG = C 7 | LC_ALL = C 8 | 9 | AM_CFLAGS = $(EXTRA_CFLAGS) 10 | AM_CPPFLAGS = -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=600 -D_BSD_SOURCE 11 | AM_CPPFLAGS += -DTEST 12 | AM_CPPFLAGS += $(clob_CFLAGS) 13 | 14 | EXTRA_DIST = $(BUILT_SOURCES) 15 | TESTS = 16 | TEST_EXTENSIONS = 17 | BUILT_SOURCES = 18 | dt_tests = 19 | bin_tests = 20 | batch_tests = 21 | check_PROGRAMS = 22 | CLEANFILES = $(check_PROGRAMS) 23 | 24 | clob_CFLAGS = -I$(top_srcdir)/src $(dfp754_CFLAGS) 25 | clob_LIBS = $(top_builddir)/src/libclob.a $(dfp754_LIBS) 26 | 27 | 28 | check_PROGRAMS += btree_01 29 | TESTS += btree_01 30 | btree_01_LDADD = $(clob_LIBS) 31 | 32 | check_PROGRAMS += btree_02 33 | TESTS += btree_02 34 | btree_02_LDADD = $(clob_LIBS) 35 | 36 | check_PROGRAMS += clob_01 37 | TESTS += clob_01 38 | clob_01_LDADD = $(clob_LIBS) 39 | 40 | check_PROGRAMS += clob_02 41 | TESTS += clob_02 42 | clob_02_LDADD = $(clob_LIBS) 43 | 44 | check_PROGRAMS += clob_03 45 | TESTS += clob_03 46 | clob_03_LDADD = $(clob_LIBS) 47 | 48 | check_PROGRAMS += clob_04 49 | TESTS += clob_04 50 | clob_04_LDADD = $(clob_LIBS) 51 | 52 | check_PROGRAMS += clob_05 53 | TESTS += clob_05 54 | clob_05_LDADD = $(clob_LIBS) 55 | 56 | check_PROGRAMS += clob_06 57 | TESTS += clob_06 58 | clob_06_LDADD = $(clob_LIBS) 59 | 60 | check_PROGRAMS += clob_07 61 | TESTS += clob_07 62 | clob_07_LDADD = $(clob_LIBS) 63 | 64 | check_PROGRAMS += unxs_xetra_01 65 | TESTS += unxs_xetra_01 66 | unxs_xetra_01_LDADD = $(clob_LIBS) 67 | 68 | check_PROGRAMS += unxs_xetra_02 69 | TESTS += unxs_xetra_02 70 | unxs_xetra_02_LDADD = $(clob_LIBS) 71 | 72 | check_PROGRAMS += unxs_xetra_03 73 | TESTS += unxs_xetra_03 74 | unxs_xetra_03_LDADD = $(clob_LIBS) 75 | 76 | check_PROGRAMS += unxs_xetra_04 77 | TESTS += unxs_xetra_04 78 | unxs_xetra_04_LDADD = $(clob_LIBS) 79 | 80 | check_PROGRAMS += unxs_xetra_05 81 | TESTS += unxs_xetra_05 82 | unxs_xetra_05_LDADD = $(clob_LIBS) 83 | 84 | check_PROGRAMS += unxs_xetra_06 85 | TESTS += unxs_xetra_06 86 | unxs_xetra_06_LDADD = $(clob_LIBS) 87 | 88 | check_PROGRAMS += unxs_xetra_07 89 | TESTS += unxs_xetra_07 90 | unxs_xetra_07_LDADD = $(clob_LIBS) 91 | 92 | check_PROGRAMS += unxs_xetra_08 93 | TESTS += unxs_xetra_08 94 | unxs_xetra_08_LDADD = $(clob_LIBS) 95 | 96 | check_PROGRAMS += unxs_xetra_09 97 | TESTS += unxs_xetra_09 98 | unxs_xetra_09_LDADD = $(clob_LIBS) 99 | 100 | 101 | check_PROGRAMS += mmod_auction_xetra_01 102 | TESTS += mmod_auction_xetra_01 103 | mmod_auction_xetra_01_LDADD = $(clob_LIBS) 104 | 105 | check_PROGRAMS += mmod_auction_xetra_02 106 | TESTS += mmod_auction_xetra_02 107 | mmod_auction_xetra_02_LDADD = $(clob_LIBS) 108 | 109 | check_PROGRAMS += mmod_auction_xetra_03 110 | TESTS += mmod_auction_xetra_03 111 | mmod_auction_xetra_03_LDADD = $(clob_LIBS) 112 | 113 | check_PROGRAMS += mmod_auction_xetra_04 114 | TESTS += mmod_auction_xetra_04 115 | mmod_auction_xetra_04_LDADD = $(clob_LIBS) 116 | 117 | check_PROGRAMS += mmod_auction_xetra_05 118 | TESTS += mmod_auction_xetra_05 119 | mmod_auction_xetra_05_LDADD = $(clob_LIBS) 120 | 121 | check_PROGRAMS += mmod_auction_xetra_06 122 | TESTS += mmod_auction_xetra_06 123 | mmod_auction_xetra_06_LDADD = $(clob_LIBS) 124 | 125 | check_PROGRAMS += mmod_auction_xetra_07 126 | TESTS += mmod_auction_xetra_07 127 | mmod_auction_xetra_07_LDADD = $(clob_LIBS) 128 | 129 | check_PROGRAMS += mmod_auction_xetra_08 130 | TESTS += mmod_auction_xetra_08 131 | mmod_auction_xetra_08_LDADD = $(clob_LIBS) 132 | 133 | check_PROGRAMS += mmod_auction_xetra_09 134 | TESTS += mmod_auction_xetra_09 135 | mmod_auction_xetra_09_LDADD = $(clob_LIBS) 136 | 137 | 138 | check_PROGRAMS += mmod_fill_or_kill_01 139 | TESTS += mmod_fill_or_kill_01 140 | mmod_fill_or_kill_01_LDADD = $(clob_LIBS) 141 | 142 | check_PROGRAMS += mmod_fill_or_kill_02 143 | TESTS += mmod_fill_or_kill_02 144 | mmod_fill_or_kill_02_LDADD = $(clob_LIBS) 145 | 146 | check_PROGRAMS += mmod_fill_or_kill_03 147 | TESTS += mmod_fill_or_kill_03 148 | mmod_fill_or_kill_03_LDADD = $(clob_LIBS) 149 | 150 | check_PROGRAMS += mmod_immediate_or_cancel_01 151 | TESTS += mmod_immediate_or_cancel_01 152 | mmod_immediate_or_cancel_01_LDADD = $(clob_LIBS) 153 | 154 | check_PROGRAMS += mmod_price_discovery_01 155 | TESTS += mmod_price_discovery_01 156 | mmod_price_discovery_01_LDADD = $(clob_LIBS) 157 | 158 | 159 | check_PROGRAMS += unxs_order_01 160 | TESTS += unxs_order_01 161 | unxs_order_01_LDADD = $(clob_LIBS) 162 | 163 | check_PROGRAMS += unxs_order_02 164 | TESTS += unxs_order_02 165 | unxs_order_02_LDADD = $(clob_LIBS) 166 | 167 | check_PROGRAMS += unxs_order_03 168 | TESTS += unxs_order_03 169 | unxs_order_03_LDADD = $(clob_LIBS) 170 | 171 | check_PROGRAMS += unxs_order_04 172 | TESTS += unxs_order_04 173 | unxs_order_04_LDADD = $(clob_LIBS) 174 | 175 | check_PROGRAMS += unxs_order_05 176 | TESTS += unxs_order_05 177 | unxs_order_05_LDADD = $(clob_LIBS) 178 | 179 | check_PROGRAMS += unxs_order_06 180 | TESTS += unxs_order_06 181 | unxs_order_06_LDADD = $(clob_LIBS) 182 | 183 | check_PROGRAMS += unxs_order_07 184 | TESTS += unxs_order_07 185 | unxs_order_07_LDADD = $(clob_LIBS) 186 | 187 | check_PROGRAMS += unxs_order_11 188 | TESTS += unxs_order_11 189 | unxs_order_11_LDADD = $(clob_LIBS) 190 | 191 | check_PROGRAMS += unxs_order_12 192 | TESTS += unxs_order_12 193 | unxs_order_12_LDADD = $(clob_LIBS) 194 | 195 | check_PROGRAMS += unxs_order_13 196 | TESTS += unxs_order_13 197 | unxs_order_13_LDADD = $(clob_LIBS) 198 | 199 | check_PROGRAMS += unxs_order_14 200 | TESTS += unxs_order_14 201 | unxs_order_14_LDADD = $(clob_LIBS) 202 | 203 | check_PROGRAMS += unxs_order_15 204 | TESTS += unxs_order_15 205 | unxs_order_15_LDADD = $(clob_LIBS) 206 | 207 | check_PROGRAMS += unxs_order_16 208 | TESTS += unxs_order_16 209 | unxs_order_16_LDADD = $(clob_LIBS) 210 | 211 | check_PROGRAMS += unxs_order_17 212 | TESTS += unxs_order_17 213 | unxs_order_17_LDADD = $(clob_LIBS) 214 | 215 | check_PROGRAMS += unxs_order_18 216 | TESTS += unxs_order_18 217 | unxs_order_18_LDADD = $(clob_LIBS) 218 | 219 | check_PROGRAMS += unxs_order_19 220 | TESTS += unxs_order_19 221 | unxs_order_19_LDADD = $(clob_LIBS) 222 | 223 | check_PROGRAMS += unxs_order_20 224 | TESTS += unxs_order_20 225 | unxs_order_20_LDADD = $(clob_LIBS) 226 | 227 | 228 | check_PROGRAMS += plqu_01 229 | TESTS += plqu_01 230 | plqu_01_LDADD = $(clob_LIBS) 231 | 232 | 233 | check_PROGRAMS += clob_stress_01 234 | clob_stress_01_LDADD = $(clob_LIBS) 235 | 236 | check_PROGRAMS += clob_stress_02 237 | clob_stress_02_LDADD = $(clob_LIBS) 238 | 239 | check_PROGRAMS += clob_stress_03 240 | clob_stress_03_LDADD = $(clob_LIBS) 241 | 242 | check_PROGRAMS += clob_stress_04 243 | clob_stress_04_LDADD = $(clob_LIBS) 244 | 245 | check_PROGRAMS += clob_stress_05 246 | clob_stress_05_LDADD = $(clob_LIBS) 247 | 248 | check_PROGRAMS += clob_stress_06 249 | clob_stress_06_LDADD = $(clob_LIBS) 250 | 251 | check_PROGRAMS += clob_stress_07 252 | clob_stress_07_LDADD = $(clob_LIBS) 253 | 254 | check_PROGRAMS += clob_stress_08 255 | clob_stress_08_LDADD = $(clob_LIBS) 256 | 257 | check_PROGRAMS += cloe_01 258 | TESTS += cloe_01 259 | cloe_01_LDADD = $(clob_LIBS) 260 | 261 | check_PROGRAMS += cloe_02 262 | TESTS += cloe_02 263 | cloe_02_LDADD = $(clob_LIBS) 264 | 265 | check_PROGRAMS += cloe_03 266 | TESTS += cloe_03 267 | cloe_03_LDADD = $(clob_LIBS) 268 | 269 | check_PROGRAMS += cloe_04 270 | TESTS += cloe_04 271 | cloe_04_LDADD = $(clob_LIBS) 272 | 273 | check_PROGRAMS += cloe_05 274 | TESTS += cloe_05 275 | cloe_05_LDADD = $(clob_LIBS) 276 | 277 | check_PROGRAMS += cloe_06 278 | TESTS += cloe_06 279 | cloe_06_LDADD = $(clob_LIBS) 280 | 281 | check_PROGRAMS += cloe_07 282 | TESTS += cloe_07 283 | cloe_07_LDADD = $(clob_LIBS) 284 | 285 | check_PROGRAMS += cloe_08 286 | TESTS += cloe_08 287 | cloe_08_LDADD = $(clob_LIBS) 288 | 289 | check_PROGRAMS += cloe_09 290 | TESTS += cloe_09 291 | cloe_09_LDADD = $(clob_LIBS) 292 | 293 | check_PROGRAMS += cloe_10 294 | TESTS += cloe_10 295 | cloe_10_LDADD = $(clob_LIBS) 296 | 297 | check_PROGRAMS += cloe_11 298 | TESTS += cloe_11 299 | cloe_11_LDADD = $(clob_LIBS) 300 | 301 | check_PROGRAMS += cloe_12 302 | TESTS += cloe_12 303 | cloe_12_LDADD = $(clob_LIBS) 304 | 305 | check_PROGRAMS += cloe_13 306 | TESTS += cloe_13 307 | cloe_13_LDADD = $(clob_LIBS) 308 | 309 | check_PROGRAMS += cloe_14 310 | TESTS += cloe_14 311 | cloe_14_LDADD = $(clob_LIBS) 312 | 313 | check_PROGRAMS += cloe_15 314 | TESTS += cloe_15 315 | cloe_15_LDADD = $(clob_LIBS) 316 | 317 | ## Makefile.am ends here 318 | -------------------------------------------------------------------------------- /test/btree_01.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "btree.h" 3 | 4 | 5 | int 6 | main(void) 7 | { 8 | btree_t t; 9 | int rc = 0; 10 | 11 | t = make_btree(false); 12 | 13 | for (size_t j = 0U; j < 100U; j++) { 14 | btree_val_t *v = btree_put(t, 1.dd+j); 15 | if (btree_val_nil_p(*v)) { 16 | *v = (btree_val_t){make_plqu(), {1.dd+j}}; 17 | printf("%p ", v); 18 | } else { 19 | rc = 1; 20 | break; 21 | } 22 | 23 | v = btree_get(t, 1.dd+j); 24 | if (v && !btree_val_nil_p(*v)) { 25 | printf(" %p %f\n", v, (double)v->sum.dis); 26 | } else { 27 | puts(""); 28 | rc = 1; 29 | break; 30 | } 31 | } 32 | 33 | free_btree(t); 34 | return rc; 35 | } 36 | -------------------------------------------------------------------------------- /test/btree_02.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "btree.h" 3 | 4 | 5 | int 6 | main(void) 7 | { 8 | btree_t t; 9 | int rc = 0; 10 | 11 | t = make_btree(true); 12 | 13 | for (size_t j = 0U; j < 100U; j++) { 14 | btree_val_t *v = btree_put(t, 1.dd+j); 15 | if (btree_val_nil_p(*v)) { 16 | *v = (btree_val_t){make_plqu(), {1.dd+j}}; 17 | printf("%p ", v); 18 | } else { 19 | rc = 1; 20 | break; 21 | } 22 | 23 | v = btree_get(t, 1.dd+j); 24 | if (v && !btree_val_nil_p(*v)) { 25 | printf(" %p %f\n", v, (double)v->sum.dis); 26 | } else { 27 | puts(""); 28 | rc = 1; 29 | break; 30 | } 31 | } 32 | 33 | free_btree(t); 34 | return rc; 35 | } 36 | -------------------------------------------------------------------------------- /test/clob_01.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | 4 | 5 | int 6 | main(void) 7 | { 8 | clob_t c; 9 | clob_oid_t i; 10 | 11 | c = make_clob(); 12 | 13 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 0.5dd, 0.0dd, .lmt = 1.23228dd}); 14 | printf("%zu\n", i.qid); 15 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 0.5dd, 0.0dd, .lmt = 1.23230dd}); 16 | printf("%zu\n", i.qid); 17 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 0.5dd, 0.0dd, .lmt = 1.23228dd}); 18 | printf("%zu\n", i.qid); 19 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 0.5dd, 0.0dd, .lmt = 1.23229dd}); 20 | printf("%zu\n", i.qid); 21 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 0.5dd, 0.0dd, .lmt = 1.23230dd}); 22 | printf("%zu\n", i.qid); 23 | 24 | printf("%zu\n", i.qid); 25 | printf("%zu\n", i.qid); 26 | printf("%zu\n", i.qid); 27 | 28 | printf("%d\n", clob_del(c, i)); 29 | printf("%d\n", clob_del(c, i)); 30 | i.qid++; 31 | printf("%d\n", clob_del(c, i)); 32 | 33 | printf("%zu\n", i.qid); 34 | 35 | printf("%zu\n", i.qid); 36 | 37 | clob_prnt(c); 38 | 39 | free_clob(c); 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /test/clob_02.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | 5 | 6 | int 7 | main(void) 8 | { 9 | clob_t c; 10 | clob_oid_t i; 11 | 12 | c = make_clob(); 13 | 14 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 0.5dd, 0.0dd, .lmt = 1.23228dd}); 15 | printf("%zu\n", i.qid); 16 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 0.5dd, 0.0dd, .lmt = 1.23230dd}); 17 | printf("%zu\n", i.qid); 18 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 0.5dd, 0.0dd, .lmt = 1.23228dd}); 19 | printf("%zu\n", i.qid); 20 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 0.5dd, 0.0dd, .lmt = 1.23229dd}); 21 | printf("%zu\n", i.qid); 22 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 0.5dd, 0.0dd, .lmt = 1.23230dd}); 23 | printf("%zu\n", i.qid); 24 | 25 | printf("%zu\n", i.qid); 26 | printf("%zu\n", i.qid); 27 | printf("%zu\n", i.qid); 28 | 29 | printf("%d\n", clob_del(c, i)); 30 | printf("%d\n", clob_del(c, i)); 31 | i.qid++; 32 | printf("%d\n", clob_del(c, i)); 33 | 34 | clob_prnt(c); 35 | 36 | /* add marketable limit order */ 37 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 0.7dd, 0.0dd, .lmt = 1.23227dd}); 38 | printf("%zu\n", i.qid); 39 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 0.3dd, 0.0dd, .lmt = 1.23229dd}); 40 | printf("%zu\n", i.qid); 41 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 0.8dd, 0.0dd, .lmt = 1.23226dd}); 42 | printf("%zu\n", i.qid); 43 | 44 | /* some market orders */ 45 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_ASK, 0.2dd, 0.0dd}); 46 | printf("%zu\n", i.qid); 47 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_ASK, 0.2dd, 0.0dd}); 48 | printf("%zu\n", i.qid); 49 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_ASK, 0.2dd, 0.0dd}); 50 | printf("%zu\n", i.qid); 51 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_ASK, 0.2dd, 0.0dd}); 52 | printf("%zu\n", i.qid); 53 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_BID, 0.3dd, 0.0dd}); 54 | printf("%zu\n", i.qid); 55 | 56 | #if 0 57 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_ASK, 0.2dd, 0.0dd}); 58 | printf("%zu\n", i.qid); 59 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_ASK, 0.2dd, 0.0dd}); 60 | printf("%zu\n", i.qid); 61 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_ASK, 0.2dd, 0.0dd}); 62 | printf("%zu\n", i.qid); 63 | #endif 64 | 65 | clob_prnt(c); 66 | 67 | puts("UNX MKT/LMT"); 68 | //clob_unx_mkt_lmt(c); 69 | puts("UNX LMT/LMT"); 70 | //clob_unx_lmt_lmt(c); 71 | puts("UNX MID/MID"); 72 | //clob_unx_mid_mid(c); 73 | 74 | clob_prnt(c); 75 | 76 | free_clob(c); 77 | return 0; 78 | } 79 | -------------------------------------------------------------------------------- /test/clob_03.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | clob_oid_t i; 13 | 14 | c = make_clob(); 15 | 16 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 0.5dd, 0.0dd, .lmt = 1.23227dd}); 17 | printf("%zu\n", i.qid); 18 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 0.5dd, 0.0dd, .lmt = 1.23230dd}); 19 | printf("%zu\n", i.qid); 20 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 0.5dd, 0.0dd, .lmt = 1.23227dd}); 21 | printf("%zu\n", i.qid); 22 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 0.5dd, 0.0dd, .lmt = 1.23228dd}); 23 | printf("%zu\n", i.qid); 24 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 0.4dd, 0.0dd, .lmt = 1.23230dd}); 25 | printf("%zu\n", i.qid); 26 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 0.5dd, 0.0dd, .lmt = 1.23231dd}); 27 | printf("%zu\n", i.qid); 28 | 29 | printf("%zu\n", i.qid); 30 | printf("%zu\n", i.qid); 31 | printf("%zu\n", i.qid); 32 | 33 | printf("%d\n", clob_del(c, i)); 34 | printf("%d\n", clob_del(c, i)); 35 | i.qid++; 36 | printf("%d\n", clob_del(c, i)); 37 | 38 | clob_prnt(c); 39 | 40 | /* add marketable limit order */ 41 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 0.7dd, 0.0dd, .lmt = 1.23226dd}); 42 | printf("%zu\n", i.qid); 43 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 0.4dd, 0.0dd, .lmt = 1.23229dd}); 44 | printf("%zu\n", i.qid); 45 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 0.2dd, 0.0dd, .lmt = 1.23231dd}); 46 | printf("%zu\n", i.qid); 47 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 0.8dd, 0.0dd, .lmt = 1.23226dd}); 48 | printf("%zu\n", i.qid); 49 | 50 | clob_prnt(c); 51 | 52 | { 53 | mmod_auc_t a = mmod_auction(c); 54 | 55 | puts("UNX AUCTION"); 56 | unxs_auction(c, a.prc, a.qty); 57 | } 58 | 59 | clob_prnt(c); 60 | 61 | free_clob(c); 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /test/clob_04.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | 4 | 5 | int 6 | main(void) 7 | { 8 | clob_t c; 9 | clob_oid_t i; 10 | 11 | c = make_clob(); 12 | 13 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 0.5dd, -4.0dd, .lmt = 1.23227dd}); 14 | printf("%zu\n", i.qid); 15 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 0.0dd, 0.0dd, .lmt = 1.23230dd}); 16 | printf("%zu\n", i.qid); 17 | 18 | clob_prnt(c); 19 | 20 | free_clob(c); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /test/clob_05.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "dfp754_d64.h" 3 | #include "clob.h" 4 | #include "unxs.h" 5 | 6 | 7 | int 8 | main(void) 9 | { 10 | clob_t c; 11 | clob_oid_t i; 12 | 13 | c = make_clob(); 14 | 15 | i = clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {50.0dd, 0.0dd}, .lmt = 1.23228dd}); 16 | clob_prnt(c); 17 | 18 | unxs_order(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_SHORT, {25.dd, 0.0dd}}, NANPX); 19 | 20 | clob_prnt(c); 21 | 22 | printf("%d\n", clob_del(c, i)); 23 | 24 | clob_prnt(c); 25 | 26 | free_clob(c); 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /test/clob_06.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "dfp754_d64.h" 3 | #include "clob.h" 4 | #include "nifty.h" 5 | 6 | 7 | int 8 | main(void) 9 | { 10 | clob_t c; 11 | clob_aggiter_t i; 12 | size_t j = 0U; 13 | 14 | c = make_clob(); 15 | 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {100.dd, 0.0dd}, .lmt = 200.0dd}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {100.dd, 0.0dd}, .lmt = 200.0dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {10.dd, 50.0dd}, .lmt = 198.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {10.dd, 50.0dd}, .lmt = 197.0dd}); 20 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {10.dd, 50.0dd}, .lmt = 198.0dd}); 21 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_SHORT, {80.dd, 0.0dd}}); 22 | 23 | puts("LMT+BID"); 24 | i = clob_aggiter(c, CLOB_TYPE_LMT, CLOB_SIDE_BID); 25 | for (; clob_aggiter_next(&i); j++) { 26 | printf("%f %f\n", (double)i.p, (double)(i.q.dis + i.q.hid)); 27 | } 28 | puts("LMT+ASK"); 29 | i = clob_aggiter(c, CLOB_TYPE_LMT, CLOB_SIDE_ASK); 30 | for (; clob_aggiter_next(&i); j++) { 31 | printf("%f %f\n", (double)i.p, (double)(i.q.dis + i.q.hid)); 32 | } 33 | puts("MKT+BID"); 34 | i = clob_aggiter(c, CLOB_TYPE_MKT, CLOB_SIDE_BID); 35 | for (; clob_aggiter_next(&i); j++) { 36 | printf("%f %f\n", (double)i.p, (double)(i.q.dis + i.q.hid)); 37 | } 38 | puts("MKT+ASK"); 39 | i = clob_aggiter(c, CLOB_TYPE_MKT, CLOB_SIDE_ASK); 40 | for (; clob_aggiter_next(&i); j++) { 41 | printf("%f %f\n", (double)i.p, (double)(i.q.dis + i.q.hid)); 42 | } 43 | 44 | free_clob(c); 45 | return j != 4; 46 | } 47 | -------------------------------------------------------------------------------- /test/clob_07.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "dfp754_d64.h" 3 | #include "clob.h" 4 | #include "nifty.h" 5 | 6 | 7 | int 8 | main(void) 9 | { 10 | clob_t c; 11 | clob_disiter_t i; 12 | size_t j = 0U; 13 | 14 | c = make_clob(); 15 | 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {100.dd, 0.0dd}, .lmt = 200.0dd}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {100.dd, 0.0dd}, .lmt = 200.0dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {10.dd, 50.0dd}, .lmt = 198.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {10.dd, 50.0dd}, .lmt = 197.0dd}); 20 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {10.dd, 50.0dd}, .lmt = 198.0dd}); 21 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_SHORT, {80.dd, 0.0dd}}); 22 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_SHORT, {100.dd, 0.0dd}}); 23 | 24 | puts("LMT+BID"); 25 | i = clob_disiter(c, CLOB_TYPE_LMT, CLOB_SIDE_BID); 26 | for (; clob_disiter_next(&i); j++) { 27 | printf("%f %f\n", (double)i.p, (double)(i.q.dis + i.q.hid)); 28 | } 29 | puts("LMT+ASK"); 30 | i = clob_disiter(c, CLOB_TYPE_LMT, CLOB_SIDE_ASK); 31 | for (; clob_disiter_next(&i); j++) { 32 | printf("%f %f\n", (double)i.p, (double)(i.q.dis + i.q.hid)); 33 | } 34 | puts("MKT+BID"); 35 | i = clob_disiter(c, CLOB_TYPE_MKT, CLOB_SIDE_BID); 36 | for (; clob_disiter_next(&i); j++) { 37 | printf("%f %f\n", (double)i.p, (double)(i.q.dis + i.q.hid)); 38 | } 39 | puts("MKT+ASK"); 40 | i = clob_disiter(c, CLOB_TYPE_MKT, CLOB_SIDE_ASK); 41 | for (; clob_disiter_next(&i); j++) { 42 | printf("%f %f\n", (double)i.p, (double)(i.q.dis + i.q.hid)); 43 | } 44 | 45 | free_clob(c); 46 | return j != 7; 47 | } 48 | -------------------------------------------------------------------------------- /test/clob_stress_01.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "nifty.h" 5 | 6 | 7 | int 8 | main(void) 9 | { 10 | clob_t c; 11 | 12 | c = make_clob(); 13 | 14 | for (size_t i = 0U; i < 10000000U; i++) { 15 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, rand() % 2, 2 + rand() % 4, 0.dd, .lmt = 100 + rand() % 100}); 16 | } 17 | 18 | clob_prnt(c); 19 | free_clob(c); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /test/clob_stress_02.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | for (size_t i = 0U; i < 10000000U; i++) { 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, rand() % 2, 2 + rand() % 4, 0.dd, .lmt = 100 + rand() % 100}); 17 | if (!((i - 1U) % 10000U)) { 18 | mmod_auc_t a = mmod_auction(c); 19 | (void)unxs_auction(c, a.prc, a.qty); 20 | //clob_prnt(c); 21 | } 22 | } 23 | 24 | //clob_prnt(c); 25 | free_clob(c); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /test/clob_stress_03.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "nifty.h" 5 | 6 | 7 | int 8 | main(void) 9 | { 10 | clob_t c; 11 | 12 | c = make_clob(); 13 | 14 | for (size_t i = 0U; i < 10000000U; i++) { 15 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, rand() % 2, 2 + rand() % 4, 0.dd}); 16 | } 17 | 18 | clob_prnt(c); 19 | free_clob(c); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /test/clob_stress_04.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "btree.h" 4 | #include "btree_val.h" 5 | #include "unxs.h" 6 | #include "mmod-auction.h" 7 | #include "nifty.h" 8 | 9 | 10 | int 11 | main(void) 12 | { 13 | clob_t c; 14 | qx_t tot[2U] = {0.dd, 0.dd}; 15 | 16 | c = make_clob(); 17 | for (size_t j = 0U; j < 1000U; j++) { 18 | clob_side_t s = rand() % 2; 19 | qx_t q = 2.dd + rand() % 4; 20 | tot[s] += q; 21 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, s, {q, 0.dd}, .lmt = 100.00dd + rand() % 81}); 22 | } 23 | 24 | clob_prnt(c); 25 | { 26 | mmod_auc_t auc = mmod_auction(c); 27 | btree_key_t a, b; 28 | 29 | unxs_auction(c, auc.prc, auc.qty -2); 30 | 31 | printf("AUC %f %f %f\n", (double)auc.prc, (double)auc.qty, (double)auc.imb); 32 | 33 | printf("TOT SUB %f %f\n", (double)tot[0], (double)tot[1]); 34 | btree_top(c.lmt[CLOB_SIDE_ASK], &a); 35 | btree_top(c.lmt[CLOB_SIDE_BID], &b); 36 | 37 | #if 0 38 | qx_t q = 0.dd; 39 | for (size_t i = 0U; i < n; i++) { 40 | //q += x[i].x.qty; 41 | printf("%f @ %f %u %u %f %zu\n", 42 | (double)x[i].x.qty, (double)x[i].x.prc, 43 | x[i].o.typ, x[i].o.sid, (double)x[i].o.prc, x[i].o.qid); 44 | } 45 | printf("TRA\t%f\t%f\t%zu\n", (double)x->x.prc, (double)q, n); 46 | #endif 47 | printf("QUO\t%f\t%f\n", (double)b, (double)a); 48 | } 49 | clob_prnt(c); 50 | 51 | free_clob(c); 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /test/clob_stress_05.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "btree.h" 4 | #include "btree_val.h" 5 | #include "unxs.h" 6 | #include "mmod-auction.h" 7 | #include "nifty.h" 8 | 9 | 10 | int 11 | main(void) 12 | { 13 | clob_t c; 14 | qx_t tot[2U] = {0.dd, 0.dd}; 15 | 16 | c = make_clob(); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_LONG, {2.dd, 0.dd}}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_SHORT, {2.dd, 1.dd}}); 19 | for (size_t j = 0U; j < 998U; j++) { 20 | clob_side_t s = rand() % 2; 21 | qx_t q = 2.dd + rand() % 4; 22 | tot[s] += q; 23 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, s, {q, 0.dd}, .lmt = 100.00dd + rand() % 81}); 24 | } 25 | 26 | clob_prnt(c); 27 | { 28 | mmod_auc_t auc = mmod_auction(c); 29 | btree_key_t a, b; 30 | 31 | unxs_auction(c, auc.prc, auc.qty); 32 | printf("AUC %f %f %f\n", (double)auc.prc, (double)auc.qty, (double)auc.imb); 33 | 34 | printf("TOT SUB %f %f\n", (double)tot[0], (double)tot[1]); 35 | btree_top(c.lmt[CLOB_SIDE_ASK], &a); 36 | btree_top(c.lmt[CLOB_SIDE_BID], &b); 37 | 38 | #if 0 39 | qx_t q = 0.dd; 40 | for (size_t i = 0U; i < n; i++) { 41 | //q += x[i].x.qty; 42 | printf("%f @ %f %u %u %f %zu v %u %u %f %zu\n", 43 | (double)x[i].x.qty, (double)x[i].x.prc, 44 | x[i].o[CLOB_SIDE_BUYER].typ, x[i].o[CLOB_SIDE_BUYER].sid, (double)x[i].o[CLOB_SIDE_BUYER].prc, x[i].o[CLOB_SIDE_BUYER].qid, 45 | x[i].o[CLOB_SIDE_SELLER].typ, x[i].o[CLOB_SIDE_SELLER].sid, (double)x[i].o[CLOB_SIDE_SELLER].prc, x[i].o[CLOB_SIDE_SELLER].qid); 46 | } 47 | printf("TRA\t%f\t%f\t%zu\n", (double)x->x.prc, (double)q, n); 48 | #endif 49 | printf("QUO\t%f\t%f\n", (double)b, (double)a); 50 | } 51 | clob_prnt(c); 52 | 53 | free_clob(c); 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /test/clob_stress_06.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "dfp754_d64.h" 3 | #include "clob.h" 4 | #include "btree.h" 5 | #include "btree_val.h" 6 | #include "unxs.h" 7 | #include "nifty.h" 8 | 9 | 10 | int 11 | main(void) 12 | { 13 | clob_t c; 14 | 15 | c = make_clob(); 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_LONG, {2.dd, 0.dd}}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_SHORT, {2.dd, 1.dd}}); 18 | for (size_t j = 0U; j < 1000000U; j++) { 19 | clob_side_t s = rand() % 2; 20 | qx_t hid = rand() % 4; 21 | px_t lmt = 100.00dd + rand() % 81; 22 | 23 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, s, {2.dd, hid}, .lmt = lmt}); 24 | unxs_order(c, (clob_ord_t){CLOB_TYPE_MKT, s ^ 1, {2.dd, (rand() % 3) + 0.00}}, NANPX); 25 | } 26 | 27 | clob_prnt(c); 28 | 29 | free_clob(c); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /test/clob_stress_07.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "dfp754_d64.h" 3 | #include "clob.h" 4 | #include "btree.h" 5 | #include "btree_val.h" 6 | #include "unxs.h" 7 | #include "nifty.h" 8 | 9 | 10 | int 11 | main(void) 12 | { 13 | clob_t c; 14 | clob_oid_t o1, o2 = {}; 15 | 16 | c = make_clob(); 17 | for (size_t j = 0U; j < 10000000U; j++) { 18 | o1 = clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_LONG, {2.dd, 0.dd}, 100.dd}); 19 | clob_del(c, o2); 20 | o2 = clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_LONG, {2.dd, 0.dd}, 102.dd}); 21 | clob_del(c, o1); 22 | } 23 | 24 | clob_prnt(c); 25 | 26 | free_clob(c); 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /test/clob_stress_08.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "dfp754_d64.h" 3 | #include "clob.h" 4 | #include "btree.h" 5 | #include "btree_val.h" 6 | #include "unxs.h" 7 | #include "nifty.h" 8 | 9 | 10 | int 11 | main(void) 12 | { 13 | clob_t c; 14 | clob_ord_t o1; 15 | clob_ord_t o2; 16 | 17 | c = make_clob(); 18 | for (size_t j = 1U; j <= 100U; j++) { 19 | //o1 = unxs_order(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {0.dd+j, 0.dd}, 6000.dd+j}, NANPX); 20 | //if (o1.qty.dis + o1.qty.hid > 0.dd) { 21 | o1 = (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {0.dd+j, 0.dd}, 6000.dd+j}; 22 | printf("%zu ", j);clob_add(c, o1); 23 | //clob_prnt(c); 24 | //} 25 | } 26 | 27 | clob_prnt(c); 28 | 29 | puts("COUNTER"); 30 | 31 | o2 = unxs_order(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {5050.dd, 0.dd}, 6100.dd}, NANPX); 32 | if (o2.qty.dis + o2.qty.hid > 0.dd) { 33 | clob_add(c, o2); 34 | } 35 | 36 | clob_prnt(c); 37 | 38 | free_clob(c); 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /test/cloe_01.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* cloe fuckup 1 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_ASK, {1300.dd, 0.0dd}}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {500.dd, 0.0dd}, .lmt = 2.85dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_BID, {1400.dd, 0.0dd}}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {500.dd, 0.0dd}, .lmt = 2.75dd}); 20 | 21 | clob_prnt(c); 22 | 23 | mmod_auc_t auc = mmod_auction(c); 24 | printf("AUCTION %f @ %f ~%f\n", (double)auc.qty, (double)auc.prc, (double)auc.imb); 25 | 26 | free_clob(c); 27 | return auc.prc != 2.85dd || auc.qty != 1400.dd || auc.imb != -400.dd; 28 | } 29 | -------------------------------------------------------------------------------- /test/cloe_02.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* cloe fuckup 1 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_BID, {1300.dd, 0.0dd}}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {500.dd, 0.0dd}, .lmt = 2.75dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_ASK, {1400.dd, 0.0dd}}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {500.dd, 0.0dd}, .lmt = 2.85dd}); 20 | 21 | clob_prnt(c); 22 | 23 | mmod_auc_t auc = mmod_auction(c); 24 | printf("AUCTION %f @ %f ~%f\n", (double)auc.qty, (double)auc.prc, (double)auc.imb); 25 | 26 | free_clob(c); 27 | return auc.prc != 2.75dd || auc.qty != 1400.dd || auc.imb != 400.dd; 28 | } 29 | -------------------------------------------------------------------------------- /test/cloe_03.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* cloe fuckup 1 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_BID, {1400.dd, 0.0dd}}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {500.dd, 0.0dd}, .lmt = 2.75dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_ASK, {1400.dd, 0.0dd}}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {500.dd, 0.0dd}, .lmt = 2.85dd}); 20 | 21 | clob_prnt(c); 22 | 23 | mmod_auc_t auc = mmod_auction(c); 24 | printf("AUCTION %f @ %f ~%f\n", (double)auc.qty, (double)auc.prc, (double)auc.imb); 25 | 26 | free_clob(c); 27 | return auc.prc != 2.80dd || auc.qty != 1400.dd || auc.imb != 0.dd; 28 | } 29 | -------------------------------------------------------------------------------- /test/cloe_04.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* cloe fuckup 1 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_ASK, {1300.dd, 0.0dd}}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {500.dd, 0.0dd}, .lmt = 2.85dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {500.dd, 0.0dd}, .lmt = 2.75dd}); 19 | 20 | clob_prnt(c); 21 | 22 | mmod_auc_t auc = mmod_auction(c); 23 | printf("AUCTION %f @ %f ~%f\n", (double)auc.qty, (double)auc.prc, (double)auc.imb); 24 | 25 | free_clob(c); 26 | return auc.prc != 2.75dd || auc.qty != 500.dd || auc.imb != -800.dd; 27 | } 28 | -------------------------------------------------------------------------------- /test/cloe_05.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* cloe fuckup 1 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {500.dd, 0.0dd}, .lmt = 2.85dd}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_BID, {1400.dd, 0.0dd}}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {500.dd, 0.0dd}, .lmt = 2.75dd}); 19 | 20 | clob_prnt(c); 21 | 22 | mmod_auc_t auc = mmod_auction(c); 23 | printf("AUCTION %f @ %f ~%f\n", (double)auc.qty, (double)auc.prc, (double)auc.imb); 24 | 25 | free_clob(c); 26 | return auc.prc != 2.85dd || auc.qty != 500.dd || auc.imb != 900.dd; 27 | } 28 | -------------------------------------------------------------------------------- /test/cloe_06.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* cloe fuckup 1 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_ASK, {1300.dd, 0.0dd}}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {0.dd, 0.0dd}, .lmt = 2.85dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {0.dd, 0.0dd}, .lmt = 2.75dd}); 19 | 20 | clob_prnt(c); 21 | 22 | mmod_auc_t auc = mmod_auction(c); 23 | printf("AUCTION %f @ %f ~%f\n", (double)auc.qty, (double)auc.prc, (double)auc.imb); 24 | 25 | free_clob(c); 26 | return auc.prc != 2.75dd || auc.qty != 0.dd || auc.imb != -1300.dd; 27 | } 28 | -------------------------------------------------------------------------------- /test/cloe_07.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* cloe fuckup 1 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {0.dd, 0.0dd}, .lmt = 2.85dd}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_BID, {1400.dd, 0.0dd}}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {0.dd, 0.0dd}, .lmt = 2.75dd}); 19 | 20 | clob_prnt(c); 21 | 22 | mmod_auc_t auc = mmod_auction(c); 23 | printf("AUCTION %f @ %f ~%f\n", (double)auc.qty, (double)auc.prc, (double)auc.imb); 24 | 25 | free_clob(c); 26 | return auc.prc != 2.85dd || auc.qty != 0.dd || auc.imb != 1400.dd; 27 | } 28 | -------------------------------------------------------------------------------- /test/cloe_08.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* cloe fuckup 1 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_ASK, {1300.dd, 0.0dd}}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {0.dd, 0.0dd}, .lmt = 2.75dd}); 18 | 19 | clob_prnt(c); 20 | 21 | mmod_auc_t auc = mmod_auction(c); 22 | printf("AUCTION %f @ %f ~%f\n", (double)auc.qty, (double)auc.prc, (double)auc.imb); 23 | 24 | free_clob(c); 25 | return auc.prc != 2.75dd || auc.qty != 0.dd || auc.imb != -1300.dd; 26 | } 27 | -------------------------------------------------------------------------------- /test/cloe_09.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* cloe fuckup 1 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {0.dd, 0.0dd}, .lmt = 2.85dd}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_BID, {1400.dd, 0.0dd}}); 18 | 19 | clob_prnt(c); 20 | 21 | mmod_auc_t auc = mmod_auction(c); 22 | printf("AUCTION %f @ %f ~%f\n", (double)auc.qty, (double)auc.prc, (double)auc.imb); 23 | 24 | free_clob(c); 25 | return auc.prc != 2.85dd || auc.qty != 0.dd || auc.imb != 1400.dd; 26 | } 27 | -------------------------------------------------------------------------------- /test/cloe_10.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* cloe fuckup 1 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_ASK, {1300.dd, 0.0dd}}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {500.dd, 0.0dd}, .lmt = 2.75dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {500.dd, 0.0dd}, .lmt = 2.80dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {500.dd, 0.0dd}, .lmt = 2.85dd}); 20 | 21 | clob_prnt(c); 22 | 23 | mmod_auc_t auc = mmod_auction(c); 24 | printf("AUCTION %f @ %f ~%f\n", (double)auc.qty, (double)auc.prc, (double)auc.imb); 25 | 26 | free_clob(c); 27 | return auc.prc != 2.75dd || auc.qty != 1300.dd || auc.imb != 200.dd; 28 | } 29 | -------------------------------------------------------------------------------- /test/cloe_11.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* cloe fuckup 1 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_BID, {1400.dd, 0.0dd}}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {500.dd, 0.0dd}, .lmt = 2.75dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {500.dd, 0.0dd}, .lmt = 2.80dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {500.dd, 0.0dd}, .lmt = 2.85dd}); 20 | 21 | clob_prnt(c); 22 | 23 | mmod_auc_t auc = mmod_auction(c); 24 | printf("AUCTION %f @ %f ~%f\n", (double)auc.qty, (double)auc.prc, (double)auc.imb); 25 | 26 | free_clob(c); 27 | return auc.prc != 2.85dd || auc.qty != 1400.dd || auc.imb != -100.dd; 28 | } 29 | -------------------------------------------------------------------------------- /test/cloe_12.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* cloe fuckup 1 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_ASK, {1600.dd, 0.0dd}}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {500.dd, 0.0dd}, .lmt = 2.75dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {500.dd, 0.0dd}, .lmt = 2.80dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {500.dd, 0.0dd}, .lmt = 2.85dd}); 20 | 21 | clob_prnt(c); 22 | 23 | mmod_auc_t auc = mmod_auction(c); 24 | printf("AUCTION %f @ %f ~%f\n", (double)auc.qty, (double)auc.prc, (double)auc.imb); 25 | 26 | free_clob(c); 27 | return auc.prc != 2.75dd || auc.qty != 1500.dd || auc.imb != -100.dd; 28 | } 29 | -------------------------------------------------------------------------------- /test/cloe_13.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* cloe fuckup 1 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_BID, {1600.dd, 0.0dd}}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {500.dd, 0.0dd}, .lmt = 2.75dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {500.dd, 0.0dd}, .lmt = 2.80dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {500.dd, 0.0dd}, .lmt = 2.85dd}); 20 | 21 | clob_prnt(c); 22 | 23 | mmod_auc_t auc = mmod_auction(c); 24 | printf("AUCTION %f @ %f ~%f\n", (double)auc.qty, (double)auc.prc, (double)auc.imb); 25 | 26 | free_clob(c); 27 | return auc.prc != 2.85dd || auc.qty != 1500.dd || auc.imb != 100.dd; 28 | } 29 | -------------------------------------------------------------------------------- /test/cloe_14.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* cloe fuckup 1 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_ASK, {1500.dd, 0.0dd}}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {500.dd, 0.0dd}, .lmt = 2.75dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {500.dd, 0.0dd}, .lmt = 2.80dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {500.dd, 0.0dd}, .lmt = 2.85dd}); 20 | 21 | clob_prnt(c); 22 | 23 | mmod_auc_t auc = mmod_auction(c); 24 | printf("AUCTION %f @ %f ~%f\n", (double)auc.qty, (double)auc.prc, (double)auc.imb); 25 | 26 | free_clob(c); 27 | return auc.prc != 2.75dd || auc.qty != 1500.dd || auc.imb != 0.dd; 28 | } 29 | -------------------------------------------------------------------------------- /test/cloe_15.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* cloe fuckup 1 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_BID, {1000.dd, 0.0dd}}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {500.dd, 0.0dd}, .lmt = 2.75dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {500.dd, 0.0dd}, .lmt = 2.80dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {500.dd, 0.0dd}, .lmt = 2.85dd}); 20 | 21 | clob_prnt(c); 22 | 23 | mmod_auc_t auc = mmod_auction(c); 24 | printf("AUCTION %f @ %f ~%f\n", (double)auc.qty, (double)auc.prc, (double)auc.imb); 25 | 26 | free_clob(c); 27 | return auc.prc != 2.80dd || auc.qty != 1000.dd || auc.imb != 0.dd; 28 | } 29 | -------------------------------------------------------------------------------- /test/mmod_auction_xetra_01.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* xetra example 1 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 100.dd, 0.0dd, .lmt = 200.0dd}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 300.dd, 0.0dd, .lmt = 198.0dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 400.dd, 0.0dd, .lmt = 197.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 300.dd, 0.0dd, .lmt = 200.0dd}); 20 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 100.dd, 0.0dd, .lmt = 196.0dd}); 21 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 300.dd, 0.0dd, .lmt = 198.0dd}); 22 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 200.dd, 0.0dd, .lmt = 199.0dd}); 23 | 24 | clob_prnt(c); 25 | 26 | mmod_auc_t auc = mmod_auction(c); 27 | printf("AUCTION %f @ %f ~%f\n", (double)auc.qty, (double)auc.prc, (double)auc.imb); 28 | 29 | free_clob(c); 30 | return auc.prc != 198.dd || auc.qty != 700.dd || auc.imb != 100.dd; 31 | } 32 | -------------------------------------------------------------------------------- /test/mmod_auction_xetra_02.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* xetra example 2 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 400.dd, 0.0dd, .lmt = 201.0dd}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 100.dd, 0.0dd, .lmt = 199.0dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 100.dd, 0.0dd, .lmt = 198.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 300.dd, 0.0dd, .lmt = 197.0dd}); 20 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 600.dd, 0.0dd, .lmt = 200.0dd}); 21 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 200.dd, 0.0dd, .lmt = 197.0dd}); 22 | 23 | clob_prnt(c); 24 | 25 | mmod_auc_t auc = mmod_auction(c); 26 | printf("AUCTION %f @ %f ~%f\n", (double)auc.qty, (double)auc.prc, (double)auc.imb); 27 | 28 | free_clob(c); 29 | return auc.prc != 200.dd || auc.qty != 500.dd || auc.imb != 100.dd; 30 | } 31 | -------------------------------------------------------------------------------- /test/mmod_auction_xetra_03.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* xetra example 3 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 200.dd, 0.0dd, .lmt = 201.0dd}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 600.dd, 0.0dd, .lmt = 198.0dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 400.dd, 0.0dd, .lmt = 197.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 100.dd, 0.0dd, .lmt = 199.0dd}); 20 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 100.dd, 0.0dd, .lmt = 201.0dd}); 21 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 300.dd, 0.0dd, .lmt = 202.0dd}); 22 | 23 | clob_prnt(c); 24 | 25 | mmod_auc_t auc = mmod_auction(c); 26 | printf("AUCTION %f @ %f ~%f\n", (double)auc.qty, (double)auc.prc, (double)auc.imb); 27 | 28 | free_clob(c); 29 | return auc.prc != 198.dd || auc.qty != 500.dd || auc.imb != -100.dd; 30 | } 31 | -------------------------------------------------------------------------------- /test/mmod_auction_xetra_04.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* xetra example 4 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 100.dd, 0.0dd, .lmt = 203.0dd}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 300.dd, 0.0dd, .lmt = 199.0dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 200.dd, 0.0dd, .lmt = 198.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 100.dd, 0.0dd, .lmt = 197.0dd}); 20 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 200.dd, 0.0dd, .lmt = 201.0dd}); 21 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 300.dd, 0.0dd, .lmt = 202.0dd}); 22 | 23 | clob_prnt(c); 24 | 25 | mmod_auc_t auc = mmod_auction(c); 26 | printf("AUCTION %f @ %f ~%f\n", (double)auc.qty, (double)auc.prc, (double)auc.imb); 27 | 28 | free_clob(c); 29 | return auc.prc != 200.dd || auc.qty != 500.dd || auc.imb != 0.dd; 30 | } 31 | -------------------------------------------------------------------------------- /test/mmod_auction_xetra_05.c: -------------------------------------------------------------------------------- 1 | #if defined HAVE_CONFIG_H 2 | # include "config.h" 3 | #endif /* HAVE_CONFIG_H */ 4 | #include 5 | #if defined HAVE_DFP754_H 6 | # include 7 | #elif defined HAVE_DFP_STDLIB_H 8 | # include 9 | #elif defined HAVE_DECIMAL_H 10 | # include 11 | #endif 12 | #include "dfp754_d64.h" 13 | #include "clob.h" 14 | #include "unxs.h" 15 | #include "mmod-auction.h" 16 | #include "nifty.h" 17 | 18 | 19 | int 20 | main(void) 21 | { 22 | clob_t c; 23 | 24 | c = make_clob(); 25 | 26 | /* xetra example 5 */ 27 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 300.dd, 0.0dd, .lmt = 202.0dd}); 28 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 200.dd, 0.0dd, .lmt = 201.0dd}); 29 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 100.dd, 0.0dd, .lmt = 200.0dd}); 30 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 400.dd, 0.0dd, .lmt = 199.0dd}); 31 | 32 | clob_prnt(c); 33 | 34 | mmod_auc_t auc = mmod_auction(c); 35 | printf("AUCTION %f @ %f ~%f\n", (double)auc.qty, (double)auc.prc, (double)auc.imb); 36 | 37 | free_clob(c); 38 | return !isnanpx(auc.prc) || auc.qty != 0.dd || auc.imb != 0.dd; 39 | } 40 | -------------------------------------------------------------------------------- /test/mmod_auction_xetra_06.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* xetra example 6 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 0.dd, 0.0dd, .lmt = 202.0dd}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_SHORT, 100.dd, 0.0dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 0.dd, 0.0dd, .lmt = 199.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_LONG, 200.dd, 0.0dd}); 20 | 21 | clob_prnt(c); 22 | 23 | mmod_auc_t auc = mmod_auction(c); 24 | printf("AUCTION %f @ %f ~%f\n", (double)auc.qty, (double)auc.prc, (double)auc.imb); 25 | 26 | free_clob(c); 27 | return auc.prc != 202.dd || auc.qty != 100.dd || auc.imb != 100.dd; 28 | } 29 | -------------------------------------------------------------------------------- /test/mmod_auction_xetra_07.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* xetra example 7 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 0.dd, 0.0dd, .lmt = 202.0dd}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_SHORT, 200.dd, 0.0dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 0.dd, 0.0dd, .lmt = 199.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_LONG, 100.dd, 0.0dd}); 20 | 21 | clob_prnt(c); 22 | 23 | mmod_auc_t auc = mmod_auction(c); 24 | printf("AUCTION %f @ %f ~%f\n", (double)auc.qty, (double)auc.prc, (double)auc.imb); 25 | 26 | free_clob(c); 27 | return auc.prc != 199.dd || auc.qty != 100.dd || auc.imb != -100.dd; 28 | } 29 | -------------------------------------------------------------------------------- /test/mmod_auction_xetra_08.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* xetra example 8 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 0.dd, 0.0dd, .lmt = 202.dd}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_SHORT, 100.dd, 0.0dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 0.dd, 0.0dd, .lmt = 199.dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_LONG, 100.dd, 0.0dd}); 20 | 21 | clob_prnt(c); 22 | 23 | mmod_auc_t auc = mmod_auction(c); 24 | printf("AUCTION %f @ %f ~%f\n", (double)auc.qty, (double)auc.prc, (double)auc.imb); 25 | 26 | free_clob(c); 27 | return auc.prc != 201.dd || auc.qty != 100.dd || auc.imb != 0.dd; 28 | } 29 | -------------------------------------------------------------------------------- /test/mmod_auction_xetra_09.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* xetra example 9 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 100.dd, 0.0dd, .lmt = 198.0dd}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 100.dd, 0.0dd, .lmt = 201.0dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 1000.dd, 0.0dd, .lmt = 202.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 100.dd, 0.0dd, .lmt = 202.0dd}); 20 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 100.dd, 0.0dd, .lmt = 199.0dd}); 21 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 1000.dd, 0.0dd, .lmt = 198.0dd}); 22 | 23 | clob_prnt(c); 24 | 25 | mmod_auc_t auc = mmod_auction(c); 26 | printf("AUCTION %f @ %f ~%f\n", (double)auc.qty, (double)auc.prc, (double)auc.imb); 27 | 28 | free_clob(c); 29 | return auc.prc != 200.dd || auc.qty != 100.dd || auc.imb != 0.dd; 30 | } 31 | -------------------------------------------------------------------------------- /test/mmod_fill_or_kill_01.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "mmod-fok.h" 4 | #include "dfp754_d64.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 100.dd, 0.0dd, .lmt = 200.0dd}); 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 300.dd, 0.0dd, .lmt = 198.0dd}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 100.dd, 0.0dd, .lmt = 196.0dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 300.dd, 0.0dd, .lmt = 197.0dd}); 19 | 20 | clob_prnt(c); 21 | 22 | int f1 = mmod_fok(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_LONG, {200.dd}, NANPX}); 23 | int f2 = mmod_fok(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_LONG, {500.dd}, NANPX}); 24 | int f3 = mmod_fok(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_SHORT, {100.dd}, NANPX}); 25 | int f4 = mmod_fok(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_SHORT, {400.dd}, NANPX}); 26 | 27 | printf("%d %d %d %d\n", f1, f2, f3, f4); 28 | 29 | clob_prnt(c); 30 | 31 | free_clob(c); 32 | return !f1 || f2 || !f3 || !f4; 33 | } 34 | -------------------------------------------------------------------------------- /test/mmod_fill_or_kill_02.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "mmod-fok.h" 4 | #include "dfp754_d64.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 100.dd, 0.0dd, .lmt = 200.0dd}); 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 300.dd, 0.0dd, .lmt = 198.0dd}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_BID, 100.dd, 0.0dd, .lmt = 196.0dd}); 18 | 19 | clob_prnt(c); 20 | 21 | int f1 = mmod_fok(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_LONG, {200.dd}, .lmt = 200.dd}); 22 | int f2 = mmod_fok(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_LONG, {200.dd}, .lmt = 197.dd}); 23 | int f3 = mmod_fok(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_SHORT, {100.dd}, .lmt = 195.dd}); 24 | int f4 = mmod_fok(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_SHORT, {200.dd}, NANPX}); 25 | 26 | printf("%d %d %d %d\n", f1, f2, f3, f4); 27 | 28 | clob_prnt(c); 29 | 30 | free_clob(c); 31 | return !f1 || f2 || !f3 || f4; 32 | } 33 | -------------------------------------------------------------------------------- /test/mmod_fill_or_kill_03.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "mmod-fok.h" 4 | #include "dfp754_d64.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 100.dd, 0.0dd, .lmt = 200.0dd}); 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 300.dd, 0.0dd, .lmt = 200.0dd}); 17 | 18 | clob_prnt(c); 19 | 20 | int f1 = mmod_fok(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_LONG, {200.dd}, NANPX}); 21 | int f2 = mmod_fok(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_LONG, {200.dd}, 199.dd}); 22 | int f3 = mmod_fok(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_LONG, {200.dd}, 200.dd}); 23 | int f4 = mmod_fok(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_LONG, {200.dd}, 201.dd}); 24 | 25 | printf("%d %d %d %d\n", f1, f2, f3, f4); 26 | 27 | clob_prnt(c); 28 | 29 | free_clob(c); 30 | return !f1 || f2 || !f3 || !f4; 31 | } 32 | -------------------------------------------------------------------------------- /test/mmod_immediate_or_cancel_01.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "mmod-ioc.h" 4 | #include "dfp754_d64.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {100.dd, 0.0dd}, .lmt = 200.0dd}); 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {300.dd, 0.0dd}, .lmt = 198.0dd}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_BID, {300.dd, 0.0dd}}); 18 | 19 | clob_prnt(c); 20 | 21 | int f1 = mmod_ioc(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_LONG, {200.dd}, NANPX}); 22 | int f2 = mmod_ioc(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_LONG, {500.dd}, .lmt = 197.0dd}); 23 | int f3 = mmod_ioc(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_LONG, {400.dd}, 199.0dd}); 24 | int f4 = mmod_ioc(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_SHORT, {100.dd}, 195.dd}); 25 | int f5 = mmod_ioc(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_SHORT, {100.dd}, NANPX}); 26 | 27 | printf("%d %d %d %d %d\n", f1, f2, f3, f4, f5); 28 | 29 | clob_prnt(c); 30 | 31 | free_clob(c); 32 | return !f1 || f2 || !f3 || !f4 || f5; 33 | } 34 | -------------------------------------------------------------------------------- /test/mmod_price_discovery_01.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "mmod-pdo.h" 4 | #include "dfp754_d64.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 300.dd, 0.0dd, .lmt = 200.0dd}); 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 100.dd, 0.0dd, .lmt = 198.0dd}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 100.dd, 0.0dd, .lmt = 196.0dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 300.dd, 0.0dd, .lmt = 197.0dd}); 19 | 20 | clob_prnt(c); 21 | 22 | mmod_pdo_t f1 = mmod_pdo(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_LONG, {200.dd}, NANPX}); 23 | mmod_pdo_t f2 = mmod_pdo(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_LONG, {500.dd}, NANPX}); 24 | mmod_pdo_t f3 = mmod_pdo(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_SHORT, {100.dd}, NANPX}); 25 | mmod_pdo_t f4 = mmod_pdo(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_SHORT, {400.dd}, 0.dd}); 26 | 27 | printf("%f %f %f %f %f %f %f %f\n", 28 | (double)f1.base, (double)f1.term, 29 | (double)f2.base, (double)f2.term, 30 | (double)f3.base, (double)f3.term, 31 | (double)f4.base, (double)f4.term); 32 | 33 | clob_prnt(c); 34 | 35 | free_clob(c); 36 | return f1.base != 200.dd || f1.term != 39800.dd || 37 | f2.base != 400.dd || f2.term != 79800.dd || 38 | f3.base != 100.dd || f3.term != 19700.dd || 39 | f4.base != 300.dd || f4.term != 59100.dd; 40 | } 41 | -------------------------------------------------------------------------------- /test/plqu_01.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | #include 3 | #include "plqu.h" 4 | 5 | 6 | int 7 | main(void) 8 | { 9 | plqu_t q; 10 | 11 | q = make_plqu(); 12 | 13 | printf("%zu\n", plqu_add(q, (plqu_val_t){0.1dd})); 14 | printf("%zu\n", plqu_add(q, (plqu_val_t){0.2dd})); 15 | printf("%zu\n", plqu_add(q, (plqu_val_t){0.3dd})); 16 | printf("%zu\n", plqu_add(q, (plqu_val_t){0.4dd})); 17 | printf("%zu\n", plqu_add(q, (plqu_val_t){0.5dd})); 18 | printf("%zu\n", plqu_add(q, (plqu_val_t){0.6dd})); 19 | printf("%f\n", (double)plqu_top(q).qty.dis); 20 | printf("%f\n", (double)plqu_pop(q).qty.dis); 21 | printf("%f\n", (double)plqu_top(q).qty.dis); 22 | printf("%f\n", (double)plqu_pop(q).qty.dis); 23 | printf("%f\n", (double)plqu_top(q).qty.dis); 24 | printf("%f\n", (double)plqu_pop(q).qty.dis); 25 | printf("%f\n", (double)plqu_top(q).qty.dis); 26 | printf("%f\n", (double)plqu_pop(q).qty.dis); 27 | printf("%zu\n", plqu_add(q, (plqu_val_t){0.7dd})); 28 | printf("%zu\n", plqu_add(q, (plqu_val_t){0.8dd})); 29 | printf("%zu\n", plqu_add(q, (plqu_val_t){0.9dd})); 30 | printf("%zu\n", plqu_add(q, (plqu_val_t){0.01dd})); 31 | printf("%zu\n", plqu_add(q, (plqu_val_t){0.11dd})); 32 | printf("%zu\n", plqu_add(q, (plqu_val_t){0.21dd})); 33 | printf("%zu\n", plqu_add(q, (plqu_val_t){0.31dd})); 34 | printf("%zu\n", plqu_add(q, (plqu_val_t){0.41dd})); 35 | printf("%zu\n", plqu_add(q, (plqu_val_t){0.51dd})); 36 | printf("%zu\n", plqu_add(q, (plqu_val_t){0.61dd})); 37 | printf("%f\n", (double)plqu_top(q).qty.dis); 38 | printf("%f\n", (double)plqu_pop(q).qty.dis); 39 | printf("%f\n", (double)plqu_top(q).qty.dis); 40 | printf("%f\n", (double)plqu_pop(q).qty.dis); 41 | printf("%f\n", (double)plqu_top(q).qty.dis); 42 | printf("%f\n", (double)plqu_pop(q).qty.dis); 43 | printf("%f\n", (double)plqu_top(q).qty.dis); 44 | printf("%f\n", (double)plqu_pop(q).qty.dis); 45 | printf("%f\n", (double)plqu_top(q).qty.dis); 46 | printf("%f\n", (double)plqu_pop(q).qty.dis); 47 | printf("%f\n", (double)plqu_top(q).qty.dis); 48 | printf("%f\n", (double)plqu_pop(q).qty.dis); 49 | printf("%f\n", (double)plqu_top(q).qty.dis); 50 | printf("%f\n", (double)plqu_pop(q).qty.dis); 51 | printf("%f\n", (double)plqu_top(q).qty.dis); 52 | printf("%f\n", (double)plqu_pop(q).qty.dis); 53 | printf("%f\n", (double)plqu_top(q).qty.dis); 54 | printf("%f\n", (double)plqu_pop(q).qty.dis); 55 | printf("%f\n", (double)plqu_top(q).qty.dis); 56 | printf("%f\n", (double)plqu_pop(q).qty.dis); 57 | printf("%f\n", (double)plqu_top(q).qty.dis); 58 | printf("%f\n", (double)plqu_pop(q).qty.dis); 59 | printf("%f\n", (double)plqu_top(q).qty.dis); 60 | printf("%f\n", (double)plqu_pop(q).qty.dis); 61 | printf("%f\n", (double)plqu_top(q).qty.dis); 62 | printf("%f\n", (double)plqu_pop(q).qty.dis); 63 | printf("%f\n", (double)plqu_top(q).qty.dis); 64 | printf("%f\n", (double)plqu_pop(q).qty.dis); 65 | printf("%f\n", (double)plqu_top(q).qty.dis); 66 | printf("%f\n", (double)plqu_pop(q).qty.dis); 67 | printf("%f\n", (double)plqu_top(q).qty.dis); 68 | printf("%f\n", (double)plqu_pop(q).qty.dis); 69 | 70 | free_plqu(q); 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /test/unxs_order_01.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "dfp754_d64.h" 3 | #include "clob.h" 4 | #include "unxs.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | int rc; 13 | 14 | c = make_clob(); 15 | c.exe = make_unxs(MODE_BI); 16 | 17 | /* xetra example 1 */ 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {100.dd, 0.0dd}, .lmt = 200.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {100.dd, 0.0dd}, .lmt = 198.0dd}); 20 | 21 | clob_prnt(c); 22 | 23 | unxs_order(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_SHORT, {5.dd, 0.0dd}}, NANPX); 24 | 25 | for (size_t i = 0U; i < c.exe->n; i++) { 26 | printf("%f @ %f %u %u %f %zu v %u %u %f %zu\n", 27 | (double)c.exe->x[i].qty, (double)c.exe->x[i].prc, 28 | c.exe->o[i * MODE_BI + CLOB_SIDE_MAKER].typ, 29 | c.exe->o[i * MODE_BI + CLOB_SIDE_MAKER].sid, 30 | (double)c.exe->o[i * MODE_BI + CLOB_SIDE_MAKER].prc, 31 | c.exe->o[i * MODE_BI + CLOB_SIDE_MAKER].qid, 32 | 33 | c.exe->o[i * MODE_BI + CLOB_SIDE_TAKER].typ, 34 | c.exe->o[i * MODE_BI + CLOB_SIDE_TAKER].sid, 35 | (double)c.exe->o[i * MODE_BI + CLOB_SIDE_TAKER].prc, 36 | c.exe->o[i * MODE_BI + CLOB_SIDE_TAKER].qid); 37 | } 38 | 39 | clob_prnt(c); 40 | 41 | rc = c.exe->n != 1U || c.exe->x->qty != 5.dd || c.exe->x->prc != 198.0dd; 42 | 43 | free_unxs(c.exe); 44 | free_clob(c); 45 | return rc; 46 | } 47 | -------------------------------------------------------------------------------- /test/unxs_order_02.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "dfp754_d64.h" 3 | #include "clob.h" 4 | #include "unxs.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | int rc; 13 | 14 | c = make_clob(); 15 | c.exe = make_unxs(MODE_BI); 16 | 17 | /* xetra example 1 */ 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {100.dd, 0.0dd}, .lmt = 200.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {100.dd, 0.0dd}, .lmt = 198.0dd}); 20 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_BID, {100.dd, 0.0dd}}); 21 | 22 | clob_prnt(c); 23 | 24 | unxs_order(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_SHORT, {5.dd, 0.0dd}}, NANPX); 25 | 26 | #if 0 27 | for (size_t i = 0U; i < n; i++) { 28 | printf("%f @ %f %u %u %f %zu v %u %u %f %zu\n", 29 | (double)x[i].x.qty, (double)x[i].x.prc, 30 | x[i].o[CLOB_SIDE_MAKER].typ, x[i].o[CLOB_SIDE_MAKER].sid, (double)x[i].o[CLOB_SIDE_MAKER].prc, x[i].o[CLOB_SIDE_MAKER].qid, 31 | x[i].o[CLOB_SIDE_TAKER].typ, x[i].o[CLOB_SIDE_TAKER].sid, (double)x[i].o[CLOB_SIDE_TAKER].prc, x[i].o[CLOB_SIDE_TAKER].qid); 32 | } 33 | #endif 34 | 35 | clob_prnt(c); 36 | 37 | rc = c.exe->n != 1U || c.exe->x->qty != 5.dd || c.exe->x->prc != 198.0dd; 38 | 39 | free_unxs(c.exe); 40 | free_clob(c); 41 | return rc; 42 | } 43 | -------------------------------------------------------------------------------- /test/unxs_order_03.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "dfp754_d64.h" 3 | #include "clob.h" 4 | #include "unxs.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | int rc; 13 | 14 | c = make_clob(); 15 | c.exe = make_unxs(MODE_BI); 16 | 17 | /* xetra example 1 */ 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {100.dd, 0.0dd}, .lmt = 200.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {100.dd, 0.0dd}, .lmt = 198.0dd}); 20 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_BID, {100.dd, 0.0dd}}); 21 | 22 | clob_prnt(c); 23 | 24 | /* eat into the limits */ 25 | unxs_order(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_SHORT, {150.dd, 0.0dd}}, NANPX); 26 | 27 | #if 0 28 | for (size_t i = 0U; i < n; i++) { 29 | printf("%f @ %f %u %u %f %zu v %u %u %f %zu\n", 30 | (double)x[i].x.qty, (double)x[i].x.prc, 31 | x[i].o[CLOB_SIDE_MAKER].typ, x[i].o[CLOB_SIDE_MAKER].sid, (double)x[i].o[CLOB_SIDE_MAKER].prc, x[i].o[CLOB_SIDE_MAKER].qid, 32 | x[i].o[CLOB_SIDE_TAKER].typ, x[i].o[CLOB_SIDE_TAKER].sid, (double)x[i].o[CLOB_SIDE_TAKER].prc, x[i].o[CLOB_SIDE_TAKER].qid); 33 | } 34 | #endif 35 | 36 | clob_prnt(c); 37 | 38 | rc = c.exe->n != 2U || 39 | c.exe->x[0U].qty != 100.dd || 40 | c.exe->x[0U].prc != 198.0dd || 41 | c.exe->x[1U].qty != 50.dd || 42 | c.exe->x[1U].prc != 198.0dd || 43 | 0; 44 | 45 | free_unxs(c.exe); 46 | free_clob(c); 47 | return rc; 48 | } 49 | -------------------------------------------------------------------------------- /test/unxs_order_04.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "dfp754_d64.h" 3 | #include "clob.h" 4 | #include "unxs.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | int rc; 13 | 14 | c = make_clob(); 15 | c.exe = make_unxs(MODE_BI); 16 | 17 | /* xetra example 1 */ 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {100.dd, 0.0dd}, .lmt = 200.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {100.dd, 0.0dd}, .lmt = 198.0dd}); 20 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_BID, {100.dd, 0.0dd}}); 21 | 22 | clob_prnt(c); 23 | 24 | /* eat into the limits */ 25 | unxs_order(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_SHORT, {200.dd, 0.0dd}}, NANPX); 26 | 27 | #if 0 28 | for (size_t i = 0U; i < n; i++) { 29 | printf("%f @ %f %u %u %f %zu v %u %u %f %zu\n", 30 | (double)x[i].x.qty, (double)x[i].x.prc, 31 | x[i].o[CLOB_SIDE_MAKER].typ, x[i].o[CLOB_SIDE_MAKER].sid, (double)x[i].o[CLOB_SIDE_MAKER].prc, x[i].o[CLOB_SIDE_MAKER].qid, 32 | x[i].o[CLOB_SIDE_TAKER].typ, x[i].o[CLOB_SIDE_TAKER].sid, (double)x[i].o[CLOB_SIDE_TAKER].prc, x[i].o[CLOB_SIDE_TAKER].qid); 33 | } 34 | #endif 35 | 36 | clob_prnt(c); 37 | 38 | rc = c.exe->n != 2U || 39 | c.exe->x[0U].qty != 100.dd || 40 | c.exe->x[0U].prc != 198.0dd || 41 | c.exe->x[1U].qty != 100.dd || 42 | c.exe->x[1U].prc != 198.0dd || 43 | 0; 44 | 45 | free_unxs(c.exe); 46 | free_clob(c); 47 | return rc; 48 | } 49 | -------------------------------------------------------------------------------- /test/unxs_order_05.c: -------------------------------------------------------------------------------- 1 | #if defined HAVE_CONFIG_H 2 | # include "config.h" 3 | #endif /* HAVE_CONFIG_H */ 4 | #include 5 | #if defined HAVE_DFP754_H 6 | # include 7 | #elif defined HAVE_DFP_STDLIB_H 8 | # include 9 | #elif defined HAVE_DECIMAL_H 10 | # include 11 | #endif 12 | #include 13 | #include "dfp754_d64.h" 14 | #include "clob.h" 15 | #include "unxs.h" 16 | #include "nifty.h" 17 | 18 | 19 | int 20 | main(void) 21 | { 22 | clob_t c; 23 | int rc; 24 | clob_ord_t o; 25 | 26 | c = make_clob(); 27 | c.exe = make_unxs(MODE_BI); 28 | 29 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {100.dd, 0.0dd}, .lmt = 200.0dd}); 30 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {100.dd, 0.0dd}, .lmt = 198.0dd}); 31 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_BID, {100.dd, 0.0dd}}); 32 | 33 | clob_prnt(c); 34 | 35 | /* less book than order */ 36 | o = unxs_order(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_SHORT, {500.dd, 0.0dd}}, NANPX); 37 | 38 | #if 0 39 | for (size_t i = 0U; i < n; i++) { 40 | printf("%f @ %f %u %u %f %zu v %u %u %f %zu\n", 41 | (double)x[i].x.qty, (double)x[i].x.prc, 42 | x[i].o[CLOB_SIDE_MAKER].typ, x[i].o[CLOB_SIDE_MAKER].sid, (double)x[i].o[CLOB_SIDE_MAKER].prc, x[i].o[CLOB_SIDE_MAKER].qid, 43 | x[i].o[CLOB_SIDE_TAKER].typ, x[i].o[CLOB_SIDE_TAKER].sid, (double)x[i].o[CLOB_SIDE_TAKER].prc, x[i].o[CLOB_SIDE_TAKER].qid); 44 | } 45 | #endif 46 | 47 | clob_prnt(c); 48 | 49 | rc = c.exe->n != 2U || 50 | o.qty.dis != 300.dd || 51 | o.qty.hid != 0.dd || 52 | c.exe->x[0U].qty != 100.dd || 53 | c.exe->x[0U].prc != 198.0dd || 54 | c.exe->x[1U].qty != 100.dd || 55 | c.exe->x[1U].prc != 198.0dd || 56 | 0; 57 | 58 | free_unxs(c.exe); 59 | free_clob(c); 60 | return rc; 61 | } 62 | -------------------------------------------------------------------------------- /test/unxs_order_06.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "dfp754_d64.h" 3 | #include "clob.h" 4 | #include "unxs.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | int rc; 13 | 14 | c = make_clob(); 15 | c.exe = make_unxs(MODE_BI); 16 | 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {100.dd, 0.0dd}, .lmt = 200.0dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {10.dd, 50.0dd}, .lmt = 198.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {10.dd, 50.0dd}, .lmt = 197.0dd}); 20 | 21 | clob_prnt(c); 22 | 23 | /* eat into the limits */ 24 | unxs_order(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_SHORT, {80.dd, 0.0dd}, NANPX}, NANPX); 25 | 26 | clob_prnt(c); 27 | 28 | rc = c.exe->n != 2U || 29 | c.exe->x[0U].qty != 60.dd || 30 | c.exe->x[0U].prc != 198.0dd || 31 | c.exe->x[1U].qty != 20.dd || 32 | c.exe->x[1U].prc != 197.0dd || 33 | 0; 34 | 35 | free_unxs(c.exe); 36 | free_clob(c); 37 | return rc; 38 | } 39 | -------------------------------------------------------------------------------- /test/unxs_order_07.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "dfp754_d64.h" 3 | #include "clob.h" 4 | #include "unxs.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {100.dd, 0.0dd}, .lmt = 200.0dd}); 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {10.dd, 50.0dd}, .lmt = 198.0dd}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {10.dd, 50.0dd}, .lmt = 197.0dd}); 18 | 19 | clob_prnt(c); 20 | 21 | /* eat into the limits */ 22 | unxs_order(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_SHORT, {80.dd, 0.0dd}}, NANPX); 23 | 24 | clob_prnt(c); 25 | 26 | free_clob(c); 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /test/unxs_order_11.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "dfp754_d64.h" 3 | #include "clob.h" 4 | #include "unxs.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | int rc; 13 | 14 | c = make_clob(); 15 | c.exe = make_unxs(MODE_BI); 16 | 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {100.dd, 0.0dd}, .lmt = 200.0dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {100.dd, 0.0dd}, .lmt = 198.0dd}); 19 | 20 | clob_prnt(c); 21 | 22 | unxs_order(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_SHORT, {5.dd, 0.0dd}, .lmt =197.0dd}, NANPX); 23 | 24 | clob_prnt(c); 25 | 26 | rc = c.exe->n != 1U || c.exe->x->qty != 5.dd || c.exe->x->prc != 198.0dd; 27 | 28 | free_unxs(c.exe); 29 | free_clob(c); 30 | return rc; 31 | } 32 | -------------------------------------------------------------------------------- /test/unxs_order_12.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "dfp754_d64.h" 3 | #include "clob.h" 4 | #include "unxs.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | int rc; 13 | 14 | c = make_clob(); 15 | c.exe = make_unxs(MODE_BI); 16 | 17 | /* xetra example 1 */ 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {100.dd, 0.0dd}, .lmt = 200.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {100.dd, 0.0dd}, .lmt = 198.0dd}); 20 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_BID, {100.dd, 0.0dd}}); 21 | 22 | clob_prnt(c); 23 | 24 | unxs_order(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_SHORT, {5.dd, 0.0dd}, .lmt = 198.dd}, NANPX); 25 | 26 | clob_prnt(c); 27 | 28 | rc = c.exe->n != 1U || c.exe->x->qty != 5.dd || c.exe->x->prc != 198.0dd; 29 | 30 | free_unxs(c.exe); 31 | free_clob(c); 32 | return rc; 33 | } 34 | -------------------------------------------------------------------------------- /test/unxs_order_13.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "dfp754_d64.h" 3 | #include "clob.h" 4 | #include "unxs.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | int rc; 13 | 14 | c = make_clob(); 15 | c.exe = make_unxs(MODE_BI); 16 | 17 | /* xetra example 1 */ 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {100.dd, 0.0dd}, .lmt = 200.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {100.dd, 0.0dd}, .lmt = 198.0dd}); 20 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_BID, {100.dd, 0.0dd}}); 21 | 22 | clob_prnt(c); 23 | 24 | /* eat into the limits */ 25 | unxs_order(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_SHORT, {150.dd, 0.0dd}, .lmt = 197.dd}, NANPX); 26 | 27 | clob_prnt(c); 28 | 29 | rc = c.exe->n != 2U || 30 | c.exe->x[0U].qty != 100.dd || 31 | c.exe->x[0U].prc != 198.0dd || 32 | c.exe->x[1U].qty != 50.dd || 33 | c.exe->x[1U].prc != 198.0dd || 34 | 0; 35 | 36 | free_unxs(c.exe); 37 | free_clob(c); 38 | return rc; 39 | } 40 | -------------------------------------------------------------------------------- /test/unxs_order_14.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "dfp754_d64.h" 3 | #include "clob.h" 4 | #include "unxs.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | int rc; 13 | 14 | c = make_clob(); 15 | c.exe = make_unxs(MODE_BI); 16 | 17 | /* xetra example 1 */ 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {100.dd, 0.0dd}, .lmt = 200.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {100.dd, 0.0dd}, .lmt = 198.0dd}); 20 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_BID, {100.dd, 0.0dd}}); 21 | 22 | clob_prnt(c); 23 | 24 | /* eat into the limits */ 25 | unxs_order(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_SHORT, {200.dd, 0.0dd}, .lmt = 197.dd}, NANPX); 26 | 27 | clob_prnt(c); 28 | 29 | rc = c.exe->n != 2U || 30 | c.exe->x[0U].qty != 100.dd || 31 | c.exe->x[0U].prc != 198.0dd || 32 | c.exe->x[1U].qty != 100.dd || 33 | c.exe->x[1U].prc != 198.0dd || 34 | 0; 35 | 36 | free_unxs(c.exe); 37 | free_clob(c); 38 | return rc; 39 | } 40 | -------------------------------------------------------------------------------- /test/unxs_order_15.c: -------------------------------------------------------------------------------- 1 | #if defined HAVE_CONFIG_H 2 | # include "config.h" 3 | #endif /* HAVE_CONFIG_H */ 4 | #include 5 | #if defined HAVE_DFP754_H 6 | # include 7 | #elif defined HAVE_DFP_STDLIB_H 8 | # include 9 | #elif defined HAVE_DECIMAL_H 10 | # include 11 | #endif 12 | #include 13 | #include "dfp754_d64.h" 14 | #include "clob.h" 15 | #include "unxs.h" 16 | #include "nifty.h" 17 | 18 | 19 | int 20 | main(void) 21 | { 22 | clob_t c; 23 | int rc; 24 | 25 | c = make_clob(); 26 | c.exe = make_unxs(MODE_BI); 27 | 28 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {100.dd, 0.0dd}, .lmt = 200.0dd}); 29 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {100.dd, 0.0dd}, .lmt = 198.0dd}); 30 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_BID, {100.dd, 0.0dd}}); 31 | 32 | clob_prnt(c); 33 | 34 | /* less book than order */ 35 | unxs_order(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_SHORT, {500.dd, 0.0dd}, .lmt = 197.dd}, NANPX); 36 | 37 | clob_prnt(c); 38 | 39 | rc = c.exe->n != 2U || 40 | c.exe->x[0U].qty != 100.dd || 41 | c.exe->x[0U].prc != 198.0dd || 42 | c.exe->x[1U].qty != 100.dd || 43 | c.exe->x[1U].prc != 198.0dd || 44 | 0; 45 | 46 | free_unxs(c.exe); 47 | free_clob(c); 48 | return rc; 49 | } 50 | -------------------------------------------------------------------------------- /test/unxs_order_16.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "dfp754_d64.h" 3 | #include "clob.h" 4 | #include "unxs.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | int rc; 13 | 14 | c = make_clob(); 15 | c.exe = make_unxs(MODE_BI); 16 | 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {100.dd, 0.0dd}, .lmt = 200.0dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {10.dd, 50.0dd}, .lmt = 198.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {10.dd, 50.0dd}, .lmt = 197.0dd}); 20 | 21 | clob_prnt(c); 22 | 23 | /* eat into the limits */ 24 | unxs_order(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_SHORT, {80.dd, 0.0dd}, .lmt = 197.dd}, NANPX); 25 | 26 | clob_prnt(c); 27 | 28 | rc = c.exe->n != 2U || 29 | c.exe->x[0U].qty != 60.dd || 30 | c.exe->x[0U].prc != 198.0dd || 31 | c.exe->x[1U].qty != 20.dd || 32 | c.exe->x[1U].prc != 197.0dd || 33 | 0; 34 | 35 | free_unxs(c.exe); 36 | free_clob(c); 37 | return rc; 38 | } 39 | -------------------------------------------------------------------------------- /test/unxs_order_17.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "dfp754_d64.h" 3 | #include "clob.h" 4 | #include "unxs.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {100.dd, 0.0dd}, .lmt = 200.0dd}); 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {10.dd, 50.0dd}, .lmt = 198.0dd}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {10.dd, 50.0dd}, .lmt = 197.0dd}); 18 | 19 | clob_prnt(c); 20 | 21 | /* eat into the limits */ 22 | unxs_order(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_SHORT, {80.dd, 0.0dd}, .lmt = 197.dd}, NANPX); 23 | 24 | clob_prnt(c); 25 | 26 | free_clob(c); 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /test/unxs_order_18.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "dfp754_d64.h" 3 | #include "clob.h" 4 | #include "unxs.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | int rc; 13 | 14 | c = make_clob(); 15 | c.exe = make_unxs(MODE_BI); 16 | 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {100.dd, 0.0dd}, .lmt = 200.0dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {10.dd, 50.0dd}, .lmt = 198.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {10.dd, 50.0dd}, .lmt = 197.0dd}); 20 | 21 | clob_prnt(c); 22 | 23 | /* eat into the limits but stop because of price constraints */ 24 | unxs_order(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_SHORT, {80.dd, 0.0dd}, .lmt = 197.5dd}, NANPX); 25 | 26 | clob_prnt(c); 27 | 28 | rc = c.exe->n != 1U || 29 | c.exe->x->qty != 60.dd || c.exe->x->prc != 198.0dd || 30 | 0; 31 | 32 | free_unxs(c.exe); 33 | free_clob(c); 34 | return rc; 35 | } 36 | -------------------------------------------------------------------------------- /test/unxs_order_19.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "dfp754_d64.h" 3 | #include "clob.h" 4 | #include "unxs.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | int rc; 13 | 14 | c = make_clob(); 15 | c.exe = make_unxs(MODE_SC); 16 | 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {100.dd, 0.0dd}, .lmt = 200.0dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {10.dd, 50.0dd}, .lmt = 198.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {10.dd, 50.0dd}, .lmt = 197.0dd}); 20 | 21 | clob_prnt(c); 22 | 23 | /* eat into the limits but stop because of price constraints */ 24 | unxs_order(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_SHORT, {80.dd, 0.0dd}, .lmt = 197.5dd}, NANPX); 25 | 26 | clob_prnt(c); 27 | 28 | rc = c.exe->n != 1U || 29 | c.exe->x->qty != 60.dd || c.exe->x->prc != 198.0dd || 30 | 0; 31 | 32 | free_unxs(c.exe); 33 | free_clob(c); 34 | return rc; 35 | } 36 | -------------------------------------------------------------------------------- /test/unxs_order_20.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "dfp754_d64.h" 3 | #include "clob.h" 4 | #include "unxs.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | int rc; 13 | 14 | c = make_clob(); 15 | c.exe = make_unxs(MODE_BI); 16 | 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, {100.dd, 0.0dd}, .lmt = 200.0dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {10.dd, 50.0dd}, .lmt = 198.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, {10.dd, 50.0dd}, .lmt = 197.0dd}); 20 | 21 | clob_prnt(c); 22 | 23 | /* eat into the limits, max slippage is 0 though */ 24 | unxs_order(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_SHORT, {80.dd, 0.0dd}, 0.dd}, NANPX); 25 | 26 | clob_prnt(c); 27 | 28 | rc = c.exe->n != 1U || 29 | c.exe->x[0U].qty != 60.dd || 30 | c.exe->x[0U].prc != 198.0dd || 31 | 0; 32 | 33 | free_unxs(c.exe); 34 | free_clob(c); 35 | return rc; 36 | } 37 | -------------------------------------------------------------------------------- /test/unxs_xetra_01.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* xetra example 1 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 100.dd, 0.0dd, .lmt = 200.0dd}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 300.dd, 0.0dd, .lmt = 198.0dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 400.dd, 0.0dd, .lmt = 197.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 300.dd, 0.0dd, .lmt = 200.0dd}); 20 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 100.dd, 0.0dd, .lmt = 196.0dd}); 21 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 300.dd, 0.0dd, .lmt = 198.0dd}); 22 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 200.dd, 0.0dd, .lmt = 199.0dd}); 23 | 24 | clob_prnt(c); 25 | 26 | { 27 | mmod_auc_t a; 28 | 29 | puts("UNX AUCTION"); 30 | a = mmod_auction(c); 31 | unxs_auction(c, a.prc, a.qty); 32 | } 33 | 34 | clob_prnt(c); 35 | 36 | free_clob(c); 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /test/unxs_xetra_02.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* xetra example 1 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 400.dd, 0.0dd, .lmt = 201.0dd}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 100.dd, 0.0dd, .lmt = 199.0dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 100.dd, 0.0dd, .lmt = 198.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 300.dd, 0.0dd, .lmt = 197.0dd}); 20 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 200.dd, 0.0dd, .lmt = 197.0dd}); 21 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 600.dd, 0.0dd, .lmt = 200.0dd}); 22 | 23 | clob_prnt(c); 24 | 25 | { 26 | mmod_auc_t a; 27 | 28 | puts("UNX AUCTION"); 29 | a = mmod_auction(c); 30 | unxs_auction(c, a.prc, a.qty); 31 | } 32 | 33 | clob_prnt(c); 34 | 35 | free_clob(c); 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /test/unxs_xetra_03.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* xetra example 1 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 200.dd, 0.0dd, .lmt = 201.0dd}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 600.dd, 0.0dd, .lmt = 198.0dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 300.dd, 0.0dd, .lmt = 202.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 100.dd, 0.0dd, .lmt = 201.0dd}); 20 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 100.dd, 0.0dd, .lmt = 199.0dd}); 21 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 400.dd, 0.0dd, .lmt = 197.0dd}); 22 | 23 | clob_prnt(c); 24 | 25 | { 26 | mmod_auc_t a; 27 | 28 | puts("UNX AUCTION"); 29 | a = mmod_auction(c); 30 | unxs_auction(c, a.prc, a.qty); 31 | } 32 | 33 | clob_prnt(c); 34 | 35 | free_clob(c); 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /test/unxs_xetra_04.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* xetra example 1 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 100.dd, 0.0dd, .lmt = 203.0dd}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 300.dd, 0.0dd, .lmt = 199.0dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 200.dd, 0.0dd, .lmt = 198.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 100.dd, 0.0dd, .lmt = 197.0dd}); 20 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 200.dd, 0.0dd, .lmt = 201.0dd}); 21 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 300.dd, 0.0dd, .lmt = 202.0dd}); 22 | 23 | clob_prnt(c); 24 | 25 | { 26 | mmod_auc_t a; 27 | 28 | puts("UNX AUCTION"); 29 | a = mmod_auction(c); 30 | unxs_auction(c, a.prc, a.qty); 31 | } 32 | 33 | clob_prnt(c); 34 | 35 | free_clob(c); 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /test/unxs_xetra_05.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* xetra example 5 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 300.dd, 0.0dd, .lmt = 202.0dd}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 200.dd, 0.0dd, .lmt = 201.0dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 300.dd, 0.0dd, .lmt = 199.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 100.dd, 0.0dd, .lmt = 200.0dd}); 20 | 21 | clob_prnt(c); 22 | 23 | { 24 | mmod_auc_t a; 25 | 26 | puts("UNX AUCTION"); 27 | a = mmod_auction(c); 28 | unxs_auction(c, a.prc, a.qty); 29 | } 30 | 31 | clob_prnt(c); 32 | 33 | free_clob(c); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /test/unxs_xetra_06.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* xetra example 6 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_LONG, 200.dd, 0.0dd}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_SHORT, 100.dd, 0.0dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 0.dd, 0.0dd, .lmt = 202.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 0.dd, 0.0dd, .lmt = 199.0dd}); 20 | 21 | clob_prnt(c); 22 | 23 | { 24 | mmod_auc_t a; 25 | 26 | puts("UNX AUCTION"); 27 | a = mmod_auction(c); 28 | unxs_auction(c, a.prc, a.qty); 29 | } 30 | 31 | clob_prnt(c); 32 | 33 | free_clob(c); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /test/unxs_xetra_07.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* xetra example 6 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_LONG, 100.dd, 0.0dd}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_SHORT, 200.dd, 0.0dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 0.dd, 0.0dd, .lmt = 202.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 0.dd, 0.0dd, .lmt = 199.0dd}); 20 | 21 | clob_prnt(c); 22 | 23 | { 24 | mmod_auc_t a; 25 | 26 | puts("UNX AUCTION"); 27 | a = mmod_auction(c); 28 | unxs_auction(c, a.prc, a.qty); 29 | } 30 | 31 | clob_prnt(c); 32 | 33 | free_clob(c); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /test/unxs_xetra_08.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* xetra example 6 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_LONG, 100.dd, 0.0dd}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_MKT, CLOB_SIDE_SHORT, 100.dd, 0.0dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 0.dd, 0.0dd, .lmt = 202.dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 0.dd, 0.0dd, .lmt = 199.dd}); 20 | 21 | clob_prnt(c); 22 | 23 | { 24 | mmod_auc_t a; 25 | 26 | puts("UNX AUCTION"); 27 | a = mmod_auction(c); 28 | unxs_auction(c, a.prc, a.qty); 29 | } 30 | 31 | clob_prnt(c); 32 | 33 | free_clob(c); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /test/unxs_xetra_09.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "clob.h" 3 | #include "unxs.h" 4 | #include "mmod-auction.h" 5 | #include "nifty.h" 6 | 7 | 8 | int 9 | main(void) 10 | { 11 | clob_t c; 12 | 13 | c = make_clob(); 14 | 15 | /* xetra example 9 */ 16 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 1000.dd, 0.0dd, .lmt = 202.0dd}); 17 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 100.dd, 0.0dd, .lmt = 201.0dd}); 18 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_ASK, 100.dd, 0.0dd, .lmt = 198.0dd}); 19 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 1000.dd, 0.0dd, .lmt = 198.0dd}); 20 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 100.dd, 0.0dd, .lmt = 199.0dd}); 21 | clob_add(c, (clob_ord_t){CLOB_TYPE_LMT, CLOB_SIDE_BID, 100.dd, 0.0dd, .lmt = 202.0dd}); 22 | 23 | clob_prnt(c); 24 | 25 | { 26 | mmod_auc_t a; 27 | 28 | puts("UNX AUCTION"); 29 | a = mmod_auction(c); 30 | unxs_auction(c, a.prc, a.qty); 31 | } 32 | 33 | clob_prnt(c); 34 | 35 | free_clob(c); 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /version.mk.in: -------------------------------------------------------------------------------- 1 | VERSION = YUCK_SCMVER_VERSION 2 | PACKAGE_VERSION = $(VERSION) 3 | PACKAGE_STRING = $(PACKAGE) $(VERSION) 4 | --------------------------------------------------------------------------------