Universal Order Book Engine
Architecture for Any Asset, Any Market, Any Representation
Version: 1.0 Date: December 2024 Status: Design Specification
Table of Contents
| Part | Title | Description |
|---|---|---|
| I | Executive Summary | Vision, scope, and key differentiators |
| II | Design Philosophy | Core principles and the universal abstraction |
| III | Core Abstractions | LONG/SHORT model, outcomes, market groups |
| IV | Multi-Outcome Markets | Beyond binary: runners, selections, legs |
| V | Synthetic Matching Engine | Cross-outcome and implied odds matching |
| VI | Asian Handicap Native Support | Lines, quarters, push, and synthetic matching |
| VII | Multi-Representation Framework | Odds, prices, percentages, and hybrids |
| VIII | Universal Data Model | Structures that work for any asset |
| IX | Matching Algorithm | Direct, synthetic, and priority rules |
| X | Scope & Boundaries | What Order Book does and does NOT do |
| XI | System Architecture | Components, data flow, event sourcing |
| XII | The Pipeline | Five-stage deterministic pipeline |
| XIII | Durability & Recovery | Event journal, fsync, crash recovery |
| XIV | Kubernetes & Deployment | K8s topology, HA, persistent volumes |
| XV | Operations & Monitoring | Prometheus, Grafana, alerting, runbooks |
| XVI | Security | Trust boundaries, mTLS, input validation |
| XVII | Testing Strategy | Test pyramid, property tests, determinism |
| XVIII | Asset Class Implementations | Betting, options, futures, prediction markets |
| XIX | Extensibility & Plugins | Adding new asset classes and representations |
| XX | Performance Considerations | Maintaining speed with flexibility |
| XXI | Comparison: SmartBets vs Universal | What changes, what stays the same |
| XXII | FAQ | Common questions answered |
| XXIII | Glossary | Term definitions |
| Appendix A | Mermaid Diagram Index | Quick reference to all diagrams |
| Appendix B | Deep Dive FAQ | Detailed layman explanations |
Appendix B Sections:
| Section | Topic |
|---|---|
| B.1 | Balance Race Condition - Why LOCK, not just CHECK |
| B.2 | Asian Handicaps for Beginners - Full walkthrough |
| B.3 | Options Trading Demystified - Greeks explained |
| B.4 | Three-Way Synthetic Matching - Step by step |
| B.5 | Summary - How it all connects |
Part I: Executive Summary
The Vision
One matching engine to rule them all.
The Universal Order Book Engine is designed to be a single, unified matching engine that can power:
- Sports betting exchanges (BACK/LAY)
- Prediction markets (YES/NO)
- Stock exchanges (BUY/SELL)
- Options markets (with Greeks and margin)
- Futures markets (with expiry and settlement)
- Cryptocurrency spot and derivatives
- Any future asset class we haven't imagined yet
Why Universal?
The insight is simple: all tradeable instruments are fundamentally the same.
Whether you're betting on Manchester United, buying Apple stock, or trading Bitcoin futures, you're doing the same thing: expressing a directional view at a price, waiting to be matched with someone who disagrees.
Key Differentiators
| Feature | Traditional Design | Universal Design |
|---|---|---|
| Market Model | Binary (BACK/LAY or BID/ASK) | N-outcome with relationships |
| Matching | Direct only | Direct + Synthetic |
| Asian Handicap | Workarounds | Native first-class support |
| Asset Classes | One per system | Infinite via adapters |
| Representations | Fixed (odds or price) | Pluggable, mixable |
| Liquidity | Fragmented per outcome | Unified via synthetic matching |
The Universal Truth
At the core of every tradeable instrument is this structure:
POSITION = (DIRECTION, OUTCOME, PRICE, QUANTITY, COLLATERAL)
Everything else—BACK/LAY, BID/ASK, YES/NO, CALL/PUT—is just a representation layer on top of this universal truth.
Diagram Explanation:
This mind map shows the three pillars of the Universal Order Book:
| Pillar | What It Means |
|---|---|
| Asset Classes | Any tradeable instrument can be modeled |
| Capabilities | Features that go beyond traditional matching |
| Guarantees | Same reliability as the SmartBets-specific design |
Part II: Design Philosophy
The Abstraction Ladder
Every trading system can be understood as layers of abstraction:
Diagram Explanation:
| Layer | Purpose | Example |
|---|---|---|
| User Interface | Human-friendly language | "Bet on Man Utd" |
| Representation | Domain-specific format | Decimal odds, USD price |
| Universal Model | Normalized structure | LONG/SHORT + probability/price |
| Matching Engine | Asset-agnostic matching | Same engine for all |
The Core Insight
All two-sided markets are isomorphic.
| Domain | Side A | Side B | Price Meaning |
|---|---|---|---|
| Betting | BACK | LAY | Decimal odds (2.0 = 50% implied) |
| Stocks | BUY | SELL | Currency (USD, EUR) |
| Prediction | YES | NO | Probability (0-100%) |
| Options | BUY | SELL | Premium + Greeks |
| Futures | LONG | SHORT | Future price |
The Universal Order Book uses LONG and SHORT as the canonical directions, with adapters that translate to/from domain-specific representations.
Design Principles
| Principle | Meaning | Implementation |
|---|---|---|
| Representation Agnostic | Core doesn't know about odds/prices | Adapters translate at boundaries |
| Outcome Agnostic | Binary, multi-runner, continuous | Unified outcome model |
| Settlement Agnostic | Engine matches, plugins settle | Pluggable settlement framework |
| Synthetic-First | Cross-outcome matching is default | Implied odds engine built-in |
Part III: Core Abstractions
The Universal Position Model
Instead of BACK/LAY or BID/ASK, we use a universal direction model:
Diagram Explanation:
| Universal | Betting | Trading | Prediction | Meaning |
|---|---|---|---|---|
| LONG | BACK | BUY | YES | Profit if outcome occurs |
| SHORT | LAY | SELL | NO | Profit if outcome doesn't occur |
The Outcome Hierarchy
Markets can have multiple outcomes with relationships:
Diagram Explanation:
| Level | What It Represents | Example |
|---|---|---|
| Event | Real-world occurrence | Football match |
| Market | Type of bet/trade | Match winner, handicap |
| Outcome | Specific selection | Man Utd win, Over 2.5 |
Outcome Relationships
Outcomes can have mathematical relationships that enable synthetic matching:
Relationship Types:
| Type | Meaning | Example | Synthetic Matching |
|---|---|---|---|
| Mutually Exclusive | Exactly one must happen | 1X2 market | SHORT on A+B = LONG on C |
| Complementary | Two outcomes sum to 100% | Over/Under | LONG Over = SHORT Under |
| Ordered | Sequential handicap lines | Asian Handicap | Cross-line synthetic |
| Independent | No relationship | Different events | No synthetic matching |
Part IV: Multi-Outcome Markets
Beyond Binary: The Multi-Runner Model
Traditional order books handle binary outcomes: this price, buy or sell. Real-world markets are more complex.
Diagram Explanation:
| Model | Outcomes | Example | Our Support |
|---|---|---|---|
| Binary | 2 | Over/Under, Yes/No | ✅ Full |
| Three-Way | 3 | 1X2 (Win/Draw/Win) | ✅ Full |
| Multi-Runner | N | Horse race, election | ✅ Full |
| Continuous | ∞ | Price of a stock | ✅ Via bucketing |
Market Types Supported
Per-Outcome Order Books
Each outcome in a multi-outcome market has its own order book:
Diagram Explanation:
| Concept | Implementation | Benefit |
|---|---|---|
| Per-Outcome Books | Each selection has LONG + SHORT | Independent liquidity per runner |
| Unified Market | All outcomes share market metadata | Consistent rules, single settlement |
| Cross-Outcome Link | Outcomes know about siblings | Enables synthetic matching |
Overround and Book Balance
Multi-outcome markets have an important concept: overround (the sum of implied probabilities).
Overround Explained:
| Scenario | Overround | What It Means | Our Response |
|---|---|---|---|
| = 100% | Fair | Zero-sum market | Ideal state |
| > 100% | Over | House edge built in | Normal for bookmakers |
| < 100% | Under | Arbitrage opportunity | Synthetic matching exploits this |
Part V: Synthetic Matching Engine
What Is Synthetic Matching?
Synthetic matching is the killer feature that maximizes liquidity. It matches orders that don't directly oppose each other by using mathematical relationships between outcomes.
The Insight: If someone wants to go LONG on Horse A, they're effectively going SHORT on "not Horse A" (i.e., all other horses). The synthetic matching engine finds these equivalences.
The Mathematics of Synthetic Matching
In a mutually exclusive market, these are equivalent:
Formula:
SHORT(Outcome_A) ≡ LONG(Outcome_B) + LONG(Outcome_C) + ... + LONG(Outcome_N)
Where: P(A) + P(B) + P(C) + ... + P(N) = 100%
How Synthetic Matching Works
Diagram Explanation:
| Step | What Happens | Why It Matters |
|---|---|---|
| 1. Check Direct | Look for opposing order | Fast path if available |
| 2. Calculate Synthetic | Combine other outcomes | Find hidden liquidity |
| 3. Compare Prices | Is synthetic price acceptable? | Only match if beneficial |
| 4. Execute | Create trades on all legs | Atomically matched |
Synthetic Matching Example: 3-Way Market
Consider a 1X2 football market (Home/Draw/Away):
Calculation:
If you LONG both Draw and Away in the right proportions, you've effectively created a SHORT on Home:
Implied Home probability = 1 - (1/3.50 + 1/3.00)
= 1 - (0.286 + 0.333)
= 1 - 0.619
= 0.381
= 2.62 odds
If we can LONG Draw @ 3.50 and Away @ 3.00,
we create synthetic SHORT Home @ 2.62
Synthetic Matching Benefits
| Benefit | Without Synthetic | With Synthetic |
|---|---|---|
| Liquidity | Only direct counterparties | All related outcomes contribute |
| Spread | Can be wide | Compressed by synthetic competition |
| Arbitrage | Can exist between outcomes | Automatically eliminated |
| Fill Rate | Lower | Significantly higher |
Part VI: Asian Handicap Native Support
Why Asian Handicap Needs Special Treatment
Asian Handicap is one of the most popular betting markets globally, but it has unique characteristics that don't fit traditional binary models:
The Challenge:
| Line Type | Outcomes | Traditional Binary? | Our Solution |
|---|---|---|---|
| Half-Goal | 2 (Win/Lose) | ✅ Yes | Standard binary market |
| Whole-Goal | 3 (Win/Lose/Push) | ❌ No | Push-aware outcome |
| Quarter-Goal | 4 (Win/Lose/Half-Win/Half-Lose) | ❌ No | Atomic split order |
Quarter-Goal Lines: Native Atomic Orders
The key innovation is treating quarter-goal lines as atomic orders that internally split into two half-goal lines:
Diagram Explanation:
| Concept | What Happens | Benefit |
|---|---|---|
| Atomic Order | User submits one order | Simple UX |
| Internal Split | Engine creates two legs | Proper matching |
| Unified Settlement | Both legs settle together | Correct payout |
Handicap Line Relationships
Asian Handicap lines have a natural ordering that enables synthetic matching:
Line Relationship Rules:
| If You Have | You Can Synthetically Create | How |
|---|---|---|
| LONG -0.5 + LONG -1.5 | LONG -1.0 | Average the positions |
| SHORT -1.0 | LONG +1.0 (same team) | Flip the sign |
| LONG Team A -1.0 | SHORT Team B +1.0 | Opposite team |
Cross-Line Synthetic Matching
The synthetic matching engine can match across handicap lines:
Push Outcome Handling
Whole-goal lines can result in a "push" where stakes are returned:
Push Implementation:
| Aspect | How We Handle It |
|---|---|
| Order Matching | Normal LONG/SHORT matching |
| Position Tracking | Track push-eligible lines |
| Settlement | Three-way: Win, Lose, or Push |
| Collateral | Full collateral still required |
Complete Asian Handicap Support Matrix
Full Feature List:
| Feature | Support | Implementation |
|---|---|---|
| Half-goal lines | ✅ Native | Standard binary outcome |
| Whole-goal lines | ✅ Native | Push-aware three-way outcome |
| Quarter-goal lines | ✅ Native | Atomic split order type |
| Direct matching | ✅ Native | Standard LONG/SHORT |
| Cross-line synthetic | ✅ Native | Adjacent line aggregation |
| Cross-team synthetic | ✅ Native | Sign-flip equivalence |
| Push settlement | ✅ Native | Three-way settlement plugin |
| Split settlement | ✅ Native | Per-leg settlement aggregation |
Part VII: Multi-Representation Framework
The Problem: Different Domains, Different Languages
Every asset class speaks a different language:
The Challenge: How do we build one engine that speaks all these languages?
The Solution: Representation Adapters
The Universal Order Book uses adapters to translate between domain-specific representations and the internal universal model:
Diagram Explanation:
| Layer | Purpose | Example |
|---|---|---|
| External API | Domain-specific interface | "BACK at 2.50 odds" |
| Adapter | Translation layer | 2.50 odds → 400,000 BP |
| Universal Core | Internal representation | Basis points (BP) |
Internal Price Representation
Internally, all prices are stored as basis points (1/10,000th units) to avoid floating-point issues:
Conversion Table:
| Representation | Example | To Basis Points | Formula |
|---|---|---|---|
| Decimal Odds | 2.50 | 400,000 BP | 1,000,000 / odds |
| Percentage | 40% | 400,000 BP | percentage × 10,000 |
| American + | +150 | 400,000 BP | 1,000,000 / (1 + american/100) |
| American - | -200 | 666,667 BP | 1,000,000 × abs(american) / (100 + abs(american)) |
| Fractional | 3/2 | 400,000 BP | 1,000,000 / (1 + numerator/denominator) |
| USD Price | $150.25 | 1,502,500 BP | price × 10,000 |
Representation Adapter Interface
Each adapter implements a standard interface:
Adapter Methods:
| Method | Purpose | Example (Odds) |
|---|---|---|
toInternal | Convert to basis points | 2.50 → 400,000 |
toExternal | Convert from basis points | 400,000 → 2.50 |
validatePrice | Check if price is valid | 0.99 → false (< 1.0) |
formatForDisplay | Human-readable string | 400,000 → "2.50" |
getTickSize | Minimum price increment | 100 BP (0.01 odds) |
roundToTick | Snap to valid tick | 2.503 → 2.50 |
Tick Sizes and Price Grids
Different representations have different tick sizes:
Why Variable Ticks?
| Reason | Explanation |
|---|---|
| Meaningful Increments | 0.01 difference at 1.50 odds matters; at 100 odds, it doesn't |
| Reduce Noise | Fewer valid prices = less queue jumping |
| Match Industry Standards | Betfair uses this grid; traders expect it |
Hybrid Markets: Mixing Representations
The most powerful feature: a single market can support multiple representations simultaneously:
Diagram Explanation:
| Interface | User Sees | Internal | Translation |
|---|---|---|---|
| Betting | BACK @ 1.80 | LONG @ 555,556 BP | 1/1.80 = 55.6% |
| Prediction | YES @ 55¢ | LONG @ 550,000 BP | Direct |
| Trading | BUY @ $0.55 | LONG @ 550,000 BP | × 10,000 |
The Key Insight: All three interfaces are contributing to the same liquidity pool. A prediction market trader and a bettor can match against each other without knowing it!
Cross-Representation Matching
Representation Configuration Per Market
Markets can be configured with allowed representations:
Configuration Options:
| Setting | Options | Example |
|---|---|---|
| Primary Representation | Odds, Price, Percentage | Odds for betting |
| Allowed Representations | List of enabled adapters | [Odds, Percentage] |
| Default for Display | Which to show by default | Odds |
| Tick Grid | Which tick structure | Betfair-style |
Part VIII: Universal Data Model
Entity Hierarchy
The data model is organized in a clear hierarchy:
Entity Descriptions:
| Entity | Purpose | Cardinality |
|---|---|---|
| Platform | Root container | 1 |
| Asset Class | Type of tradeable | Many (betting, stocks, etc.) |
| Event | Real-world occurrence | Many per asset class |
| Market | Trading venue for event | Many per event |
| Outcome | Possible result | Many per market |
| Order Book | LONG + SHORT queues | 1 per outcome |
| Price Level | Orders at same price | Many per book |
| Order | Individual order | Many per level |
Core Entities
Event
| Field | Type | Description |
|---|---|---|
event_id | UUID | Unique identifier |
name | String | Event name |
asset_class | AssetClass | Type of asset |
start_time | Timestamp | When event starts |
end_time | Timestamp | When event ends |
status | EventStatus | SCHEDULED, LIVE, CLOSED, SETTLED |
metadata | Map | Additional properties |
markets | List | Markets for this event |
Market
| Field | Type | Description |
|---|---|---|
market_id | UUID | Unique identifier |
event_id | UUID | Parent event |
market_type | MarketType | Type of market |
name | String | Market name |
status | MarketStatus | OPEN, SUSPENDED, CLOSED |
representations | List | Supported price formats |
tick_grid | TickGrid | Valid price increments |
synthetic_enabled | Boolean | Allow synthetic matching |
settlement_type | SettlementType | How to settle |
relationship_type | RelationshipType | MUTUALLY_EXCLUSIVE, COMPLEMENTARY, ORDERED, INDEPENDENT |
outcomes | List | Possible outcomes |
Outcome
| Field | Type | Description |
|---|---|---|
outcome_id | UUID | Unique identifier |
market_id | UUID | Parent market |
name | String | Outcome name |
status | OutcomeStatus | ACTIVE, SUSPENDED, WON, LOST, VOID |
long_book | BTreeMap | Orders betting FOR |
short_book | BTreeMap | Orders betting AGAINST |
total_matched | Amount | Total volume matched |
volume_24h | Amount | 24-hour volume |
last_matched_price | Price | Most recent trade price |
Order
| Field | Type | Description |
|---|---|---|
order_id | UUID | Unique identifier |
client_order_id | String | Client-provided ID |
sequence_number | u64 | Global sequence for ordering |
outcome_id | UUID | Which outcome |
direction | Direction | LONG or SHORT |
price | BasisPoints | Internal price (0-1,000,000) |
quantity | Amount | Size of order |
filled_quantity | Amount | How much has matched |
status | OrderStatus | PENDING, OPEN, PARTIALLY_FILLED, FILLED, CANCELLED |
created_at | Timestamp | When created |
updated_at | Timestamp | Last modification |
expires_at | Timestamp | Optional expiration |
order_type | OrderType | LIMIT, MARKET, IOC, FOK |
time_in_force | TimeInForce | GTC, GTD, IOC, FOK |
parent_order_id | UUID | For composite orders (quarter-lines) |
legs | List | Order legs for composite orders |
State Machine: Order Lifecycle
State Transitions:
| From | To | Trigger |
|---|---|---|
| PENDING | OPEN | Order passes validation |
| PENDING | REJECTED | Invalid price, quantity, etc. |
| OPEN | PARTIALLY_FILLED | Matched some quantity |
| OPEN | FILLED | Matched all quantity |
| OPEN | CANCELLED | Cancel request |
| OPEN | EXPIRED | TTL exceeded |
| PARTIALLY_FILLED | FILLED | Remaining matched |
| PARTIALLY_FILLED | CANCELLED | Cancel remainder |
State Machine: Market Lifecycle
Indexing Strategy
For fast lookups, we maintain multiple indexes:
Index Performance:
| Lookup | Index Used | Time Complexity |
|---|---|---|
| Order by ID | Primary HashMap | O(1) |
| Order by client ID | by_client_order | O(1) |
| User's orders | by_user | O(1) + O(orders) |
| Best price | OrderBook BTree | O(1) first element |
| All at price | PriceLevel queue | O(1) |
Part IX: Matching Algorithm
Matching Priority: Price-Time with Synthetic
The matching algorithm follows this priority:
Priority Rules:
| Priority | Rule | Rationale |
|---|---|---|
| 1. Price | Better price always wins | Fair to liquidity providers |
| 2. Direct | Direct match before synthetic | Simpler, faster execution |
| 3. Time | FIFO within same price | Rewards early liquidity |
Direct Matching Flow
Synthetic Matching Flow
Synthetic Matching: Mutually Exclusive Example
For a 3-way market (Home/Draw/Away):
Trade Execution
When a match occurs, trades are created:
Matching Invariants
These invariants must ALWAYS hold:
Invariant Enforcement:
| Invariant | Enforcement Mechanism |
|---|---|
| No crossed books | Match any crossable orders immediately |
| Price improvement | Execute at resting order's price |
| Quantity conservation | Atomic update of both orders |
| Atomic execution | Transaction around synthetic |
| No self-trade | Check user_id before matching |
| Deterministic | Single-threaded, no randomness |
Part X: Scope & Boundaries
What the Order Book Does
The Order Book has one job: match orders. It does this job extremely well.
What the Order Book Does NOT Do
These are explicitly NOT the Order Book's responsibility:
Clear Separation of Concerns
The Contract
| Component | Input | Output | Guarantees |
|---|---|---|---|
| Backend → Order Book | Pre-validated orders | Trade events | Orders have valid balance |
| Order Book → Backend | Trade events | Settlement actions | Events are durable, ordered |
| Backend → User | Settlement results | Fund transfers | Correct payouts |
Why This Separation?
| Concern | Why NOT in Order Book | Benefit |
|---|---|---|
| Settlement | Different per asset class, needs oracle integration | Order Book stays generic |
| Balance | Requires user context, database access | Order Book stays fast |
| Auth | Security boundary, needs tokens | Order Book stays simple |
| Risk | Business rules, compliance | Order Book stays focused |
The Order Book is a pure matching engine. It receives pre-validated orders and produces deterministic trade events. Everything else is the Backend's responsibility.
Part XI: System Architecture
High-Level Component Diagram
Component Descriptions:
| Component | Responsibility | Scaling |
|---|---|---|
| gRPC Gateway | Order submission, queries | Horizontal |
| WebSocket Gateway | Real-time streaming | Horizontal |
| Market Router | Route to correct engine shard | Horizontal |
| Sequencer | Assign global sequence numbers | Single (HA pair) |
| Event Journal | Durable event log | Replicated |
| Matching Engine | Core matching logic | Sharded by market |
| Synthetic Engine | Cross-outcome matching | Per shard |
| Settlement Engine | Position settlement | Horizontal |
Data Flow: Order Lifecycle
Sharding Strategy
For horizontal scaling, markets are sharded:
Sharding Rules:
| Rule | Implementation | Benefit |
|---|---|---|
| Shard by Market | hash(market_id) mod N | Related orders go to same shard |
| Event Affinity | All markets for event on same shard | Enables cross-market synthetic |
| Hot Market Isolation | Popular markets get dedicated shard | Prevent hotspots |
| Dynamic Rebalancing | Move markets between shards | Handle load changes |
Event Sourcing Architecture
Part XII: The Pipeline - Detailed Architecture
The Five-Stage Pipeline
The heart of the Universal Order Book is a deterministic pipeline inspired by the LMAX Disruptor architecture:
Pipeline Stages:
| Stage | Component | Responsibility | Threading |
|---|---|---|---|
| 1. Gateway | gRPC/WebSocket | Accept connections, validate format | Multi-threaded |
| 2. Sequencer | Monotonic Counter | Assign global ordering | Single-threaded |
| 3. Journal | Append-only Log | Durability before processing | Single-threaded |
| 4. Engine | Matching Core | Match orders, update state | Single-threaded |
| 5. Publisher | Event Fan-out | Notify subscribers | Multi-threaded |
The Danger Zone: Durability Boundary
The critical insight: never acknowledge until durable.
The Guarantee:
| Crash Point | Client Received ACK? | Order Status |
|---|---|---|
| Before fsync | No | Lost (client retries) |
| During fsync | No | Lost (client retries) |
| After fsync, before engine | Yes | Will be replayed |
| After engine | Yes | Processed, will be replayed |
Sequencer: The Source of Truth
Sequence Number Rules:
| Rule | Explanation |
|---|---|
| Monotonic | Each number > previous, always |
| Gapless | 1, 2, 3, 4... never 1, 2, 4 |
| Global | Same sequence across all markets |
| Persistent | Counter saved to disk, restored on restart |
Part XIII: Durability & Recovery
The Event Journal
The journal is an append-only log that records every event before processing:
Journal Entry Format
Each journal entry has a self-describing binary format:
Field Descriptions:
| Field | Size | Purpose |
|---|---|---|
| Magic | 4 bytes | Identifies valid entry (0xORDRBOOK) |
| Version | 1 byte | Format version for upgrades |
| Length | 4 bytes | Total entry size for seeking |
| Sequence | 8 bytes | Global sequence number |
| EventType | 2 bytes | OrderReceived, TradeExecuted, etc. |
| Timestamp | 8 bytes | Nanosecond precision |
| Payload | Variable | Protobuf-encoded event data |
| CRC32 | 4 bytes | Corruption detection |
The fsync Barrier
The fsync call is the durability boundary:
fsync Strategies:
| Strategy | Latency | Durability | Use Case |
|---|---|---|---|
| Every write | ~1-5ms | Maximum | Production |
| Batched (10ms) | ~0.5ms avg | High | High throughput |
| Async | ~0.1ms | Low | Development only |
Crash Recovery Process
Recovery Timeline:
| Phase | Time | What Happens |
|---|---|---|
| Load Snapshot | ~100ms | Restore state to sequence N |
| Replay Journal | ~2ms/1000 events | Apply events N+1 to current |
| Verify State | ~10ms | Hash comparison |
| Total | < 3 seconds | For 1M events |
Snapshot Strategy
Snapshots accelerate recovery by checkpointing state:
Snapshot Retention:
| Policy | Keep | Purpose |
|---|---|---|
| Latest | Always | Fast recovery |
| Hourly | 24 hours | Recent rollback |
| Daily | 7 days | Investigation |
| Weekly | 4 weeks | Audit |
Part XIV: Kubernetes & Deployment
Production Topology
Pod Specifications
Order Book Pod
Resource Configuration:
| Resource | Request | Limit | Rationale |
|---|---|---|---|
| CPU | 2 cores | 4 cores | Single-threaded + headroom |
| Memory | 4Gi | 8Gi | Order books + journal buffer |
| Storage | 100Gi | N/A | Journal + snapshots |
| IOPS | 10,000 | N/A | fsync performance |
Persistent Volume Configuration
Storage Requirements:
| Mount | Size | I/O Pattern | Backup |
|---|---|---|---|
/data/journal | 80Gi | Sequential write | Continuous |
/data/snapshots | 20Gi | Periodic write | Hourly to S3 |
/config | 1Gi | Read-only | ConfigMap |
High Availability Strategy
Availability Targets:
| Metric | Target | Measurement |
|---|---|---|
| Uptime | 99.9% | 8.7 hours/year downtime |
| RTO | < 30 seconds | Time to recover |
| RPO | 0 | No data loss |
| Failover | Automatic | K8s handles |
Deployment Strategy
Deployment Checklist:
| Step | Action | Rollback |
|---|---|---|
| 1 | Announce maintenance window | N/A |
| 2 | Stop accepting new orders | Resume |
| 3 | Drain pending orders | Wait |
| 4 | Take snapshot | N/A |
| 5 | Deploy new version | Revert image |
| 6 | Replay and verify | Use old snapshot |
| 7 | Resume trading | Rollback |
Part XV: Operations & Monitoring
Observability Stack
Key Metrics
Critical Metrics:
| Metric | Alert Threshold | Severity |
|---|---|---|
matching_latency_p99 | > 100ms | Critical |
journal_write_latency_p99 | > 50ms | Critical |
memory_used_bytes | > 80% limit | Warning |
events_per_second | < 100 for 5min | Warning |
up | 0 | Critical |
sequence_number | Not increasing | Critical |
Grafana Dashboards
Dashboard Panels:
| Dashboard | Key Panels |
|---|---|
| Overview | Status, Orders/sec, P99 latency, Error rate |
| Performance | Latency histograms, Throughput, Queue depth |
| Business | Trade volume, Spread, Book depth, Active orders |
| System | CPU, Memory, Disk I/O, Network |
| Debug | Sequence gaps, Journal segments, Match breakdown |
Alerting Rules
Runbook: Common Issues
Part XVI: Security
Security Model
The Universal Order Book operates on a defense in depth model:
Trust Boundaries
Trust Levels:
| Zone | Trust Level | Access |
|---|---|---|
| Untrusted | None | Public internet |
| DMZ | Limited | Filtered traffic |
| Trusted | High | Internal services only |
Security Measures
| Measure | Implementation | Purpose |
|---|---|---|
| Network Isolation | Private subnet, no public IP | Reduce attack surface |
| mTLS | Mutual TLS between services | Authenticate both parties |
| Input Validation | Protobuf schema + business rules | Prevent injection |
| Self-Trade Prevention | Check user_id before match | Prevent wash trading |
| Rate Limiting | At gateway level | Prevent DoS |
| Audit Logging | All events journaled | Forensics, compliance |
What Order Book Does NOT Handle
| Security Function | Handled By | Reason |
|---|---|---|
| User authentication | Backend | Separation of concerns |
| Password management | Backend | Order Book has no user concept |
| Balance validation | Backend | Order Book trusts pre-validation |
| Fraud detection | Backend + ML | Requires user context |
| KYC/AML | Backend | Regulatory requirement |
Part XVII: Testing Strategy
Test Pyramid
Test Distribution:
| Level | Count | Time | Coverage |
|---|---|---|---|
| Unit | ~2000 | 30s | Core logic, adapters |
| Integration | ~200 | 2min | Journal, matching, recovery |
| E2E | ~50 | 5min | Full flow with backend |
Critical Test Scenarios
Scenario Details:
| Scenario | What We Test | How |
|---|---|---|
| Crash Recovery | State after replay = state before crash | Inject crash, compare hashes |
| Synthetic Matching | Implied odds calculated correctly | Property-based tests |
| Asian Handicap | Push, half-win, half-lose settle correctly | Exhaustive scenarios |
| Multi-Rep | Odds trader matches percentage trader | Cross-format test suite |
| Self-Trade | Same user_id orders don't match | Inject self-crossing orders |
| Sequence Gaps | Gaps detected, processing halted | Remove journal entries |
Property-Based Testing
Determinism Testing
The Determinism Guarantee:
Given the same sequence of input events, the engine MUST produce the exact same output, regardless of when or where it runs.
Part XVIII: Asset Class Implementations
Supported Asset Classes
The Universal Order Book supports these asset classes out of the box:
Sports Betting Adapter
Prediction Markets Adapter
Options Adapter
Futures Adapter
Asset Class Comparison
| Feature | Betting | Prediction | Equity | Options | Futures |
|---|---|---|---|---|---|
| Terminology | BACK/LAY | YES/NO | BUY/SELL | BUY/SELL | LONG/SHORT |
| Price Unit | Odds | Cents | Currency | Premium | Price |
| Sizing | Stake | Shares | Shares | Contracts | Contracts |
| Expiry | Event time | Resolution | None | Fixed date | Fixed date |
| Settlement | Binary | Binary | Trade-out | Exercise | Delivery/Cash |
| Margin | Full stake | Full cost | T+2 | Premium + margin | Margin |
| Synthetic | Multi-runner | Multi-outcome | N/A | Put-Call parity | Calendar spread |
Part XIX: Extensibility & Plugins
Plugin Architecture Overview
The Universal Order Book is designed for extensibility through well-defined plugin interfaces:
Adding a New Asset Class
To add support for a new asset class:
Plugin Interface Contracts
RepresentationPlugin Interface
| Method | Parameters | Returns | Description |
|---|---|---|---|
toInternal | external price | BasisPoints | Convert to internal format |
toExternal | internal price | ExternalPrice | Convert to display format |
validate | price | Result | Validate price is valid |
getTickGrid | none | TickGrid | Get valid price increments |
format | price | String | Format for display |
SettlementPlugin Interface
| Method | Parameters | Returns | Description |
|---|---|---|---|
getSettlementType | none | Type | Get settlement type |
calculatePayout | position, result | Amount | Calculate winnings |
validateSettlement | market | Result | Validate settlement valid |
getRequiredCollateral | order | Amount | Collateral needed |
ValidationPlugin Interface
| Method | Parameters | Returns | Description |
|---|---|---|---|
validateOrder | order | Result | Validate order is valid |
validateMarket | market | Result | Validate market config |
getConstraints | none | Constraints | Get validation rules |
SyntheticPlugin Interface
| Method | Parameters | Returns | Description |
|---|---|---|---|
canSyntheticMatch | market | Boolean | Is synthetic enabled |
calculateSynthetic | order, books | Match | Find synthetic match |
getRelatedOutcomes | outcome | Outcomes | Get complementary outcomes |
Configuration-Driven Markets
Markets are created via configuration, not code:
Part XX: Performance Considerations
Performance vs Flexibility Trade-offs
Adding universality introduces overhead. Here's how we minimize it:
Performance Targets
| Metric | SmartBets Design | Universal Design | Overhead |
|---|---|---|---|
| Throughput | 10,000 orders/sec | 8,000 orders/sec | 20% |
| P50 Latency | 5ms | 6ms | 20% |
| P99 Latency | 50ms | 60ms | 20% |
| Memory per market | 500KB | 600KB | 20% |
| Recovery time | 2 seconds | 2.5 seconds | 25% |
Note: The overhead is acceptable given the massive increase in flexibility.
Optimization Strategies
Benchmarking Approach
Part XXI: Comparison: SmartBets vs Universal
Feature Comparison
| Feature | SmartBets Design | Universal Design |
|---|---|---|
| Market Model | Binary (BACK/LAY) | N-outcome |
| Synthetic Matching | ❌ None | ✅ Full |
| Asian Handicap | ⚠️ Workarounds | ✅ Native |
| Multi-Runner | ❌ Separate markets | ✅ Single market |
| Asset Classes | Betting only | Any asset |
| Representations | Odds only | Pluggable |
| Settlement | Backend handles | Pluggable plugins |
| Complexity | Simple | More complex |
| Performance | Optimal | ~20% overhead |
Architecture Comparison
When to Use Which
Decision Guide:
| Scenario | Recommendation |
|---|---|
| Sports betting only, simple markets | SmartBets Design |
| Need Asian Handicap, multi-runner | Universal Design |
| Future expansion to other assets | Universal Design |
| Maximum performance critical | SmartBets Design |
| Platform play / multi-vertical | Universal Design |
Part XXII: FAQ
General Questions
Q: Why not just use separate systems for different asset classes?
A: Maintenance burden, duplicated logic, inconsistent behavior. One universal engine means one codebase, one ops team, one set of guarantees.
Q: How does synthetic matching affect latency?
A: Synthetic matching only runs when direct matching fails. Direct matches are unchanged. Synthetic adds ~10ms for 3-way markets, ~20ms for 10+ runners.
Q: Can I use the Universal design for SmartBets?
A: Yes! Configure it with sports_betting asset class, BACK/LAY representation, and disable synthetic matching. You get the SmartBets behavior with future expansion capability.
Asian Handicap Questions
Q: How are quarter-goal lines stored?
A: As atomic composite orders. The user submits one order, but internally it's stored as two linked legs on adjacent half-goal lines.
Q: What happens if only one leg of a quarter-goal matches?
A: Both legs must match or neither does. Quarter-goal orders are "all-or-nothing" at the order level (though they can partial fill proportionally).
Q: How does push settlement work?
A: The settlement plugin recognizes when the final margin equals the handicap line exactly, and returns the stake instead of paying out or deducting.
Synthetic Matching Questions
Q: Can synthetic matching create arbitrage?
A: No, it eliminates arbitrage. If prices across outcomes allow risk-free profit, synthetic matching will immediately match those orders.
Q: How fast is synthetic calculation?
A: For a 3-way market: ~1ms. For a 10-runner: ~5ms. For complex Asian Handicap lines: ~3ms. All acceptable.
Q: What if someone games the synthetic engine?
A: Synthetic trades execute at fair prices calculated from the book. There's no information asymmetry to exploit.
Representation Questions
Q: Can the same user use different representations?
A: Yes! User A can submit in odds, User B in percentages. They'll match against each other seamlessly.
Q: How do tick sizes work across representations?
A: Each representation has its own tick grid. Prices are validated in the representation's grid, then converted to basis points for matching.
Q: What about rounding errors?
A: Basis points provide sufficient precision for all representations. Any display rounding is purely cosmetic.
Extension Questions
Q: How do I add a new asset class?
A: Implement the four plugin interfaces (representation, settlement, validation, synthetic), register in the plugin registry, and create market configurations.
Q: Can plugins be loaded at runtime?
A: Yes, the plugin registry supports dynamic loading. However, for performance, we recommend compile-time registration for known asset classes.
Part XXIII: Glossary
| Term | Definition |
|---|---|
| Adapter | Component that translates between external representation and internal model |
| Asian Handicap | Betting market type that applies a goal handicap to level the playing field |
| Atomic Order | Order that appears as one to user but internally consists of multiple linked legs |
| Basis Points (BP) | Internal price unit; 10,000 BP = 1% probability or 1.00 currency unit |
| Complementary Outcomes | Two outcomes that sum to 100% (e.g., Over/Under) |
| Direct Match | Match between orders on the same outcome's opposing books |
| Event | Real-world occurrence that markets are based on |
| Half-Goal Line | Asian Handicap line ending in .5 (e.g., -0.5, -1.5) |
| Implied Probability | Probability derived from odds: 1/odds |
| LONG | Universal direction: profit if outcome occurs |
| Market | Trading venue for a specific aspect of an event |
| Multi-Runner | Market with more than 2 outcomes (e.g., horse race) |
| Mutually Exclusive | Outcomes where exactly one must occur |
| Outcome | Possible result within a market |
| Overround | Sum of implied probabilities across all outcomes; >100% means house edge |
| Plugin | Modular component implementing a specific interface |
| Price-Time Priority | Matching rule: better price first, then earlier time |
| Push | Settlement result where stakes are returned (no win/loss) |
| Quarter-Goal Line | Asian Handicap line ending in .25 or .75 |
| Representation | How prices are displayed (odds, percentage, currency) |
| Settlement | Process of determining and executing payouts |
| SHORT | Universal direction: profit if outcome doesn't occur |
| Synthetic Match | Match created by combining orders across related outcomes |
| Ternary Settlement | Settlement with three outcomes: win, lose, or void |
| Tick Grid | Valid price levels for a representation |
| Whole-Goal Line | Asian Handicap line without decimal (e.g., 0, -1, -2) |
Appendix A: Mermaid Diagram Index
For quick reference, this document contains the following diagrams:
| Part | Diagram | Description |
|---|---|---|
| I | Mind Map | Universal Order Book capabilities |
| II | Flowchart | Abstraction ladder |
| II | Table | Direction mapping across domains |
| III | Flowchart | Universal position model |
| III | Flowchart | Outcome hierarchy |
| III | Flowchart | Outcome relationships |
| IV | Flowchart | Multi-outcome model comparison |
| IV | Flowchart | Market types taxonomy |
| IV | Flowchart | Per-outcome order books |
| IV | Flowchart | Overround explanation |
| V | Flowchart | With vs without synthetic |
| V | Flowchart | Synthetic equivalence |
| V | Sequence | Synthetic matching process |
| V | Flowchart | 3-way market synthetic example |
| V | Flowchart | Synthetic benefits |
| VI | Flowchart | Asian Handicap types |
| VI | Flowchart | Quarter-goal atomic orders |
| VI | Flowchart | Handicap line relationships |
| VI | Sequence | Cross-line synthetic matching |
| VI | Flowchart | Push outcome handling |
| VI | Flowchart | Asian Handicap feature matrix |
| VII | Flowchart | Different domain languages |
| VII | Flowchart | Representation adapters |
| VII | Flowchart | Internal price representation |
| VII | Flowchart | Adapter interface |
| VII | Flowchart | Tick sizes |
| VII | Flowchart | Hybrid markets |
| VII | Sequence | Cross-representation matching |
| VII | Flowchart | Market representation config |
| VIII | Flowchart | Entity hierarchy |
| VIII | Flowchart | Event entity |
| VIII | Flowchart | Market entity |
| VIII | Flowchart | Outcome entity |
| VIII | Flowchart | Order entity |
| VIII | State Diagram | Order lifecycle |
| VIII | State Diagram | Market lifecycle |
| VIII | Flowchart | Indexing strategy |
| IX | Flowchart | Matching priority |
| IX | Flowchart | Direct matching flow |
| IX | Flowchart | Synthetic matching flow |
| IX | Flowchart | Mutually exclusive example |
| IX | Sequence | Trade execution |
| IX | Flowchart | Matching invariants |
| X | Flowchart | Order Book responsibilities |
| X | Flowchart | What Order Book does NOT do |
| X | Sequence | Separation of concerns |
| XI | Flowchart | System components |
| XI | Sequence | Order lifecycle data flow |
| XI | Flowchart | Sharding strategy |
| XI | Flowchart | Event sourcing |
| XII | Flowchart | Five-stage pipeline |
| XII | Sequence | Danger zone - durability boundary |
| XII | Flowchart | Sequencer properties |
| XIII | Flowchart | Journal structure |
| XIII | Flowchart | Journal entry format |
| XIII | Flowchart | fsync barrier |
| XIII | Flowchart | Crash recovery process |
| XIII | Flowchart | Snapshot strategy |
| XIV | Flowchart | Kubernetes production topology |
| XIV | Flowchart | Order Book pod specification |
| XIV | Flowchart | Persistent volume configuration |
| XIV | Flowchart | High availability strategy |
| XIV | Flowchart | Blue-green deployment |
| XV | Flowchart | Observability stack |
| XV | Flowchart | Key metrics categories |
| XV | Flowchart | Dashboard hierarchy |
| XV | Flowchart | Alert severity levels |
| XV | Flowchart | Common issues runbook |
| XVI | Flowchart | Security layers |
| XVI | Flowchart | Trust boundaries |
| XVII | Flowchart | Test pyramid |
| XVII | Flowchart | Critical test scenarios |
| XVII | Flowchart | Property-based testing |
| XVII | Flowchart | Determinism verification |
| XVIII | Flowchart | Asset class adapters |
| XVIII | Flowchart | Sports betting adapter |
| XVIII | Flowchart | Prediction markets adapter |
| XVIII | Flowchart | Options adapter |
| XVIII | Flowchart | Futures adapter |
| XIX | Flowchart | Plugin architecture |
| XIX | Flowchart | Adding new asset class |
| XIX | Flowchart | Plugin interfaces |
| XIX | Flowchart | Configuration-driven markets |
| XX | Flowchart | Performance concerns |
| XX | Flowchart | Optimization strategies |
| XX | Flowchart | Benchmarking approach |
| XXI | Flowchart | Architecture comparison |
| XXI | Flowchart | Decision guide |
Appendix B: Frequently Asked Questions - Deep Dive
This appendix provides detailed, layman-friendly explanations for common questions about the Universal Order Book architecture.
B.1: The Balance Race Condition Problem
The Question
"If the backend checks user balance, it's fine, then gives the order to the order book. While the order is in the order book, another order from the same user comes that also reaches the order book after the backend checks. Now at the time of matching, the user doesn't have sufficient funds but the order is still matched. Should the backend check again after matching, or just pass it to Solana?"
The Problem Visualized
Imagine this scenario:
Timeline:
─────────────────────────────────────────────────────────────────────►
User has $100 in their account
T1: User submits Order A for $80
Backend checks: $100 >= $80? ✓ YES
Backend sends Order A to Order Book
T2: User submits Order B for $50
Backend checks: $100 >= $50? ✓ YES (balance hasn't changed yet!)
Backend sends Order B to Order Book
T3: Order Book matches Order A ($80)
T4: Order Book matches Order B ($50)
PROBLEM: User committed $130 but only had $100!
This is called a race condition - two processes (Order A and Order B) are racing, and the result depends on timing.
Why "Check Again After Match" Doesn't Work
You might think: "Just check the balance again when the trade comes back."
Problem: The trade already happened! The counterparty was told their order matched. You can't "un-match" a trade.
If we reject Order B after matching:
User A: "I matched with User B!"
User B: "Actually, nevermind, User B didn't have money"
User A: "But you told me the trade happened!"
This breaks trust in the entire system.
The Solution: LOCK, Don't Just CHECK
The correct approach is to lock (escrow) funds at submission time, not just check them.
WRONG APPROACH: Check
──────────────────────────
"Do you have $80?" → "Yes" → Continue
(But the $80 is still available for other orders!)
RIGHT APPROACH: Lock
──────────────────────────
"Reserve $80 now" → Money moved to locked state → Continue
(Now only $20 is available for other orders!)
The Correct Flow
Timeline with LOCKING:
─────────────────────────────────────────────────────────────────────►
User has: Available = $100, Locked = $0
T1: User submits Order A for $80
Backend LOCKS $80
User now has: Available = $20, Locked = $80
Backend sends Order A to Order Book
T2: User submits Order B for $50
Backend tries to lock $50
Available is only $20
$20 < $50 → REJECTED immediately!
Order B never reaches Order Book
T3: Order Book matches Order A ($80)
No problem - funds were already secured
RESULT: No race condition possible!
Balance States Explained
Think of your money like physical locations:
┌─────────────────────────────────────────────────────────────────────┐
│ YOUR ACCOUNT ($100 total) │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ AVAILABLE │ │ LOCKED │ │ IN POSITION │ │
│ │ │ │ (Escrowed) │ │ (At Risk) │ │
│ │ $100 │ │ $0 │ │ $0 │ │
│ │ │ │ │ │ │ │
│ │ Can place │ │ Reserved │ │ Committed │ │
│ │ new orders │ │ for pending │ │ to matched │ │
│ │ │ │ orders │ │ bets │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
When you place an order:
BEFORE placing $80 order:
├── Available: $100
├── Locked: $0
└── In Position: $0
AFTER order submitted (before match):
├── Available: $20 ← Reduced immediately!
├── Locked: $80 ← Reserved for this order
└── In Position: $0
AFTER order matches:
├── Available: $20
├── Locked: $0 ← Released
└── In Position: $80 ← Now at risk in the bet
What About Partial Fills?
If your $80 order only partially fills (say, $50 matches):
AFTER partial match ($50 of $80):
├── Available: $20
├── Locked: $30 ← Remaining unmatched portion
└── In Position: $50 ← Matched portion
If you CANCEL the remaining $30:
├── Available: $50 ← $30 returned!
├── Locked: $0
└── In Position: $50
The Answer to Your Question
| Question | Answer |
|---|---|
| Should backend check again after trade? | NO |
| Should it pass to Solana to check? | NO |
| What should backend do instead? | LOCK funds at submission time |
| Why? | Race condition is prevented before it can happen |
Summary
┌─────────────────────────────────────────────────────────────────────┐
│ THE GOLDEN RULE │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ Never just CHECK a balance - always LOCK it. │
│ │
│ Checking = "Do you have money?" (informational) │
│ Locking = "I'm taking this money now" (transactional) │
│ │
│ The Order Book only receives pre-funded orders. │
│ The money question is settled BEFORE matching. │
│ │
└─────────────────────────────────────────────────────────────────────┘
B.2: Asian Handicaps Explained for Complete Beginners
What Problem Does Asian Handicap Solve?
Imagine you want to bet on a football match: Manchester City vs Norwich City.
Everyone knows Man City is much stronger. The traditional odds might be:
| Outcome | Odds | What It Means |
|---|---|---|
| Man City Win | 1.10 | Bet $100, win only $10 |
| Draw | 8.00 | Bet $100, win $700 |
| Norwich Win | 25.00 | Bet $100, win $2400 |
The problem: Man City at 1.10 is a terrible bet. You risk $100 to win $10. Even if they're 90% likely to win, one loss wipes out nine wins!
The Asian Handicap Solution
Idea: Give Norwich a "head start" to make it fair.
Instead of betting "Man City wins", you bet "Man City wins by MORE than 2 goals".
This is written as: Man City -2 or equivalently Norwich +2
How to Read Handicap Lines
Norwich +2 means:
"Add 2 goals to Norwich's final score, THEN see who wins"
Example: Real score is Man City 3 - 0 Norwich
Adjusted score: Man City 3 - 2 Norwich
Man City still "wins" the handicap bet
Example: Real score is Man City 2 - 0 Norwich
Adjusted score: Man City 2 - 2 Norwich
It's a TIE! This is called a PUSH.
The Full Range of Handicap Lines
Let's say Man City beats Norwich 2-0. Here's what happens with different handicaps:
| Handicap | Norwich's Adjusted Score | Result |
|---|---|---|
| Norwich +0 | 2-0 | Man City backers WIN |
| Norwich +0.5 | 2-0.5 | Man City backers WIN |
| Norwich +1 | 2-1 | Man City backers WIN |
| Norwich +1.5 | 2-1.5 | Man City backers WIN |
| Norwich +2 | 2-2 | PUSH (money returned) |
| Norwich +2.5 | 2-2.5 | Norwich backers WIN! |
| Norwich +3 | 2-3 | Norwich backers WIN |
Why Half-Goals Exist (+0.5, +1.5, +2.5)
You can't score half a goal in football. So half-goal lines eliminate ties.
With +2 handicap:
- 2-0 final → 2-2 adjusted → PUSH (tie, money back)
With +2.5 handicap:
- 2-0 final → 2-2.5 adjusted → Norwich "wins" (no tie possible)
Half-goal = guaranteed winner, no push
Quarter-Goal Lines (+0.25, +0.75, +1.25, etc.)
Sometimes +2 feels too tight and +2.5 feels too generous. Quarter-goals split the difference.
Here's the secret: A quarter-goal line is actually TWO BETS combined!
Norwich +2.25 means:
├── 50% of your stake on Norwich +2
└── 50% of your stake on Norwich +2.5
It's NOT a real line - it's shorthand for two bets!
Quarter-Goal Outcomes Explained
Let's say you bet $100 on Norwich +2.25 at odds of 1.90:
Scenario 1: Man City wins 1-0
| Leg | Handicap | Adjusted | Result | Payout |
|---|---|---|---|---|
| Leg 1 ($50) | +2 | 1-2 | Norwich WIN | $50 × 1.90 = $95 |
| Leg 2 ($50) | +2.5 | 1-2.5 | Norwich WIN | $50 × 1.90 = $95 |
| Total | FULL WIN | $190 (profit $90) |
Scenario 2: Man City wins 2-0
| Leg | Handicap | Adjusted | Result | Payout |
|---|---|---|---|---|
| Leg 1 ($50) | +2 | 2-2 | PUSH | $50 back |
| Leg 2 ($50) | +2.5 | 2-2.5 | Norwich WIN | $50 × 1.90 = $95 |
| Total | HALF WIN | $145 (profit $45) |
Scenario 3: Man City wins 3-0
| Leg | Handicap | Adjusted | Result | Payout |
|---|---|---|---|---|
| Leg 1 ($50) | +2 | 3-2 | City WIN | Lose $50 |
| Leg 2 ($50) | +2.5 | 3-2.5 | City WIN | Lose $50 |
| Total | FULL LOSE | $0 (lose $100) |
Scenario 4: Man City wins 2-0 (close one)
Wait, that's the same as Scenario 2. Let me do Man City 3-1:
| Leg | Handicap | Adjusted | Result | Payout |
|---|---|---|---|---|
| Leg 1 ($50) | +2 | 3-3 | PUSH | $50 back |
| Leg 2 ($50) | +2.5 | 3-3.5 | Norwich WIN | $95 |
| Total | HALF WIN | $145 |
The Five Possible Outcomes with Quarter Lines
| Outcome | What Happens | When |
|---|---|---|
| Full Win | Both legs win | Margin < both lines |
| Half Win | One leg wins, one pushes | Margin = lower line |
| Push | Both legs push | (Impossible with quarters) |
| Half Lose | One leg loses, one pushes | Margin = higher line |
| Full Lose | Both legs lose | Margin > both lines |
Visual Summary
You bet: Norwich +2.25 for $100
Man City wins by: 1 goal 2 goals 3 goals 4+ goals
│ │ │ │
▼ ▼ ▼ ▼
+2.0 leg ($50): WIN PUSH LOSE LOSE
+2.5 leg ($50): WIN WIN LOSE LOSE
│ │ │ │
▼ ▼ ▼ ▼
Your outcome: FULL WIN HALF WIN HALF LOSE* FULL LOSE
Return: $190 $145 $50** $0
* If exactly 3-1, it's HALF LOSE (push on +2, lose on +2.5)
** Actually for 3-0: lose both legs = $0. For 3-1: $50 back
Why the Order Book Handles This Specially
The Order Book treats quarter-line bets as atomic composite orders:
User places: BACK Norwich +2.25 @ 1.90 for $100
Order Book internally creates:
┌─────────────────────────────────────────┐
│ ATOMIC ORDER GROUP │
│ (must execute together or not at all) │
├─────────────────────────────────────────┤
│ Leg 1: BACK Norwich +2.0 @ 1.90 for $50│
│ Leg 2: BACK Norwich +2.5 @ 1.90 for $50│
└─────────────────────────────────────────┘
Both legs are matched together. You can't have one leg matched and the other not.
B.3: Options Trading Demystified
The Common Misconception
Many people think options are impossibly complex because of terms like:
"Delta, Gamma, Theta, Vega, Rho, Black-Scholes,
implied volatility, time decay, strike price..."
But here's the truth: Most of this complexity is NOT relevant for order matching!
What You Actually Specify When Trading Options
When you place an options order, you specify exactly 6 things:
| Parameter | Example | Plain English |
|---|---|---|
| Underlying | AAPL | What stock/asset |
| Strike Price | $150 | The price threshold |
| Expiration | Jan 17, 2025 | When does it expire |
| Type | Call | Betting price goes up (or Put for down) |
| Your Price | $5.00 | How much you'll pay per share |
| Quantity | 10 contracts | How many (usually 100 shares each) |
That's it! No Greeks in the order.
What Are The Greeks Then?
The Greeks are measurements that describe how an option behaves - they're calculated AFTER you own the option, not when you order it.
Think of it like buying a car:
When you BUY the car, you specify:
- Make: Toyota
- Model: Camry
- Year: 2024
- Color: Blue
- Price: $30,000
The car's CHARACTERISTICS (calculated later):
- Fuel efficiency: 32 mpg
- 0-60 time: 7.5 seconds
- Turning radius: 18 feet
You don't say "I want a car with 32 mpg" - you say
"I want a Camry" and then learn it gets 32 mpg.
OPTIONS WORK THE SAME WAY!
The Greeks Explained Simply
| Greek | What It Measures | Car Analogy |
|---|---|---|
| Delta | How much option moves when stock moves $1 | Speed |
| Gamma | How fast Delta changes | Acceleration |
| Theta | Value lost per day from time passing | Depreciation |
| Vega | Sensitivity to market volatility | Sensitivity to road conditions |
| Rho | Sensitivity to interest rates | Sensitivity to fuel prices |
Key insight: You don't order an option by its Greeks. You order it by its specifications (strike, expiry, type), and then the Greeks describe its behavior.
Options Are Just Bets With a Deadline
Strip away the jargon, and an option is just:
A CALL OPTION is a bet that says:
"I bet the stock will be ABOVE the strike price by the expiration date"
A PUT OPTION is a bet that says:
"I bet the stock will be BELOW the strike price by the expiration date"
Example: Apple $150 Call expiring January 2025
Plain English:
"I bet that Apple stock will be above $150 on January 17, 2025"
If I'm right (AAPL is at $170 on that date):
- My option is worth $20 per share ($170 - $150)
- I paid $5 per share
- Profit: $15 per share
If I'm wrong (AAPL is at $140 on that date):
- My option is worthless (why pay $150 for something worth $140?)
- I lose my $5 per share
How Options Map to Our Universal Model
| Domain | What You're Betting On | Direction | Price |
|---|---|---|---|
| Sports Bet | "Man City wins" | BACK | 1.85 odds |
| Prediction | "Trump wins election" | YES | $0.52 |
| Call Option | "AAPL above $150 on Jan 25" | BUY | $5.00 |
| Put Option | "AAPL below $150 on Jan 25" | BUY | $3.00 |
The matching is identical in all cases: find someone willing to take the other side at a compatible price.
Where Do Greeks Come In?
Greeks are used by SURROUNDING SERVICES, not the order book:
┌─────────────────────────────────────────────────────────────────────┐
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ PRICING │ │ RISK │ │
│ │ SERVICE │ │ SERVICE │ │
│ │ │ │ │ │
│ │ Calculates │ │ Calculates │ │
│ │ fair price │ │ Greeks for │ │
│ │ using Black- │ │ margin & │ │
│ │ Scholes │ │ hedging │ │
│ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │
│ │ ┌─────────────────┐ │ │
│ │ │ │ │ │
│ └────────►│ ORDER BOOK │◄─────────┘ │
│ │ │ │
│ │ Doesn't know │ │
│ │ about Greeks! │ │
│ │ │ │
│ │ Just matches: │ │
│ │ "BUY AAPL $150 │ │
│ │ Call @ $5.00" │ │
│ │ vs │ │
│ │ "SELL AAPL $150 │ │
│ │ Call @ $5.00" │ │
│ │ │ │
│ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
Strike Prices = Handicap Lines
Here's a beautiful parallel:
ASIAN HANDICAP LINES: OPTIONS STRIKE PRICES:
Norwich +3.0 (very safe) AAPL $120 Call (very likely)
Norwich +2.5 AAPL $130 Call
Norwich +2.0 AAPL $140 Call
Norwich +1.5 AAPL $150 Call (current price)
Norwich +1.0 AAPL $160 Call
Norwich +0.5 AAPL $170 Call
Norwich +0.0 (risky) AAPL $180 Call (unlikely)
Both are "lines" on a spectrum!
The Order Book handles them the same way.
Multi-Leg Options Strategies = Quarter-Goal Bets
Complex options strategies are just composite orders - exactly like quarter-goal Asian Handicaps!
| Strategy | Legs | What It Means |
|---|---|---|
| Bull Call Spread | Buy $150 Call, Sell $160 Call | "AAPL between $150-$160" |
| Straddle | Buy $150 Call, Buy $150 Put | "AAPL will move a lot (either direction)" |
| Iron Condor | 4 options at different strikes | "AAPL will stay in a range" |
The Order Book handles these as atomic groups - all legs match together or none do.
B.4: Three-Way Synthetic Matching Explained
The Setup: A Football Match with 3 Outcomes
Consider: Man City vs Liverpool
Three possible outcomes (exactly one will happen):
- Home Win (Man City wins)
- Draw
- Away Win (Liverpool wins)
The Problem: Everyone Wants to BACK
Imagine three users:
- Alice: Wants to BACK Home Win at odds 2.00
- Bob: Wants to BACK Draw at odds 3.33
- Charlie: Wants to BACK Away Win at odds 5.00
In traditional matching, nothing happens! Everyone is betting "for" something, nobody is betting "against" anything.
TRADITIONAL MATCHING:
Home Win book: [BACK Alice $100] ... waiting ... [no LAY orders]
Draw book: [BACK Bob $60] ... waiting ... [no LAY orders]
Away Win book: [BACK Charlie $40] ... waiting ... [no LAY orders]
Result: Everyone waiting. No trades. Frustrated users.
The Key Insight
Here's the magic realization:
If you're betting FOR Home Win...
You're automatically betting AGAINST Draw AND Away Win!
If Home wins → Alice wins, Bob loses, Charlie loses
If Draw → Alice loses, Bob wins, Charlie loses
If Away → Alice loses, Bob loses, Charlie wins
These three people are natural counterparties to each other!
The Mathematics
In a fair market with 3 outcomes, probabilities must sum to 100%:
| Outcome | Probability | Fair Odds |
|---|---|---|
| Home Win | 50% | 2.00 |
| Draw | 30% | 3.33 |
| Away Win | 20% | 5.00 |
| Total | 100% |
Now, let's verify the synthetic match works:
Alice's bet: BACK Home @ 2.00 for $100
- If Home wins: Profit $100
- If Draw: Lose $100
- If Away: Lose $100
Bob's bet: BACK Draw @ 3.33 for $60
- If Home wins: Lose $60
- If Draw: Profit $140 (win $200, stake was $60)
- If Away: Lose $60
Charlie's bet: BACK Away @ 5.00 for $40
- If Home wins: Lose $40
- If Draw: Lose $40
- If Away: Profit $160 (win $200, stake was $40)
Let's Check if It Balances
| Outcome | Alice | Bob | Charlie | TOTAL |
|---|---|---|---|---|
| Home Wins | +$100 | -$60 | -$40 | $0 ✓ |
| Draw | -$100 | +$140 | -$40 | $0 ✓ |
| Away Wins | -$100 | -$60 | +$160 | $0 ✓ |
The payoffs exactly cancel out! This is a perfect match.
What the Order Book Does
SYNTHETIC MATCHING:
1. Alice submits: BACK Home @ 2.00 for $100
2. Order Book thinks: "Can I synthesize a LAY Home?"
3. Checks other markets:
- Bob has: BACK Draw @ 3.33 for $60 ✓
- Charlie has: BACK Away @ 5.00 for $40 ✓
4. Calculates: Bob + Charlie together = LAY Home!
5. Executes THREE-WAY MATCH:
- Alice matched against (Bob + Charlie)
- All three orders filled!
- Emit 3 trade confirmations
Visual Representation
Alice
BACK Home
$100
│
┌─────────┴─────────┐
│ SYNTHETIC LAY │
│ (Created from │
│ Bob + Charlie) │
└─────────┬─────────┘
│
┌───────────┴───────────┐
│ │
Bob Charlie
BACK Draw BACK Away
$60 $40
The Synthetic Relationship
┌─────────────────────────────────────────────────────────────────────┐
│ THE THREE-WAY RELATIONSHIP │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ BACK Home = LAY (Draw + Away) │
│ BACK Draw = LAY (Home + Away) │
│ BACK Away = LAY (Home + Draw) │
│ │
│ In other words: │
│ Betting FOR one outcome = Betting AGAINST all others combined │
│ │
└─────────────────────────────────────────────────────────────────────┘
How the Stakes Are Calculated
The stakes must be proportional to the probabilities:
To synthesize LAY Home (liability = $100):
The "NOT Home" probability = P(Draw) + P(Away) = 30% + 20% = 50%
Stake on BACK Draw = $100 × (30% / 50%) = $100 × 0.6 = $60
Stake on BACK Away = $100 × (20% / 50%) = $100 × 0.4 = $40
Total stake: $60 + $40 = $100 ✓
Why This Matters
Without synthetic matching:
| Metric | Result |
|---|---|
| Matched orders | 0 |
| Happy users | 0 |
| Trading volume | $0 |
| Market efficiency | Poor |
With synthetic matching:
| Metric | Result |
|---|---|
| Matched orders | 3 |
| Happy users | 3 |
| Trading volume | $200 |
| Market efficiency | Excellent |
Extending to 4+ Outcomes (Horse Racing)
The same principle extends to any number of outcomes:
HORSE RACE: 6 Horses
BACK Horse A = LAY (B + C + D + E + F)
If you BACK Horse A, you're betting against ALL other horses.
If someone BACKs each of the other 5 horses in the right proportions,
together they form a synthetic LAY on Horse A.
→ 6-way synthetic match possible!
Summary
┌─────────────────────────────────────────────────────────────────────┐
│ THREE-WAY SYNTHETIC MATCHING │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ KEY INSIGHT: │
│ In mutually exclusive outcomes, everyone betting BACK on │
│ different outcomes are natural counterparties. │
│ │
│ WHAT THE ENGINE DOES: │
│ 1. Recognize that BACK orders on all outcomes complete each other│
│ 2. Calculate proportional stakes │
│ 3. Match them as a group │
│ 4. Ensure payoffs balance to zero in all scenarios │
│ │
│ WHY IT'S POWERFUL: │
│ Creates liquidity where none appeared to exist! │
│ │
└─────────────────────────────────────────────────────────────────────┘
B.5: Summary - How It All Fits Together
The Universal Order Book Philosophy
┌─────────────────────────────────────────────────────────────────────┐
│ │
│ The Order Book has ONE job: Match orders at compatible prices │
│ │
│ Everything else is handled elsewhere: │
│ • Balance management → Backend │
│ • Settlement/Payouts → Backend │
│ • Greeks calculation → Pricing Service │
│ • User authentication → Backend │
│ │
└─────────────────────────────────────────────────────────────────────┘
The Universal Language
Every tradeable thing, regardless of domain, can be expressed as:
| Element | Description |
|---|---|
| WHAT | The specific outcome (team wins, price above X, etc.) |
| DIRECTION | LONG (for) or SHORT (against) |
| PRICE | What you're willing to pay or receive |
| SIZE | How much exposure |
Complex Features Built from Simple Parts
| Feature | How It Works |
|---|---|
| Asian Handicap Quarters | Composite order with 2 legs on adjacent lines |
| Options Spreads | Composite order with 2+ legs at different strikes |
| Synthetic Matching | Matching BACK against combined BACKs on other outcomes |
| Cross-Line Matching | Using mathematical relationships between related outcomes |
The Key Guarantees
| Guarantee | How It's Achieved |
|---|---|
| No overspending | Lock (don't just check) funds at submission |
| Fair matching | Price-time priority |
| Deterministic replay | Single-threaded engine, event journal |
| No data loss | fsync before acknowledgment |
| Balanced book | Synthetic matches sum to zero in all outcomes |
Document End
This architecture specification defines the Universal Order Book Engine - a matching engine capable of supporting any tradeable asset class with full synthetic matching, native Asian Handicap support, pluggable representations, and complete infrastructure for production deployment.