jspurefix 5.11.2 → 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.
Files changed (104) hide show
  1. package/.gitattributes +4 -0
  2. package/dist/buffer/index.d.ts +6 -0
  3. package/dist/buffer/index.js +6 -0
  4. package/dist/buffer/index.js.map +1 -1
  5. package/dist/collections/index.d.ts +1 -0
  6. package/dist/collections/index.js +16 -0
  7. package/dist/collections/index.js.map +1 -1
  8. package/dist/config/winston-logger.js +2 -0
  9. package/dist/config/winston-logger.js.map +1 -1
  10. package/dist/dictionary/contained/index.d.ts +3 -0
  11. package/dist/dictionary/contained/index.js +3 -0
  12. package/dist/dictionary/contained/index.js.map +1 -1
  13. package/dist/dictionary/index.d.ts +5 -0
  14. package/dist/dictionary/index.js +5 -0
  15. package/dist/dictionary/index.js.map +1 -1
  16. package/dist/generator/applicability.d.ts +3 -0
  17. package/dist/generator/applicability.js +48 -0
  18. package/dist/generator/applicability.js.map +1 -0
  19. package/dist/generator/case-builder.d.ts +34 -0
  20. package/dist/generator/case-builder.js +111 -0
  21. package/dist/generator/case-builder.js.map +1 -0
  22. package/dist/generator/corpus-store.d.ts +43 -0
  23. package/dist/generator/corpus-store.js +115 -0
  24. package/dist/generator/corpus-store.js.map +1 -0
  25. package/dist/generator/index.d.ts +12 -0
  26. package/dist/generator/index.js +29 -0
  27. package/dist/generator/index.js.map +1 -0
  28. package/dist/generator/instrument-universe.d.ts +54 -0
  29. package/dist/generator/instrument-universe.js +286 -0
  30. package/dist/generator/instrument-universe.js.map +1 -0
  31. package/dist/generator/layout.d.ts +46 -0
  32. package/dist/generator/layout.js +208 -0
  33. package/dist/generator/layout.js.map +1 -0
  34. package/dist/generator/market-context.d.ts +64 -0
  35. package/dist/generator/market-context.js +119 -0
  36. package/dist/generator/market-context.js.map +1 -0
  37. package/dist/generator/outcome.d.ts +16 -0
  38. package/dist/generator/outcome.js +71 -0
  39. package/dist/generator/outcome.js.map +1 -0
  40. package/dist/generator/realistic-generator.d.ts +53 -0
  41. package/dist/generator/realistic-generator.js +275 -0
  42. package/dist/generator/realistic-generator.js.map +1 -0
  43. package/dist/generator/rng.d.ts +12 -0
  44. package/dist/generator/rng.js +60 -0
  45. package/dist/generator/rng.js.map +1 -0
  46. package/dist/generator/scatter.d.ts +50 -0
  47. package/dist/generator/scatter.js +285 -0
  48. package/dist/generator/scatter.js.map +1 -0
  49. package/dist/generator/scenarios.d.ts +13 -0
  50. package/dist/generator/scenarios.js +139 -0
  51. package/dist/generator/scenarios.js.map +1 -0
  52. package/dist/generator/value-conventions.d.ts +15 -0
  53. package/dist/generator/value-conventions.js +217 -0
  54. package/dist/generator/value-conventions.js.map +1 -0
  55. package/dist/index.d.ts +6 -0
  56. package/dist/index.js +4 -0
  57. package/dist/index.js.map +1 -1
  58. package/dist/jsfix-cmd.d.ts +5 -0
  59. package/dist/jsfix-cmd.js +161 -0
  60. package/dist/jsfix-cmd.js.map +1 -1
  61. package/dist/store/fix-msg-ascii-store-resend.js +2 -2
  62. package/dist/store/fix-msg-ascii-store-resend.js.map +1 -1
  63. package/dist/store/fix-msg-store-record.d.ts +1 -1
  64. package/dist/store/fix-msg-store-record.js.map +1 -1
  65. package/dist/store/index.d.ts +1 -0
  66. package/dist/store/index.js +1 -0
  67. package/dist/store/index.js.map +1 -1
  68. package/dist/transport/index.d.ts +7 -0
  69. package/dist/transport/index.js +7 -0
  70. package/dist/transport/index.js.map +1 -1
  71. package/dist/transport/session/index.d.ts +1 -0
  72. package/dist/transport/session/index.js +1 -0
  73. package/dist/transport/session/index.js.map +1 -1
  74. package/docs/generated-cases.md +237 -0
  75. package/docs/instrumentation.md +14 -0
  76. package/docs/scattered-components.md +60 -5
  77. package/jsfix.test_client.txt +62 -62
  78. package/jsfix.test_server.txt +72 -72
  79. package/package.json +5 -2
  80. package/src/buffer/index.ts +6 -0
  81. package/src/collections/index.ts +1 -1
  82. package/src/config/winston-logger.ts +8 -0
  83. package/src/dictionary/contained/index.ts +3 -0
  84. package/src/dictionary/index.ts +5 -0
  85. package/src/generator/applicability.ts +87 -0
  86. package/src/generator/case-builder.ts +167 -0
  87. package/src/generator/corpus-store.ts +166 -0
  88. package/src/generator/index.ts +12 -0
  89. package/src/generator/instrument-universe.ts +347 -0
  90. package/src/generator/layout.ts +279 -0
  91. package/src/generator/market-context.ts +207 -0
  92. package/src/generator/outcome.ts +102 -0
  93. package/src/generator/realistic-generator.ts +404 -0
  94. package/src/generator/rng.ts +92 -0
  95. package/src/generator/scatter.ts +432 -0
  96. package/src/generator/scenarios.ts +167 -0
  97. package/src/generator/value-conventions.ts +295 -0
  98. package/src/index.ts +12 -0
  99. package/src/jsfix-cmd.ts +204 -0
  100. package/src/store/fix-msg-ascii-store-resend.ts +2 -1
  101. package/src/store/fix-msg-store-record.ts +4 -1
  102. package/src/store/index.ts +1 -0
  103. package/src/transport/index.ts +10 -0
  104. package/src/transport/session/index.ts +1 -0
@@ -0,0 +1,275 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RealisticGenerator = void 0;
4
+ const contained_1 = require("../dictionary/contained");
5
+ const tag_type_1 = require("../buffer/tag/tag-type");
6
+ const rng_1 = require("./rng");
7
+ const market_context_1 = require("./market-context");
8
+ const value_conventions_1 = require("./value-conventions");
9
+ const instrument_universe_1 = require("./instrument-universe");
10
+ const applicability_1 = require("./applicability");
11
+ const coreSets = /^(Instrument|InstrumentLeg|UnderlyingInstrument|OrderQtyData|Parties|NestedParties[0-9]?|InstrmtLegGrp|TrdInstrmtLegGrp|InstrmtMDReqGrp|MDIncGrp|MDFullGrp)$/;
12
+ const legSet = /Leg(s|Grp|$|[A-Z])|InstrmtLeg/;
13
+ const underlyingSet = /Und(erlying|Instrmt)/;
14
+ class RealisticGenerator {
15
+ constructor(definitions, options = {}) {
16
+ var _a, _b, _c, _d, _e, _f;
17
+ this.definitions = definitions;
18
+ this.options = options;
19
+ this.assetClass = instrument_universe_1.AssetClass.Equity;
20
+ this.rng = new rng_1.Rng((_a = options.seed) !== null && _a !== void 0 ? _a : 0x5eed);
21
+ this.density = (_b = options.density) !== null && _b !== void 0 ? _b : 1.0;
22
+ this.maxDepth = (_c = options.maxDepth) !== null && _c !== void 0 ? _c : 6;
23
+ this.maxGroupInstances = (_d = options.maxGroupInstances) !== null && _d !== void 0 ? _d : 2;
24
+ const include = (_e = options.include) !== null && _e !== void 0 ? _e : [];
25
+ this.forcedTags = include.filter(s => /^[0-9]+$/.test(s)).map(s => parseInt(s, 10));
26
+ this.forced = new Set(include.filter(s => !/^[0-9]+$/.test(s)));
27
+ this.suppressed = new Set((_f = options.exclude) !== null && _f !== void 0 ? _f : []);
28
+ }
29
+ generate(msgType) {
30
+ var _a, _b;
31
+ const definition = this.definitions.message.get(msgType);
32
+ if (!definition) {
33
+ throw new Error(`definitions do not contain type ${msgType}`);
34
+ }
35
+ const instrument = this.resolveInstrument();
36
+ const market = new market_context_1.MarketContext({
37
+ rng: this.rng,
38
+ instrument,
39
+ assetClass: this.options.assetClass,
40
+ asOf: this.options.asOf,
41
+ senderCompId: this.options.senderCompId,
42
+ targetCompId: this.options.targetCompId
43
+ });
44
+ const conventions = new value_conventions_1.ValueConventions(market);
45
+ this.assetClass = market.instrument.assetClass;
46
+ const state = { path: [], depth: 0, instance: 0, mustInclude: this.forcedTags };
47
+ const object = (_a = this.build(definition, market, conventions, state)) !== null && _a !== void 0 ? _a : {};
48
+ return {
49
+ msgType: (_b = definition.msgType) !== null && _b !== void 0 ? _b : msgType,
50
+ name: definition.name,
51
+ object,
52
+ market,
53
+ definition
54
+ };
55
+ }
56
+ resolveInstrument() {
57
+ const wanted = this.options.instrument;
58
+ if (!wanted)
59
+ return undefined;
60
+ if (typeof wanted !== 'string')
61
+ return wanted;
62
+ const found = instrument_universe_1.InstrumentUniverse.byName(wanted);
63
+ if (!found) {
64
+ throw new Error(`no instrument named ${wanted} - try one of ${instrument_universe_1.InstrumentUniverse.all.map(i => i.symbol).join(', ')}`);
65
+ }
66
+ return found;
67
+ }
68
+ build(set, market, conventions, state) {
69
+ const o = {};
70
+ const fields = set.fields;
71
+ for (let i = 0; i < fields.length; ++i) {
72
+ const field = fields[i];
73
+ switch (field.type) {
74
+ case contained_1.ContainedFieldType.Simple:
75
+ this.simple(o, set, field, i, conventions, state);
76
+ break;
77
+ case contained_1.ContainedFieldType.Component:
78
+ this.component(o, field, market, conventions, state);
79
+ break;
80
+ case contained_1.ContainedFieldType.Group:
81
+ this.group(o, field, market, conventions, state);
82
+ break;
83
+ default:
84
+ break;
85
+ }
86
+ }
87
+ return Object.keys(o).length > 0 ? o : null;
88
+ }
89
+ simple(o, set, sf, index, conventions, state) {
90
+ const definition = sf.definition;
91
+ if (definition.tagType === tag_type_1.TagType.Length && RealisticGenerator.rawFollows(set, index)) {
92
+ return;
93
+ }
94
+ const dotted = RealisticGenerator.dot(state.path, sf.name);
95
+ if (this.suppressed.has(dotted) || this.suppressed.has(sf.name))
96
+ return;
97
+ const must = state.mustInclude.includes(definition.tag);
98
+ if (!must && !sf.required && !this.isForced(dotted, sf.name)) {
99
+ if (!(0, applicability_1.fieldApplies)(sf.name, this.assetClass))
100
+ return;
101
+ if (!this.rng.bool(this.probability(sf)))
102
+ return;
103
+ }
104
+ const fieldContext = { path: state.path, instance: state.instance };
105
+ const value = conventions.value(definition, fieldContext);
106
+ if (value != null && value !== '') {
107
+ o[sf.name] = value;
108
+ }
109
+ }
110
+ component(o, cf, market, conventions, state) {
111
+ const name = cf.name;
112
+ if (name === 'StandardHeader' || name === 'StandardTrailer')
113
+ return;
114
+ const dotted = RealisticGenerator.dot(state.path, name);
115
+ if (this.suppressed.has(dotted) || this.suppressed.has(name))
116
+ return;
117
+ const definition = cf.definition;
118
+ const carries = RealisticGenerator.carriesAny(definition, state.mustInclude);
119
+ if (!cf.required && !carries && !this.isForced(dotted, name)) {
120
+ if (state.depth >= this.maxDepth)
121
+ return;
122
+ if (!(0, applicability_1.setApplies)(name, this.assetClass))
123
+ return;
124
+ if (!this.rng.bool(this.componentProbability(name, state.depth)))
125
+ return;
126
+ }
127
+ const restore = this.enter(name, market, state.instance);
128
+ const child = this.build(definition, market, conventions, {
129
+ path: [...state.path, name],
130
+ depth: state.depth + 1,
131
+ instance: state.instance,
132
+ mustInclude: state.mustInclude.filter(t => definition.containedTag[t])
133
+ });
134
+ restore();
135
+ if (child) {
136
+ o[name] = child;
137
+ }
138
+ }
139
+ group(o, gf, market, conventions, state) {
140
+ var _a;
141
+ const name = gf.name;
142
+ const dotted = RealisticGenerator.dot(state.path, name);
143
+ if (this.suppressed.has(dotted) || this.suppressed.has(name))
144
+ return;
145
+ const definition = gf.definition;
146
+ const carries = RealisticGenerator.carriesAny(definition, state.mustInclude);
147
+ if (!gf.required && !carries && !this.isForced(dotted, name)) {
148
+ if (state.depth >= this.maxDepth)
149
+ return;
150
+ if (!(0, applicability_1.setApplies)(name, this.assetClass))
151
+ return;
152
+ if (!this.rng.bool(this.groupProbability(name, state.depth)))
153
+ return;
154
+ }
155
+ const isLegs = legSet.test(name) || legSet.test(definition.name);
156
+ const legs = market.instrument.legs;
157
+ const count = isLegs && legs && legs.length > 0
158
+ ? legs.length
159
+ : this.instances(state.depth);
160
+ const delimiter = (_a = definition.firstSimple) === null || _a === void 0 ? void 0 : _a.definition.tag;
161
+ const inherited = state.mustInclude.filter(t => definition.containedTag[t]);
162
+ const must = delimiter ? [delimiter, ...inherited] : inherited;
163
+ const instances = [];
164
+ for (let i = 0; i < count; ++i) {
165
+ const restore = this.enter(name, market, i);
166
+ const instance = this.build(definition, market, conventions, {
167
+ path: [...state.path, name],
168
+ depth: state.depth + 1,
169
+ instance: i,
170
+ mustInclude: must
171
+ });
172
+ restore();
173
+ if (instance && RealisticGenerator.hasOwnSimple(instance, definition)) {
174
+ instances.push(instance);
175
+ }
176
+ }
177
+ if (instances.length > 0) {
178
+ o[name] = instances;
179
+ }
180
+ }
181
+ enter(name, market, instance) {
182
+ var _a;
183
+ const wasLeg = market.leg;
184
+ const wasUnderlying = market.underlying;
185
+ const legs = market.instrument.legs;
186
+ if (legSet.test(name) && legs && legs.length > 0) {
187
+ market.leg = legs[instance % legs.length];
188
+ }
189
+ else if (underlyingSet.test(name)) {
190
+ market.underlying = (_a = market.underlying) !== null && _a !== void 0 ? _a : instrument_universe_1.InstrumentUniverse.choose(this.rng, market.instrument.assetClass === instrument_universe_1.AssetClass.Spread ? instrument_universe_1.AssetClass.Future : instrument_universe_1.AssetClass.Equity);
191
+ }
192
+ else {
193
+ return () => { };
194
+ }
195
+ return () => {
196
+ market.leg = wasLeg;
197
+ market.underlying = wasUnderlying;
198
+ };
199
+ }
200
+ probability(sf) {
201
+ const tag = sf.definition.tag;
202
+ let base;
203
+ if (value_conventions_1.ValueConventions.knows(tag)) {
204
+ base = 0.75;
205
+ }
206
+ else if (tag < 500) {
207
+ base = 0.3;
208
+ }
209
+ else {
210
+ base = 0.08;
211
+ }
212
+ return Math.min(1, base * this.density);
213
+ }
214
+ componentProbability(name, depth) {
215
+ if (coreSets.test(name))
216
+ return Math.min(1, 0.9 * Math.max(0.5, this.density));
217
+ return Math.min(1, (0.45 / (depth + 1)) * this.density);
218
+ }
219
+ groupProbability(name, depth) {
220
+ if (coreSets.test(name))
221
+ return Math.min(1, 0.8 * Math.max(0.5, this.density));
222
+ return Math.min(1, (0.35 / (depth + 1)) * this.density);
223
+ }
224
+ instances(depth) {
225
+ const cap = Math.max(1, this.maxGroupInstances - depth + 1);
226
+ return this.rng.int(1, Math.min(this.maxGroupInstances, cap));
227
+ }
228
+ isForced(dotted, name) {
229
+ if (this.forced.has(dotted) || this.forced.has(name))
230
+ return true;
231
+ for (const f of this.forced) {
232
+ if (f.startsWith(`${dotted}.`))
233
+ return true;
234
+ }
235
+ return false;
236
+ }
237
+ static hasOwnSimple(o, set) {
238
+ for (const field of set.fields) {
239
+ switch (field.type) {
240
+ case contained_1.ContainedFieldType.Simple:
241
+ if (o[field.name] != null && o[field.name] !== '')
242
+ return true;
243
+ break;
244
+ case contained_1.ContainedFieldType.Component: {
245
+ const cf = field;
246
+ const child = o[cf.name];
247
+ if (child && RealisticGenerator.hasOwnSimple(child, cf.definition))
248
+ return true;
249
+ break;
250
+ }
251
+ default:
252
+ break;
253
+ }
254
+ }
255
+ return false;
256
+ }
257
+ static carriesAny(set, tags) {
258
+ for (const t of tags) {
259
+ if (set.containedTag[t])
260
+ return true;
261
+ }
262
+ return false;
263
+ }
264
+ static rawFollows(set, index) {
265
+ const next = set.fields[index + 1];
266
+ if (!next || next.type !== contained_1.ContainedFieldType.Simple)
267
+ return false;
268
+ return next.definition.tagType === tag_type_1.TagType.RawData;
269
+ }
270
+ static dot(path, name) {
271
+ return path.length > 0 ? `${path.join('.')}.${name}` : name;
272
+ }
273
+ }
274
+ exports.RealisticGenerator = RealisticGenerator;
275
+ //# sourceMappingURL=realistic-generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realistic-generator.js","sourceRoot":"","sources":["../../src/generator/realistic-generator.ts"],"names":[],"mappings":"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","sourcesContent":["import { ILooseObject } from '../collections/collection'\nimport {\n ContainedComponentField,\n ContainedFieldType,\n ContainedGroupField,\n ContainedSimpleField,\n IContainedSet\n} from '../dictionary/contained'\nimport { FixDefinitions, MessageDefinition } from '../dictionary/definition'\nimport { TagType } from '../buffer/tag/tag-type'\nimport { Rng } from './rng'\nimport { MarketContext } from './market-context'\nimport { IFieldContext, ValueConventions } from './value-conventions'\nimport { AssetClass, IInstrumentSpec, InstrumentUniverse } from './instrument-universe'\nimport { fieldApplies, setApplies } from './applicability'\n\n/**\n * Builds an object for a message type that a counterparty might plausibly have sent.\n *\n * The difference from `MessageGenerator` is what gets left out. The old generator asked\n * \"should this tag be present\" of every tag independently at one probability, which at\n * any useful density produces every field in the dictionary and a message no human can\n * read. Here optional fields are tiered - a field the generator understands is likely,\n * an ordinary one is occasional, an exotic one is rare - so the shape of the output\n * resembles the shape of real traffic even before the values are looked at.\n *\n * Two structural guarantees the encoder depends on are maintained by construction:\n *\n * - every instance of a repeating group carries the group delimiter, propagated down\n * through whatever nested component happens to own it;\n * - a component that ends up with no fields at all is dropped rather than emitted\n * empty.\n */\n\nexport interface IGeneratorOptions {\n /** same seed, same message, byte for byte */\n readonly seed?: number\n /**\n * multiplier on the optional field probabilities. 0 gives required fields only;\n * 1 is the natural rate; above 1 fattens the message toward the old behaviour.\n */\n readonly density?: number\n readonly asOf?: Date\n readonly instrument?: string | IInstrumentSpec\n readonly assetClass?: AssetClass\n /** optional components below this depth are not populated; required ones still are */\n readonly maxDepth?: number\n /** upper bound on instances of any one group */\n readonly maxGroupInstances?: number\n /**\n * dotted paths or bare names that must appear, e.g. `Instrument` or\n * `TrdCapRptSideGrp.Parties`. Used by the scatter planner to guarantee the shape it\n * is about to take apart.\n */\n readonly include?: readonly string[]\n readonly exclude?: readonly string[]\n readonly senderCompId?: string\n readonly targetCompId?: string\n}\n\nexport interface IGeneratedMessage {\n readonly msgType: string\n readonly name: string\n readonly object: ILooseObject\n readonly market: MarketContext\n readonly definition: MessageDefinition\n}\n\ninterface IWalkState {\n readonly path: readonly string[]\n readonly depth: number\n readonly instance: number\n /** tags that must be emitted somewhere below here, whatever the dice say */\n readonly mustInclude: readonly number[]\n}\n\n/**\n * Components a message of any kind is very likely to carry. Without this the tiering\n * treats `Instrument` as no more probable than any other optional component, and a\n * market data refresh comes out describing the price of nothing at all.\n */\nconst coreSets = /^(Instrument|InstrumentLeg|UnderlyingInstrument|OrderQtyData|Parties|NestedParties[0-9]?|InstrmtLegGrp|TrdInstrmtLegGrp|InstrmtMDReqGrp|MDIncGrp|MDFullGrp)$/\n\n/** a set that names legs, as opposed to a field that merely starts with Leg */\nconst legSet = /Leg(s|Grp|$|[A-Z])|InstrmtLeg/\n/** UndInstrmtGrp and UnderlyingInstrument both, since the abbreviation is not uniform */\nconst underlyingSet = /Und(erlying|Instrmt)/\n\nexport class RealisticGenerator {\n private readonly rng: Rng\n private readonly density: number\n private readonly maxDepth: number\n private readonly maxGroupInstances: number\n private readonly forced: Set<string>\n private readonly forcedTags: number[]\n private readonly suppressed: Set<string>\n private assetClass: AssetClass = AssetClass.Equity\n\n constructor (\n public readonly definitions: FixDefinitions,\n public readonly options: IGeneratorOptions = {}) {\n this.rng = new Rng(options.seed ?? 0x5eed)\n this.density = options.density ?? 1.0\n this.maxDepth = options.maxDepth ?? 6\n this.maxGroupInstances = options.maxGroupInstances ?? 2\n // an entry that is all digits is a tag, which is the portable way to name a field:\n // repository dictionaries call a group TrdInstrmtLegGrp and QuickFIX calls it NoLegs,\n // but both agree that it is 555\n const include = options.include ?? []\n this.forcedTags = include.filter(s => /^[0-9]+$/.test(s)).map(s => parseInt(s, 10))\n this.forced = new Set<string>(include.filter(s => !/^[0-9]+$/.test(s)))\n this.suppressed = new Set<string>(options.exclude ?? [])\n }\n\n public generate (msgType: string): IGeneratedMessage {\n const definition = this.definitions.message.get(msgType)\n if (!definition) {\n throw new Error(`definitions do not contain type ${msgType}`)\n }\n const instrument = this.resolveInstrument()\n const market = new MarketContext({\n rng: this.rng,\n instrument,\n assetClass: this.options.assetClass,\n asOf: this.options.asOf,\n senderCompId: this.options.senderCompId,\n targetCompId: this.options.targetCompId\n })\n const conventions = new ValueConventions(market)\n this.assetClass = market.instrument.assetClass\n const state: IWalkState = { path: [], depth: 0, instance: 0, mustInclude: this.forcedTags }\n const object = this.build(definition, market, conventions, state) ?? {}\n return {\n msgType: definition.msgType ?? msgType,\n name: definition.name,\n object,\n market,\n definition\n }\n }\n\n private resolveInstrument (): IInstrumentSpec | undefined {\n const wanted = this.options.instrument\n if (!wanted) return undefined\n if (typeof wanted !== 'string') return wanted\n const found = InstrumentUniverse.byName(wanted)\n if (!found) {\n throw new Error(`no instrument named ${wanted} - try one of ${InstrumentUniverse.all.map(i => i.symbol).join(', ')}`)\n }\n return found\n }\n\n private build (\n set: IContainedSet,\n market: MarketContext,\n conventions: ValueConventions,\n state: IWalkState): ILooseObject | null {\n const o: ILooseObject = {}\n const fields = set.fields\n for (let i = 0; i < fields.length; ++i) {\n const field = fields[i]\n switch (field.type) {\n case ContainedFieldType.Simple:\n this.simple(o, set, field as ContainedSimpleField, i, conventions, state)\n break\n case ContainedFieldType.Component:\n this.component(o, field as ContainedComponentField, market, conventions, state)\n break\n case ContainedFieldType.Group:\n this.group(o, field as ContainedGroupField, market, conventions, state)\n break\n default:\n break\n }\n }\n return Object.keys(o).length > 0 ? o : null\n }\n\n private simple (\n o: ILooseObject,\n set: IContainedSet,\n sf: ContainedSimpleField,\n index: number,\n conventions: ValueConventions,\n state: IWalkState): void {\n const definition = sf.definition\n // the encoder writes a Length from the RawData that follows it, so supplying one\n // here would only give it the chance to disagree\n if (definition.tagType === TagType.Length && RealisticGenerator.rawFollows(set, index)) {\n return\n }\n const dotted = RealisticGenerator.dot(state.path, sf.name)\n if (this.suppressed.has(dotted) || this.suppressed.has(sf.name)) return\n const must = state.mustInclude.includes(definition.tag)\n if (!must && !sf.required && !this.isForced(dotted, sf.name)) {\n if (!fieldApplies(sf.name, this.assetClass)) return\n if (!this.rng.bool(this.probability(sf))) return\n }\n const fieldContext: IFieldContext = { path: state.path, instance: state.instance }\n const value = conventions.value(definition, fieldContext)\n if (value != null && value !== '') {\n o[sf.name] = value\n }\n }\n\n private component (\n o: ILooseObject,\n cf: ContainedComponentField,\n market: MarketContext,\n conventions: ValueConventions,\n state: IWalkState): void {\n const name = cf.name\n if (name === 'StandardHeader' || name === 'StandardTrailer') return\n const dotted = RealisticGenerator.dot(state.path, name)\n if (this.suppressed.has(dotted) || this.suppressed.has(name)) return\n\n const definition = cf.definition\n const carries = RealisticGenerator.carriesAny(definition, state.mustInclude)\n if (!cf.required && !carries && !this.isForced(dotted, name)) {\n if (state.depth >= this.maxDepth) return\n if (!setApplies(name, this.assetClass)) return\n if (!this.rng.bool(this.componentProbability(name, state.depth))) return\n }\n const restore = this.enter(name, market, state.instance)\n const child = this.build(definition, market, conventions, {\n path: [...state.path, name],\n depth: state.depth + 1,\n instance: state.instance,\n // only the tags this component can actually reach travel further down\n mustInclude: state.mustInclude.filter(t => definition.containedTag[t])\n })\n restore()\n if (child) {\n o[name] = child\n }\n }\n\n private group (\n o: ILooseObject,\n gf: ContainedGroupField,\n market: MarketContext,\n conventions: ValueConventions,\n state: IWalkState): void {\n const name = gf.name\n const dotted = RealisticGenerator.dot(state.path, name)\n if (this.suppressed.has(dotted) || this.suppressed.has(name)) return\n\n const definition = gf.definition\n const carries = RealisticGenerator.carriesAny(definition, state.mustInclude)\n if (!gf.required && !carries && !this.isForced(dotted, name)) {\n if (state.depth >= this.maxDepth) return\n if (!setApplies(name, this.assetClass)) return\n if (!this.rng.bool(this.groupProbability(name, state.depth))) return\n }\n\n const isLegs = legSet.test(name) || legSet.test(definition.name)\n const legs = market.instrument.legs\n // a strategy has exactly the legs it has, so the group size is not a dice roll\n const count = isLegs && legs && legs.length > 0\n ? legs.length\n : this.instances(state.depth)\n\n // every instance has to open with the group delimiter or the encoder rejects it,\n // and the delimiter may be owned by a component nested inside the instance body\n const delimiter = definition.firstSimple?.definition.tag\n const inherited = state.mustInclude.filter(t => definition.containedTag[t])\n const must = delimiter ? [delimiter, ...inherited] : inherited\n\n const instances: ILooseObject[] = []\n for (let i = 0; i < count; ++i) {\n const restore = this.enter(name, market, i)\n const instance = this.build(definition, market, conventions, {\n path: [...state.path, name],\n depth: state.depth + 1,\n instance: i,\n mustInclude: must\n })\n restore()\n // an instance whose only content is a nested group carries no delimiter, and the\n // encoder rejects the whole group for it. This happens where `firstSimple` cannot\n // name a delimiter to force - a group whose body opens with another group - so the\n // guarantee above is not always enough and the shape has to be checked for.\n if (instance && RealisticGenerator.hasOwnSimple(instance, definition)) {\n instances.push(instance)\n }\n }\n\n if (instances.length > 0) {\n o[name] = instances\n }\n }\n\n /**\n * Descending into a set that names legs or underlyings moves the market context onto\n * that leg or underlying, so `LegPrice` inside the second leg resolves against the\n * second contract without the value layer knowing where it is. Returns the undo, so\n * the context is restored however the walk below it turns out.\n *\n * Both a group and the component inside it are checked, because dictionaries disagree\n * about which one carries the name - `UndInstrmtGrp` wrapping `UnderlyingInstrument`\n * in the repository rendering, a bare `NoUnderlyings` in QuickFIX.\n */\n private enter (name: string, market: MarketContext, instance: number): () => void {\n const wasLeg = market.leg\n const wasUnderlying = market.underlying\n const legs = market.instrument.legs\n if (legSet.test(name) && legs && legs.length > 0) {\n market.leg = legs[instance % legs.length]\n } else if (underlyingSet.test(name)) {\n market.underlying = market.underlying ?? InstrumentUniverse.choose(\n this.rng,\n market.instrument.assetClass === AssetClass.Spread ? AssetClass.Future : AssetClass.Equity)\n } else {\n return () => {}\n }\n return () => {\n market.leg = wasLeg\n market.underlying = wasUnderlying\n }\n }\n\n /**\n * How likely an optional simple field is to appear. A field the value layer knows by\n * tag is one a real message of this type probably carries; a low numbered tag is\n * everyday FIX; everything else is somebody else's extension and should be rare.\n */\n private probability (sf: ContainedSimpleField): number {\n const tag = sf.definition.tag\n let base: number\n if (ValueConventions.knows(tag)) {\n base = 0.75\n } else if (tag < 500) {\n base = 0.3\n } else {\n base = 0.08\n }\n return Math.min(1, base * this.density)\n }\n\n private componentProbability (name: string, depth: number): number {\n if (coreSets.test(name)) return Math.min(1, 0.9 * Math.max(0.5, this.density))\n return Math.min(1, (0.45 / (depth + 1)) * this.density)\n }\n\n private groupProbability (name: string, depth: number): number {\n if (coreSets.test(name)) return Math.min(1, 0.8 * Math.max(0.5, this.density))\n return Math.min(1, (0.35 / (depth + 1)) * this.density)\n }\n\n private instances (depth: number): number {\n const cap = Math.max(1, this.maxGroupInstances - depth + 1)\n return this.rng.int(1, Math.min(this.maxGroupInstances, cap))\n }\n\n private isForced (dotted: string, name: string): boolean {\n if (this.forced.has(dotted) || this.forced.has(name)) return true\n // forcing a path forces everything above it\n for (const f of this.forced) {\n if (f.startsWith(`${dotted}.`)) return true\n }\n return false\n }\n\n /**\n * whether this object emits at least one simple field at its own level - through\n * nested components, which the encoder counts as the same level, but not through a\n * group, which is framed separately and cannot serve as a delimiter\n */\n private static hasOwnSimple (o: ILooseObject, set: IContainedSet): boolean {\n for (const field of set.fields) {\n switch (field.type) {\n case ContainedFieldType.Simple:\n if (o[field.name] != null && o[field.name] !== '') return true\n break\n case ContainedFieldType.Component: {\n const cf = field as ContainedComponentField\n const child = o[cf.name]\n if (child && RealisticGenerator.hasOwnSimple(child as ILooseObject, cf.definition)) return true\n break\n }\n default:\n break\n }\n }\n return false\n }\n\n private static carriesAny (set: IContainedSet, tags: readonly number[]): boolean {\n for (const t of tags) {\n if (set.containedTag[t]) return true\n }\n return false\n }\n\n private static rawFollows (set: IContainedSet, index: number): boolean {\n const next = set.fields[index + 1]\n if (!next || next.type !== ContainedFieldType.Simple) return false\n return (next as ContainedSimpleField).definition.tagType === TagType.RawData\n }\n\n private static dot (path: readonly string[], name: string): string {\n return path.length > 0 ? `${path.join('.')}.${name}` : name\n }\n}\n"]}
@@ -0,0 +1,12 @@
1
+ export declare class Rng {
2
+ private state;
3
+ constructor(seed?: number);
4
+ next(): number;
5
+ int(min: number, max: number): number;
6
+ bool(probability?: number): boolean;
7
+ pick<T>(from: readonly T[]): T;
8
+ frontBiased(count: number, bias?: number): number;
9
+ around(centre: number, spreadPct: number, tick: number): number;
10
+ private static decimals;
11
+ shuffled<T>(from: readonly T[]): T[];
12
+ }
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Rng = void 0;
4
+ class Rng {
5
+ constructor(seed = 0x5eed) {
6
+ this.state = (seed >>> 0) || 0x9e3779b9;
7
+ }
8
+ next() {
9
+ this.state = (this.state + 0x6d2b79f5) >>> 0;
10
+ let t = this.state;
11
+ t = Math.imul(t ^ (t >>> 15), t | 1);
12
+ t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
13
+ return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
14
+ }
15
+ int(min, max) {
16
+ if (max < min)
17
+ return min;
18
+ return min + Math.floor(this.next() * (max - min + 1));
19
+ }
20
+ bool(probability = 0.5) {
21
+ return this.next() < probability;
22
+ }
23
+ pick(from) {
24
+ return from[this.int(0, from.length - 1)];
25
+ }
26
+ frontBiased(count, bias = 3) {
27
+ if (count <= 1)
28
+ return 0;
29
+ return Math.min(count - 1, Math.floor(Math.pow(this.next(), bias) * count));
30
+ }
31
+ around(centre, spreadPct, tick) {
32
+ const move = centre * spreadPct * (this.next() * 2 - 1);
33
+ const raw = centre + move;
34
+ const snapped = Math.round(raw / tick) * tick;
35
+ const dp = Rng.decimals(tick);
36
+ return Number(snapped.toFixed(dp));
37
+ }
38
+ static decimals(tick) {
39
+ const s = tick.toString();
40
+ const dot = s.indexOf('.');
41
+ if (dot < 0)
42
+ return 0;
43
+ const exp = s.indexOf('e');
44
+ if (exp > 0)
45
+ return Math.min(10, parseInt(s.substring(exp + 2), 10));
46
+ return Math.min(10, s.length - dot - 1);
47
+ }
48
+ shuffled(from) {
49
+ const a = from.slice();
50
+ for (let i = a.length - 1; i > 0; --i) {
51
+ const j = this.int(0, i);
52
+ const t = a[i];
53
+ a[i] = a[j];
54
+ a[j] = t;
55
+ }
56
+ return a;
57
+ }
58
+ }
59
+ exports.Rng = Rng;
60
+ //# sourceMappingURL=rng.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rng.js","sourceRoot":"","sources":["../../src/generator/rng.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A small deterministic generator, so a corpus written today reproduces byte for byte\n * tomorrow. `Math.random` is fine for a benchmark that only wants volume; it is no use\n * at all for a fixture someone has to debug, where \"run it again and get the same\n * message\" is the whole point.\n *\n * mulberry32 - 32 bits of state, uniform enough for choosing fields and prices, and\n * short enough to port to cspurefix unchanged.\n */\nexport class Rng {\n private state: number\n\n constructor (seed: number = 0x5eed) {\n // 0 is a fixed point of the mixer, so fold it away rather than silently degenerate\n this.state = (seed >>> 0) || 0x9e3779b9\n }\n\n /**\n * uniform in [0, 1)\n */\n public next (): number {\n this.state = (this.state + 0x6d2b79f5) >>> 0\n let t = this.state\n t = Math.imul(t ^ (t >>> 15), t | 1)\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61)\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296\n }\n\n /**\n * uniform integer in [min, max] inclusive\n */\n public int (min: number, max: number): number {\n if (max < min) return min\n return min + Math.floor(this.next() * (max - min + 1))\n }\n\n public bool (probability: number = 0.5): boolean {\n return this.next() < probability\n }\n\n public pick<T> (from: readonly T[]): T {\n return from[this.int(0, from.length - 1)]\n }\n\n /**\n * an index into `count` items, biased toward the front. `bias` of 1 is uniform;\n * higher values pull harder toward 0.\n *\n * used for enumerated fields, where the dictionary lists values roughly in order of\n * how ordinary they are - Side 1 and 2 before the twenty exotic ones - so a uniform\n * pick produces a message no counterparty would ever send.\n */\n public frontBiased (count: number, bias: number = 3): number {\n if (count <= 1) return 0\n return Math.min(count - 1, Math.floor(Math.pow(this.next(), bias) * count))\n }\n\n /**\n * a value near `centre`, within +/- `spreadPct`, snapped to `tick`\n */\n public around (centre: number, spreadPct: number, tick: number): number {\n const move = centre * spreadPct * (this.next() * 2 - 1)\n const raw = centre + move\n const snapped = Math.round(raw / tick) * tick\n // ticks are decimal fractions, so re-round to kill the binary residue\n const dp = Rng.decimals(tick)\n return Number(snapped.toFixed(dp))\n }\n\n private static decimals (tick: number): number {\n const s = tick.toString()\n const dot = s.indexOf('.')\n if (dot < 0) return 0\n const exp = s.indexOf('e')\n if (exp > 0) return Math.min(10, parseInt(s.substring(exp + 2), 10))\n return Math.min(10, s.length - dot - 1)\n }\n\n /**\n * shuffle a copy, Fisher-Yates from the seeded stream\n */\n public shuffled<T> (from: readonly T[]): T[] {\n const a = from.slice()\n for (let i = a.length - 1; i > 0; --i) {\n const j = this.int(0, i)\n const t = a[i]\n a[i] = a[j]\n a[j] = t\n }\n return a\n }\n}\n"]}
@@ -0,0 +1,50 @@
1
+ import { ILayout, LayoutNode } from './layout';
2
+ import { Rng } from './rng';
3
+ export declare enum Containment {
4
+ Root = "root",
5
+ Within = "within",
6
+ Deeper = "deeper"
7
+ }
8
+ export interface IScatterSite {
9
+ readonly level: string;
10
+ readonly component: string;
11
+ readonly containment: Containment;
12
+ readonly structureDepth: number;
13
+ readonly fragments: number;
14
+ readonly tags: number[];
15
+ readonly contendedTags: number[];
16
+ }
17
+ interface ISiteRef {
18
+ readonly level: LayoutNode;
19
+ readonly component: LayoutNode;
20
+ readonly containment: Containment;
21
+ readonly structureDepth: number;
22
+ }
23
+ export interface IScatterPlan {
24
+ readonly depth: number;
25
+ readonly sites: readonly IScatterSite[];
26
+ }
27
+ export interface IScatterResult {
28
+ readonly wire: string;
29
+ readonly plan: IScatterPlan;
30
+ readonly order: readonly number[];
31
+ }
32
+ export declare class Scatterer {
33
+ private readonly layout;
34
+ private readonly rng;
35
+ private readonly fragments;
36
+ constructor(layout: ILayout, rng: Rng, fragments?: number);
37
+ plan(depth: number): ISiteRef[];
38
+ scatter(depth: number, delimiter: string): IScatterResult;
39
+ private static contended;
40
+ private static runs;
41
+ private findChain;
42
+ private static candidates;
43
+ private findInside;
44
+ private units;
45
+ private orderLevel;
46
+ private arrange;
47
+ private static weave;
48
+ private static split;
49
+ }
50
+ export {};