FastMM documentation
FastMM C++ API 0.6.0
Public headers, tier 1 and tier 2
Loading...
Searching...
No Matches
enums.hpp
Go to the documentation of this file.
1#pragma once
2// All engine enumerations. Every enum is `enum class` with a fixed underlying type so it
3// can be embedded in trivially copyable messages; to_string() is for logs/diagnostics.
4#include <cstddef>
5#include <cstdint>
6#include <string_view>
7
8namespace fastmm {
9
10enum class Side : std::uint8_t { Buy = 0, Sell = 1 };
11[[nodiscard]] constexpr Side opposite(Side s) noexcept {
14[[nodiscard]] constexpr int sign(Side s) noexcept {
15 return s == Side::Buy ? 1 : -1;
17[[nodiscard]] constexpr std::string_view to_string(Side s) noexcept {
18 return s == Side::Buy ? "Buy" : "Sell";
20
21enum class OrderType : std::uint8_t { Limit = 0, Market = 1, PostOnly = 2 };
22[[nodiscard]] constexpr std::string_view to_string(OrderType t) noexcept {
23 switch (t) {
25 return "Limit";
27 return "Market";
29 return "PostOnly";
30 }
31 return "?";
32}
33
34enum class TimeInForce : std::uint8_t { Gtc = 0, Ioc = 1, Fok = 2, Day = 3 };
35[[nodiscard]] constexpr std::string_view to_string(TimeInForce t) noexcept {
36 switch (t) {
38 return "GTC";
40 return "IOC";
42 return "FOK";
44 return "DAY";
45 }
46 return "?";
47}
48
49enum class AssetClass : std::uint8_t {
50 Spot = 0,
52 Future = 2,
53 Option = 3,
54 Fx = 4,
55 Equity = 5
56};
57[[nodiscard]] constexpr std::string_view to_string(AssetClass a) noexcept {
58 switch (a) {
60 return "Spot";
62 return "Perpetual";
64 return "Future";
66 return "Option";
67 case AssetClass::Fx:
68 return "Fx";
70 return "Equity";
71 }
72 return "?";
73}
74
75enum class OptionType : std::uint8_t { None = 0, Call = 1, Put = 2 };
76
77enum class OrderState : std::uint8_t {
78 PendingNew = 0,
79 Live = 1,
81 PendingCancel = 3,
83 Filled = 5,
84 Canceled = 6,
85 Rejected = 7,
86 Expired = 8,
87};
88[[nodiscard]] constexpr bool is_terminal(OrderState s) noexcept {
89 return s >= OrderState::Filled;
91[[nodiscard]] constexpr bool is_pending(OrderState s) noexcept {
94}
95[[nodiscard]] constexpr std::string_view to_string(OrderState s) noexcept {
96 switch (s) {
98 return "PendingNew";
100 return "Live";
102 return "PartiallyFilled";
104 return "PendingCancel";
106 return "PendingReplace";
108 return "Filled";
110 return "Canceled";
112 return "Rejected";
114 return "Expired";
115 }
116 return "?";
117}
118
119// Ordered exactly like RiskEngine::check_new evaluates them (5.7), followed by OMS /
120// transport / venue reasons.
121enum class RejectReason : std::uint8_t {
122 None = 0,
124 VenueKilled = 2,
126 InvalidTick = 4,
127 InvalidLot = 5,
129 StaleMarketData = 7,
130 PriceCollar = 8,
131 FatFinger = 9,
132 MaxOrderQty = 10,
133 MaxOrderNotional = 11,
134 MaxPosition = 12,
135 MaxOpenOrders = 13,
137 RateLimit = 15,
138 MaxLoss = 16,
139 MaxGrossNotional = 17, // portfolio |position| at the last marks, over every instrument
140 MaxNetNotional = 18,
141 // [accounting]: the rate of the order's settlement currency is unknown or stale, and the order
142 // would add to its exposure while max_loss or an exposure cap is set.
143 FxRateUnknown = 19,
144 // [risk] max_feed_lag_ms: the venue's market data is late (core/venue_health.hpp) and the order
145 // could rest there without reducing the position.
146 FeedLag = 20,
147 // [risk.underlying.<BASE>] max_net: the net position in the order's underlying, in base units
148 // over every instrument, with the open orders on the order's side and the order itself, would
149 // move further past the limit.
150 MaxUnderlyingNet = 21,
151 // The underlying cannot be measured: an inverse contract in it has a position or open orders (or
152 // is the order's instrument) and no current mark.
154 // The account's balance on the venue, as the venue last reported it less what the engine's own
155 // orders and fills took since (core/balance_book.hpp), does not cover the order: a spot sell
156 // above the free base asset, a spot buy whose notional plus taker fee is above the free quote
157 // asset, a derivative whose initial margin is above the available margin ([risk] check_balance).
158 BalanceShort = 23,
159 // OMS / transport
160 PoolExhausted = 32,
161 UnknownOrder = 33,
162 InvalidState = 34,
163 DuplicateId = 35,
164 TransportFull = 36,
165 NotReconciled = 37,
166 InvalidTag = 38, // a direct order used a user_tag in the QuoteManager's range
167 // The connector's table of the orders it has sent is full: it could not record this one (whose
168 // fills, amends and replies it would then not map back), so it did not send it.
169 OrderTableFull = 39,
170 // NewOrderRequest::account names a venue that is neither the instrument's nor a member of its
171 // pool (core/account_pool.hpp); refused locally.
172 InvalidAccount = 40,
173 // fastmm-gateway's account guards ([gateway]), refused before the order reached the connector
174 GatewayRateLimit = 48, // the venue's order rate, shared by every attached strategy
175 GatewayOpenNotional = 49, // the notional working at the venue, over every attached strategy
176 GatewayNotOwner = 50, // the instrument belongs to another attachment (or none)
177 GatewayAccountKilled = 51, // [gateway] max_loss tripped the account's kill switch
178 GatewayGrossNotional = 52, // the account's |position| at the marks, over every instrument
179 GatewayNetNotional = 53, // the account's signed position at the marks
180 GatewayFxRateUnknown = 54, // [accounting]: the order's currency has no current rate
181 GatewayUnderlyingNet = 55, // [gateway.underlying.<BASE>] max_net, over every strategy and venue
182 GatewayUnderlyingMarkUnknown = 56, // an inverse contract of the underlying has no current mark
183 GatewaySelfTrade = 57, // it would cross another attached strategy's resting order
184 GatewayBalanceShort = 58, // the account's balance, less every attached strategy's orders
185 // Venue-originated
186 VenueReject = 64,
189 VenueRateLimit = 67,
191};
192[[nodiscard]] constexpr std::string_view to_string(RejectReason r) noexcept {
193 switch (r) {
195 return "None";
197 return "KillSwitch";
199 return "VenueKilled";
201 return "InstrumentDisabled";
203 return "InvalidTick";
205 return "InvalidLot";
207 return "BelowMinNotional";
209 return "StaleMarketData";
211 return "PriceCollar";
213 return "FatFinger";
215 return "MaxOrderQty";
217 return "MaxOrderNotional";
219 return "MaxPosition";
221 return "MaxOpenOrders";
223 return "SelfTradePrevention";
225 return "RateLimit";
227 return "MaxLoss";
229 return "MaxGrossNotional";
231 return "MaxNetNotional";
233 return "FxRateUnknown";
235 return "FeedLag";
237 return "MaxUnderlyingNet";
239 return "UnderlyingMarkUnknown";
241 return "BalanceShort";
243 return "PoolExhausted";
245 return "UnknownOrder";
247 return "InvalidState";
249 return "DuplicateId";
251 return "TransportFull";
253 return "NotReconciled";
255 return "InvalidTag";
257 return "OrderTableFull";
259 return "InvalidAccount";
261 return "GatewayRateLimit";
263 return "GatewayOpenNotional";
265 return "GatewayNotOwner";
267 return "GatewayAccountKilled";
269 return "GatewayGrossNotional";
271 return "GatewayNetNotional";
273 return "GatewayFxRateUnknown";
275 return "GatewayUnderlyingNet";
277 return "GatewayUnderlyingMarkUnknown";
279 return "GatewaySelfTrade";
281 return "GatewayBalanceShort";
283 return "VenueReject";
285 return "PostOnlyWouldCross";
287 return "InsufficientBalance";
289 return "VenueRateLimit";
291 return "VenueUnknownOrder";
292 }
293 return "?";
294}
295
296// Message discriminator carried in EventHeader::type. BookDelta is 1 so the dispatch
297// switch's most likely case is the first compare.
298enum class EventType : std::uint8_t {
299 Padding = 0, // ring wrap filler, never dispatched
301 BookSnapshot = 2,
302 BookTicker = 3,
303 Trade = 4,
304 OrderAck = 5,
305 OrderReject = 6,
306 OrderCancelAck = 7,
308 OrderFill = 9,
309 OrderExpired = 10,
310 PositionUpdate = 11,
311 Timer = 12,
312 Control = 13,
313 ConnectionState = 14,
314 Reconcile = 15,
315 LatencySample = 16,
316 OutNewOrder = 17,
317 OutCancel = 18,
318 OutReplace = 19,
319 OrderAddL3 = 20,
320 OrderExecL3 = 21,
321 OrderCancelL3 = 22,
322 OrderReplaceL3 = 23,
323 OptionTicker = 24, // mark / implied vols / greeks of one option (OptionTickerMsg)
324 EngineTime = 25, // journal only: the engine clock at start / finish / a delta overflow
325 ParamUpdate = 26, // new strategy parameter values (ParamUpdateMsg)
326 Funding = 27, // a perpetual funding payment booked by the venue (FundingMsg)
327 Balance = 28, // the account's holding of one asset on one venue (BalanceMsg)
328 PerpState = 29, // mark, index and funding of one derivative (PerpStateMsg)
329 StrategyState = 30, // journal only: the strategy's state and the positions (StrategyStateMsg)
330 Count = 31,
331};
332[[nodiscard]] constexpr std::string_view to_string(EventType t) noexcept {
333 switch (t) {
335 return "Padding";
337 return "BookDelta";
339 return "BookSnapshot";
341 return "BookTicker";
342 case EventType::Trade:
343 return "Trade";
345 return "OrderAck";
347 return "OrderReject";
349 return "OrderCancelAck";
351 return "OrderCancelReject";
353 return "OrderFill";
355 return "OrderExpired";
357 return "PositionUpdate";
358 case EventType::Timer:
359 return "Timer";
361 return "Control";
363 return "ConnectionState";
365 return "Reconcile";
367 return "LatencySample";
369 return "OutNewOrder";
371 return "OutCancel";
373 return "OutReplace";
375 return "OrderAddL3";
377 return "OrderExecL3";
379 return "OrderCancelL3";
381 return "OrderReplaceL3";
383 return "OptionTicker";
385 return "EngineTime";
387 return "ParamUpdate";
389 return "Funding";
391 return "Balance";
393 return "PerpState";
395 return "StrategyState";
396 case EventType::Count:
397 return "Count";
398 }
399 return "?";
400}
401
402enum class ConnState : std::uint8_t {
403 Disconnected = 0,
405 Live = 2,
406 Stale = 3,
407 Resyncing = 4,
408 Dead = 5,
409};
410[[nodiscard]] constexpr std::string_view to_string(ConnState s) noexcept {
411 switch (s) {
413 return "Disconnected";
415 return "Connecting";
416 case ConnState::Live:
417 return "Live";
418 case ConnState::Stale:
419 return "Stale";
421 return "Resyncing";
422 case ConnState::Dead:
423 return "Dead";
424 }
425 return "?";
426}
427
428// The asset a fill's commission is charged in. Binance spot charges a buy in the base asset
429// (you receive less), a sell in the quote asset, and either in BNB when the discount is enabled.
430enum class FeeAsset : std::uint8_t { Quote = 0, Base = 1, Other = 2 };
431
432enum class Liquidity : std::uint8_t { Unknown = 0, Maker = 1, Taker = 2 };
433[[nodiscard]] constexpr std::string_view to_string(Liquidity l) noexcept {
434 switch (l) {
436 return "Unknown";
437 case Liquidity::Maker:
438 return "Maker";
439 case Liquidity::Taker:
440 return "Taker";
441 }
442 return "?";
443}
444
445enum class ControlCommand : std::uint8_t {
446 Stop = 0,
448 ResumeQuotes = 2,
449 TripKill = 3,
450 ResetKill = 4,
451 Reload = 5,
452 FlushStats = 6,
453 RecalibrateTsc = 7,
454 // A venue connector gave up on one venue (arg: KillReason, hdr.venue: the venue): the engine
455 // trips that venue's kill bit only. Sent through the venue's order ring, so it is journaled and
456 // replays like any other engine input.
457 TripVenueKill = 8,
458 // Operator flatten (arg: the slippage allowance in basis points, 0 takes [engine]
459 // flatten_slippage_bps; hdr.instrument: one instrument, invalid for every one): the engine
460 // stops quoting in that scope, cancels its orders and sends reduce-only IOC slices through the
461 // touch until the position is flat (core/engine.hpp).
462 Flatten = 9,
463 // New risk limits for RiskEngine::set_limits. The message is a ControlLimitsMsg: a ControlMsg
464 // with a RiskLimits payload (core/messages.hpp).
465 SetLimits = 10,
466 // Engine -> venue, on the outbound ring (hdr.venue: the venue): the engine and the venue
467 // disagree about an order (a cancel rejected more than three times), so the connector runs the
468 // reconciliation it runs after a reconnect. The engine ignores it as an input.
469 Reconcile = 11,
470 // A new [risk.underlying.<BASE>] max_net for RiskEngine::set_underlying_limit. The message is a
471 // ControlUnderlyingMsg: the underlying's index in the session's plan, and the limit in `arg`.
473 // A warm standby took the instance lock (fastmm-live --standby): arg is the PnL carried from
474 // earlier sessions (Notional raw, two's complement), read from the kill file once the session
475 // before it had written it last, and the strategy restores the state staged with
476 // Engine::stage_strategy_state (none in a replay).
477 TakeOver = 13,
478 // A pool treasury's transfer (core/treasury.hpp): planned, sent, done, failed or timed out. The
479 // message is a ControlTransferMsg; the engine counts it and changes nothing, so the journal holds
480 // every transfer next to the balances it moved.
481 Transfer = 14,
482};
483[[nodiscard]] constexpr std::string_view to_string(ControlCommand c) noexcept {
484 switch (c) {
486 return "Stop";
488 return "PullQuotes";
490 return "ResumeQuotes";
492 return "TripKill";
494 return "ResetKill";
496 return "Reload";
498 return "FlushStats";
500 return "RecalibrateTsc";
502 return "TripVenueKill";
504 return "Flatten";
506 return "SetLimits";
508 return "Reconcile";
510 return "SetUnderlyingLimit";
512 return "TakeOver";
514 return "Transfer";
515 }
516 return "?";
517}
518
519// Why a kill switch (global or one venue's) was tripped. The engine records the first reason per
520// flag; fastmm-live decides from it whether to exit ([engine] on_kill) and shows it in the status.
521enum class KillReason : std::uint8_t {
522 None = 0,
523 Requested = 1, // ControlCommand::TripKill: shutdown, operator
524 MaxLoss = 2, // [risk] max_loss
525 TransportFull = 3, // the outbound ring to a venue was full
526 JournalOverflow = 4, // the journal ring was full
527 AllVenuesKilled = 5, // every venue with instruments has its own kill bit set
528 VenueFatal = 6, // venue error map: bad key, signature, permission, failed auth
529 VenueHardStop = 7, // venue error map: REST stopped (IP ban)
530 OrderRingOverflow = 8, // fastmm-live: a venue's order-event ring overflowed
531 StrategyError = 9, // a strategy hook reported an error (Python hot hooks)
532 FeedLost = 10, // a multicast feed cannot rebuild its books (nasdaq_itch)
533 OrderIdsExhausted = 11, // the session's 32-bit client order id sequence is used up
534 DeadMansSwitchLost = 12, // the venue-side countdown could not be refreshed within its window
535 GatewayMaxLoss = 13, // fastmm-gateway: the account's [gateway] max_loss, over every strategy
536 GatewayOperator = 14, // fastmm-gateway: an operator's `kill` on the gateway's control socket
537};
538// Kill reasons are kept per venue id for ids 0..kKillVenueSlots-1; higher ids share the last slot,
539// as they share the last kill bit (RiskEngine::venue_bit).
540inline constexpr std::size_t kKillVenueSlots = 31;
541[[nodiscard]] constexpr std::string_view to_string(KillReason r) noexcept {
542 switch (r) {
544 return "None";
546 return "Requested";
548 return "MaxLoss";
550 return "TransportFull";
552 return "JournalOverflow";
554 return "AllVenuesKilled";
556 return "VenueFatal";
558 return "VenueHardStop";
560 return "OrderRingOverflow";
562 return "StrategyError";
564 return "FeedLost";
566 return "OrderIdsExhausted";
568 return "DeadMansSwitchLost";
570 return "GatewayMaxLoss";
572 return "GatewayOperator";
573 }
574 return "?";
575}
576
577// How far an operator flatten (ControlCommand::Flatten) got. The engine publishes it with its
578// live stats and fastmm-live copies it into the status file and the control socket's `status`.
579enum class FlattenState : std::uint8_t {
580 Off = 0, // none was asked for in this session
581 Working = 1, // quoting is off in its scope and reduce-only slices are going out
582 Flat = 2, // it finished: no position left in its scope
583 TimedOut = 3, // [engine] flatten_timeout_ms elapsed with a position left; it gave up
584 Stopped = 4, // the operator resumed quoting before it finished
585};
586[[nodiscard]] constexpr std::string_view to_string(FlattenState s) noexcept {
587 switch (s) {
589 return "Off";
591 return "Working";
593 return "Flat";
595 return "TimedOut";
597 return "Stopped";
598 }
599 return "?";
600}
601
602enum class LogLevel : std::uint8_t { Trace = 0, Debug = 1, Info = 2, Warn = 3, Error = 4, Off = 5 };
603[[nodiscard]] constexpr std::string_view to_string(LogLevel l) noexcept {
604 switch (l) {
606 return "TRACE";
607 case LogLevel::Debug:
608 return "DEBUG";
609 case LogLevel::Info:
610 return "INFO";
611 case LogLevel::Warn:
612 return "WARN";
613 case LogLevel::Error:
614 return "ERROR";
615 case LogLevel::Off:
616 return "OFF";
617 }
618 return "?";
619}
620
621} // namespace fastmm
Definition strategy.hpp:16
OrderType
Definition enums.hpp:23
LogLevel
Definition enums.hpp:604
OrderState
Definition enums.hpp:79
constexpr bool is_pending(OrderState s) noexcept
Definition enums.hpp:93
ConnState
Definition enums.hpp:404
AssetClass
Definition enums.hpp:51
FlattenState
How far an operator flatten (ControlCommand::Flatten) got.
Definition enums.hpp:581
@ Flat
it finished: no position left in its scope
@ Working
quoting is off in its scope and reduce-only slices are going out
@ TimedOut
[engine] flatten_timeout_ms elapsed with a position left; it gave up
@ Stopped
the operator resumed quoting before it finished
@ Off
none was asked for in this session
KillReason
Why a kill switch (global or one venue's) was tripped.
Definition enums.hpp:523
@ OrderIdsExhausted
the session's 32-bit client order id sequence is used up
@ TransportFull
the outbound ring to a venue was full
@ VenueHardStop
venue error map: REST stopped (IP ban)
@ VenueFatal
venue error map: bad key, signature, permission, failed auth
@ AllVenuesKilled
every venue with instruments has its own kill bit set
@ OrderRingOverflow
fastmm-live: a venue's order-event ring overflowed
@ JournalOverflow
the journal ring was full
@ GatewayMaxLoss
fastmm-gateway: the account's [gateway] max_loss, over every strategy
@ MaxLoss
[risk] max_loss
@ DeadMansSwitchLost
the venue-side countdown could not be refreshed within its window
@ StrategyError
a strategy hook reported an error (Python hot hooks)
@ GatewayOperator
fastmm-gateway: an operator's kill on the gateway's control socket
@ FeedLost
a multicast feed cannot rebuild its books (nasdaq_itch)
@ Requested
ControlCommand::TripKill: shutdown, operator.
EventType
Message discriminator carried in EventHeader::type.
Definition enums.hpp:300
@ EngineTime
journal only: the engine clock at start / finish / a delta overflow
@ Funding
a perpetual funding payment booked by the venue (FundingMsg)
@ Balance
the account's holding of one asset on one venue (BalanceMsg)
@ Padding
ring wrap filler, never dispatched
@ StrategyState
journal only: the strategy's state and the positions (StrategyStateMsg)
@ OptionTicker
mark / implied vols / greeks of one option (OptionTickerMsg)
@ ParamUpdate
new strategy parameter values (ParamUpdateMsg)
@ PerpState
mark, index and funding of one derivative (PerpStateMsg)
RejectReason
Ordered exactly like RiskEngine::check_new evaluates them (5.7), followed by OMS / transport / venue ...
Definition enums.hpp:123
@ GatewayUnderlyingMarkUnknown
an inverse contract of the underlying has no current mark
@ GatewayAccountKilled
[gateway] max_loss tripped the account's kill switch
@ GatewayNetNotional
the account's signed position at the marks
@ UnderlyingMarkUnknown
The underlying cannot be measured: an inverse contract in it has a position or open orders (or is the...
@ GatewayNotOwner
the instrument belongs to another attachment (or none)
@ GatewayUnderlyingNet
[gateway.underlying.<BASE>] max_net, over every strategy and venue
@ GatewayOpenNotional
the notional working at the venue, over every attached strategy
@ GatewayRateLimit
fastmm-gateway's account guards ([gateway]), refused before the order reached the connector
@ VenueReject
Venue-originated.
@ MaxUnderlyingNet
[risk.underlying.
@ GatewayBalanceShort
the account's balance, less every attached strategy's orders
@ GatewaySelfTrade
it would cross another attached strategy's resting order
@ FxRateUnknown
[accounting]: the rate of the order's settlement currency is unknown or stale, and the order would ad...
@ BalanceShort
The account's balance on the venue, as the venue last reported it less what the engine's own orders a...
@ FeedLag
[risk] max_feed_lag_ms: the venue's market data is late (core/venue_health.hpp) and the order could r...
@ MaxGrossNotional
portfolio |position| at the last marks, over every instrument
@ InvalidAccount
NewOrderRequest::account names a venue that is neither the instrument's nor a member of its pool (cor...
@ OrderTableFull
The connector's table of the orders it has sent is full: it could not record this one (whose fills,...
@ PoolExhausted
OMS / transport.
@ GatewayFxRateUnknown
[accounting]: the order's currency has no current rate
@ GatewayGrossNotional
the account's |position| at the marks, over every instrument
@ InvalidTag
a direct order used a user_tag in the QuoteManager's range
constexpr Side opposite(Side s) noexcept
Definition enums.hpp:13
Side
Definition enums.hpp:12
FeeAsset
The asset a fill's commission is charged in.
Definition enums.hpp:432
constexpr int sign(Side s) noexcept
Definition enums.hpp:16
constexpr bool is_terminal(OrderState s) noexcept
Definition enums.hpp:90
TimeInForce
Definition enums.hpp:36
constexpr std::string_view to_string(ParamType t) noexcept
Definition params.hpp:63
OptionType
Definition enums.hpp:77
constexpr std::size_t kKillVenueSlots
Kill reasons are kept per venue id for ids 0..kKillVenueSlots-1; higher ids share the last slot,...
Definition enums.hpp:542
Liquidity
Definition enums.hpp:434
ControlCommand
Definition enums.hpp:447
@ TripVenueKill
A venue connector gave up on one venue (arg: KillReason, hdr.venue: the venue): the engine trips that...
@ SetLimits
New risk limits for RiskEngine::set_limits.
@ Flatten
Operator flatten (arg: the slippage allowance in basis points, 0 takes [engine] flatten_slippage_bps;...
@ Transfer
A pool treasury's transfer (core/treasury.hpp): planned, sent, done, failed or timed out.
@ SetUnderlyingLimit
A new [risk.underlying.
@ TakeOver
A warm standby took the instance lock (fastmm-live --standby): arg is the PnL carried from earlier se...
@ Reconcile
Engine -> venue, on the outbound ring (hdr.venue: the venue): the engine and the venue disagree about...