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// Strategy registry (8.6, ADR-0012): name -> parameter schema + one factory per transport kind,
3// each producing an IEngineRunner. Strategies are added by a registration function
4// (strategies/module.hpp):
5//
6// void mm::register_strategies(fastmm::StrategyRegistry& r) {
7// fastmm::register_strategy<mm::MicropriceMM>(r); // Sim + Replay + Live factories
8// }
9//
10// Nothing registers itself: apps pass their registration functions to fastmm::cli::live /
11// backtest / replay, and the built-in strategies come from fastmm::register_builtin_strategies().
12// This header does not parse the Engine template; make_engine_runner<S>() lives in
13// strategies/engine_factory.hpp.
15#include "fastmm/core/engine_runner.hpp"
17#include "fastmm/core/msg_ring.hpp"
21
22#include <array>
23#include <cstddef>
24#include <cstdint>
25#include <memory>
26#include <string_view>
27#include <vector>
28
29namespace fastmm {
30
31enum class TransportKind : std::uint8_t { Sim = 0, Live = 1, Replay = 2, Count = 3 };
32[[nodiscard]] constexpr std::string_view to_string(TransportKind k) noexcept {
33 switch (k) {
35 return "sim";
37 return "live";
39 return "replay";
41 return "count";
42 }
43 return "?";
44}
45
46// Everything a factory needs that is backend-independent. `backend` points at the bundle the
47// runtime provides for the requested kind (sim::SimBackend, sim::ReplayBackend, live::LiveBackend)
48// holding clock, transport and feed.
49struct RunnerDeps {
50 EngineConfig engine;
51 const InstrumentTable* instruments = nullptr;
53 MsgRing* journal_ring = nullptr;
54 // Where the engine hands fills, orders, positions and kill events for a storage backend
55 // (core/record_stream.hpp); null disables them at no cost.
56 MsgRing* record_ring = nullptr;
57 void* backend = nullptr;
58};
60inline constexpr std::size_t kTransportKinds = static_cast<std::size_t>(TransportKind::Count);
61
63 using Factory = std::unique_ptr<IEngineRunner> (*)(TransportKind, RunnerDeps&);
64 // Builds a publisher for this strategy's parameters over `sink`, its copy seeded with the
65 // values the session configured the strategy with, so fastmm-live can accept parameter changes
66 // while it runs (src/live/control_socket.cpp). Null when the parameters are not a FASTMM_PARAMS
67 // struct (a hot strategy builds its schema at run time and brings its own publisher). Throws
68 // std::invalid_argument on a value the schema refuses (startup only).
69 using PublisherFactory = std::unique_ptr<ParamPublisher> (*)(ParamSink, const ParamMap&);
70 std::string_view name; // must outlive the registry (S::name() returns a literal)
71 const ParamSchema* schema = nullptr;
72 std::array<Factory, kTransportKinds> factories{}; // indexed by TransportKind
75 [[nodiscard]] bool supports(TransportKind k) const noexcept {
76 const auto i = static_cast<std::size_t>(k);
77 return i < kTransportKinds && factories[i] != nullptr;
78 }
79};
80
81enum class AddResult : std::uint8_t {
82 Added, // the factory is now registered for (name, kind)
83 AlreadyPresent, // the same schema and factory were registered before: nothing changed
84 Conflict, // `name` is registered with a different schema, or (name, kind) with another factory
85 Invalid, // empty name, null schema or factory, or an invalid kind
86};
87[[nodiscard]] constexpr std::string_view to_string(AddResult r) noexcept {
88 switch (r) {
90 return "added";
92 return "already present";
94 return "conflict";
96 return "invalid";
97 }
98 return "?";
99}
100
101class StrategyRegistry {
102 public:
103 // The registry the CLIs, run_backtest(cfg, name), replay_journal and Python use. Not
104 // thread-safe for writers: register before starting threads. Tests use a local registry.
105 static StrategyRegistry& instance() {
106 static StrategyRegistry r;
107 return r;
108 }
109
110 // Registers `factory` for one transport kind of `name`. Registering the same schema and factory
111 // again does nothing (AlreadyPresent); anything that would replace or disagree with an existing
112 // registration changes nothing and returns Conflict.
113 AddResult try_add(std::string_view name,
114 const ParamSchema* schema,
117 StrategyEntry::PublisherFactory publisher = nullptr) {
118 const auto k = static_cast<std::size_t>(kind);
119 if (name.empty() || factory == nullptr || k >= kTransportKinds || schema == nullptr)
120 return AddResult::Invalid;
121 for (StrategyEntry& e : entries_) {
122 if (e.name != name) continue;
123 if (e.schema != schema) return AddResult::Conflict;
124 if (e.publisher == nullptr) e.publisher = publisher;
125 if (e.factories[k] == factory) return AddResult::AlreadyPresent;
126 if (e.factories[k] != nullptr) return AddResult::Conflict;
127 e.factories[k] = factory;
128 return AddResult::Added;
129 }
130 StrategyEntry e{name, schema, {}, publisher};
131 e.factories[k] = factory;
132 entries_.push_back(e);
133 return AddResult::Added;
134 }
135 [[nodiscard]] const StrategyEntry* find(std::string_view name) const noexcept {
136 for (const StrategyEntry& e : entries_) {
137 if (e.name == name) return &e;
138 }
139 return nullptr;
140 }
141 [[nodiscard]] const std::vector<StrategyEntry>& entries() const noexcept { return entries_; }
142 // Builds a runner; null when `name` or its factory for `kind` is missing, or the factory refuses
143 // (wrong backend). Throws std::invalid_argument on bad parameters (startup only).
144 [[nodiscard]] std::unique_ptr<IEngineRunner> make(std::string_view name,
145 TransportKind kind,
146 RunnerDeps& deps) const {
147 const StrategyEntry* e = find(name);
148 if (e == nullptr || !e->supports(kind)) return nullptr;
149 return e->factories[static_cast<std::size_t>(kind)](kind, deps);
150 }
151
152 private:
153 std::vector<StrategyEntry> entries_;
154};
155
156[[nodiscard]] inline const std::vector<StrategyEntry>& list_strategies() {
159
160} // namespace fastmm
Dense-by-id table built at startup; symbol lookup is a sorted FlatMap keyed by (venue,...
Definition instrument.hpp:141
Definition params.hpp:102
Definition registry.hpp:103
const std::vector< StrategyEntry > & entries() const noexcept
Definition registry.hpp:143
AddResult try_add(std::string_view name, const ParamSchema *schema, TransportKind kind, StrategyEntry::Factory factory, StrategyEntry::PublisherFactory publisher=nullptr)
Registers factory for one transport kind of name.
Definition registry.hpp:115
const StrategyEntry * find(std::string_view name) const noexcept
Definition registry.hpp:137
std::unique_ptr< IEngineRunner > make(std::string_view name, TransportKind kind, RunnerDeps &deps) const
Builds a runner; null when name or its factory for kind is missing, or the factory refuses (wrong bac...
Definition registry.hpp:146
static StrategyRegistry & instance()
The registry the CLIs, run_backtest(cfg, name), replay_journal and Python use.
Definition registry.hpp:107
EngineConfig: the per-session settings an Engine is constructed with.
Instrument: the single definition of a tradable contract (5.3 / 5.15).
Definition strategy.hpp:16
constexpr std::size_t kTransportKinds
Definition registry.hpp:62
const std::vector< StrategyEntry > & list_strategies()
Definition registry.hpp:158
TransportKind
Definition registry.hpp:33
constexpr std::string_view to_string(ParamType t) noexcept
Definition params.hpp:63
AddResult
Definition registry.hpp:83
@ Invalid
empty name, null schema or factory, or an invalid kind
@ AlreadyPresent
the same schema and factory were registered before: nothing changed
@ Conflict
name is registered with a different schema, or (name, kind) with another factory
@ Added
the factory is now registered for (name, kind)
std::map< std::string, std::string > ParamMap
Definition params.hpp:119
ParamPublisher: builds ParamUpdate messages for a running engine, off the engine thread (ADR-0013).
Strategy parameter schema (8.6, ADR-0012).
Strategy concept and the StrategyBase helper (8.6).
Where a built update goes; push returns false when it was not accepted (full).
Definition param_publisher.hpp:45
Everything a factory needs that is backend-independent.
Definition registry.hpp:51
MsgRing * journal_ring
Definition registry.hpp:55
void * backend
Definition registry.hpp:59
const InstrumentTable * instruments
Definition registry.hpp:53
ParamMap params
Definition registry.hpp:54
MsgRing * record_ring
Where the engine hands fills, orders, positions and kill events for a storage backend (core/record_st...
Definition registry.hpp:58
EngineConfig engine
Definition registry.hpp:52
Definition registry.hpp:64
std::unique_ptr< IEngineRunner >(*)(TransportKind, RunnerDeps &) Factory
Definition registry.hpp:65
const ParamSchema * schema
Definition registry.hpp:73
bool supports(TransportKind k) const noexcept
Definition registry.hpp:77
std::array< Factory, kTransportKinds > factories
indexed by TransportKind
Definition registry.hpp:74
std::unique_ptr< ParamPublisher >(*)(ParamSink, const ParamMap &) PublisherFactory
Builds a publisher for this strategy's parameters over sink, its copy seeded with the values the sess...
Definition registry.hpp:71
PublisherFactory publisher
Definition registry.hpp:75
std::string_view name
must outlive the registry (S::name() returns a literal)
Definition registry.hpp:72