19#include "fastmm/core/engine.hpp"
23#include "fastmm/sim/matching_engine.hpp"
24#include "fastmm/sim/sim_transport.hpp"
50 static_cast<void>(t.
add(i));
54struct HarnessOptions {
68 using EngineType = Engine<S, SimClock, SimTransport, InlineFeed>;
74 clock_(options_.start),
76 std::make_unique<SimTransport>(clock_, options_.instruments, transport_config())),
77 feed_(std::make_unique<InlineFeed>(1U << 20)),
78 strategy_(std::make_unique<S>()) {
79 if constexpr (
requires { strategy_->configure(params); }) {
80 if (
auto err = strategy_->configure(params))
throw std::invalid_argument(*err);
82 if (!params.empty())
throw std::invalid_argument(
"strategy takes no parameters");
84 engine_ = std::make_unique<EngineType>(
95 if (p ==
nullptr)
throw std::length_error(
"StrategyHarness: feed full");
101 d->bid_count = d->ask_count = 1;
102 d->last_update_id = ++seq_;
103 d->levels()[0] =
Level{bid, size};
104 d->levels()[1] =
Level{ask, size};
116 t.aggressor = aggressor;
128 const auto it = std::find_if(
129 orders.begin(), orders.end(), [side](
const Order& o) { return o.side == side; });
130 if (it == orders.end())
return false;
132 taker.account = kTakerAccount;
134 taker.instrument = id;
138 taker.price = it->price;
139 taker.qty = qty.
is_positive() ? qty : it->leaves_qty();
140 static_cast<void>(transport_->matching_engine().submit(taker, clock_.
now()));
146 std::vector<Order> v;
150 std::sort(v.begin(), v.end(), [](
const Order& a,
const Order& b) {
151 if (a.side != b.side) return a.side == Side::Buy;
152 return a.side == Side::Buy ? a.price > b.price : a.price < b.price;
172 void publish(
const std::vector<ParamPublisher::ParamValue>& values) {
174 if constexpr (
requires { strategy_->params(); }) {
177 throw std::invalid_argument(*err);
178 }
else if (!values.empty()) {
179 throw std::invalid_argument(
"strategy takes no parameters");
189 if (!feed_->push(h))
throw std::length_error(
"StrategyHarness: feed full");
200 const Timestamp t_ord = transport_->next_order_arrival();
201 const Timestamp t_in = transport_->next_inbound_ts();
202 const Timestamp t_timer = engine_->timers().next_expiry();
204 if (t_in < t) t = t_in;
205 if (t_timer < t) t = t_timer;
206 if (t > until)
break;
207 if (t > clock_.
now()) clock_.
set(t);
209 transport_->process_order_arrival();
210 }
else if (t == t_in) {
211 static_cast<void>(transport_->deliver_next_inbound(*feed_));
213 }
else if (engine_->step() == 0 && engine_->timers().next_expiry() <= clock_.
now()) {
225 [[nodiscard]] S&
strategy() noexcept {
return *strategy_; }
229 [[nodiscard]]
static Price price(std::string_view s) {
231 if (!r)
throw std::invalid_argument(
"StrategyHarness: bad price " + std::string(s));
234 [[nodiscard]]
static Qty quantity(std::string_view s) {
236 if (!r)
throw std::invalid_argument(
"StrategyHarness: bad quantity " + std::string(s));
241 static constexpr AccountId kTakerAccount = 7;
243 [[nodiscard]] SimTransportConfig transport_config()
const {
244 SimTransportConfig c;
246 c.ack_in = LatencyParams{options_.
latency, Duration{}};
247 c.md_in = LatencyParams{};
253 void stamp(EventHeader& h)
const noexcept {
254 h.recv_ts = clock_.
now();
255 h.exch_ts = clock_.
now();
256 h.t0_cycles = clock_.
cycles();
259 ConnectionStateMsg m{};
272 while (engine_->step() > 0) {
276 HarnessOptions options_;
278 std::unique_ptr<SimTransport> transport_;
279 std::unique_ptr<InlineFeed> feed_;
280 std::unique_ptr<S> strategy_;
281 std::unique_ptr<EngineType> engine_;
282 std::uint64_t seq_ = 0;
283 std::uint64_t taker_seq_ = 0;
Dense-by-id table built at startup; symbol lookup is a sorted FlatMap keyed by (venue,...
Definition instrument.hpp:141
bool contains(InstrumentId id) const noexcept
Definition instrument.hpp:163
const Instrument & get(InstrumentId id) const noexcept
Definition instrument.hpp:164
Result< InstrumentId, InstrumentError > add(const Instrument &inst) noexcept
Definition instrument.hpp:149
Definition param_publisher.hpp:57
std::optional< std::string > build(const std::vector< ParamValue > &values, InstrumentId inst, ParamUpdateMsg &out) const
The update publish() would send, without sending it or changing the copy; the error message when it i...
Definition param_publisher.hpp:122
static constexpr InstrumentId kAllInstruments
Definition param_publisher.hpp:60
Cycles cycles() const noexcept
Definition time.hpp:343
void set(Timestamp t) noexcept
Definition time.hpp:352
Timestamp now() const noexcept
Definition time.hpp:342
Definition strategy_harness.hpp:68
static Price price(std::string_view s)
Definition strategy_harness.hpp:226
static InstrumentId instrument() noexcept
Definition strategy_harness.hpp:224
Engine< S, SimClock, SimTransport, InlineFeed > EngineType
Definition strategy_harness.hpp:70
void trade(Price px, Qty qty, Side aggressor, InstrumentId id=InstrumentId{0})
Definition strategy_harness.hpp:112
EngineType & engine() noexcept
Definition strategy_harness.hpp:221
void resume_quotes()
Definition strategy_harness.hpp:166
void disconnect(std::uint8_t channel=0, VenueId v=VenueId{0})
Channel 0 is market data (the engine clears the venue's books), 1 is order entry.
Definition strategy_harness.hpp:159
void book(std::string_view bid, std::string_view ask, InstrumentId id=InstrumentId{0})
Definition strategy_harness.hpp:109
void push(EventHeader &h)
Any other message, delivered to the engine at the current time.
Definition strategy_harness.hpp:186
void publish(const std::vector< ParamPublisher::ParamValue > &values)
A ParamUpdate of values (names and values as in [strategy.params]) for all instruments,...
Definition strategy_harness.hpp:171
SimTransport & venue_transport() noexcept
Definition strategy_harness.hpp:223
void advance(Duration d)
Moves virtual time forward by d, delivering orders to the venue, acks and fills to the engine and fir...
Definition strategy_harness.hpp:195
void reconnect(std::uint8_t channel=0, VenueId v=VenueId{0})
Definition strategy_harness.hpp:162
void book(Price bid, Price ask, Qty size=Qty::from_int(1), InstrumentId id=InstrumentId{0})
A one-level snapshot each side.
Definition strategy_harness.hpp:94
std::vector< Order > working_orders(InstrumentId id=InstrumentId{0}) const
Our working orders (Live or PartiallyFilled): bids best first, then asks best first.
Definition strategy_harness.hpp:145
S & strategy() noexcept
Definition strategy_harness.hpp:222
Timestamp now() const noexcept
Definition strategy_harness.hpp:218
bool fill(Side side, Qty qty=Qty{}, InstrumentId id=InstrumentId{0})
Fills our best working order on side (quantity 0: its whole remainder) with a taker order at the venu...
Definition strategy_harness.hpp:126
void pull_quotes()
Definition strategy_harness.hpp:165
static Qty quantity(std::string_view s)
Definition strategy_harness.hpp:231
Instrument: the single definition of a tradable contract (5.3 / 5.15).
Event bus message structs (5.5).
Definition strategy_harness.hpp:40
InstrumentTable harness_instruments()
BTCUSDT on venue 0: tick 0.01, lot 0.001.
Definition strategy_harness.hpp:43
ConnState
Definition enums.hpp:404
@ ParamUpdate
new strategy parameter values (ParamUpdateMsg)
constexpr Side opposite(Side s) noexcept
Definition enums.hpp:13
constexpr void init_header(M &m, EventType type, InstrumentId inst={}, VenueId venue={}, std::uint32_t len=static_cast< std::uint32_t >(sizeof(M))) noexcept
For fixed-size messages len defaults to sizeof(M); BookDeltaMsg passes size_for().
Definition messages.hpp:75
Side
Definition enums.hpp:12
StrongId< struct InstrumentTag, std::uint32_t > InstrumentId
Dense index into the engine's instrument table.
Definition strong_id.hpp:38
Fixed< struct PriceTag > Price
Definition fixed_point.hpp:332
constexpr Duration seconds(std::int64_t v) noexcept
Definition time.hpp:41
constexpr Duration microseconds(std::int64_t v) noexcept
Definition time.hpp:35
ControlCommand
Definition enums.hpp:447
StrongId< struct VenueTag, std::uint8_t > VenueId
Definition strong_id.hpp:39
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 concept and the StrategyBase helper (8.6).
Bids then asks follow the fixed part as a flexible array of Level (bid_count + ask_count).
Definition messages.hpp:99
static constexpr std::uint32_t size_for(std::uint32_t bids, std::uint32_t asks) noexcept
Definition messages.hpp:107
std::int64_t ns
Definition time.hpp:23
Definition engine_config.hpp:21
QuoteParams quotes
Definition engine_config.hpp:74
constexpr bool is_positive() const noexcept
Definition fixed_point.hpp:302
static constexpr Fixed from_int(std::int64_t units) noexcept
Whole units, e.g. from_int(100) == 100.00000000.
Definition fixed_point.hpp:161
static constexpr std::optional< Fixed > from_decimal(std::string_view s) noexcept
Exact parse of "[+-]digits[.digits]".
Definition fixed_point.hpp:174
Definition strong_id.hpp:54
Definition instrument.hpp:29
@ kEnabled
Definition instrument.hpp:31
VenueId venue
1
Definition instrument.hpp:43
Symbol symbol
21
Definition instrument.hpp:56
One price level. Shared by book messages and the L2 book.
Definition messages.hpp:30
constexpr bool is_working() const noexcept
Definition order.hpp:49
Where a built update goes; push returns false when it was not accepted (full).
Definition param_publisher.hpp:45
New strategy parameter values (ADR-0013): up to kMaxFields (field index, raw value) pairs,...
Definition messages.hpp:574
Duration min_requote_interval
Definition quote_manager.hpp:93
Definition messages.hpp:140
Definition strategy_harness.hpp:56
InstrumentTable instruments
Definition strategy_harness.hpp:57
Duration latency
order out and ack back, each way
Definition strategy_harness.hpp:63
EngineConfig engine
Definition strategy_harness.hpp:58
Timestamp start
Definition strategy_harness.hpp:64