1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
use crateInstrumentNameExchange;
use Constructor;
use ;
/// The venue an [`Instrument`](super::Instrument)s **market data** is sourced from, when that
/// differs from the venue it is **executed** on.
///
/// # Why this exists
/// Position and `pnl_unrealised` state is strictly `InstrumentIndex`-scoped: a position opened by a
/// fill only receives live PnL from market events tagged with *that* index. Modelling "priced by
/// venue A, traded on venue B" as two separate `Instrument`s would therefore leave the traded
/// instrument's PnL permanently stale, because the price updates would land on the other index.
/// A `DataVenue` keeps both roles on **one** instrument, and so on one ledger.
///
/// # Fallback
/// Both fields fall back to the execution venue's equivalents, so a `DataVenue` only has to state
/// what actually differs:
/// - no `DataVenue` at all ⇒ market data is sourced from `Instrument::exchange` under
/// `Instrument::name_exchange`, which is the behaviour of every single-venue instrument;
/// - a `DataVenue` with `name_exchange: None` ⇒ the data venue spells the symbol exactly as the
/// execution venue does.
///
/// Read them through [`Instrument::data_exchange`](super::Instrument::data_exchange) and
/// [`Instrument::data_name_exchange`](super::Instrument::data_name_exchange) rather than reaching
/// into the fields, so the fallback is applied in one place.
///
/// # `name_exchange` is not cosmetic
/// Two venues routinely spell one economic instrument differently — London Strategic Edge quotes BP
/// as `BP.L` while a US broker lists it as `BP` — so a data venue that could only carry an exchange
/// identifier would subscribe under the *execution* venue's symbol and silently receive nothing, or
/// worse, receive a different instrument's prices.
///
/// # Suitability (caller obligation)
/// Sourcing prices from one venue and filling on another means **the decision price is not the fill
/// price**: the two venues have separate books, and a data venue that publishes an aggregated or
/// synthetic series (a CFD or index proxy) has no book at all. That basis mismatch is sound for
/// research and paper trading, but for real capital it is a property the caller must opt into
/// knowingly — the library cannot detect it.
///
/// # When a `DataVenue` is the wrong tool
/// A `DataVenue` models **one** economic instrument that two venues both quote — the same shares,
/// the same contract, the same pair — where all that differs is who publishes the prices and how
/// they spell the symbol. It does not model *related but distinct* instruments: a spot-metal or
/// index CFD against the corresponding future, a perpetual against its underlying spot, one
/// maturity against another. Those have their own tick sizes, expiries, funding and basis;
/// collapsing them onto one `Instrument` would mark a position against a series that is not that
/// position's own market, and the resulting `pnl_unrealised` would be wrong rather than stale.
///
/// Trading one off the other is the **two-instrument pattern**, and it needs no library support:
///
/// 1. Register **both** as ordinary `Instrument`s — the one you price, and the one you trade. Each
/// carries its own kind, its own underlying and its own venue. Only the traded instrument needs
/// an execution client registered against its exchange.
/// 2. Subscribe to market data for both, or for the priced one alone.
/// 3. Read the priced instrument's state in the strategy, and emit orders keyed to the **traded**
/// instrument. Nothing couples an order's instrument to the instrument whose prices motivated
/// it — the order interface takes whatever instrument key you give it.
/// 4. Own the conversion. Hedge ratio, contract multiplier, quantity and basis are a trading
/// decision the library has no way to derive, and getting them wrong is silent.
///
/// The consequence to accept is the mirror image of the case this type exists for: the two
/// instruments keep **separate** ledgers. Position and `pnl_unrealised` live on the traded
/// instrument, which is correct, and the priced instrument holds no position at all. Reconciling
/// them — treating an exposure opened against one as a hedge for a signal from the other — is the
/// caller's, because only the caller knows the relationship.
///
/// This is also what makes a non-executable kind usable for live decisions. An instrument kind no
/// execution client accepts can still price a strategy; it simply cannot be the instrument an order
/// names.
// Test code: panics on bad input are acceptable