@huskly/ibkr-client 1.3.1 → 1.4.0

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/README.md CHANGED
@@ -177,6 +177,52 @@ applies to definition discovery and market-data snapshots. An aborted operation
177
177
  signal reason when it is an `Error`. A non-error custom reason is retained as the `cause` of an
178
178
  `Error`. An `AbortController` without a custom reason uses the standard `AbortError`.
179
179
 
180
+ #### Bounded strike discovery
181
+
182
+ One security definition costs one paced `secdef/info` request, so the cost of discovery is
183
+ proportional to the number of strikes the month lists. A broad index lists thousands of strikes, and
184
+ a caller usually uses only a small band of them. Give `strikeRange` to resolve only that band:
185
+
186
+ ```ts
187
+ const chain = await client.getOptionChain("SPX", expiry, "P", {
188
+ strikeRange: { min: 6800, max: 7400 },
189
+ });
190
+ ```
191
+
192
+ - Both bounds are inclusive, and each bound is optional. An open bound keeps every strike on that
193
+ side. No `strikeRange` keeps every listed strike, which is the behavior of earlier versions.
194
+ - A bound that is not a finite number, and a `min` above the `max`, are refused with a `TypeError`
195
+ before any request.
196
+ - A band that keeps none of the listed strikes fails with an error. It does not report an empty
197
+ chain, because an empty chain looks like an unlisted expiry.
198
+ - Discovery memoizes each band separately, so a narrow result can never answer a request for a
199
+ different band.
200
+ - The `STRIKES` and `DEFINITIONS` telemetry phases report `listedStrikeCount` and
201
+ `selectedStrikeCount`, so you can measure what the band removed.
202
+
203
+ #### Security-definition cache
204
+
205
+ A security definition is identity: conid, symbol, underlying, expiry, strike, and right. It holds no
206
+ price, no greek, and no availability, and it does not change for a listed contract. Give an
207
+ `optionDefinitionCache` to keep those definitions between runs and remove their requests:
208
+
209
+ ```ts
210
+ const client = new IbkrClient(config, {
211
+ optionDefinitionCache: {
212
+ get: (keys) => store.read(keys), // aligned to `keys` by index; `null` is a miss
213
+ set: (entries) => store.write(entries),
214
+ },
215
+ });
216
+ ```
217
+
218
+ - The key is the underlying conid, the month token, the right, and the strike.
219
+ - An empty array is a hit that records a strike IBKR does not list. `null` is a miss.
220
+ - The cache is an accelerator, never an authority. A rejected read, a result of the wrong length, or
221
+ a record that is not a whole contract for its key is treated as a miss, and the broker answers.
222
+ - A partial or malformed broker answer is never stored.
223
+ - A failed write never fails discovery.
224
+ - The `DEFINITIONS` telemetry phase reports `cachedDefinitionCount` beside `definitionRequestCount`.
225
+
180
226
  ### Broker-neutral derivative discovery
181
227
 
182
228
  `IbkrClient` implements the capability-specific `DerivativeDiscoveryClient` without adding
@@ -1,5 +1,5 @@
1
1
  import type { IbkrOauth1Config } from "./oauthConfig.js";
2
- import type { AccountBalances, ActiveDerivativeOrder, AuthStatus, BrokerAccountOrders, BrokerClient, BrokerInstrument, BrokerInstrumentSearchProjection, BrokerOrdersOptions, BrokerPosition, BrokerQuote, BrokerQuoteOptions, BrokerQuoteRequest, BrokerTransactionHistory, BrokerErrorDetail, DerivativeContract, DerivativeContractQuery, DerivativeComboExecutionRequest, DerivativeComboReconciliation, DerivativeComboReconciliationRequest, DerivativeComboPreviewRequest, DerivativeComboPreviewResult, DerivativeContingentChildOrderRequest, DerivativeContingentParentOrderRequest, DerivativeDiscoveryClient, DerivativeExecutionClient, DerivativeExecution, DerivativeExecutionQuery, DerivativeMultiOrderResult, DerivativeOrderGraphLookup, DerivativeOrderGraphRequest, DerivativeOrderGraphResult, DerivativeOrderGraphWarningContinuation, DerivativeOrderCancellationResult, DerivativeOrderCancelRequest, DerivativeOrderLifecycle, DerivativeOrderLookup, DerivativeOrderSubmissionResult, DerivativeSingleOrderRequest, DerivativePreviewClient, DerivativeExpiry, DerivativeExpiryQuery, DerivativeQuote, DerivativeReferenceQuote, OptionChainSnapshot, OptionContract, OptionDiscoveryTelemetry, OptionMarketQuote, OptionQuoteRequest, OptionRight, PriceHistoryContractCandidate, PriceHistoryRequest, PriceHistoryResult, PriceHistoryTelemetry, TradingDiagnostics } from "../types.js";
2
+ import type { AccountBalances, ActiveDerivativeOrder, AuthStatus, BrokerAccountOrders, BrokerClient, BrokerInstrument, BrokerInstrumentSearchProjection, BrokerOrdersOptions, BrokerPosition, BrokerQuote, BrokerQuoteOptions, BrokerQuoteRequest, BrokerTransactionHistory, BrokerErrorDetail, DerivativeContract, DerivativeContractQuery, DerivativeComboExecutionRequest, DerivativeComboReconciliation, DerivativeComboReconciliationRequest, DerivativeComboPreviewRequest, DerivativeComboPreviewResult, DerivativeContingentChildOrderRequest, DerivativeContingentParentOrderRequest, DerivativeDiscoveryClient, DerivativeExecutionClient, DerivativeExecution, DerivativeExecutionQuery, DerivativeMultiOrderResult, DerivativeOrderGraphLookup, DerivativeOrderGraphRequest, DerivativeOrderGraphResult, DerivativeOrderGraphWarningContinuation, DerivativeOrderCancellationResult, DerivativeOrderCancelRequest, DerivativeOrderLifecycle, DerivativeOrderLookup, DerivativeOrderSubmissionResult, DerivativeSingleOrderRequest, DerivativePreviewClient, DerivativeExpiry, DerivativeExpiryQuery, DerivativeQuote, DerivativeReferenceQuote, OptionChainSnapshot, OptionContract, OptionDefinitionCache, OptionDiscoveryTelemetry, OptionMarketQuote, OptionStrikeRange, OptionQuoteRequest, OptionRight, PriceHistoryContractCandidate, PriceHistoryRequest, PriceHistoryResult, PriceHistoryTelemetry, TradingDiagnostics } from "../types.js";
3
3
  import { type IbkrRequestSchedulerOptions, type IbkrRequestTelemetry } from "./requestScheduler.js";
4
4
  interface IbkrRequestInput {
5
5
  path: string;
@@ -7,10 +7,17 @@ interface IbkrRequestInput {
7
7
  params?: Record<string, string | number | boolean | null | undefined>;
8
8
  data?: object;
9
9
  }
10
- /** Controls one option-chain or expiry-discovery operation. */
11
10
  export interface OptionDiscoveryOptions {
12
11
  /** Stop this operation without canceling work owned by another caller. */
13
12
  signal?: AbortSignal;
13
+ /**
14
+ * Resolve only the strikes inside this inclusive band.
15
+ *
16
+ * One security definition costs one paced `secdef/info` request, so a month that lists thousands
17
+ * of strikes costs thousands of requests. A caller that can name the strikes it uses makes the
18
+ * cost proportional to that band. Without a band every listed strike is resolved.
19
+ */
20
+ strikeRange?: OptionStrikeRange;
14
21
  }
15
22
  export interface IbkrClientOptions {
16
23
  requestScheduler?: Omit<IbkrRequestSchedulerOptions, "classifyError" | "onTelemetry">;
@@ -19,6 +26,13 @@ export interface IbkrClientOptions {
19
26
  onPriceHistoryTelemetry?: (event: PriceHistoryTelemetry) => void;
20
27
  /** Receive safe timing and request counts for option-discovery phases. */
21
28
  onOptionDiscoveryTelemetry?: (event: OptionDiscoveryTelemetry) => void;
29
+ /**
30
+ * Supply resolved security definitions so discovery does not request them again.
31
+ *
32
+ * The cache is an accelerator and never an authority: a rejected read, a malformed record, or a
33
+ * misaligned result is treated as a miss, and the broker then answers.
34
+ */
35
+ optionDefinitionCache?: OptionDefinitionCache;
22
36
  }
23
37
  /** Safe HTTP response evidence retained when the raw transport rejects a request. */
24
38
  export interface IbkrHttpErrorResponse {
@@ -68,6 +82,7 @@ export declare class IbkrClient implements BrokerClient, DerivativeDiscoveryClie
68
82
  private initPromise?;
69
83
  private accountIdPromise?;
70
84
  private readonly optionDiscovery;
85
+ private readonly optionDefinitionCache;
71
86
  private readonly optionContractResolution;
72
87
  private readonly priceHistoryContractResolution;
73
88
  private readonly derivativeDiscovery;
@@ -291,6 +306,16 @@ export declare class IbkrClient implements BrokerClient, DerivativeDiscoveryClie
291
306
  private discoverOptions;
292
307
  private loadOptionUnderlying;
293
308
  private loadOptionContracts;
309
+ /**
310
+ * Read one definition for each request from the cache, aligned by index.
311
+ *
312
+ * Every failure mode collapses to "miss": no cache, a rejected read, a misaligned result, or a
313
+ * record that is not a valid contract for the key it answers. The broker is then asked, so a bad
314
+ * cache costs time and never changes an answer.
315
+ */
316
+ private readCachedOptionDefinitions;
317
+ /** Store resolved definitions. A store failure is never fatal: the identity came from IBKR. */
318
+ private writeCachedOptionDefinitions;
294
319
  private fetchOptionChainSnapshot;
295
320
  private fetchNullableOptionQuotes;
296
321
  private fetchOptionQuotes;
@@ -1 +1 @@
1
- {"version":3,"file":"ibkrClient.d.ts","sourceRoot":"","sources":["../../src/ibkr/ibkrClient.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ibkrClient.d.ts","sourceRoot":"","sources":["../../src/ibkr/ibkrClient.ts"],"names":[],"mappings":"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"}
@@ -272,6 +272,59 @@ function monthCodes(fromDate, toDate) {
272
272
  }
273
273
  return result;
274
274
  }
275
+ /** Refuse a band that is not made of finite numbers, or that can never select a strike. */
276
+ function normalizeStrikeRange(range) {
277
+ if (range === undefined)
278
+ return undefined;
279
+ const { min, max } = range;
280
+ if (min !== undefined && !Number.isFinite(min)) {
281
+ throw new TypeError("Option strike range min must be a finite number");
282
+ }
283
+ if (max !== undefined && !Number.isFinite(max)) {
284
+ throw new TypeError("Option strike range max must be a finite number");
285
+ }
286
+ if (min !== undefined && max !== undefined && min > max) {
287
+ throw new TypeError(`Option strike range min ${String(min)} is above max ${String(max)}`);
288
+ }
289
+ if (min === undefined && max === undefined)
290
+ return undefined;
291
+ return range;
292
+ }
293
+ /** One stable memo token for a band, so a narrowed result cannot answer a wider request. */
294
+ function strikeRangeKey(range) {
295
+ if (range === undefined)
296
+ return "*";
297
+ return `${String(range.min ?? "-inf")}..${String(range.max ?? "+inf")}`;
298
+ }
299
+ /** A strike that IBKR does not report as a finite number is never selected. */
300
+ function strikeInRange(strike, range) {
301
+ if (!Number.isFinite(strike))
302
+ return false;
303
+ if (range === undefined)
304
+ return true;
305
+ if (range.min !== undefined && strike < range.min)
306
+ return false;
307
+ if (range.max !== undefined && strike > range.max)
308
+ return false;
309
+ return true;
310
+ }
311
+ /** A cached record is used only when it is a whole contract and it answers the key it is filed under. */
312
+ function isCachedOptionContract(value, key) {
313
+ if (!isUnknownRecord(value))
314
+ return false;
315
+ const { conid, symbol, underlying, expiry, strike, right } = value;
316
+ return (typeof conid === "number" &&
317
+ Number.isFinite(conid) &&
318
+ typeof symbol === "string" &&
319
+ symbol.length > 0 &&
320
+ typeof underlying === "string" &&
321
+ underlying.length > 0 &&
322
+ typeof expiry === "string" &&
323
+ expiry.length > 0 &&
324
+ typeof strike === "number" &&
325
+ strike === key.strike &&
326
+ right === key.right);
327
+ }
275
328
  /** A typed HTTP failure from the IBKR transport. */
276
329
  export class IbkrHttpError extends Error {
277
330
  status;
@@ -337,6 +390,7 @@ export class IbkrClient {
337
390
  initPromise;
338
391
  accountIdPromise;
339
392
  optionDiscovery = new Map();
393
+ optionDefinitionCache;
340
394
  optionContractResolution = new Map();
341
395
  priceHistoryContractResolution = new Map();
342
396
  derivativeDiscovery = new Map();
@@ -350,6 +404,7 @@ export class IbkrClient {
350
404
  this.raw = new RawIbkrClientCtor(config);
351
405
  this.onPriceHistoryTelemetry = options.onPriceHistoryTelemetry ?? (() => undefined);
352
406
  this.onOptionDiscoveryTelemetry = options.onOptionDiscoveryTelemetry ?? (() => undefined);
407
+ this.optionDefinitionCache = options.optionDefinitionCache;
353
408
  this.onRequestTelemetry = options.onRequestTelemetry ?? (() => undefined);
354
409
  const schedulerOptions = options.requestScheduler;
355
410
  this.requestNow = schedulerOptions?.now ?? (() => this.now());
@@ -3724,16 +3779,24 @@ export class IbkrClient {
3724
3779
  }
3725
3780
  discoverOptions(symbol, month, right, options = {}) {
3726
3781
  const normalized = symbol.trim().toUpperCase();
3782
+ const strikeRange = normalizeStrikeRange(options.strikeRange);
3783
+ const discoveryOptions = {
3784
+ ...(options.signal === undefined ? {} : { signal: options.signal }),
3785
+ ...(strikeRange === undefined ? {} : { strikeRange }),
3786
+ };
3727
3787
  if (options.signal !== undefined) {
3728
- return this.loadOptionContracts(normalized, month, right, options.signal);
3788
+ return this.loadOptionContracts(normalized, month, right, discoveryOptions);
3729
3789
  }
3730
- const key = `${normalized}:${month}:${right ?? "*"}`;
3790
+ // The band belongs in the memo key. A narrowed result holds only part of the month, so it must
3791
+ // never answer a later request for a different band.
3792
+ const bandKey = strikeRangeKey(strikeRange);
3793
+ const key = `${normalized}:${month}:${right ?? "*"}:${bandKey}`;
3731
3794
  const cached = this.optionDiscovery.get(key);
3732
3795
  if (cached !== undefined)
3733
3796
  return cached;
3734
3797
  let discovery;
3735
3798
  if (right !== undefined) {
3736
- const complete = this.optionDiscovery.get(`${normalized}:${month}:*`);
3799
+ const complete = this.optionDiscovery.get(`${normalized}:${month}:*:${bandKey}`);
3737
3800
  if (complete !== undefined) {
3738
3801
  discovery = complete.then((result) => ({
3739
3802
  contracts: result.contracts.filter((contract) => contract.right === right),
@@ -3741,7 +3804,7 @@ export class IbkrClient {
3741
3804
  }));
3742
3805
  }
3743
3806
  }
3744
- discovery ??= this.loadOptionContracts(normalized, month, right);
3807
+ discovery ??= this.loadOptionContracts(normalized, month, right, discoveryOptions);
3745
3808
  const pending = discovery.catch((error) => {
3746
3809
  if (this.optionDiscovery.get(key) === pending)
3747
3810
  this.optionDiscovery.delete(key);
@@ -3767,7 +3830,9 @@ export class IbkrClient {
3767
3830
  throw new Error(`IBKR lost the selected underlying for ${symbol}`);
3768
3831
  return { conid: underlying.conid, symbol };
3769
3832
  }
3770
- async loadOptionContracts(symbol, month, right, callerSignal) {
3833
+ async loadOptionContracts(symbol, month, right, options = {}) {
3834
+ const callerSignal = options.signal;
3835
+ const strikeRange = normalizeStrikeRange(options.strikeRange);
3771
3836
  const operation = new AbortController();
3772
3837
  const abortFromCaller = () => {
3773
3838
  operation.abort(callerSignal?.reason);
@@ -3777,7 +3842,7 @@ export class IbkrClient {
3777
3842
  else
3778
3843
  callerSignal?.addEventListener("abort", abortFromCaller, { once: true });
3779
3844
  try {
3780
- const { underlying, requests } = await this.withSecdefPriming(async () => {
3845
+ const { underlying, requests, listedStrikeCount } = await this.withSecdefPriming(async () => {
3781
3846
  const searchStarted = this.requestNow();
3782
3847
  const selectedUnderlying = await this.loadOptionUnderlying(symbol, operation.signal);
3783
3848
  this.emitOptionDiscoveryTelemetry({
@@ -3786,29 +3851,19 @@ export class IbkrClient {
3786
3851
  month,
3787
3852
  right: right ?? null,
3788
3853
  durationMs: this.elapsedSince(searchStarted),
3789
- definitionRequestCount: 0,
3790
- snapshotBatchCount: 0,
3791
3854
  });
3792
3855
  const strikesStarted = this.requestNow();
3793
3856
  const strikes = await this.req({
3794
3857
  path: "iserver/secdef/strikes",
3795
3858
  params: { conid: String(selectedUnderlying.conid), sectype: "OPT", month },
3796
3859
  }, operation.signal);
3797
- this.emitOptionDiscoveryTelemetry({
3798
- phase: "STRIKES",
3799
- symbol,
3800
- month,
3801
- right: right ?? null,
3802
- durationMs: this.elapsedSince(strikesStarted),
3803
- definitionRequestCount: 0,
3804
- snapshotBatchCount: 0,
3805
- });
3860
+ const strikesDurationMs = this.elapsedSince(strikesStarted);
3806
3861
  const callStrikes = strikes.call ?? [];
3807
3862
  const putStrikes = strikes.put ?? [];
3808
3863
  if (callStrikes.length === 0 && putStrikes.length === 0) {
3809
3864
  throw new Error(`IBKR returned empty option strikes for ${symbol} ${month} after secdef/search priming`);
3810
3865
  }
3811
- const definitionRequests = [
3866
+ const listed = [
3812
3867
  ...(right === undefined || right === "C"
3813
3868
  ? callStrikes.map((strike) => ({ strike, right: "C" }))
3814
3869
  : []),
@@ -3816,12 +3871,48 @@ export class IbkrClient {
3816
3871
  ? putStrikes.map((strike) => ({ strike, right: "P" }))
3817
3872
  : []),
3818
3873
  ];
3819
- return { underlying: selectedUnderlying, requests: definitionRequests };
3874
+ // One security definition costs one paced request, so the band is applied here, before any
3875
+ // definition is requested. Applying it later would keep the full cost of the month.
3876
+ const selected = listed.filter(({ strike }) => strikeInRange(strike, strikeRange));
3877
+ this.emitOptionDiscoveryTelemetry({
3878
+ phase: "STRIKES",
3879
+ symbol,
3880
+ month,
3881
+ right: right ?? null,
3882
+ durationMs: strikesDurationMs,
3883
+ listedStrikeCount: listed.length,
3884
+ selectedStrikeCount: selected.length,
3885
+ });
3886
+ // A band that keeps nothing is a caller mistake, not an empty chain. Reporting it as an
3887
+ // empty result would look like an unlisted expiry.
3888
+ if (listed.length > 0 && selected.length === 0) {
3889
+ throw new Error(`IBKR option strike range [${String(strikeRange?.min ?? "-inf")}, ` +
3890
+ `${String(strikeRange?.max ?? "+inf")}] selected none of the ` +
3891
+ `${String(listed.length)} listed strikes for ${symbol} ${month}`);
3892
+ }
3893
+ return {
3894
+ underlying: selectedUnderlying,
3895
+ requests: selected,
3896
+ listedStrikeCount: listed.length,
3897
+ };
3820
3898
  });
3821
3899
  const definitionsStarted = this.requestNow();
3822
3900
  const contracts = [];
3823
3901
  let malformedDefinitionCount = 0;
3824
- for (const batch of chunks(requests, OPTION_SECDEF_INFO_BATCH_SIZE)) {
3902
+ const cached = await this.readCachedOptionDefinitions(underlying.conid, month, requests);
3903
+ const pending = [];
3904
+ let cachedDefinitionCount = 0;
3905
+ for (const [position, request] of requests.entries()) {
3906
+ const hit = cached[position];
3907
+ if (hit === undefined || hit === null) {
3908
+ pending.push(request);
3909
+ continue;
3910
+ }
3911
+ cachedDefinitionCount += 1;
3912
+ contracts.push(...hit);
3913
+ }
3914
+ const resolved = [];
3915
+ for (const batch of chunks(pending, OPTION_SECDEF_INFO_BATCH_SIZE)) {
3825
3916
  let responses;
3826
3917
  try {
3827
3918
  responses = await Promise.all(batch.map(({ strike, right: requestRight }) => this.req({
@@ -3841,13 +3932,17 @@ export class IbkrClient {
3841
3932
  operation.abort(error);
3842
3933
  throw error;
3843
3934
  }
3844
- for (const response of responses) {
3935
+ for (const [position, response] of responses.entries()) {
3845
3936
  if (!Array.isArray(response)) {
3846
3937
  throw new Error(`IBKR returned malformed option definitions for ${symbol} ${month}`);
3847
3938
  }
3939
+ const request = batch[position];
3940
+ const resolvedForRequest = [];
3941
+ let requestHadMalformedRecord = false;
3848
3942
  for (const raw of response) {
3849
3943
  if (!isUnknownRecord(raw)) {
3850
3944
  malformedDefinitionCount += 1;
3945
+ requestHadMalformedRecord = true;
3851
3946
  continue;
3852
3947
  }
3853
3948
  let contract;
@@ -3864,23 +3959,43 @@ export class IbkrClient {
3864
3959
  }
3865
3960
  catch {
3866
3961
  malformedDefinitionCount += 1;
3962
+ requestHadMalformedRecord = true;
3867
3963
  continue;
3868
3964
  }
3869
3965
  if (contract)
3870
- contracts.push(contract);
3871
- else
3966
+ resolvedForRequest.push(contract);
3967
+ else {
3872
3968
  malformedDefinitionCount += 1;
3969
+ requestHadMalformedRecord = true;
3970
+ }
3971
+ }
3972
+ contracts.push(...resolvedForRequest);
3973
+ // A partial answer is never stored. A later run must ask the broker again rather than
3974
+ // read a record that already lost contracts.
3975
+ if (request !== undefined && !requestHadMalformedRecord) {
3976
+ resolved.push({
3977
+ key: {
3978
+ underlyingConid: underlying.conid,
3979
+ month,
3980
+ right: request.right,
3981
+ strike: request.strike,
3982
+ },
3983
+ contracts: resolvedForRequest,
3984
+ });
3873
3985
  }
3874
3986
  }
3875
3987
  }
3988
+ await this.writeCachedOptionDefinitions(resolved);
3876
3989
  this.emitOptionDiscoveryTelemetry({
3877
3990
  phase: "DEFINITIONS",
3878
3991
  symbol,
3879
3992
  month,
3880
3993
  right: right ?? null,
3881
3994
  durationMs: this.elapsedSince(definitionsStarted),
3882
- definitionRequestCount: requests.length,
3883
- snapshotBatchCount: 0,
3995
+ definitionRequestCount: pending.length,
3996
+ listedStrikeCount,
3997
+ selectedStrikeCount: requests.length,
3998
+ cachedDefinitionCount,
3884
3999
  });
3885
4000
  if (requests.length === 0)
3886
4001
  return { contracts: [], malformedDefinitionCount: 0 };
@@ -3894,6 +4009,59 @@ export class IbkrClient {
3894
4009
  callerSignal?.removeEventListener("abort", abortFromCaller);
3895
4010
  }
3896
4011
  }
4012
+ /**
4013
+ * Read one definition for each request from the cache, aligned by index.
4014
+ *
4015
+ * Every failure mode collapses to "miss": no cache, a rejected read, a misaligned result, or a
4016
+ * record that is not a valid contract for the key it answers. The broker is then asked, so a bad
4017
+ * cache costs time and never changes an answer.
4018
+ */
4019
+ async readCachedOptionDefinitions(underlyingConid, month, requests) {
4020
+ const cache = this.optionDefinitionCache;
4021
+ if (cache === undefined || requests.length === 0)
4022
+ return requests.map(() => null);
4023
+ const keys = requests.map(({ strike, right }) => ({
4024
+ underlyingConid,
4025
+ month,
4026
+ right,
4027
+ strike,
4028
+ }));
4029
+ // The result is treated as untrusted data, not as the declared type. An implementation that
4030
+ // returns the wrong shape must degrade to a miss, never to a fabricated contract.
4031
+ let answer;
4032
+ try {
4033
+ answer = await cache.get(keys);
4034
+ }
4035
+ catch {
4036
+ return requests.map(() => null);
4037
+ }
4038
+ if (!Array.isArray(answer) || answer.length !== keys.length)
4039
+ return requests.map(() => null);
4040
+ const records = answer;
4041
+ return keys.map((key, position) => {
4042
+ const record = records[position];
4043
+ if (record === null || record === undefined)
4044
+ return null;
4045
+ if (!Array.isArray(record))
4046
+ return null;
4047
+ const cachedContracts = record;
4048
+ if (!cachedContracts.every((contract) => isCachedOptionContract(contract, key)))
4049
+ return null;
4050
+ return cachedContracts;
4051
+ });
4052
+ }
4053
+ /** Store resolved definitions. A store failure is never fatal: the identity came from IBKR. */
4054
+ async writeCachedOptionDefinitions(entries) {
4055
+ const cache = this.optionDefinitionCache;
4056
+ if (cache === undefined || entries.length === 0)
4057
+ return;
4058
+ try {
4059
+ await cache.set(entries);
4060
+ }
4061
+ catch {
4062
+ // A cache is an accelerator. Discovery already holds the broker answer.
4063
+ }
4064
+ }
3897
4065
  async fetchOptionChainSnapshot(contracts, malformedDefinitionCount, telemetry, signal) {
3898
4066
  const fields = [
3899
4067
  "bid",
@@ -4026,6 +4194,11 @@ export class IbkrClient {
4026
4194
  try {
4027
4195
  const result = this.onOptionDiscoveryTelemetry({
4028
4196
  event: "OPTION_DISCOVERY_PHASE",
4197
+ definitionRequestCount: 0,
4198
+ snapshotBatchCount: 0,
4199
+ listedStrikeCount: 0,
4200
+ selectedStrikeCount: 0,
4201
+ cachedDefinitionCount: 0,
4029
4202
  ...event,
4030
4203
  });
4031
4204
  void Promise.resolve(result).catch(() => undefined);