jspurefix 5.11.3 → 5.11.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitattributes +4 -0
- package/dist/buffer/index.d.ts +6 -0
- package/dist/buffer/index.js +6 -0
- package/dist/buffer/index.js.map +1 -1
- package/dist/collections/index.d.ts +1 -0
- package/dist/collections/index.js +16 -0
- package/dist/collections/index.js.map +1 -1
- package/dist/dictionary/contained/index.d.ts +3 -0
- package/dist/dictionary/contained/index.js +3 -0
- package/dist/dictionary/contained/index.js.map +1 -1
- package/dist/dictionary/index.d.ts +5 -0
- package/dist/dictionary/index.js +5 -0
- package/dist/dictionary/index.js.map +1 -1
- package/dist/generator/applicability.d.ts +3 -0
- package/dist/generator/applicability.js +48 -0
- package/dist/generator/applicability.js.map +1 -0
- package/dist/generator/case-builder.d.ts +34 -0
- package/dist/generator/case-builder.js +111 -0
- package/dist/generator/case-builder.js.map +1 -0
- package/dist/generator/corpus-store.d.ts +43 -0
- package/dist/generator/corpus-store.js +115 -0
- package/dist/generator/corpus-store.js.map +1 -0
- package/dist/generator/index.d.ts +12 -0
- package/dist/generator/index.js +29 -0
- package/dist/generator/index.js.map +1 -0
- package/dist/generator/instrument-universe.d.ts +54 -0
- package/dist/generator/instrument-universe.js +286 -0
- package/dist/generator/instrument-universe.js.map +1 -0
- package/dist/generator/layout.d.ts +46 -0
- package/dist/generator/layout.js +208 -0
- package/dist/generator/layout.js.map +1 -0
- package/dist/generator/market-context.d.ts +64 -0
- package/dist/generator/market-context.js +119 -0
- package/dist/generator/market-context.js.map +1 -0
- package/dist/generator/outcome.d.ts +16 -0
- package/dist/generator/outcome.js +71 -0
- package/dist/generator/outcome.js.map +1 -0
- package/dist/generator/realistic-generator.d.ts +53 -0
- package/dist/generator/realistic-generator.js +275 -0
- package/dist/generator/realistic-generator.js.map +1 -0
- package/dist/generator/rng.d.ts +12 -0
- package/dist/generator/rng.js +60 -0
- package/dist/generator/rng.js.map +1 -0
- package/dist/generator/scatter.d.ts +50 -0
- package/dist/generator/scatter.js +285 -0
- package/dist/generator/scatter.js.map +1 -0
- package/dist/generator/scenarios.d.ts +13 -0
- package/dist/generator/scenarios.js +139 -0
- package/dist/generator/scenarios.js.map +1 -0
- package/dist/generator/value-conventions.d.ts +15 -0
- package/dist/generator/value-conventions.js +217 -0
- package/dist/generator/value-conventions.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/jsfix-cmd.d.ts +5 -0
- package/dist/jsfix-cmd.js +161 -0
- package/dist/jsfix-cmd.js.map +1 -1
- package/dist/store/fix-msg-ascii-store-resend.js +2 -2
- package/dist/store/fix-msg-ascii-store-resend.js.map +1 -1
- package/dist/store/fix-msg-store-record.d.ts +1 -1
- package/dist/store/fix-msg-store-record.js.map +1 -1
- package/dist/store/index.d.ts +1 -0
- package/dist/store/index.js +1 -0
- package/dist/store/index.js.map +1 -1
- package/dist/transport/index.d.ts +7 -0
- package/dist/transport/index.js +7 -0
- package/dist/transport/index.js.map +1 -1
- package/dist/transport/session/index.d.ts +1 -0
- package/dist/transport/session/index.js +1 -0
- package/dist/transport/session/index.js.map +1 -1
- package/docs/generated-cases.md +237 -0
- package/docs/scattered-components.md +60 -5
- package/jsfix.test_client.txt +62 -62
- package/jsfix.test_server.txt +72 -72
- package/package.json +5 -2
- package/src/buffer/index.ts +6 -0
- package/src/collections/index.ts +1 -1
- package/src/dictionary/contained/index.ts +3 -0
- package/src/dictionary/index.ts +5 -0
- package/src/generator/applicability.ts +87 -0
- package/src/generator/case-builder.ts +167 -0
- package/src/generator/corpus-store.ts +166 -0
- package/src/generator/index.ts +12 -0
- package/src/generator/instrument-universe.ts +347 -0
- package/src/generator/layout.ts +279 -0
- package/src/generator/market-context.ts +207 -0
- package/src/generator/outcome.ts +102 -0
- package/src/generator/realistic-generator.ts +404 -0
- package/src/generator/rng.ts +92 -0
- package/src/generator/scatter.ts +432 -0
- package/src/generator/scenarios.ts +167 -0
- package/src/generator/value-conventions.ts +295 -0
- package/src/index.ts +12 -0
- package/src/jsfix-cmd.ts +204 -0
- package/src/store/fix-msg-ascii-store-resend.ts +2 -1
- package/src/store/fix-msg-store-record.ts +4 -1
- package/src/store/index.ts +1 -0
- package/src/transport/index.ts +10 -0
- package/src/transport/session/index.ts +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/transport/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAwB;AACxB,+CAA4B;AAC5B,iDAA8B;AAC9B,kDAA+B;AAC/B,oDAAiC;AACjC,gDAA6B;AAC7B,kDAA+B;AAC/B,gDAA6B;AAC7B,oDAAiC;AACjC,wDAAqC;AAGrC,oEAAiD;AACjD,oEAAiD;AACjD,4CAAyB","sourcesContent":["export * from './duplex'\nexport * from './fix-entity'\nexport * from './fix-acceptor'\nexport * from './fix-initiator'\nexport * from './msg-transmitter'\nexport * from './msg-payload'\nexport * from './send-callback'\nexport * from './tick-action'\nexport * from './msg-application'\nexport * from './ascii/ascii-session'\n// the factory an application extends to customise its Logon or header - it belongs\n// at the root alongside ASessionMsgFactory, not behind a dist/ path\nexport * from './ascii/ascii-session-msg-factory'\nexport * from './fixml/fixml-session-msg-factory'\nexport * from './session'\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/transport/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAwB;AACxB,+CAA4B;AAC5B,iDAA8B;AAC9B,kDAA+B;AAC/B,oDAAiC;AACjC,gDAA6B;AAC7B,kDAA+B;AAC/B,gDAA6B;AAC7B,oDAAiC;AACjC,wDAAqC;AAGrC,oEAAiD;AACjD,oEAAiD;AACjD,4CAAyB;AACzB,4CAAyB;AAIzB,kEAA+C;AAC/C,oDAAiC;AACjC,oEAAiD;AACjD,sDAAmC;AACnC,sDAAmC;AACnC,oDAAiC","sourcesContent":["export * from './duplex'\nexport * from './fix-entity'\nexport * from './fix-acceptor'\nexport * from './fix-initiator'\nexport * from './msg-transmitter'\nexport * from './msg-payload'\nexport * from './send-callback'\nexport * from './tick-action'\nexport * from './msg-application'\nexport * from './ascii/ascii-session'\n// the factory an application extends to customise its Logon or header - it belongs\n// at the root alongside ASessionMsgFactory, not behind a dist/ path\nexport * from './ascii/ascii-session-msg-factory'\nexport * from './fixml/fixml-session-msg-factory'\nexport * from './session'\nexport * from './factory'\n// the transport description types an application writes in its session JSON -\n// the concrete tcp/http entities stay out of the root barrel so that requiring\n// jspurefix does not drag express in behind them\nexport * from './tcp/tcp-transport-description'\nexport * from './tcp/tls-options'\nexport * from './http/http-transport-description'\nexport * from './http/http-adapter'\nexport * from './http/html-options'\nexport * from './http/html-route'\n"]}
|
|
@@ -28,4 +28,5 @@ __exportStar(require("./resend-request-manager"), exports);
|
|
|
28
28
|
__exportStar(require("./fix-clock"), exports);
|
|
29
29
|
__exportStar(require("./session-registry"), exports);
|
|
30
30
|
__exportStar(require("./clone-session-description"), exports);
|
|
31
|
+
__exportStar(require("./fix-session-state-args"), exports);
|
|
31
32
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/transport/session/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0DAAuC;AACvC,gDAA6B;AAC7B,sDAAmC;AACnC,qDAAkC;AAClC,2DAAwC;AACxC,wDAAqC;AACrC,wDAAqC;AACrC,kDAA+B;AAC/B,iEAA8C;AAC9C,2DAAwC;AACxC,2DAAwC;AACxC,8CAA2B;AAC3B,qDAAkC;AAClC,8DAA2C","sourcesContent":["export * from './a-session-msg-factory'\nexport * from './fix-session'\nexport * from './fix-session-state'\nexport * from './make-fix-session'\nexport * from './session-50-description'\nexport * from './session-description'\nexport * from './session-msg-factory'\nexport * from './session-state'\nexport * from './session-sequence-coordinator'\nexport * from './session-sequence-store'\nexport * from './resend-request-manager'\nexport * from './fix-clock'\nexport * from './session-registry'\nexport * from './clone-session-description'\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/transport/session/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0DAAuC;AACvC,gDAA6B;AAC7B,sDAAmC;AACnC,qDAAkC;AAClC,2DAAwC;AACxC,wDAAqC;AACrC,wDAAqC;AACrC,kDAA+B;AAC/B,iEAA8C;AAC9C,2DAAwC;AACxC,2DAAwC;AACxC,8CAA2B;AAC3B,qDAAkC;AAClC,8DAA2C;AAC3C,2DAAwC","sourcesContent":["export * from './a-session-msg-factory'\nexport * from './fix-session'\nexport * from './fix-session-state'\nexport * from './make-fix-session'\nexport * from './session-50-description'\nexport * from './session-description'\nexport * from './session-msg-factory'\nexport * from './session-state'\nexport * from './session-sequence-coordinator'\nexport * from './session-sequence-store'\nexport * from './resend-request-manager'\nexport * from './fix-clock'\nexport * from './session-registry'\nexport * from './clone-session-description'\nexport * from './fix-session-state-args'\n"]}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# Generated cases — measuring the scattered component problem
|
|
2
|
+
|
|
3
|
+
Companion to [`scattered-components.md`](scattered-components.md). That note argues from
|
|
4
|
+
the shape of the dictionary; this one reports what actually happens when messages of that
|
|
5
|
+
shape are put through the parser.
|
|
6
|
+
|
|
7
|
+
Everything here is produced by `src/generator/`, reachable from the command line:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
npm run scenarios
|
|
11
|
+
npm run scenario -- --scenario=spread-trade-capture
|
|
12
|
+
npm run doll -- --scenario=spread-trade-capture --russian-doll=2
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## How a case is built
|
|
16
|
+
|
|
17
|
+
Four steps, and the third is the one that makes the results worth anything.
|
|
18
|
+
|
|
19
|
+
1. **Generate** an object for a message type, populated to look like traffic rather than
|
|
20
|
+
to exercise the dictionary — a book of real instruments, prices on tick, quantities in
|
|
21
|
+
whole lots, dates that agree with each other, and optional fields chosen by how likely
|
|
22
|
+
a real counterparty is to send them.
|
|
23
|
+
2. **Encode** it. The encoder emits in dictionary order, so the result is contiguous by
|
|
24
|
+
construction.
|
|
25
|
+
3. **Parse the canonical encoding.** This is the oracle. There is no hand-written
|
|
26
|
+
expectation anywhere in the corpus that could itself be wrong.
|
|
27
|
+
4. **Permute the body tokens** so that one or more components become non-adjacent, in a
|
|
28
|
+
way the specification still permits, and parse that. It is the same message, so any
|
|
29
|
+
difference is the engine losing information.
|
|
30
|
+
|
|
31
|
+
Because step 4 only re-orders, the byte count and the sum of the bytes are unchanged, so
|
|
32
|
+
`BodyLength` and `CheckSum` remain correct without being recomputed. The only ordering
|
|
33
|
+
the wire genuinely constrains is honoured: a repeating group run is atomic and moves as a
|
|
34
|
+
block, and the delimiter stays first inside each instance.
|
|
35
|
+
|
|
36
|
+
## What `--russian-doll n` means
|
|
37
|
+
|
|
38
|
+
A **site** is one component made non-adjacent within its level. Depth `n` asks for `n`
|
|
39
|
+
sites along one path into the message. Each site records its **structure depth** — how
|
|
40
|
+
many group instance bodies enclose it — and that number turns out to be the whole story.
|
|
41
|
+
|
|
42
|
+
## The measurement — repo44
|
|
43
|
+
|
|
44
|
+
Ten scenarios against `repo44`, forty seeds each, doll depths 1 to 3: 1,200 cases.
|
|
45
|
+
|
|
46
|
+
| Sites at | Cases | Scattered parse matches the oracle |
|
|
47
|
+
| --- | --- | --- |
|
|
48
|
+
| structure depth 0 (message body) | 749 | **749** |
|
|
49
|
+
| structure depth 1 (inside a group instance) | 238 | **0** |
|
|
50
|
+
| no scatterable site in the message | 213 | — |
|
|
51
|
+
|
|
52
|
+
Two things stand out.
|
|
53
|
+
|
|
54
|
+
**The shipped repair holds completely at depth 0.** Every case the generator could
|
|
55
|
+
construct with a component scattered in the message body round-tripped exactly, across
|
|
56
|
+
equities, futures, options, bonds, spreads, market data and allocations. Eight years
|
|
57
|
+
without a complaint looks less like luck than it did.
|
|
58
|
+
|
|
59
|
+
**Nothing at depth 1 survives, and nothing at depth 1 is rejected either.** Not one case
|
|
60
|
+
in 238 produced a parse error. The message is accepted, `invalid()`, `missing()` and
|
|
61
|
+
`undefinedForMsg()` all report nothing wrong, and the application is handed a component
|
|
62
|
+
with fields missing. This is the outcome the design note calls strictly worse than the
|
|
63
|
+
bug being fixed, and it is what actually happens today.
|
|
64
|
+
|
|
65
|
+
A depth-1 case reduced to its essentials — an ICE Brent calendar spread whose
|
|
66
|
+
`InstrumentLeg` is scattered inside its leg group instance:
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
canonical ...|555=2|600=BRN|607=217|611=20260822|623=1|624=1|539=1|...
|
|
70
|
+
scattered ...|555=2|600=BRN|539=1|524=NPID-60012|566=71.32|607=217|611=20260822|623=1|624=1|...
|
|
71
|
+
|
|
72
|
+
InstrumentLeg.LegProduct canonical 217 scattered absent
|
|
73
|
+
InstrumentLeg.LegMaturityDate canonical 20260822 scattered absent
|
|
74
|
+
InstrumentLeg.LegRatioQty canonical 1 scattered absent
|
|
75
|
+
InstrumentLeg.LegSide canonical 1 scattered absent
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
On `repo44` the loss is always a subset — no case produced a *wrong* value, only a
|
|
79
|
+
missing one. That does not survive contact with the next dictionary.
|
|
80
|
+
|
|
81
|
+
## The measurement — qf50sp2
|
|
82
|
+
|
|
83
|
+
The same sweep against the QuickFIX FIX50SP2 dictionary, 750 cases, is a different and
|
|
84
|
+
less comfortable picture.
|
|
85
|
+
|
|
86
|
+
| Sites at | Contended tag on the wire | Cases | Match the oracle |
|
|
87
|
+
| --- | --- | --- | --- |
|
|
88
|
+
| structure depth 0 | yes | 319 | 174 |
|
|
89
|
+
| structure depth 0 | no | 181 | 176 |
|
|
90
|
+
| structure depth 1 | yes | 164 | 36 |
|
|
91
|
+
| structure depth 1 | no | 62 | 0 |
|
|
92
|
+
|
|
93
|
+
**Depth 0 is no longer safe.** 150 of 500 message-body cases produce a different object,
|
|
94
|
+
and 145 of those 150 are the collision phase 0 predicted. The QuickFIX FIX50SP2 dictionary
|
|
95
|
+
declares `Currency(15)` inside `Instrument` *and* again beside it at message level, in 57
|
|
96
|
+
places. When `Instrument` arrives scattered, the shipped repair attributes the message
|
|
97
|
+
level `Currency` to `Instrument`:
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
Instrument.Currency canonical absent scattered "USD"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
That is a different failure from the depth-1 one, and a worse one. At depth 1 the engine
|
|
104
|
+
loses a field, which a careful application can notice. Here it **invents** one that looks
|
|
105
|
+
entirely legitimate. This is the shipped repair, in the library today, on a dictionary the
|
|
106
|
+
library ships — pinned by
|
|
107
|
+
[`src/test/ascii/fragment-contention.test.ts`](../src/test/ascii/fragment-contention.test.ts).
|
|
108
|
+
|
|
109
|
+
It also settles open decision 1 in the design note from the evidence rather than from
|
|
110
|
+
taste: the collision map is not a nicety for the generalisation, it is missing from the
|
|
111
|
+
repair that already exists.
|
|
112
|
+
|
|
113
|
+
## The true russian doll does exist — just not in 4.4
|
|
114
|
+
|
|
115
|
+
**Standard FIX 4.4 almost never offers a component nested inside another component where
|
|
116
|
+
both own two or more tags of their own.** The components inside `Instrument` are group
|
|
117
|
+
wrappers owning a single `NoXXX`, so the literal doll of the design note —
|
|
118
|
+
`SecurityXLinkage` scattered within a scattered `Instrument` — has no instance in `repo44`
|
|
119
|
+
at all. The reachable second level there is a component scattered inside a *group
|
|
120
|
+
instance*: a different axis, the same defect, since detection is populated only while
|
|
121
|
+
`structureStack.length === 1`.
|
|
122
|
+
|
|
123
|
+
FIX 5.0SP2 does have it. `Instrument.PricingDateTime` and `Instrument.OptionExercise` are
|
|
124
|
+
components inside `Instrument` carrying several tags each, and every generated case that
|
|
125
|
+
scattered one inside a scattered `Instrument` produced a wrong object — at structure depth
|
|
126
|
+
0, where the repair is supposed to work. These are the remaining 5 depth-0 failures that
|
|
127
|
+
the `Currency` collision does not explain.
|
|
128
|
+
|
|
129
|
+
So phase 3 has two independent things to handle, and a dictionary to test each against:
|
|
130
|
+
recursion into nested components (5.0SP2) and repair below the message body (either).
|
|
131
|
+
|
|
132
|
+
## Which shapes a dictionary can express
|
|
133
|
+
|
|
134
|
+
The cases with no site at all are not a failure of the tool. `InstrmtMDReqGrp` in FIX 4.4
|
|
135
|
+
contains nothing but `Instrument`, so there is no sibling field to interleave and the
|
|
136
|
+
component cannot be made non-adjacent. Worth knowing before designing a repair for a shape
|
|
137
|
+
the wire cannot carry.
|
|
138
|
+
|
|
139
|
+
## The corpus
|
|
140
|
+
|
|
141
|
+
`data/corpus/` holds edge cases as **bytes**, not as recipes. One directory per case:
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
data/corpus/<name>/case.json metadata, the scatter plan, and the expected outcome
|
|
145
|
+
data/corpus/<name>/canonical.txt the contiguous encoding - the oracle
|
|
146
|
+
data/corpus/<name>/scattered.txt the same bytes, legally re-ordered
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
The generator is how a case is *found*; it is not what a case *is*. A seed reproduces a
|
|
150
|
+
message only while the generator is unchanged — move one probability in the value
|
|
151
|
+
conventions and the random stream reshuffles, so every seed yields a different message and
|
|
152
|
+
every recorded expectation quietly stops describing what it was written for. A corpus that
|
|
153
|
+
has to be regenerated to be read is not a corpus. `case.json` records the seed under
|
|
154
|
+
`origin` as provenance, not as a way to rebuild.
|
|
155
|
+
|
|
156
|
+
Each entry records not just *whether* the engine copes but *how* it fails, so a change in
|
|
157
|
+
the shape of the damage fails the test too:
|
|
158
|
+
|
|
159
|
+
| outcome | meaning |
|
|
160
|
+
| --- | --- |
|
|
161
|
+
| `round-trips` | the scattered ordering parses to the same object |
|
|
162
|
+
| `loses-fields` | parses with fields dropped; every value present is still correct |
|
|
163
|
+
| `mis-attributes` | parses, and carries a value the message never said — the dangerous one |
|
|
164
|
+
| `rejected` | refused outright, which for a legal ordering is a defect, but a loud one |
|
|
165
|
+
|
|
166
|
+
### What is in it
|
|
167
|
+
|
|
168
|
+
| case | dictionary | outcome |
|
|
169
|
+
| --- | --- | --- |
|
|
170
|
+
| `instrument-scattered-in-body` | repo44 | round-trips |
|
|
171
|
+
| `equity-fill-instrument-scattered` | repo44 | round-trips |
|
|
172
|
+
| `bond-instrument-scattered` | repo44 | round-trips |
|
|
173
|
+
| `allocation-instrument-scattered` | repo44 | round-trips |
|
|
174
|
+
| `leg-scattered-in-group-instance` | repo44 | loses-fields |
|
|
175
|
+
| `md-entry-instrument-scattered` | repo44 | loses-fields |
|
|
176
|
+
| `currency-inside-instrument` | qf50sp2 | round-trips |
|
|
177
|
+
| `currency-claimed-by-sibling` | qf50sp2 | **mis-attributes** |
|
|
178
|
+
| `nested-component-in-instrument` | qf50sp2 | loses-fields |
|
|
179
|
+
|
|
180
|
+
Four cases where the engine is right, four where it drops data, one where it invents data —
|
|
181
|
+
across two dictionaries, at both structure depths, in five message types.
|
|
182
|
+
|
|
183
|
+
### Growing it
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
npm run doll -- --scenario=spread-trade-capture --russian-doll=2 --seed=1 --as-of=2026-01-15T10:30:00Z --corpus-add=my-case --note="what this shows"
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
The tool prints what it found, writes the three files, and tells you what outcome it
|
|
190
|
+
recorded. **Read it before committing** — the recorded expectation is an assertion about
|
|
191
|
+
this engine, and nothing checks that a human agreed with it.
|
|
192
|
+
|
|
193
|
+
A case whose outcome is not `round-trips` is a defect described precisely enough that
|
|
194
|
+
fixing it will fail this test. That is the point. When one is fixed, update the entry
|
|
195
|
+
rather than deleting it.
|
|
196
|
+
|
|
197
|
+
## The tests
|
|
198
|
+
|
|
199
|
+
Three files, doing three different jobs.
|
|
200
|
+
|
|
201
|
+
[`corpus.test.ts`](../src/test/ascii/corpus.test.ts) walks `data/corpus/` and asserts each
|
|
202
|
+
entry still behaves as recorded, down to which leaf paths are missing or added. It also
|
|
203
|
+
asserts the corpus stays worth having — non-empty, covering more than one dictionary, both
|
|
204
|
+
structure depths, and all three of working / losing / inventing.
|
|
205
|
+
|
|
206
|
+
[`generated-scatter.test.ts`](../src/test/ascii/generated-scatter.test.ts) is breadth. It
|
|
207
|
+
sweeps 400 freshly generated cases on every run — 272 message-body sites over 8 scenarios,
|
|
208
|
+
62 below-body sites over 4 — and asserts the *rule*: everything at structure depth 0 round
|
|
209
|
+
trips, nothing below it does, and nothing is ever rejected. Every assertion is over a
|
|
210
|
+
counted population with a floor, so a generator that stopped producing sites fails the
|
|
211
|
+
suite instead of passing it quietly.
|
|
212
|
+
|
|
213
|
+
> An earlier version of that file used `test.each` with an early `return` for cases the
|
|
214
|
+
> generator could not produce. Eight of its forty tests passed while asserting nothing at
|
|
215
|
+
> all. Counted populations with floors are the fix, and the lesson generalises: a test that
|
|
216
|
+
> can skip itself is a test that can stop testing.
|
|
217
|
+
|
|
218
|
+
[`fragment-contention.test.ts`](../src/test/ascii/fragment-contention.test.ts) proves the
|
|
219
|
+
`qf50sp2` `Currency` defect is systemic rather than one unlucky message, and that it fires
|
|
220
|
+
only where the collision is declared: every value the engine invents is that one contended
|
|
221
|
+
tag, and a message not carrying it is never harmed.
|
|
222
|
+
|
|
223
|
+
Both non-round-trip groups are written to be **inverted, not deleted**, when the repair is
|
|
224
|
+
generalised. They are the acceptance criteria for phase 3.
|
|
225
|
+
|
|
226
|
+
## Reproducing a case
|
|
227
|
+
|
|
228
|
+
A seed fixes every choice the generator makes, but dates are read off the wall clock
|
|
229
|
+
unless anchored, so both are needed:
|
|
230
|
+
|
|
231
|
+
```
|
|
232
|
+
npm run doll -- --scenario=spread-trade-capture --russian-doll=2 \
|
|
233
|
+
--seed=42 --as-of=2026-01-15T10:30:00Z --unit
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
`--unit` writes `canonical.txt`, `fix.txt` (the scattered ordering), `object.json`,
|
|
237
|
+
`plan.json` and `case.txt` into the working directory.
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
# Scattered components — analysis and plan of attack
|
|
2
2
|
|
|
3
|
-
**Status: analysis, with
|
|
4
|
-
sets out a generalisation of the fragmented component repair already shipped, why it
|
|
5
|
-
believed tractable, what it would cost, and the order the work would land in. It is
|
|
3
|
+
**Status: analysis, with phases 0 and 0b landed.** Nothing in the parser has changed. This
|
|
4
|
+
note sets out a generalisation of the fragmented component repair already shipped, why it
|
|
5
|
+
is believed tractable, what it would cost, and the order the work would land in. It is
|
|
6
6
|
written to port — the same shape applies to cspurefix.
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
Phase 0b has since measured the problem rather than reasoning about it, and turned up one
|
|
9
|
+
thing this note did not expect: **the repair that already shipped mis-attributes a
|
|
10
|
+
contended tag on the `qf50sp2` dictionary**, inventing an `Instrument.Currency` the
|
|
11
|
+
counterparty never sent. That is a live defect rather than a generalisation, and open
|
|
12
|
+
decision 1 below is really its fix. See [`generated-cases.md`](generated-cases.md).
|
|
13
|
+
|
|
14
|
+
There is still no urgency behind it. The library has been in use for eight years and
|
|
15
|
+
exactly one counterparty has produced the shape that motivated the existing repair. This is the
|
|
10
16
|
argument being written down while it is fresh, not a queue-jumping defect.
|
|
11
17
|
|
|
12
18
|
## Where this starts
|
|
@@ -204,6 +210,52 @@ committee is, and the broker dialects are the ones most likely to also send the
|
|
|
204
210
|
messages this whole exercise is about. On the evidence here the collision map is not a
|
|
205
211
|
defensive nicety at the edge of the design; it is load-bearing.
|
|
206
212
|
|
|
213
|
+
### Phase 0b — how bad is it, measured *(landed)*
|
|
214
|
+
|
|
215
|
+
Phase 0 asked whether the dictionary permits a repair. This asks what the engine does
|
|
216
|
+
today when it meets the shape, which until now was reasoned about rather than observed.
|
|
217
|
+
|
|
218
|
+
`src/generator/` builds a message that reads like traffic, encodes it canonically, then
|
|
219
|
+
permutes the body tokens into a legal but scattered ordering. The canonical parse is the
|
|
220
|
+
oracle, so no expectation is hand written. Two dictionaries, ~2,000 cases, three findings —
|
|
221
|
+
and the first one is not about this plan at all.
|
|
222
|
+
|
|
223
|
+
**1. The shipped repair is already wrong on `qf50sp2`, and phase 0 said why.** That
|
|
224
|
+
dictionary declares `Currency(15)` inside `Instrument` and again beside it at message
|
|
225
|
+
level. When `Instrument` arrives scattered, the repair claims the *sibling's* tag:
|
|
226
|
+
`Instrument.Currency` appears in the parsed object carrying a value the counterparty sent
|
|
227
|
+
at message level. 145 of 500 message-body cases. This is not a failure of the
|
|
228
|
+
generalisation; it is a defect in the code that shipped, on a dictionary this library
|
|
229
|
+
distributes, and it moves open decision 1 from a design preference to a bug fix.
|
|
230
|
+
|
|
231
|
+
**2. At depth 1 nothing survives, and nothing is rejected.** On `repo44`, 749 of 749
|
|
232
|
+
message-body cases round trip exactly, and 0 of 238 cases one level down. Every one of the
|
|
233
|
+
238 parsed cleanly, reported no missing or invalid fields, and handed the application a
|
|
234
|
+
component with fields dropped. Silently wrong data, exactly as feared.
|
|
235
|
+
|
|
236
|
+
**3. The literal russian doll is a FIX 5.0 shape, not a 4.4 one.** Standard FIX 4.4 has
|
|
237
|
+
essentially no component nested inside another component where both own two or more tags —
|
|
238
|
+
the components inside `Instrument` are group wrappers owning one `NoXXX`. FIX 5.0SP2 does:
|
|
239
|
+
`Instrument.PricingDateTime`, `Instrument.OptionExercise`. Every case scattering one of
|
|
240
|
+
those inside a scattered `Instrument` produced a wrong object, at structure depth 0.
|
|
241
|
+
|
|
242
|
+
So phase 3 has two separable obligations with a dictionary to test each against — recursion
|
|
243
|
+
into nested components (`qf50sp2`) and repair below the message body (either) — and phase 0
|
|
244
|
+
has produced a defect that need not wait for either.
|
|
245
|
+
|
|
246
|
+
See [`generated-cases.md`](generated-cases.md) for method, tables and worked examples.
|
|
247
|
+
|
|
248
|
+
Nine of these cases are frozen as bytes in `data/corpus/`, each recording not just whether
|
|
249
|
+
the engine copes but *how* it fails — `round-trips`, `loses-fields` or `mis-attributes`,
|
|
250
|
+
down to the leaf paths involved. Four are cases the engine gets right, four where it drops
|
|
251
|
+
data, one where it invents it. The corpus is meant to grow: `--corpus-add` on the generator
|
|
252
|
+
keeps whatever the tool turns up next.
|
|
253
|
+
|
|
254
|
+
Three tests: `corpus.test.ts` walks the frozen cases, `generated-scatter.test.ts` sweeps
|
|
255
|
+
400 fresh ones each run and asserts the rule over counted populations, and
|
|
256
|
+
`fragment-contention.test.ts` shows the `Currency` mis-attribution is systemic. The
|
|
257
|
+
non-round-trip groups are written to be inverted, not deleted, when the repair lands.
|
|
258
|
+
|
|
207
259
|
### Phase 1 — the accessor seam
|
|
208
260
|
|
|
209
261
|
Give `SegmentDescription` `owns(pos)` and `forEachPosition(cb)`; move the four `msg-view`
|
|
@@ -267,6 +319,9 @@ protocol errors into wrong objects.
|
|
|
267
319
|
1. Should a collision found by phase 0 refuse repair for the colliding pair only, or for
|
|
268
320
|
the whole set containing them? The `qf50sp2` result argues for the pair — refusing all
|
|
269
321
|
of `NewOrderSingle` over one contended tag would give up a great deal for very little.
|
|
322
|
+
**No longer hypothetical:** phase 0b showed the shipped repair claiming the contended
|
|
323
|
+
`Currency` in 145 of 500 cases, so whichever answer is chosen has to be applied to the
|
|
324
|
+
existing repair and not only to the generalisation.
|
|
270
325
|
2. Should the collision map be computed once at dictionary load, or lazily on first repair?
|
|
271
326
|
3. Should a dictionary with collisions say so at load time? An operator onboarding a broker
|
|
272
327
|
dialect would want to know before a live session does, and phase 0 is cheap enough to
|
package/jsfix.test_client.txt
CHANGED
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=
|
|
2
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=
|
|
3
|
-
8=FIX.4.4|9=0000079|35=2|49=init-comp|56=accept-comp|34=2|57=fix|52=
|
|
4
|
-
8=FIX.4.4|9=0000112|35=4|49=accept-comp|56=init-comp|34=1|57=fix|43=Y|52=
|
|
5
|
-
8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=
|
|
6
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=
|
|
7
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=
|
|
8
|
-
8=FIX.4.4|9=0000079|35=2|49=init-comp|56=accept-comp|34=2|57=fix|52=
|
|
9
|
-
8=FIX.4.4|9=0000112|35=4|49=accept-comp|56=init-comp|34=1|57=fix|43=Y|52=
|
|
10
|
-
8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=
|
|
11
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=
|
|
12
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=
|
|
13
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=2|57=fix|52=
|
|
14
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=
|
|
15
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=
|
|
16
|
-
8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=
|
|
17
|
-
8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=
|
|
18
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=
|
|
19
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=
|
|
20
|
-
8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=
|
|
21
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=
|
|
22
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=
|
|
23
|
-
8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=0|57=fix|52=
|
|
24
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=
|
|
25
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=5|57=fix|52=
|
|
26
|
-
8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=
|
|
27
|
-
8=FIX.4.4|9=0000110|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=
|
|
28
|
-
8=FIX.4.4|9=0000125|35=3|49=accept-comp|56=init-comp|34=1|57=fix|52=
|
|
29
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=
|
|
30
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=
|
|
31
|
-
8=FIX.4.4|9=0000111|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=
|
|
32
|
-
8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=
|
|
33
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=
|
|
34
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=
|
|
35
|
-
8=FIX.4.4|9=0000146|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=
|
|
36
|
-
8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=
|
|
37
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=
|
|
38
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=
|
|
39
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=
|
|
40
|
-
8=FIX.4.4|9=0000145|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=
|
|
41
|
-
8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=
|
|
42
|
-
8=FIX.4.4|9=0000116|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=
|
|
43
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=
|
|
44
|
-
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=2|57=fix|52=
|
|
45
|
-
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=3|57=fix|52=
|
|
46
|
-
8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=
|
|
47
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=
|
|
48
|
-
8=FIX.4.4|9=0000116|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=
|
|
49
|
-
8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=2|57=fix|52=
|
|
50
|
-
8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=3|57=fix|52=
|
|
51
|
-
8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=4|57=fix|52=
|
|
52
|
-
8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=5|57=fix|52=
|
|
53
|
-
8=FIX.4.4|9=0000116|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=
|
|
54
|
-
8=FIX.4.4|9=0000116|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=
|
|
55
|
-
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=2|57=fix|52=
|
|
56
|
-
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=3|57=fix|52=
|
|
57
|
-
8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=2|57=fix|52=
|
|
58
|
-
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=4|57=fix|52=
|
|
59
|
-
8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=
|
|
60
|
-
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=
|
|
61
|
-
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=
|
|
62
|
-
8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=
|
|
1
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:34:32.252|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=103|
|
|
2
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260827-17:34:32.257|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=156|
|
|
3
|
+
8=FIX.4.4|9=0000079|35=2|49=init-comp|56=accept-comp|34=2|57=fix|52=20260827-17:34:32.258|7=1|16=1|10=244|
|
|
4
|
+
8=FIX.4.4|9=0000112|35=4|49=accept-comp|56=init-comp|34=1|57=fix|43=Y|52=20260827-17:34:32.262|122=20260827-17:34:32.261|123=Y|36=2|10=108|
|
|
5
|
+
8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260827-17:34:34.261|58=test_server confirming logout|10=087|
|
|
6
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:34:36.884|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=118|
|
|
7
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260827-17:34:36.886|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=168|
|
|
8
|
+
8=FIX.4.4|9=0000079|35=2|49=init-comp|56=accept-comp|34=2|57=fix|52=20260827-17:34:36.887|7=1|16=0|10=255|
|
|
9
|
+
8=FIX.4.4|9=0000112|35=4|49=accept-comp|56=init-comp|34=1|57=fix|43=Y|52=20260827-17:34:36.889|122=20260827-17:34:36.889|123=Y|36=2|10=147|
|
|
10
|
+
8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260827-17:34:38.888|58=test_server confirming logout|10=106|
|
|
11
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:34:41.290|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=105|
|
|
12
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260827-17:34:41.292|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=155|
|
|
13
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=2|57=fix|52=20260827-17:34:41.292|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=108|
|
|
14
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:34:41.720|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=103|
|
|
15
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260827-17:34:41.721|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=152|
|
|
16
|
+
8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260827-17:34:42.723|58=test_server confirming logout|10=089|
|
|
17
|
+
8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=3|57=fix|52=20260827-17:34:43.293|58=test_client initiate logout|10=110|
|
|
18
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:34:45.431|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=106|
|
|
19
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260827-17:34:45.432|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=155|
|
|
20
|
+
8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260827-17:34:46.434|58=test_server confirming logout|10=092|
|
|
21
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:34:49.031|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=106|
|
|
22
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260827-17:34:49.032|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=155|
|
|
23
|
+
8=FIX.4.4|9=0000101|35=5|49=init-comp|56=accept-comp|34=0|57=fix|52=20260827-17:34:50.033|58=test_client initiate logout|10=097|
|
|
24
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:34:52.431|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=104|
|
|
25
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=5|57=fix|52=20260827-17:34:52.432|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=157|
|
|
26
|
+
8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260827-17:34:53.434|58=test_server confirming logout|10=090|
|
|
27
|
+
8=FIX.4.4|9=0000110|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:34:55.818|98=0|141=Y|553=js-client|554=pwd-client|10=184|
|
|
28
|
+
8=FIX.4.4|9=0000125|35=3|49=accept-comp|56=init-comp|34=1|57=fix|52=20260827-17:34:55.819|45=1|372=A|373=1|58=msgType A missing required tag 108|10=018|
|
|
29
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:35:00.292|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=103|
|
|
30
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260827-17:35:00.294|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=153|
|
|
31
|
+
8=FIX.4.4|9=0000111|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=20260827-17:35:00.295|45=2|372=ZZ|373=11|58=msgType ZZ unknown|10=155|
|
|
32
|
+
8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260827-17:35:02.295|58=test_server confirming logout|10=091|
|
|
33
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:35:04.876|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=115|
|
|
34
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260827-17:35:04.877|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=164|
|
|
35
|
+
8=FIX.4.4|9=0000146|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=20260827-17:35:04.878|45=2|372=0|373=5|58=msgType 0 checksum failed. received = 95 computed = 143|10=087|
|
|
36
|
+
8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260827-17:35:06.878|58=test_server confirming logout|10=102|
|
|
37
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:35:08.876|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=119|
|
|
38
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:35:13.271|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=104|
|
|
39
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260827-17:35:13.272|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=153|
|
|
40
|
+
8=FIX.4.4|9=0000145|35=3|49=accept-comp|56=init-comp|34=2|57=fix|52=20260827-17:35:13.273|45=2|372=0|373=5|58=msgType 0 checksum failed. received = 95 computed = 59|10=033|
|
|
41
|
+
8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260827-17:35:15.275|58=test_server confirming logout|10=093|
|
|
42
|
+
8=FIX.4.4|9=0000116|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:35:17.650|98=0|108=2|141=Y|553=js-client|554=pwd-client|10=059|
|
|
43
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260827-17:35:17.651|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=158|
|
|
44
|
+
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=2|57=fix|52=20260827-17:35:19.656|112=Thu, 27 Aug 2026 17:35:19 GMT|10=173|
|
|
45
|
+
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=3|57=fix|52=20260827-17:35:21.658|112=Thu, 27 Aug 2026 17:35:21 GMT|10=162|
|
|
46
|
+
8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260827-17:35:23.654|58=test_server confirming logout|10=092|
|
|
47
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:35:26.141|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=104|
|
|
48
|
+
8=FIX.4.4|9=0000116|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260827-17:35:26.146|98=0|108=2|141=Y|553=js-server|554=pwd-server|10=107|
|
|
49
|
+
8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=2|57=fix|52=20260827-17:35:28.150|112=Thu, 27 Aug 2026 17:35:28 GMT|10=162|
|
|
50
|
+
8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=3|57=fix|52=20260827-17:35:30.153|112=Thu, 27 Aug 2026 17:35:30 GMT|10=152|
|
|
51
|
+
8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=4|57=fix|52=20260827-17:35:32.156|112=Thu, 27 Aug 2026 17:35:32 GMT|10=160|
|
|
52
|
+
8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=5|57=fix|52=20260827-17:35:34.148|58=test_server confirming logout|10=095|
|
|
53
|
+
8=FIX.4.4|9=0000116|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:35:36.520|98=0|108=2|141=Y|553=js-client|554=pwd-client|10=056|
|
|
54
|
+
8=FIX.4.4|9=0000116|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260827-17:35:36.521|98=0|108=5|141=Y|553=js-server|554=pwd-server|10=108|
|
|
55
|
+
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=2|57=fix|52=20260827-17:35:38.525|112=Thu, 27 Aug 2026 17:35:38 GMT|10=170|
|
|
56
|
+
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=3|57=fix|52=20260827-17:35:40.526|112=Thu, 27 Aug 2026 17:35:40 GMT|10=158|
|
|
57
|
+
8=FIX.4.4|9=0000104|35=0|49=accept-comp|56=init-comp|34=2|57=fix|52=20260827-17:35:41.531|112=Thu, 27 Aug 2026 17:35:41 GMT|10=155|
|
|
58
|
+
8=FIX.4.4|9=0000104|35=0|49=init-comp|56=accept-comp|34=4|57=fix|52=20260827-17:35:42.529|112=Thu, 27 Aug 2026 17:35:42 GMT|10=166|
|
|
59
|
+
8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=3|57=fix|52=20260827-17:35:44.522|58=test_server confirming logout|10=090|
|
|
60
|
+
8=FIX.4.4|9=0000117|35=A|49=init-comp|56=accept-comp|34=1|57=fix|52=20260827-17:37:54.447|98=0|108=30|141=Y|553=js-client|554=pwd-client|10=116|
|
|
61
|
+
8=FIX.4.4|9=0000117|35=A|49=accept-comp|56=init-comp|34=1|57=fix|52=20260827-17:37:54.455|98=0|108=30|141=Y|553=js-server|554=pwd-server|10=163|
|
|
62
|
+
8=FIX.4.4|9=0000103|35=5|49=accept-comp|56=init-comp|34=2|57=fix|52=20260827-17:37:55.459|58=test_server confirming logout|10=102|
|