FastMM documentation
FastMM C++ API 0.6.0
Public headers, tier 1 and tier 2
Loading...
Searching...
No Matches
registry.hpp
Go to the documentation of this file.
1#pragma once
2// Venue registry: `[venues.<name>] kind` -> the connector that serves it. An entry carries the
3// venue's capabilities, the `[venues.<name>]` keys the venue owns and one factory, so nothing
4// about a connector reaches the core: the central schema (include/fastmm/config/schema.hpp) knows
5// only the generic keys, and no `if (kind == X)` lives outside a venue's own code.
6//
7// Nothing registers itself, for the same reason the strategy and storage registries do not (a
8// static library's self-registering object is dropped by the linker):
9// fastmm::venues::register_builtin_venues() adds the connectors FastMM ships, and an out-of-tree
10// venue calls add() before the session starts (examples/external-venue).
11//
12// constexpr VenueKeySpec kEchoKeys[] = {
13// {"greeting", KeyType::String, false, "echo: text the venue sends back (default \"hi\")"},
14// };
15// VenueRegistry::instance().add({.name = "echo",
16// .summary = "an echo venue",
17// .keys = kEchoKeys,
18// .caps = {.credentials = false},
19// .make = &make_echo_venue});
20//
21// docs/how-to/venues/add-a-venue.md walks through it; tools/docs_config_ref.py reads the key
22// tables out of the registration files so a venue's keys land in the configuration reference.
25#include "fastmm/net/source_address.hpp"
27
28#include <cstdint>
29#include <memory>
30#include <span>
31#include <string>
32#include <string_view>
33#include <vector>
34
35namespace fastmm::venues {
36
37// Runtime knobs every connector honours, passed to the factory. Anything venue-specific is a
38// config key the venue owns instead.
39// [venues.<x>] source_ip / source_interface as a net::SourceAddress.
40[[nodiscard]] inline net::SourceAddress source_address(const VenueSection& s) {
41 return net::SourceAddress{s.source_ip, s.source_interface};
43
44struct VenueFactoryOptions {
45 bool dry_run = false; // public market data only: no keys, no orders
46 std::string record_raw_dir; // non-empty: append raw frames to <dir>/<venue>-<channel>.jsonl
47 bool busy_poll = false; // [engine] spin_mode = "busy": Venue::poll() must make progress
48 // A pool member ([venues.<x>] pool_of): the venue whose instruments this account takes orders
49 // for. The connector opens its order and user sessions only, no market data, and resolves
50 // symbols on that venue's id (its own id goes on the events). Invalid: a venue of its own.
52 // The venue is a pool's primary or member: its account shares the IP's request weight with the
53 // pool's other accounts (connectors that count weight per IP).
54 bool pooled = false;
55};
57// What a connector declares about itself before one exists. The session and the engine read these
58// instead of testing `kind`. `replace` and `order_entry` say what the connector can do; whether a
59// given instance does is Venue::caps() (a dry run, order_entry = "none", missing credentials).
60struct VenueCapabilities {
61 bool credentials = true; // needs api_key / api_secret outside a dry run
62 bool order_entry = true; // can send orders at all
63 bool replace = false; // can amend a resting order in place
64 bool positions = false; // reports positions from the venue
65 bool polls = false; // Venue::poll() drives its sockets; the reactor never wakes for them
66 // Can fetch what the account executed since a point in time, so a reconciliation replays the
67 // fills the private stream missed instead of inferring them from a cum_qty jump. False: a fill
68 // that finished an order while the stream was down is not recoverable on this venue, and the
69 // engine says so (EngineStats::estimated_reconciles) rather than assuming it did not happen.
70 bool executions = false;
71 // Runs as a member of an account pool ([venues.<x>] pool_of, core/account_pool.hpp): the order
72 // path alone, for the primary's instruments, without market data of its own.
73 bool account_pools = false;
74 // Binds every outbound connection (WebSocket, REST, the blocking control requests) to the
75 // section's source address ([venues.<x>] source_ip / source_interface, net/source_address.hpp).
76 bool bind_source = false;
77 // Can move an asset between the accounts of a pool (Venue::transfer,
78 // VenueCaps::internal_transfer) once it is given the credentials: a pool treasury
79 // ([venues.<primary>.treasury]) needs it.
80 bool internal_transfer = false;
81};
83// One `[venues.<name>]` key a venue owns. `doc` is the Meaning column of the configuration
84// reference: say what the key does, its unit and its default, as schema.hpp does.
85struct VenueKeySpec {
86 std::string_view key;
89 std::string_view doc;
90};
92struct VenueEntry {
93 // Throws std::invalid_argument (a bad URL, a key the connector rejects); the message names the
94 // venue. The section's keys have been validated against `keys` before this is called.
95 using Factory = std::unique_ptr<Venue> (*)(VenueId,
96 const VenueSection&,
98
99 // Every member has a default, so a registration names only the ones it needs.
100 std::string_view name; // the `kind` value; outlives the registry
101 std::string_view summary; // one line for the connector table
102 std::span<const std::string_view> aliases = {}; // other `kind` values that select this entry
103 std::span<const VenueKeySpec> keys = {}; // the keys it owns, beyond the generic ones
105 Factory make = nullptr;
108enum class AddResult : std::uint8_t { Added, AlreadyPresent, Conflict, Invalid };
109[[nodiscard]] constexpr std::string_view to_string(AddResult r) noexcept {
110 switch (r) {
112 return "added";
114 return "already present";
116 return "conflict";
118 return "invalid";
119 }
120 return "?";
121}
122
123class VenueRegistry {
124 public:
125 // The registry fastmm-live resolves `kind` through. Not thread-safe for writers: register
126 // before starting threads. Tests use a local registry.
127 static VenueRegistry& instance();
128
129 // Registering the same factory under the same name again changes nothing (AlreadyPresent);
130 // anything that would replace an entry, or a name an entry already claims as an alias, changes
131 // nothing and returns Conflict.
132 AddResult add(VenueEntry entry);
133 // By `kind`: the entry's name or one of its aliases.
134 [[nodiscard]] const VenueEntry* find(std::string_view kind) const noexcept;
135 [[nodiscard]] const std::vector<VenueEntry>& entries() const noexcept { return entries_; }
136 // Every accepted `kind`, names and aliases, comma-separated, for an error message.
137 [[nodiscard]] std::string kinds() const;
138
139 private:
140 std::vector<VenueEntry> entries_;
141};
142
143// Adds the connectors FastMM ships (binance_spot, binance_usdm, bybit, deribit, nasdaq_itch).
144// Idempotent; make_venue() and validate_venues() call it for the default registry.
146
147// Checks every `[venues.<name>]` section against the key table of the venue its `kind` names, the
148// way the central schema checks the generic keys: a key the venue does not own, a key of the wrong
149// type or a missing required key throws ConfigError with the line. An unknown `kind` throws too.
150// Call it once after loading a configuration; fastmm-live does.
151void validate_venues(const Config& cfg, const VenueRegistry& r = VenueRegistry::instance());
152
153// Builds the connector `section.kind` names. Throws std::invalid_argument for an unknown kind,
154// ConfigError for a key of the wrong type and whatever the connector throws for a bad value.
155std::unique_ptr<Venue> make_venue(VenueId id,
156 const VenueSection& section,
158std::unique_ptr<Venue> make_venue(VenueId id,
159 const VenueSection& section,
161 const VenueRegistry& r);
162
163} // namespace fastmm::venues
Definition config.hpp:302
Definition registry.hpp:125
const std::vector< VenueEntry > & entries() const noexcept
Definition registry.hpp:137
std::string kinds() const
Every accepted kind, names and aliases, comma-separated, for an error message.
static VenueRegistry & instance()
The registry fastmm-live resolves kind through.
const VenueEntry * find(std::string_view kind) const noexcept
By kind: the entry's name or one of its aliases.
AddResult add(VenueEntry entry)
Registering the same factory under the same name again changes nothing (AlreadyPresent); anything tha...
Typed configuration (8.7).
Definition venue.hpp:38
constexpr std::string_view to_string(ChannelState s) noexcept
Definition venue.hpp:51
net::SourceAddress source_address(const VenueSection &s)
Runtime knobs every connector honours, passed to the factory.
Definition registry.hpp:42
AddResult
Definition registry.hpp:110
std::unique_ptr< Venue > make_venue(VenueId id, const VenueSection &section, const VenueFactoryOptions &opts)
Builds the connector section.kind names.
void validate_venues(const Config &cfg, const VenueRegistry &r=VenueRegistry::instance())
Checks every [venues.
void register_builtin_venues(VenueRegistry &r=VenueRegistry::instance())
Adds the connectors FastMM ships (binance_spot, binance_usdm, bybit, deribit, nasdaq_itch).
KeyType
Definition schema.hpp:22
StrongId< struct VenueTag, std::uint8_t > VenueId
Definition strong_id.hpp:39
Declarative config schema (8.7): every known key with its section, type and whether it is required.
Definition config.hpp:155
What a connector declares about itself before one exists.
Definition registry.hpp:62
bool internal_transfer
Can move an asset between the accounts of a pool (Venue::transfer, VenueCaps::internal_transfer) once...
Definition registry.hpp:82
bool polls
Venue::poll() drives its sockets; the reactor never wakes for them.
Definition registry.hpp:67
bool bind_source
Binds every outbound connection (WebSocket, REST, the blocking control requests) to the section's sou...
Definition registry.hpp:78
bool order_entry
can send orders at all
Definition registry.hpp:64
bool replace
can amend a resting order in place
Definition registry.hpp:65
bool positions
reports positions from the venue
Definition registry.hpp:66
bool executions
Can fetch what the account executed since a point in time, so a reconciliation replays the fills the ...
Definition registry.hpp:72
bool credentials
needs api_key / api_secret outside a dry run
Definition registry.hpp:63
bool account_pools
Runs as a member of an account pool ([venues.
Definition registry.hpp:75
Definition registry.hpp:94
std::span< const VenueKeySpec > keys
the keys it owns, beyond the generic ones
Definition registry.hpp:105
std::unique_ptr< Venue >(*)(VenueId, const VenueSection &, const VenueFactoryOptions &) Factory
Throws std::invalid_argument (a bad URL, a key the connector rejects); the message names the venue.
Definition registry.hpp:99
std::span< const std::string_view > aliases
other kind values that select this entry
Definition registry.hpp:104
VenueCapabilities caps
Definition registry.hpp:106
Factory make
Definition registry.hpp:107
std::string_view name
Every member has a default, so a registration names only the ones it needs.
Definition registry.hpp:102
std::string_view summary
one line for the connector table
Definition registry.hpp:103
Definition registry.hpp:46
std::string record_raw_dir
non-empty: append raw frames to <dir>/<venue>-<channel>.jsonl
Definition registry.hpp:48
bool pooled
The venue is a pool's primary or member: its account shares the IP's request weight with the pool's o...
Definition registry.hpp:56
bool dry_run
public market data only: no keys, no orders
Definition registry.hpp:47
bool busy_poll
[engine] spin_mode = "busy": Venue::poll() must make progress
Definition registry.hpp:49
VenueId pool_of
A pool member ([venues.
Definition registry.hpp:53
One [venues.
Definition registry.hpp:87
std::string_view doc
Definition registry.hpp:91
bool required
Definition registry.hpp:90
std::string_view key
Definition registry.hpp:88
KeyType type
Definition registry.hpp:89
Venue: the control-path interface every exchange connector implements (6.2).