@xbbg/langgraph 1.2.7 → 1.3.1
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 +43 -2
- package/dist/index.d.ts +90 -4
- package/dist/index.js +1083 -623
- package/dist/index.js.map +1 -1
- package/package.json +6 -3
package/dist/index.js
CHANGED
|
@@ -51,6 +51,7 @@ var BLOOMBERG_TOOL_NAMES = [
|
|
|
51
51
|
"xbbg_ext_cdx",
|
|
52
52
|
"xbbg_ext_currency",
|
|
53
53
|
"xbbg_ext_bql_builder",
|
|
54
|
+
"xbbg_ext_chart_spec",
|
|
54
55
|
"xbbg_ext_market_session",
|
|
55
56
|
"xbbg_ext_yas_overrides",
|
|
56
57
|
"xbbg_ext_constants",
|
|
@@ -65,6 +66,13 @@ var DEFAULT_MAX_BQL_QUERY_CHARS = 4e3;
|
|
|
65
66
|
var DEFAULT_MAX_SEARCH_SPEC_CHARS = 1e3;
|
|
66
67
|
var DEFAULT_MAX_STREAM_UPDATES = 10;
|
|
67
68
|
var DEFAULT_MAX_STREAM_WAIT_MS = 15e3;
|
|
69
|
+
var DEFAULT_ENGINE_REQUEST_TIMEOUT_MS = 6e4;
|
|
70
|
+
function engineConfigWithDefaults(config) {
|
|
71
|
+
if (config?.requestTimeoutMs !== void 0) {
|
|
72
|
+
return config;
|
|
73
|
+
}
|
|
74
|
+
return { ...config, requestTimeoutMs: DEFAULT_ENGINE_REQUEST_TIMEOUT_MS };
|
|
75
|
+
}
|
|
68
76
|
function positiveInteger(value, fallback, name) {
|
|
69
77
|
if (value === void 0) {
|
|
70
78
|
return fallback;
|
|
@@ -82,7 +90,7 @@ function normalizeBloombergToolsOptions(options = {}) {
|
|
|
82
90
|
core: options.core,
|
|
83
91
|
disabledTools: disabledToolSet(options.disabledTools),
|
|
84
92
|
engine: options.engine,
|
|
85
|
-
engineConfig: options.engineConfig,
|
|
93
|
+
engineConfig: engineConfigWithDefaults(options.engineConfig),
|
|
86
94
|
maxBqlQueryChars: positiveInteger(
|
|
87
95
|
options.maxBqlQueryChars,
|
|
88
96
|
DEFAULT_MAX_BQL_QUERY_CHARS,
|
|
@@ -167,180 +175,6 @@ function createCoreResolver(options = {}) {
|
|
|
167
175
|
options: normalized
|
|
168
176
|
};
|
|
169
177
|
}
|
|
170
|
-
function inputJsonSchema(schema) {
|
|
171
|
-
const jsonSchema = zodToJsonSchema.zodToJsonSchema(schema, {
|
|
172
|
-
$refStrategy: "none",
|
|
173
|
-
effectStrategy: "input",
|
|
174
|
-
pipeStrategy: "input"
|
|
175
|
-
});
|
|
176
|
-
delete jsonSchema.$schema;
|
|
177
|
-
delete jsonSchema.definitions;
|
|
178
|
-
return jsonSchema;
|
|
179
|
-
}
|
|
180
|
-
function createBloombergStructuredTool(func, fields) {
|
|
181
|
-
const providerToolDefinition = {
|
|
182
|
-
type: "function",
|
|
183
|
-
function: {
|
|
184
|
-
description: fields.description,
|
|
185
|
-
name: fields.name,
|
|
186
|
-
parameters: inputJsonSchema(fields.schema)
|
|
187
|
-
}
|
|
188
|
-
};
|
|
189
|
-
return tools.tool(
|
|
190
|
-
func,
|
|
191
|
-
{
|
|
192
|
-
...fields,
|
|
193
|
-
extras: { providerToolDefinition }
|
|
194
|
-
}
|
|
195
|
-
);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
// src/cdx-fields.ts
|
|
199
|
-
var CDX_INFO_FIELDS = Object.freeze([
|
|
200
|
-
"ROLLING_SERIES",
|
|
201
|
-
"VERSION",
|
|
202
|
-
"ON_THE_RUN_CURRENT_BD_INDICATOR",
|
|
203
|
-
"CDS_FIRST_ACCRUAL_START_DATE",
|
|
204
|
-
"NAME",
|
|
205
|
-
"NUM_CURRENT_COMPANIES_CCY_TKR",
|
|
206
|
-
"NUM_ORIG_COMPANIES_CRNCY_TKR",
|
|
207
|
-
"PX_LAST"
|
|
208
|
-
]);
|
|
209
|
-
var CDX_PRICING_FIELDS = Object.freeze([
|
|
210
|
-
"PX_LAST",
|
|
211
|
-
"PX_BID",
|
|
212
|
-
"PX_ASK",
|
|
213
|
-
"UPFRONT_LAST",
|
|
214
|
-
"UPFRONT_BID",
|
|
215
|
-
"UPFRONT_ASK",
|
|
216
|
-
"CDS_FLAT_SPREAD",
|
|
217
|
-
"UPFRONT_FEE",
|
|
218
|
-
"PV_CDS_PREMIUM_LEG",
|
|
219
|
-
"PV_CDS_DEFAULT_LEG"
|
|
220
|
-
]);
|
|
221
|
-
var CDX_RISK_FIELDS = Object.freeze([
|
|
222
|
-
"SW_CNV_BPV",
|
|
223
|
-
"SW_EQV_BPV",
|
|
224
|
-
"CDS_SPREAD_MID_MODIFIED_DURATION",
|
|
225
|
-
"CDS_SPREAD_MID_CONVEXITY",
|
|
226
|
-
"RECOVERY_RATE_SEN",
|
|
227
|
-
"CDS_RECOVERY_RT"
|
|
228
|
-
]);
|
|
229
|
-
|
|
230
|
-
// src/descriptions.ts
|
|
231
|
-
var REQUIRED_TOOL_INSTRUCTIONS = [
|
|
232
|
-
"# Bloomberg tool usage",
|
|
233
|
-
"- Use these tools only for server-side Bloomberg data access through @xbbg/core. Never imply Bloomberg data was retrieved unless a tool call actually returned it.",
|
|
234
|
-
"- Ask a clarifying question before calling a tool when any security identity, field mnemonic, date range, currency, periodicity, intraday interval, timezone, override, or universe is ambiguous.",
|
|
235
|
-
"- Do not invent Bloomberg tickers, field mnemonics, overrides, or BQL functions. If the user gives a field description rather than a confident mnemonic, call xbbg_bflds first.",
|
|
236
|
-
"",
|
|
237
|
-
"## Security identifiers",
|
|
238
|
-
"- Prefer fully qualified Bloomberg securities supplied by the user, such as <TICKER> <MARKET_SECTOR>, <INDEX_TICKER> <MARKET_SECTOR>, or <CREDIT_INDEX_TICKER> <MARKET_SECTOR>.",
|
|
239
|
-
"- For raw security identifiers, request or pass Bloomberg identifier syntax directly: /isin/<ISIN> for ISINs or /cusip/<CUSIP> for CUSIPs.",
|
|
240
|
-
"- Do not pass raw ISIN or CUSIP strings when the request is meant to identify a security. Do not use xbbg_bsrch as a replacement for a known ticker, ISIN, or CUSIP.",
|
|
241
|
-
"- For dealer quote / BQR workflows, use xbbg_bqr with a fixed-income identifier plus a dealer quote source such as /isin/<ISIN>@<QUOTE_SOURCE> <MARKET_SECTOR>. For raw intraday ticks, use xbbg_bdtick.",
|
|
242
|
-
"",
|
|
243
|
-
"## Core request tools",
|
|
244
|
-
"- xbbg_bdp: current or reference point-in-time fields. Use a small explicit securities list and a small explicit fields list. Use includeSecurityErrors only when the caller wants Bloomberg security errors in the response.",
|
|
245
|
-
"- xbbg_bdh: historical daily or periodic time series. Always provide explicit start and end dates in YYYY-MM-DD or YYYYMMDD form. Ask before choosing periodicity, currency, fill behavior, adjustment overrides, or a wide output table.",
|
|
246
|
-
"- xbbg_bds: Bloomberg bulk/table fields. Provide exactly one bulk field; do not use bds for ordinary multi-field reference data.",
|
|
247
|
-
"- xbbg_bdib: intraday bars only. Provide one ticker, explicit ISO start/end datetimes with time components, a positive interval in minutes, and timezone context when datetimes are naive.",
|
|
248
|
-
"- xbbg_bdtick: intraday tick data. Provide one ticker, explicit ISO start/end datetimes with time components, and explicit eventTypes unless the default event stream is intended. Use includeBrokerCodes or includeConditionCodes only when those columns are needed.",
|
|
249
|
-
"- xbbg_bql: BQL expressions only when the user asks for BQL or the request is naturally expressed as a bounded BQL query. Keep queries short, explicit, and scoped to the requested universe.",
|
|
250
|
-
"- xbbg_bsrch: Bloomberg search-grid or saved-search workflows only. Do not use it for ordinary security lookup.",
|
|
251
|
-
"- xbbg_bqr: Bloomberg Quote Request / dealer quotes. Prefer fixed-income identifier inputs with a dealer quote source such as /isin/<ISIN>@<QUOTE_SOURCE> <MARKET_SECTOR>, explicit start/end datetimes with time components, and explicit event types.",
|
|
252
|
-
"- xbbg_bflds: Bloomberg field metadata/search. Provide exactly one of fields or searchSpec; use searchSpec for natural-language field names and fields for known mnemonics.",
|
|
253
|
-
"- xbbg_beqs: Bloomberg equity screening by named BEQS screen. Prefer this over hand-written BQL when the user names an existing Bloomberg screen.",
|
|
254
|
-
"- xbbg_yas: fixed-income YAS recipe fields. Prefer this over manual YAS-style BDP requests when the user asks for yield, duration, spread, or price analytics.",
|
|
255
|
-
"- xbbg_preferreds: preferred stock discovery from an equity ticker. Prefer this over xbbg_ext_bql_builder plus xbbg_bql when the user wants the actual preferreds result.",
|
|
256
|
-
"- xbbg_corporate_bonds: bounded corporate bond universe query for a company ticker. Prefer this over generic BQL for company debt discovery.",
|
|
257
|
-
"- xbbg_index_members: index constituents through the core index recipe. Prefer this over generic BDS/BQL members when the user asks for constituents.",
|
|
258
|
-
"- xbbg_resolve_isins: resolves supplied ISIN strings to Bloomberg securities. Pass raw ISIN strings only for this recipe; otherwise use /isin/<ISIN> syntax with data tools.",
|
|
259
|
-
"- xbbg_issuer_isins: issuer/bond ISIN workflow for supplied bond ISIN strings.",
|
|
260
|
-
"- xbbg_etf_holdings: ETF holdings recipe for a single ETF ticker. Prefer this over generic BQL holdings when the user asks for ETF constituents.",
|
|
261
|
-
"- xbbg_stream_snapshot: bounded live market-data observation from //blp/mktdata. Requires explicit maxUpdates and always terminates/unsubscribes.",
|
|
262
|
-
"- xbbg_mktbar_snapshot: bounded live market-bar observation from //blp/mktbar for one ticker. Requires explicit maxUpdates and always terminates/unsubscribes.",
|
|
263
|
-
"- xbbg_depth_snapshot: bounded market-depth observation from //blp/mktdepthdata for one ticker. Requires explicit maxUpdates and always terminates/unsubscribes.",
|
|
264
|
-
"",
|
|
265
|
-
"## BQL guidance",
|
|
266
|
-
"- BQL is a complete Bloomberg Query Language expression sent as one query string; the tool does not assemble get/for/with clauses for you.",
|
|
267
|
-
"- Basic shape: get(<FIELD_1>, <FIELD_2>) for(<UNIVERSE>). Use placeholders such as '<TICKER> <MARKET_SECTOR>', holdings('<ETF_TICKER> <MARKET_SECTOR>'), or members('<INDEX_TICKER> <MARKET_SECTOR>') until the user supplies real inputs.",
|
|
268
|
-
"- Use BQL for universe-oriented analytics and screens only when the user provides a bounded universe, filters, and date range.",
|
|
269
|
-
"- Prefer xbbg_ext_bql_builder instead of hand-writing BQL for supported workflows: preferred stocks, corporate bonds, and ETF holdings.",
|
|
270
|
-
"- Do not use BQL just because the user asks for normal reference data; xbbg_bdp is simpler for current fields and xbbg_bdh is simpler for historical time series.",
|
|
271
|
-
"",
|
|
272
|
-
"## Output handling",
|
|
273
|
-
"- Tool results use LangChain content_and_artifact output: content starts with a compact summary and then includes bounded model-readable JSON; artifact is the structured bounded envelope with tool, rowCount, truncated, and data for application code.",
|
|
274
|
-
"- If a response is empty, truncated, or contains Bloomberg/security errors, say that directly. Do not fill gaps from memory or assumptions."
|
|
275
|
-
];
|
|
276
|
-
var OPTIONAL_EXTENSION_INSTRUCTIONS = [
|
|
277
|
-
"",
|
|
278
|
-
"## Extension helper tools",
|
|
279
|
-
"- xbbg_ext_ticker: ticker hygiene before live calls. parse_ticker splits a Bloomberg ticker, normalize_tickers trims/canonicalizes lists, filter_equity_tickers keeps equity-like tickers, is_specific_contract checks futures specificity, and validate_generic_ticker rejects malformed generic futures tickers.",
|
|
280
|
-
"- xbbg_ext_futures: futures contract construction and selection. Use build_futures_ticker for root/month/year/asset assembly, get_futures_months for month-code lookup, generate_candidates for generic-to-specific candidates, contract_index for generic contract rank, filter_candidates_by_cycle for HMUZ/quarterly cycles, and filter_valid_contracts to keep contracts valid for a date.",
|
|
281
|
-
"- xbbg_ext_cdx: CDX ticker workflow support. Use parse_cdx_ticker to understand a CDX ticker, previous_cdx_series to roll back a series, cdx_gen_to_specific to resolve a generic CDX to a target series, and cdx_info/cdx_pricing/cdx_risk for predefined BDP field bundles. cdx_pricing and cdx_risk accept recoveryRate, which becomes the CDS_RR override.",
|
|
282
|
-
"- xbbg_ext_currency: currency-planning helpers. build_fx_pair constructs the Bloomberg FX pair and conversion factor, same_currency avoids unnecessary conversion, and currencies_needing_conversion identifies which currencies differ from a target before requesting converted values.",
|
|
283
|
-
"- xbbg_ext_bql_builder: safe BQL generators for common xbbg workflows. Use build_preferreds_query for preferred-stock discovery from an equity, build_corporate_bonds_query for company bond universes with optional currency/active filters, and build_etf_holdings_query for ETF constituents. Prefer these builders over hand-writing those BQL shapes.",
|
|
284
|
-
"- xbbg_ext_market_session: exchange calendar/timezone support. derive_sessions turns day session times into session blocks, infer_timezone maps country codes to timezones, session_times_to_utc converts local sessions to UTC, get_market_rule gets MIC/exchange rules, default_turnover_dates and default_bqr_datetimes provide bounded defaults, and get/list_exchange_override inspect configured exchange metadata.",
|
|
285
|
-
"- xbbg_ext_yas_overrides: builds flat YAS override maps for fixed-income BDP requests when the lower-level BDP workflow is required. Prefer xbbg_yas for actual YAS recipe fields.",
|
|
286
|
-
"- xbbg_ext_constants: static lookup/format helpers for date parsing/formatting, futures month code/name mappings, dividend type mappings, and known dividend/ETF output columns.",
|
|
287
|
-
"- xbbg_ext_columns: post-processing helpers for Bloomberg-shaped tables. Use rename_dividend_columns, rename_etf_columns, or build_earning_header_rename when explaining or normalizing response column names after a request.",
|
|
288
|
-
"- xbbg_ext_calculate: small numeric helper for Bloomberg workflows. calculate_level_percentages pairs observed values with levels; values and levels must have the same length."
|
|
289
|
-
];
|
|
290
|
-
var OPTIONAL_LIMIT_INSTRUCTIONS = [
|
|
291
|
-
"",
|
|
292
|
-
"## Request limits and inputs",
|
|
293
|
-
"- Keep Bloomberg requests bounded: explicit securities, explicit fields, explicit dates, limited rows, and no broad exploratory pulls unless the user narrows the universe.",
|
|
294
|
-
"- Respect configured tool limits for securities, fields, rows, string size, BQL length, and search spec length. Ask the user to narrow the request rather than exceeding them.",
|
|
295
|
-
"- Use flat primitive overrides and kwargs only: string, number, or boolean values. Do not send nested objects, arrays, or inferred defaults as overrides."
|
|
296
|
-
];
|
|
297
|
-
var BLOOMBERG_TOOL_INSTRUCTIONS = [
|
|
298
|
-
...REQUIRED_TOOL_INSTRUCTIONS,
|
|
299
|
-
...OPTIONAL_EXTENSION_INSTRUCTIONS,
|
|
300
|
-
...OPTIONAL_LIMIT_INSTRUCTIONS
|
|
301
|
-
].join("\n");
|
|
302
|
-
function getBloombergToolInstructions(options = {}) {
|
|
303
|
-
const includeExtensionGuidance = options.includeExtensionGuidance ?? true;
|
|
304
|
-
const includeLimitReminder = options.includeLimitReminder ?? true;
|
|
305
|
-
const lines = [...REQUIRED_TOOL_INSTRUCTIONS];
|
|
306
|
-
if (includeExtensionGuidance) {
|
|
307
|
-
lines.push(...OPTIONAL_EXTENSION_INSTRUCTIONS);
|
|
308
|
-
}
|
|
309
|
-
if (includeLimitReminder) {
|
|
310
|
-
lines.push(...OPTIONAL_LIMIT_INSTRUCTIONS);
|
|
311
|
-
}
|
|
312
|
-
return lines.join("\n");
|
|
313
|
-
}
|
|
314
|
-
var BDP_DESCRIPTION = 'Bloomberg reference data for current or point-in-time fields. Use for a small bounded list of fully qualified securities. Use /isin/<ISIN> for ISINs and /cusip/<CUSIP> for CUSIPs. Example: securities ["<TICKER> <MARKET_SECTOR>"], fields ["<FIELD>"].';
|
|
315
|
-
var BDH_DESCRIPTION = 'Bloomberg historical time series. Requires explicit start and end dates; ask before using if the date range or periodicity is ambiguous. Use /isin/<ISIN> for ISINs and /cusip/<CUSIP> for CUSIPs. Example: securities ["<TICKER> <MARKET_SECTOR>"], fields ["<FIELD>"], start "<START_DATE>", end "<END_DATE>".';
|
|
316
|
-
var BDS_DESCRIPTION = 'Bloomberg bulk/table reference data. Requires exactly one bulk field, not a field list. Use /isin/<ISIN> for ISINs and /cusip/<CUSIP> for CUSIPs. Example: securities ["<INDEX_TICKER> <MARKET_SECTOR>"], field "<BULK_FIELD>".';
|
|
317
|
-
var BDIB_DESCRIPTION = 'Bloomberg intraday bars. Requires one ticker plus explicit ISO start/end datetimes with time components and a positive interval in minutes. Use /isin/<ISIN> for ISINs and /cusip/<CUSIP> for CUSIPs. Example: ticker "<TICKER> <MARKET_SECTOR>", start "<START_DATETIME>", end "<END_DATETIME>", interval <MINUTES>.';
|
|
318
|
-
var BDTICK_DESCRIPTION = 'Bloomberg intraday tick data. Requires one ticker plus explicit ISO start/end datetimes with time components. Set eventTypes explicitly, for example ["<EVENT_TYPE>"], and includeBrokerCodes/includeConditionCodes only when needed.';
|
|
319
|
-
var BQL_DESCRIPTION = "Bloomberg Query Language expression sent as one complete query string. Use for bounded universe analytics with placeholder-shaped syntax such as get(<FIELD>) for('<TICKER> <MARKET_SECTOR>'), holdings('<ETF_TICKER> <MARKET_SECTOR>'), members('<INDEX_TICKER> <MARKET_SECTOR>'), filters with with(...), or dates=range(...). Prefer xbbg_bdp/xbbg_bdh for simple reference or historical requests.";
|
|
320
|
-
var BSRCH_DESCRIPTION = 'Bloomberg search/grid request. Use for saved-search or ExcelGetGrid-style Bloomberg searches, not ordinary security lookup. Example searchSpec "<SEARCH_SPEC>".';
|
|
321
|
-
var BQR_DESCRIPTION = 'Bloomberg Quote Request / dealer quotes. Use for fixed-income dealer quote ticks, preferably with an ISIN plus dealer source such as "/isin/<ISIN>@<QUOTE_SOURCE> <MARKET_SECTOR>"; requires explicit ISO start/end datetimes with time components. Set eventTypes explicitly, for example ["<EVENT_TYPE>"].';
|
|
322
|
-
var BFLDS_DESCRIPTION = 'Bloomberg field metadata and field search. Use first when a field mnemonic is uncertain. Provide exactly one of fields or searchSpec. Example: fields ["<FIELD>"] or searchSpec "<FIELD_SEARCH_TEXT>".';
|
|
323
|
-
var BEQS_DESCRIPTION = "Bloomberg equity screening by named BEQS screen. Use when the user names an existing Bloomberg screen and wants its bounded result set. Prefer this over hand-written BQL for saved Bloomberg screens.";
|
|
324
|
-
var YAS_DESCRIPTION = "Bloomberg fixed-income YAS recipe fields for one or more bonds. Use for yield, duration, spread, benchmark, or price analytics; provide explicit fields and optional settlement/yield/price inputs.";
|
|
325
|
-
var PREFERREDS_DESCRIPTION = "Preferred stock discovery for one equity ticker. Use when the user asks for preferred shares or preferred stock securities related to an issuer.";
|
|
326
|
-
var CORPORATE_BONDS_DESCRIPTION = "Corporate bond universe query for one issuer/company ticker, with optional currency, active-only filter, and result fields. Prefer this over generic BQL for company debt discovery.";
|
|
327
|
-
var INDEX_MEMBERS_DESCRIPTION = "Index constituent recipe for one Bloomberg index. Use for bounded member lists and optional historical/as-of constituent membership.";
|
|
328
|
-
var RESOLVE_ISINS_DESCRIPTION = "Resolve raw ISIN strings to Bloomberg securities through the core ISIN recipe. Do not add /isin/ prefixes in this tool; pass the exact ISIN strings supplied by the user.";
|
|
329
|
-
var ISSUER_ISINS_DESCRIPTION = "Issuer/bond ISIN workflow for supplied bond ISIN strings. Use for issuer-level ISIN discovery starting from known bond ISINs.";
|
|
330
|
-
var ETF_HOLDINGS_DESCRIPTION = "ETF holdings recipe for one ETF ticker. Use when the user asks for ETF constituents or holdings and wants the bounded holdings result.";
|
|
331
|
-
var STREAM_SNAPSHOT_DESCRIPTION = "Bounded live market-data snapshot from //blp/mktdata. Collects at most maxUpdates updates until timeout/done, then always unsubscribes; use for finite observations, not open subscriptions.";
|
|
332
|
-
var MKTBAR_SNAPSHOT_DESCRIPTION = "Bounded live market-bar snapshot from //blp/mktbar for one ticker. Collects at most maxUpdates updates until timeout/done, then always unsubscribes.";
|
|
333
|
-
var DEPTH_SNAPSHOT_DESCRIPTION = "Bounded live market-depth snapshot from //blp/mktdepthdata for one ticker. Collects at most maxUpdates updates until timeout/done, then always unsubscribes.";
|
|
334
|
-
var EXT_TICKER_DESCRIPTION = "Ticker hygiene helpers: parse_ticker, normalize_tickers, filter_equity_tickers, is_specific_contract, and validate_generic_ticker.";
|
|
335
|
-
var EXT_FUTURES_DESCRIPTION = "Futures helpers for contract construction and selection: build_futures_ticker, generate_candidates, contract_index, filter_candidates_by_cycle, filter_valid_contracts, and get_futures_months.";
|
|
336
|
-
var EXT_CDX_DESCRIPTION = "CDX helpers for parsing, series rolling/resolution, and predefined info/pricing/risk BDP field bundles.";
|
|
337
|
-
var EXT_CURRENCY_DESCRIPTION = "Currency planning helpers: build FX pairs, test same-currency requests, and find currencies needing conversion.";
|
|
338
|
-
var EXT_BQL_BUILDER_DESCRIPTION = "BQL builders for preferred stocks, corporate bonds, and ETF holdings. Prefer to construct those bounded BQL shapes before xbbg_bql.";
|
|
339
|
-
var EXT_MARKET_SESSION_DESCRIPTION = "Market session and timezone helpers for deriving sessions, UTC windows, market rules, exchange metadata, turnover defaults, and BQR datetime defaults.";
|
|
340
|
-
var EXT_YAS_OVERRIDES_DESCRIPTION = "Build flat Bloomberg YAS override maps for fixed-income analytics fields.";
|
|
341
|
-
var EXT_CONSTANTS_DESCRIPTION = "Static Bloomberg helper constants for date parsing/formatting, futures months, dividend types, and ETF/dividend columns.";
|
|
342
|
-
var EXT_COLUMNS_DESCRIPTION = "Column rename helpers for dividend, ETF, and earnings-shaped Bloomberg responses.";
|
|
343
|
-
var EXT_CALCULATE_DESCRIPTION = "Small numeric helper operations for Bloomberg workflows, including level percentage calculations.";
|
|
344
178
|
|
|
345
179
|
// src/result-limits.ts
|
|
346
180
|
var MAX_RESULT_DEPTH = 32;
|
|
@@ -383,7 +217,16 @@ function limitValue(value, maxRows, maxStringChars, state, depth = 0, seen = /*
|
|
|
383
217
|
state.truncated = true;
|
|
384
218
|
return "[Circular]";
|
|
385
219
|
}
|
|
220
|
+
if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer) {
|
|
221
|
+
state.truncated = true;
|
|
222
|
+
return `[binary data: ${value.byteLength} bytes]`;
|
|
223
|
+
}
|
|
386
224
|
if (!isPlainObject(value)) {
|
|
225
|
+
const toJSON = value.toJSON;
|
|
226
|
+
if (typeof toJSON === "function") {
|
|
227
|
+
seen.add(value);
|
|
228
|
+
return limitValue(toJSON.call(value), maxRows, maxStringChars, state, depth + 1, seen);
|
|
229
|
+
}
|
|
387
230
|
return value;
|
|
388
231
|
}
|
|
389
232
|
seen.add(value);
|
|
@@ -402,12 +245,12 @@ function rowCountOf(value) {
|
|
|
402
245
|
if (typeof value !== "object" || value === null) {
|
|
403
246
|
return null;
|
|
404
247
|
}
|
|
405
|
-
const
|
|
406
|
-
const rowCount =
|
|
248
|
+
const record3 = value;
|
|
249
|
+
const rowCount = record3.rowCount;
|
|
407
250
|
if (typeof rowCount === "number" && Number.isInteger(rowCount) && rowCount >= 0) {
|
|
408
251
|
return rowCount;
|
|
409
252
|
}
|
|
410
|
-
const updateCount =
|
|
253
|
+
const updateCount = record3.updateCount;
|
|
411
254
|
if (typeof updateCount === "number" && Number.isInteger(updateCount) && updateCount >= 0) {
|
|
412
255
|
return updateCount;
|
|
413
256
|
}
|
|
@@ -462,8 +305,10 @@ function limitResult(value, maxRows, maxStringChars) {
|
|
|
462
305
|
function summarizeEnvelope(envelope) {
|
|
463
306
|
const rowText = envelope.rowCount === null ? "row count unknown" : `${envelope.rowCount} row${envelope.rowCount === 1 ? "" : "s"}`;
|
|
464
307
|
const notes = [];
|
|
465
|
-
if (envelope.rowCount === 0) {
|
|
466
|
-
notes.push(
|
|
308
|
+
if (envelope.rowCount === 0 || envelope.data === null || envelope.data === void 0) {
|
|
309
|
+
notes.push(
|
|
310
|
+
"empty result; verify identifiers, fields, and date range before concluding no data exists"
|
|
311
|
+
);
|
|
467
312
|
}
|
|
468
313
|
if (envelope.truncated) {
|
|
469
314
|
notes.push("artifact truncated to configured limits");
|
|
@@ -503,16 +348,596 @@ function createToolResult(tool2, value, maxRows, maxStringChars) {
|
|
|
503
348
|
function throwWithToolContext(tool2, error) {
|
|
504
349
|
const prefix = `${tool2} failed`;
|
|
505
350
|
if (error instanceof Error) {
|
|
506
|
-
if (
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
351
|
+
if (error.message.startsWith(prefix)) {
|
|
352
|
+
throw error;
|
|
353
|
+
}
|
|
354
|
+
const wrapped = new Error(`${prefix}: ${error.message}`, { cause: error });
|
|
355
|
+
wrapped.name = error.name;
|
|
356
|
+
throw wrapped;
|
|
357
|
+
}
|
|
358
|
+
throw new Error(`${prefix}: ${String(error)}`);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// src/langchain-tool.ts
|
|
362
|
+
function inputJsonSchema(schema) {
|
|
363
|
+
const jsonSchema = zodToJsonSchema.zodToJsonSchema(schema, {
|
|
364
|
+
$refStrategy: "none",
|
|
365
|
+
effectStrategy: "input",
|
|
366
|
+
pipeStrategy: "input"
|
|
367
|
+
});
|
|
368
|
+
delete jsonSchema.$schema;
|
|
369
|
+
delete jsonSchema.definitions;
|
|
370
|
+
return jsonSchema;
|
|
371
|
+
}
|
|
372
|
+
function toolParameterJsonSchema(toolInstance) {
|
|
373
|
+
const schema = toolInstance.schema;
|
|
374
|
+
if (schema !== null && typeof schema === "object" && !("safeParse" in schema)) {
|
|
375
|
+
return schema;
|
|
376
|
+
}
|
|
377
|
+
return inputJsonSchema(schema);
|
|
378
|
+
}
|
|
379
|
+
function createBloombergStructuredTool(func, fields) {
|
|
380
|
+
const providerToolDefinition = {
|
|
381
|
+
type: "function",
|
|
382
|
+
function: {
|
|
383
|
+
description: fields.description,
|
|
384
|
+
name: fields.name,
|
|
385
|
+
parameters: inputJsonSchema(fields.schema)
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
const guarded = async (input, config) => {
|
|
389
|
+
try {
|
|
390
|
+
config?.signal?.throwIfAborted();
|
|
391
|
+
} catch (error) {
|
|
392
|
+
throwWithToolContext(fields.name, error);
|
|
393
|
+
}
|
|
394
|
+
return await func(input, config);
|
|
395
|
+
};
|
|
396
|
+
return tools.tool(
|
|
397
|
+
guarded,
|
|
398
|
+
{
|
|
399
|
+
...fields,
|
|
400
|
+
extras: { providerToolDefinition }
|
|
401
|
+
}
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// src/chart-spec.ts
|
|
406
|
+
var VEGA_SCHEMA = "https://vega.github.io/schema/vega-lite/v5.json";
|
|
407
|
+
var COMPONENT_NAME = "xbbg_chart";
|
|
408
|
+
var X_FIELD_CANDIDATES = ["date", "time", "datetime", "timestamp"];
|
|
409
|
+
var LABEL_FIELD_CANDIDATES = ["ticker", "security", "member", "name", "label"];
|
|
410
|
+
var SERIES_FIELD_CANDIDATES = ["ticker", "security", "field", "side", "category"];
|
|
411
|
+
var VALUE_FIELD_CANDIDATES = [
|
|
412
|
+
"value",
|
|
413
|
+
"PX_LAST",
|
|
414
|
+
"close",
|
|
415
|
+
"price",
|
|
416
|
+
"weight",
|
|
417
|
+
"marketValue",
|
|
418
|
+
"market_value"
|
|
419
|
+
];
|
|
420
|
+
var OPEN_FIELD_CANDIDATES = ["open", "OPEN", "PX_OPEN"];
|
|
421
|
+
var HIGH_FIELD_CANDIDATES = ["high", "HIGH", "PX_HIGH"];
|
|
422
|
+
var LOW_FIELD_CANDIDATES = ["low", "LOW", "PX_LOW"];
|
|
423
|
+
var CLOSE_FIELD_CANDIDATES = ["close", "CLOSE", "PX_LAST", "last", "value"];
|
|
424
|
+
var SIDE_FIELD_CANDIDATES = ["side", "SIDE", "type"];
|
|
425
|
+
var PRICE_FIELD_CANDIDATES = ["price", "PRICE", "px", "PX"];
|
|
426
|
+
var SIZE_FIELD_CANDIDATES = ["size", "SIZE", "quantity", "qty", "volume"];
|
|
427
|
+
function defaultChartForSource(source) {
|
|
428
|
+
switch (source) {
|
|
429
|
+
case "bdib":
|
|
430
|
+
return "candlestick";
|
|
431
|
+
case "depth":
|
|
432
|
+
return "depth";
|
|
433
|
+
case "holdings":
|
|
434
|
+
return "bar";
|
|
435
|
+
case "bdh":
|
|
436
|
+
case "rows":
|
|
437
|
+
return "line";
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
function fieldExists(rows, field) {
|
|
441
|
+
for (const row of rows) {
|
|
442
|
+
if (Object.prototype.hasOwnProperty.call(row, field)) {
|
|
443
|
+
return true;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
return false;
|
|
447
|
+
}
|
|
448
|
+
function findCandidateField(rows, candidates) {
|
|
449
|
+
for (const candidate of candidates) {
|
|
450
|
+
if (fieldExists(rows, candidate)) {
|
|
451
|
+
return candidate;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
const first = rows[0];
|
|
455
|
+
if (first === void 0) {
|
|
456
|
+
return void 0;
|
|
457
|
+
}
|
|
458
|
+
const keys = Object.keys(first);
|
|
459
|
+
for (const candidate of candidates) {
|
|
460
|
+
const lower = candidate.toLowerCase();
|
|
461
|
+
const match = keys.find((key) => key.toLowerCase() === lower);
|
|
462
|
+
if (match !== void 0 && fieldExists(rows, match)) {
|
|
463
|
+
return match;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
return void 0;
|
|
467
|
+
}
|
|
468
|
+
function requireField(rows, field, label, candidates) {
|
|
469
|
+
const resolved = field ?? findCandidateField(rows, candidates);
|
|
470
|
+
if (resolved === void 0 || !fieldExists(rows, resolved)) {
|
|
471
|
+
throw new Error(
|
|
472
|
+
`Missing ${label}; pass ${label} explicitly or include one of: ${candidates.join(", ")}`
|
|
473
|
+
);
|
|
474
|
+
}
|
|
475
|
+
return resolved;
|
|
476
|
+
}
|
|
477
|
+
function hasFiniteNumber(rows, field) {
|
|
478
|
+
for (const row of rows) {
|
|
479
|
+
if (typeof row[field] === "number" && Number.isFinite(row[field])) {
|
|
480
|
+
return true;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
return false;
|
|
484
|
+
}
|
|
485
|
+
function firstNumericField(rows, excludedField) {
|
|
486
|
+
const first = rows[0];
|
|
487
|
+
if (first === void 0) {
|
|
488
|
+
return void 0;
|
|
489
|
+
}
|
|
490
|
+
for (const key of Object.keys(first)) {
|
|
491
|
+
if (key !== excludedField && hasFiniteNumber(rows, key)) {
|
|
492
|
+
return key;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
return void 0;
|
|
496
|
+
}
|
|
497
|
+
function requireNumericField(rows, field, label) {
|
|
498
|
+
if (!hasFiniteNumber(rows, field)) {
|
|
499
|
+
throw new Error(`${label} (${field}) must contain at least one finite numeric value`);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
function inferVegaType(rows, field) {
|
|
503
|
+
for (const row of rows) {
|
|
504
|
+
const value = row[field];
|
|
505
|
+
if (typeof value === "number") {
|
|
506
|
+
return "quantitative";
|
|
507
|
+
}
|
|
508
|
+
if (typeof value === "string" && (/^\d{4}-\d{2}-\d{2}(?:$|[T\s])/u.test(value) || /^\d{8}$/u.test(value))) {
|
|
509
|
+
return "temporal";
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
return "nominal";
|
|
513
|
+
}
|
|
514
|
+
function normalizeTemporalRows(rows, field) {
|
|
515
|
+
let normalized;
|
|
516
|
+
for (let index = 0; index < rows.length; index += 1) {
|
|
517
|
+
const row = rows[index];
|
|
518
|
+
if (row === void 0) {
|
|
519
|
+
continue;
|
|
520
|
+
}
|
|
521
|
+
const value = row[field];
|
|
522
|
+
if (typeof value !== "string" || !/^\d{8}$/u.test(value)) {
|
|
523
|
+
normalized?.push(row);
|
|
524
|
+
continue;
|
|
525
|
+
}
|
|
526
|
+
normalized ??= rows.slice(0, index);
|
|
527
|
+
normalized.push({
|
|
528
|
+
...row,
|
|
529
|
+
[field]: `${value.slice(0, 4)}-${value.slice(4, 6)}-${value.slice(6, 8)}`
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
return normalized ?? rows;
|
|
533
|
+
}
|
|
534
|
+
function tooltip(fields) {
|
|
535
|
+
return fields.map((field) => ({
|
|
536
|
+
field,
|
|
537
|
+
type: field === "_xbbg_value" ? "quantitative" : "nominal"
|
|
538
|
+
}));
|
|
539
|
+
}
|
|
540
|
+
function datumField(field) {
|
|
541
|
+
return `datum[${JSON.stringify(field)}]`;
|
|
542
|
+
}
|
|
543
|
+
function buildGenericSpec(input, rows, chart, title) {
|
|
544
|
+
const xField = requireField(rows, input.xField, "xField", X_FIELD_CANDIDATES);
|
|
545
|
+
let yFields;
|
|
546
|
+
if (input.yFields !== void 0) {
|
|
547
|
+
yFields = input.yFields;
|
|
548
|
+
} else {
|
|
549
|
+
const yField = findCandidateField(rows, VALUE_FIELD_CANDIDATES) ?? firstNumericField(rows, xField);
|
|
550
|
+
if (yField === void 0) {
|
|
551
|
+
throw new Error("Missing yFields; include at least one numeric value field");
|
|
552
|
+
}
|
|
553
|
+
yFields = [yField];
|
|
554
|
+
}
|
|
555
|
+
if (yFields.length === 0) {
|
|
556
|
+
throw new Error("Missing yFields; include at least one numeric value field");
|
|
557
|
+
}
|
|
558
|
+
for (const field of yFields) {
|
|
559
|
+
if (!fieldExists(rows, field)) {
|
|
560
|
+
throw new Error(`Missing y field: ${field}`);
|
|
561
|
+
}
|
|
562
|
+
requireNumericField(rows, field, "yField");
|
|
563
|
+
}
|
|
564
|
+
const normalizedRows = inferVegaType(rows, xField) === "temporal" ? normalizeTemporalRows(rows, xField) : rows;
|
|
565
|
+
const seriesField = input.seriesField ?? (yFields.length === 1 ? findCandidateField(rows, SERIES_FIELD_CANDIDATES) : void 0);
|
|
566
|
+
if (seriesField !== void 0 && !fieldExists(rows, seriesField)) {
|
|
567
|
+
throw new Error(`Missing series field: ${seriesField}`);
|
|
568
|
+
}
|
|
569
|
+
const mark = chart === "scatter" ? "point" : chart;
|
|
570
|
+
const encoding = {
|
|
571
|
+
x: { field: xField, title: xField, type: inferVegaType(normalizedRows, xField) }
|
|
572
|
+
};
|
|
573
|
+
const transform = [];
|
|
574
|
+
if (yFields.length === 1) {
|
|
575
|
+
const yField = yFields[0];
|
|
576
|
+
if (yField === void 0) {
|
|
577
|
+
throw new Error("Missing yFields; include at least one numeric value field");
|
|
578
|
+
}
|
|
579
|
+
encoding.y = { field: yField, title: yField, type: "quantitative" };
|
|
580
|
+
if (seriesField !== void 0) {
|
|
581
|
+
encoding.color = { field: seriesField, title: seriesField, type: "nominal" };
|
|
511
582
|
}
|
|
512
|
-
|
|
583
|
+
encoding.tooltip = tooltip([
|
|
584
|
+
xField,
|
|
585
|
+
...seriesField === void 0 ? [] : [seriesField],
|
|
586
|
+
yField
|
|
587
|
+
]);
|
|
588
|
+
} else {
|
|
589
|
+
transform.push({ as: ["_xbbg_series", "_xbbg_value"], fold: yFields });
|
|
590
|
+
encoding.y = { field: "_xbbg_value", title: "value", type: "quantitative" };
|
|
591
|
+
encoding.color = { field: "_xbbg_series", title: "series", type: "nominal" };
|
|
592
|
+
if (seriesField !== void 0) {
|
|
593
|
+
encoding.detail = { field: seriesField, type: "nominal" };
|
|
594
|
+
}
|
|
595
|
+
encoding.tooltip = tooltip([
|
|
596
|
+
xField,
|
|
597
|
+
...seriesField === void 0 ? [] : [seriesField],
|
|
598
|
+
"_xbbg_series",
|
|
599
|
+
"_xbbg_value"
|
|
600
|
+
]);
|
|
601
|
+
}
|
|
602
|
+
const spec = {
|
|
603
|
+
$schema: VEGA_SCHEMA,
|
|
604
|
+
data: { values: normalizedRows },
|
|
605
|
+
description: `xbbg ${chart} chart spec for ${input.source}`,
|
|
606
|
+
mark: { type: mark, tooltip: true },
|
|
607
|
+
title,
|
|
608
|
+
...transform.length === 0 ? {} : { transform },
|
|
609
|
+
encoding
|
|
610
|
+
};
|
|
611
|
+
return { spec, xField, yFields, ...seriesField === void 0 ? {} : { seriesField } };
|
|
612
|
+
}
|
|
613
|
+
function buildBarSpec(input, rows, title) {
|
|
614
|
+
const xField = requireField(
|
|
615
|
+
rows,
|
|
616
|
+
input.xField ?? input.labelField,
|
|
617
|
+
"labelField",
|
|
618
|
+
LABEL_FIELD_CANDIDATES
|
|
619
|
+
);
|
|
620
|
+
const yField = requireField(
|
|
621
|
+
rows,
|
|
622
|
+
input.valueField ?? input.yFields?.[0],
|
|
623
|
+
"valueField",
|
|
624
|
+
VALUE_FIELD_CANDIDATES
|
|
625
|
+
);
|
|
626
|
+
requireNumericField(rows, yField, "valueField");
|
|
627
|
+
const seriesField = input.seriesField;
|
|
628
|
+
if (seriesField !== void 0 && !fieldExists(rows, seriesField)) {
|
|
629
|
+
throw new Error(`Missing series field: ${seriesField}`);
|
|
630
|
+
}
|
|
631
|
+
const encoding = {
|
|
632
|
+
x: { field: xField, sort: "-y", title: xField, type: inferVegaType(rows, xField) },
|
|
633
|
+
y: { field: yField, title: yField, type: "quantitative" },
|
|
634
|
+
tooltip: tooltip([xField, ...seriesField === void 0 ? [] : [seriesField], yField])
|
|
635
|
+
};
|
|
636
|
+
if (seriesField !== void 0) {
|
|
637
|
+
encoding.color = { field: seriesField, title: seriesField, type: "nominal" };
|
|
638
|
+
}
|
|
639
|
+
return {
|
|
640
|
+
spec: {
|
|
641
|
+
$schema: VEGA_SCHEMA,
|
|
642
|
+
data: { values: rows },
|
|
643
|
+
description: `xbbg bar chart spec for ${input.source}`,
|
|
644
|
+
encoding,
|
|
645
|
+
mark: { type: "bar", tooltip: true },
|
|
646
|
+
title
|
|
647
|
+
},
|
|
648
|
+
xField,
|
|
649
|
+
yFields: [yField],
|
|
650
|
+
...seriesField === void 0 ? {} : { seriesField }
|
|
651
|
+
};
|
|
652
|
+
}
|
|
653
|
+
function buildCandlestickSpec(input, rows, title) {
|
|
654
|
+
const xField = requireField(rows, input.xField, "xField", X_FIELD_CANDIDATES);
|
|
655
|
+
const openField = requireField(rows, input.openField, "openField", OPEN_FIELD_CANDIDATES);
|
|
656
|
+
const highField = requireField(rows, input.highField, "highField", HIGH_FIELD_CANDIDATES);
|
|
657
|
+
const lowField = requireField(rows, input.lowField, "lowField", LOW_FIELD_CANDIDATES);
|
|
658
|
+
const closeField = requireField(rows, input.closeField, "closeField", CLOSE_FIELD_CANDIDATES);
|
|
659
|
+
for (const [label, field] of [
|
|
660
|
+
["openField", openField],
|
|
661
|
+
["highField", highField],
|
|
662
|
+
["lowField", lowField],
|
|
663
|
+
["closeField", closeField]
|
|
664
|
+
]) {
|
|
665
|
+
requireNumericField(rows, field, label);
|
|
666
|
+
}
|
|
667
|
+
const normalizedRows = inferVegaType(rows, xField) === "temporal" ? normalizeTemporalRows(rows, xField) : rows;
|
|
668
|
+
const color = {
|
|
669
|
+
condition: { test: `${datumField(closeField)} >= ${datumField(openField)}`, value: "#137333" },
|
|
670
|
+
value: "#c5221f"
|
|
671
|
+
};
|
|
672
|
+
return {
|
|
673
|
+
spec: {
|
|
674
|
+
$schema: VEGA_SCHEMA,
|
|
675
|
+
data: { values: normalizedRows },
|
|
676
|
+
description: `xbbg candlestick chart spec for ${input.source}`,
|
|
677
|
+
encoding: {
|
|
678
|
+
x: { field: xField, title: xField, type: inferVegaType(normalizedRows, xField) }
|
|
679
|
+
},
|
|
680
|
+
layer: [
|
|
681
|
+
{
|
|
682
|
+
mark: "rule",
|
|
683
|
+
encoding: {
|
|
684
|
+
color,
|
|
685
|
+
tooltip: tooltip([xField, openField, highField, lowField, closeField]),
|
|
686
|
+
y: { field: lowField, title: "price", type: "quantitative" },
|
|
687
|
+
y2: { field: highField }
|
|
688
|
+
}
|
|
689
|
+
},
|
|
690
|
+
{
|
|
691
|
+
mark: "bar",
|
|
692
|
+
encoding: {
|
|
693
|
+
color,
|
|
694
|
+
y: { field: openField, title: "price", type: "quantitative" },
|
|
695
|
+
y2: { field: closeField }
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
],
|
|
699
|
+
title
|
|
700
|
+
},
|
|
701
|
+
xField,
|
|
702
|
+
yFields: [openField, highField, lowField, closeField]
|
|
703
|
+
};
|
|
704
|
+
}
|
|
705
|
+
function buildDepthSpec(input, rows, title) {
|
|
706
|
+
const priceField = requireField(
|
|
707
|
+
rows,
|
|
708
|
+
input.priceField ?? input.xField,
|
|
709
|
+
"priceField",
|
|
710
|
+
PRICE_FIELD_CANDIDATES
|
|
711
|
+
);
|
|
712
|
+
const sizeField = requireField(
|
|
713
|
+
rows,
|
|
714
|
+
input.sizeField ?? input.valueField ?? input.yFields?.[0],
|
|
715
|
+
"sizeField",
|
|
716
|
+
SIZE_FIELD_CANDIDATES
|
|
717
|
+
);
|
|
718
|
+
const sideField = requireField(
|
|
719
|
+
rows,
|
|
720
|
+
input.sideField ?? input.seriesField,
|
|
721
|
+
"sideField",
|
|
722
|
+
SIDE_FIELD_CANDIDATES
|
|
723
|
+
);
|
|
724
|
+
requireNumericField(rows, priceField, "priceField");
|
|
725
|
+
requireNumericField(rows, sizeField, "sizeField");
|
|
726
|
+
return {
|
|
727
|
+
spec: {
|
|
728
|
+
$schema: VEGA_SCHEMA,
|
|
729
|
+
data: { values: rows },
|
|
730
|
+
description: `xbbg market depth chart spec for ${input.source}`,
|
|
731
|
+
encoding: {
|
|
732
|
+
color: { field: sideField, title: sideField, type: "nominal" },
|
|
733
|
+
tooltip: tooltip([sideField, priceField, sizeField]),
|
|
734
|
+
x: { field: priceField, title: priceField, type: "quantitative" },
|
|
735
|
+
y: { field: sizeField, title: sizeField, type: "quantitative" }
|
|
736
|
+
},
|
|
737
|
+
mark: { type: "bar", tooltip: true },
|
|
738
|
+
title
|
|
739
|
+
},
|
|
740
|
+
xField: priceField,
|
|
741
|
+
yFields: [sizeField],
|
|
742
|
+
seriesField: sideField
|
|
743
|
+
};
|
|
744
|
+
}
|
|
745
|
+
function createChartSpec(input) {
|
|
746
|
+
const maxPoints = input.maxPoints ?? input.rows.length;
|
|
747
|
+
const rows = input.rows.length > maxPoints ? input.rows.slice(0, maxPoints) : input.rows;
|
|
748
|
+
if (rows.length === 0) {
|
|
749
|
+
throw new Error("rows must contain at least one chart data row");
|
|
750
|
+
}
|
|
751
|
+
const chart = input.chart ?? defaultChartForSource(input.source);
|
|
752
|
+
const title = input.title ?? `${input.source} ${chart}`;
|
|
753
|
+
const warnings = [];
|
|
754
|
+
if (rows.length !== input.rows.length) {
|
|
755
|
+
warnings.push(
|
|
756
|
+
`Chart spec contains first ${rows.length} of ${input.rows.length} rows; narrow the upstream request for a complete visualization.`
|
|
757
|
+
);
|
|
758
|
+
}
|
|
759
|
+
const built = chart === "candlestick" ? buildCandlestickSpec(input, rows, title) : chart === "depth" ? buildDepthSpec(input, rows, title) : chart === "bar" ? buildBarSpec(input, rows, title) : buildGenericSpec(input, rows, chart, title);
|
|
760
|
+
const summary = {
|
|
761
|
+
chart,
|
|
762
|
+
inputRows: input.rows.length,
|
|
763
|
+
renderer: "vega-lite",
|
|
764
|
+
rowCount: rows.length,
|
|
765
|
+
source: input.source,
|
|
766
|
+
title,
|
|
767
|
+
truncatedInput: rows.length !== input.rows.length,
|
|
768
|
+
xField: built.xField,
|
|
769
|
+
yFields: built.yFields,
|
|
770
|
+
...built.seriesField === void 0 ? {} : { seriesField: built.seriesField }
|
|
771
|
+
};
|
|
772
|
+
return {
|
|
773
|
+
kind: "xbbg.visualization",
|
|
774
|
+
version: 1,
|
|
775
|
+
component: COMPONENT_NAME,
|
|
776
|
+
renderer: "vega-lite",
|
|
777
|
+
rowCount: rows.length,
|
|
778
|
+
inputRowCount: input.rows.length,
|
|
779
|
+
truncatedInput: rows.length !== input.rows.length,
|
|
780
|
+
source: input.source,
|
|
781
|
+
chart,
|
|
782
|
+
summary,
|
|
783
|
+
spec: built.spec,
|
|
784
|
+
warnings
|
|
785
|
+
};
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
// src/cdx-fields.ts
|
|
789
|
+
var CDX_INFO_FIELDS = Object.freeze([
|
|
790
|
+
"ROLLING_SERIES",
|
|
791
|
+
"VERSION",
|
|
792
|
+
"ON_THE_RUN_CURRENT_BD_INDICATOR",
|
|
793
|
+
"CDS_FIRST_ACCRUAL_START_DATE",
|
|
794
|
+
"NAME",
|
|
795
|
+
"NUM_CURRENT_COMPANIES_CCY_TKR",
|
|
796
|
+
"NUM_ORIG_COMPANIES_CRNCY_TKR",
|
|
797
|
+
"PX_LAST"
|
|
798
|
+
]);
|
|
799
|
+
var CDX_PRICING_FIELDS = Object.freeze([
|
|
800
|
+
"PX_LAST",
|
|
801
|
+
"PX_BID",
|
|
802
|
+
"PX_ASK",
|
|
803
|
+
"UPFRONT_LAST",
|
|
804
|
+
"UPFRONT_BID",
|
|
805
|
+
"UPFRONT_ASK",
|
|
806
|
+
"CDS_FLAT_SPREAD",
|
|
807
|
+
"UPFRONT_FEE",
|
|
808
|
+
"PV_CDS_PREMIUM_LEG",
|
|
809
|
+
"PV_CDS_DEFAULT_LEG"
|
|
810
|
+
]);
|
|
811
|
+
var CDX_RISK_FIELDS = Object.freeze([
|
|
812
|
+
"SW_CNV_BPV",
|
|
813
|
+
"SW_EQV_BPV",
|
|
814
|
+
"CDS_SPREAD_MID_MODIFIED_DURATION",
|
|
815
|
+
"CDS_SPREAD_MID_CONVEXITY",
|
|
816
|
+
"RECOVERY_RATE_SEN",
|
|
817
|
+
"CDS_RECOVERY_RT"
|
|
818
|
+
]);
|
|
819
|
+
|
|
820
|
+
// src/descriptions.ts
|
|
821
|
+
var REQUIRED_TOOL_INSTRUCTIONS = [
|
|
822
|
+
"# Bloomberg tool usage",
|
|
823
|
+
"- Use these tools only for server-side Bloomberg data access through @xbbg/core. Never imply Bloomberg data was retrieved unless a tool call actually returned it.",
|
|
824
|
+
"- Ask a clarifying question before calling a tool when any security identity, field mnemonic, date range, currency, periodicity, intraday interval, timezone, override, or universe is ambiguous.",
|
|
825
|
+
"- Do not invent Bloomberg tickers, field mnemonics, overrides, or BQL functions. If the user gives a field description rather than a confident mnemonic, call xbbg_bflds first.",
|
|
826
|
+
"- Issue one tool call per dataset and read any error before retrying; never probe parameter variants in parallel. Omit optional output-shape parameters such as format unless the user asked for a specific shape.",
|
|
827
|
+
"",
|
|
828
|
+
"## Security identifiers",
|
|
829
|
+
"- Pass each security in the form the user supplied it; never translate between identifier kinds on your own.",
|
|
830
|
+
"- User supplied a Bloomberg ticker: pass it through fully qualified as <TICKER> <MARKET_SECTOR>, for example <TICKER> <EXCHANGE> Equity, <INDEX_TICKER> Index, or <CCY_PAIR> Curncy.",
|
|
831
|
+
"- The market sector ending (Bloomberg yellow key) is part of the security string. The sectors are: Equity, Index, Curncy, Comdty, Corp, Govt, Muni, Mtge, M-Mkt, and Pfd. Equity securities carry an exchange or composite code before the sector (<TICKER> <EXCHANGE> Equity); preferred securities use the Pfd sector; corporate and government bonds use Corp and Govt. Request tools pass the security through to Bloomberg without validating the sector, so copy it exactly as the user supplied it.",
|
|
832
|
+
"- User supplied a raw ISIN or CUSIP: pass Bloomberg identifier syntax directly: /isin/<ISIN> or /cusip/<CUSIP>. Never pass the bare identifier without its prefix, except to xbbg_resolve_isins and xbbg_issuer_isins, which take raw ISIN strings.",
|
|
833
|
+
"- <TICKER> <MARKET_SECTOR> is a format template, not authorization to construct a ticker. Never invent, recall from memory, or guess the Bloomberg ticker behind an identifier the user gave; identifier syntax is already a complete, valid security input. Use xbbg_resolve_isins only when the user wants the resolved Bloomberg security itself.",
|
|
834
|
+
"- Recipe tools that take tickers (xbbg_preferreds, xbbg_corporate_bonds, xbbg_index_members, xbbg_etf_holdings) do not accept identifier syntax. When the user supplied an ISIN or CUSIP for those workflows, resolve it with xbbg_resolve_isins first and use the returned Bloomberg security; never guess the ticker.",
|
|
835
|
+
"- Do not use xbbg_bsrch as a replacement for a known ticker, ISIN, or CUSIP.",
|
|
836
|
+
"- For dealer quote / BQR workflows, use xbbg_bqr with a fixed-income identifier plus a dealer quote source such as /isin/<ISIN>@<QUOTE_SOURCE> <MARKET_SECTOR>. For raw intraday ticks, use xbbg_bdtick.",
|
|
837
|
+
"",
|
|
838
|
+
"## Core request tools",
|
|
839
|
+
"- xbbg_bdp: current or reference point-in-time fields. Use a small explicit securities list and a small explicit fields list. Use includeSecurityErrors only when the caller wants Bloomberg security errors in the response.",
|
|
840
|
+
"- xbbg_bdh: historical daily or periodic time series. Always provide explicit start and end dates in YYYY-MM-DD or YYYYMMDD form. Ask before choosing periodicity, currency, fill behavior, adjustment overrides, or a wide output table.",
|
|
841
|
+
"- xbbg_bds: Bloomberg bulk/table fields. Provide exactly one bulk field; do not use bds for ordinary multi-field reference data.",
|
|
842
|
+
"- xbbg_bdib: intraday bars only. Provide one ticker, explicit ISO start/end datetimes with time components, a positive interval in minutes, and timezone context when datetimes are naive.",
|
|
843
|
+
"- xbbg_bdtick: intraday tick data. Provide one ticker, explicit ISO start/end datetimes with time components, and explicit eventTypes unless the default event stream is intended. Use includeBrokerCodes or includeConditionCodes only when those columns are needed.",
|
|
844
|
+
"- xbbg_bql: BQL expressions only when the user asks for BQL or the request is naturally expressed as a bounded BQL query. Keep queries short, explicit, and scoped to the requested universe.",
|
|
845
|
+
"- xbbg_bsrch: Bloomberg search-grid or saved-search workflows only. Do not use it for ordinary security lookup.",
|
|
846
|
+
"- xbbg_bqr: Bloomberg Quote Request / dealer quotes. Prefer fixed-income identifier inputs with a dealer quote source such as /isin/<ISIN>@<QUOTE_SOURCE> <MARKET_SECTOR>, explicit start/end datetimes with time components, and explicit event types.",
|
|
847
|
+
"- xbbg_bflds: Bloomberg field metadata/search. Provide exactly one of fields or searchSpec; use searchSpec for natural-language field names and fields for known mnemonics.",
|
|
848
|
+
"- xbbg_beqs: Bloomberg equity screening by named BEQS screen. Prefer this over hand-written BQL when the user names an existing Bloomberg screen.",
|
|
849
|
+
"- xbbg_yas: fixed-income YAS recipe fields. Prefer this over manual YAS-style BDP requests when the user asks for yield, duration, spread, or price analytics.",
|
|
850
|
+
"- xbbg_preferreds: preferred stock discovery from the issuer's common equity ticker, never a guessed preferred ('Pfd') ticker. Resolve a supplied ISIN/CUSIP with xbbg_resolve_isins first. Prefer this over xbbg_ext_bql_builder plus xbbg_bql when the user wants the actual preferreds result.",
|
|
851
|
+
"- xbbg_corporate_bonds: bounded corporate bond universe query for a company ticker. Prefer this over generic BQL for company debt discovery.",
|
|
852
|
+
"- xbbg_index_members: index constituents through the core index recipe. Prefer this over generic BDS/BQL members when the user asks for constituents.",
|
|
853
|
+
"- xbbg_resolve_isins: resolves supplied ISIN strings to Bloomberg securities. Pass raw ISIN strings only for this recipe; otherwise use /isin/<ISIN> syntax with data tools.",
|
|
854
|
+
"- xbbg_issuer_isins: issuer/bond ISIN workflow for supplied bond ISIN strings.",
|
|
855
|
+
"- xbbg_etf_holdings: ETF holdings recipe for a single ETF ticker. Prefer this over generic BQL holdings when the user asks for ETF constituents.",
|
|
856
|
+
"- xbbg_stream_snapshot: bounded live market-data observation from //blp/mktdata. Requires explicit maxUpdates and always terminates/unsubscribes.",
|
|
857
|
+
"- xbbg_mktbar_snapshot: bounded live market-bar observation from //blp/mktbar for one ticker. Requires explicit maxUpdates and always terminates/unsubscribes.",
|
|
858
|
+
"- xbbg_depth_snapshot: bounded market-depth observation from //blp/mktdepthdata for one ticker. Requires explicit maxUpdates and always terminates/unsubscribes.",
|
|
859
|
+
"",
|
|
860
|
+
"## BQL guidance",
|
|
861
|
+
"- BQL is a complete Bloomberg Query Language expression sent as one query string; the tool does not assemble get/for/with clauses for you.",
|
|
862
|
+
"- Basic shape: get(<FIELD_1>, <FIELD_2>) for(<UNIVERSE>). Use placeholders such as '<TICKER> <MARKET_SECTOR>', holdings('<ETF_TICKER> <MARKET_SECTOR>'), or members('<INDEX_TICKER> <MARKET_SECTOR>') until the user supplies real inputs.",
|
|
863
|
+
"- Use BQL for universe-oriented analytics and screens only when the user provides a bounded universe, filters, and date range.",
|
|
864
|
+
"- Prefer xbbg_ext_bql_builder instead of hand-writing BQL for supported workflows: preferred stocks, corporate bonds, and ETF holdings.",
|
|
865
|
+
"- Do not use BQL just because the user asks for normal reference data; xbbg_bdp is simpler for current fields and xbbg_bdh is simpler for historical time series.",
|
|
866
|
+
"",
|
|
867
|
+
"## Output handling",
|
|
868
|
+
"- Tool results use LangChain content_and_artifact output: content starts with a compact summary and then includes bounded model-readable JSON; artifact is the structured bounded envelope with tool, rowCount, truncated, and data for application code.",
|
|
869
|
+
"- If a response is empty, truncated, or contains Bloomberg/security errors, say that directly. Do not fill gaps from memory or assumptions."
|
|
870
|
+
];
|
|
871
|
+
var OPTIONAL_EXTENSION_INSTRUCTIONS = [
|
|
872
|
+
"",
|
|
873
|
+
"## Extension helper tools",
|
|
874
|
+
"- xbbg_ext_ticker: ticker hygiene before live calls. parse_ticker splits generic futures-style tickers only \u2014 asset endings Index, Curncy, Comdty, or Corp as <ROOT><N> <ASSET>, or <ROOT><N> <EXCHANGE> Equity \u2014 and rejects other market sectors (Pfd, Govt, Muni, Mtge, M-Mkt) and non-futures securities. normalize_tickers trims/canonicalizes lists, filter_equity_tickers keeps equity-like tickers, is_specific_contract checks futures specificity, and validate_generic_ticker rejects malformed generic futures tickers.",
|
|
875
|
+
"- xbbg_ext_futures: futures contract construction and selection. Use build_futures_ticker for root/month/year/asset assembly, get_futures_months for month-code lookup, generate_candidates for generic-to-specific candidates, contract_index for generic contract rank, filter_candidates_by_cycle for HMUZ/quarterly cycles, and filter_valid_contracts to keep contracts valid for a date.",
|
|
876
|
+
"- xbbg_ext_cdx: CDX ticker workflow support. Use parse_cdx_ticker to understand a CDX ticker, previous_cdx_series to roll back a series, cdx_gen_to_specific to resolve a generic CDX to a target series, and cdx_info/cdx_pricing/cdx_risk for predefined BDP field bundles. cdx_pricing and cdx_risk accept recoveryRate, which becomes the CDS_RR override.",
|
|
877
|
+
"- xbbg_ext_currency: currency-planning helpers. build_fx_pair constructs the Bloomberg FX pair and conversion factor, same_currency avoids unnecessary conversion, and currencies_needing_conversion identifies which currencies differ from a target before requesting converted values.",
|
|
878
|
+
"- xbbg_ext_bql_builder: safe BQL generators for common xbbg workflows. Use build_preferreds_query for preferred-stock discovery from an equity, build_corporate_bonds_query for company bond universes with optional currency/active filters, and build_etf_holdings_query for ETF constituents. Prefer these builders over hand-writing those BQL shapes.",
|
|
879
|
+
"- xbbg_ext_chart_spec: renderer-neutral chart spec helper. Convert bounded rows from xbbg_bdh, xbbg_bdib, holdings, depth, or already-shaped row data into a Vega-Lite JSON spec for frontend rendering; do not use it as proof that Bloomberg data was fetched.",
|
|
880
|
+
"- xbbg_ext_market_session: exchange calendar/timezone support. derive_sessions turns day session times into session blocks, infer_timezone maps country codes to timezones, session_times_to_utc converts local sessions to UTC, get_market_rule gets MIC/exchange rules, default_turnover_dates and default_bqr_datetimes provide bounded defaults, and get/list_exchange_override inspect configured exchange metadata.",
|
|
881
|
+
"- xbbg_ext_yas_overrides: builds flat YAS override maps for fixed-income BDP requests when the lower-level BDP workflow is required. Prefer xbbg_yas for actual YAS recipe fields.",
|
|
882
|
+
"- xbbg_ext_constants: static lookup/format helpers for date parsing/formatting, futures month code/name mappings, dividend type mappings, and known dividend/ETF output columns.",
|
|
883
|
+
"- xbbg_ext_columns: post-processing helpers for Bloomberg-shaped tables. Use rename_dividend_columns, rename_etf_columns, or build_earning_header_rename when explaining or normalizing response column names after a request.",
|
|
884
|
+
"- xbbg_ext_calculate: small numeric helper for Bloomberg workflows. calculate_level_percentages pairs observed values with levels; values and levels must have the same length."
|
|
885
|
+
];
|
|
886
|
+
var OPTIONAL_LIMIT_INSTRUCTIONS = [
|
|
887
|
+
"",
|
|
888
|
+
"## Request limits and inputs",
|
|
889
|
+
"- Keep Bloomberg requests bounded: explicit securities, explicit fields, explicit dates, limited rows, and no broad exploratory pulls unless the user narrows the universe.",
|
|
890
|
+
"- Respect configured tool limits for securities, fields, rows, string size, BQL length, and search spec length. Ask the user to narrow the request rather than exceeding them.",
|
|
891
|
+
"- Use flat primitive overrides and kwargs only: string, number, or boolean values. Do not send nested objects, arrays, or inferred defaults as overrides."
|
|
892
|
+
];
|
|
893
|
+
var BLOOMBERG_TOOL_INSTRUCTIONS = [
|
|
894
|
+
...REQUIRED_TOOL_INSTRUCTIONS,
|
|
895
|
+
...OPTIONAL_EXTENSION_INSTRUCTIONS,
|
|
896
|
+
...OPTIONAL_LIMIT_INSTRUCTIONS
|
|
897
|
+
].join("\n");
|
|
898
|
+
function getBloombergToolInstructions(options = {}) {
|
|
899
|
+
const includeExtensionGuidance = options.includeExtensionGuidance ?? true;
|
|
900
|
+
const includeLimitReminder = options.includeLimitReminder ?? true;
|
|
901
|
+
const lines = [...REQUIRED_TOOL_INSTRUCTIONS];
|
|
902
|
+
if (includeExtensionGuidance) {
|
|
903
|
+
lines.push(...OPTIONAL_EXTENSION_INSTRUCTIONS);
|
|
513
904
|
}
|
|
514
|
-
|
|
905
|
+
if (includeLimitReminder) {
|
|
906
|
+
lines.push(...OPTIONAL_LIMIT_INSTRUCTIONS);
|
|
907
|
+
}
|
|
908
|
+
return lines.join("\n");
|
|
515
909
|
}
|
|
910
|
+
var BDP_DESCRIPTION = 'Bloomberg reference data for current or point-in-time fields. Use for a small bounded list of fully qualified securities. Use /isin/<ISIN> for ISINs and /cusip/<CUSIP> for CUSIPs. Example: securities ["<TICKER> <MARKET_SECTOR>"], fields ["<FIELD>"].';
|
|
911
|
+
var BDH_DESCRIPTION = 'Bloomberg historical time series. Requires explicit start and end dates; ask before using if the date range or periodicity is ambiguous. Use /isin/<ISIN> for ISINs and /cusip/<CUSIP> for CUSIPs. Example: securities ["<TICKER> <MARKET_SECTOR>"], fields ["<FIELD>"], start "<START_DATE>", end "<END_DATE>".';
|
|
912
|
+
var BDS_DESCRIPTION = 'Bloomberg bulk/table reference data. Requires exactly one bulk field, not a field list. Use /isin/<ISIN> for ISINs and /cusip/<CUSIP> for CUSIPs. Example: securities ["<INDEX_TICKER> <MARKET_SECTOR>"], field "<BULK_FIELD>".';
|
|
913
|
+
var BDIB_DESCRIPTION = 'Bloomberg intraday bars. Requires one ticker plus explicit ISO start/end datetimes with time components and a positive interval in minutes. Use /isin/<ISIN> for ISINs and /cusip/<CUSIP> for CUSIPs. Example: ticker "<TICKER> <MARKET_SECTOR>", start "<START_DATETIME>", end "<END_DATETIME>", interval <MINUTES>.';
|
|
914
|
+
var BDTICK_DESCRIPTION = 'Bloomberg intraday tick data. Requires one ticker plus explicit ISO start/end datetimes with time components. Set eventTypes explicitly, for example ["<EVENT_TYPE>"], and includeBrokerCodes/includeConditionCodes only when needed.';
|
|
915
|
+
var BQL_DESCRIPTION = "Bloomberg Query Language expression sent as one complete query string. Use for bounded universe analytics with placeholder-shaped syntax such as get(<FIELD>) for('<TICKER> <MARKET_SECTOR>'), holdings('<ETF_TICKER> <MARKET_SECTOR>'), members('<INDEX_TICKER> <MARKET_SECTOR>'), filters with with(...), or dates=range(...). Prefer xbbg_bdp/xbbg_bdh for simple reference or historical requests.";
|
|
916
|
+
var BSRCH_DESCRIPTION = 'Bloomberg search/grid request. Use for saved-search or ExcelGetGrid-style Bloomberg searches, not ordinary security lookup. Example searchSpec "<SEARCH_SPEC>".';
|
|
917
|
+
var BQR_DESCRIPTION = 'Bloomberg Quote Request / dealer quotes. Use for fixed-income dealer quote ticks, preferably with an ISIN plus dealer source such as "/isin/<ISIN>@<QUOTE_SOURCE> <MARKET_SECTOR>"; requires explicit ISO start/end datetimes with time components. Set eventTypes explicitly, for example ["<EVENT_TYPE>"].';
|
|
918
|
+
var BFLDS_DESCRIPTION = 'Bloomberg field metadata and field search. Use first when a field mnemonic is uncertain. Provide exactly one of fields or searchSpec. Example: fields ["<FIELD>"] or searchSpec "<FIELD_SEARCH_TEXT>".';
|
|
919
|
+
var BEQS_DESCRIPTION = "Bloomberg equity screening by named BEQS screen. Use when the user names an existing Bloomberg screen and wants its bounded result set. Prefer this over hand-written BQL for saved Bloomberg screens.";
|
|
920
|
+
var YAS_DESCRIPTION = "Bloomberg fixed-income YAS recipe fields for one or more bonds. Use for yield, duration, spread, benchmark, or price analytics; provide explicit fields and optional settlement/yield/price inputs. Pass securities as supplied: '<TICKER> <MARKET_SECTOR>' or identifier syntax such as '/isin/<ISIN> <MARKET_SECTOR>'.";
|
|
921
|
+
var PREFERREDS_DESCRIPTION = "Preferred stock discovery for one issuer. Takes the issuer's common equity ticker such as '<TICKER> US Equity', never a preferred ('Pfd') ticker and never a guessed one. If the user supplied an ISIN or CUSIP, resolve it with xbbg_resolve_isins first.";
|
|
922
|
+
var CORPORATE_BONDS_DESCRIPTION = "Corporate bond universe query for one issuer/company equity ticker, with optional currency, active-only filter, and result fields. Prefer this over generic BQL for company debt discovery. If the user supplied an ISIN or CUSIP, resolve it with xbbg_resolve_isins first; never guess the ticker.";
|
|
923
|
+
var INDEX_MEMBERS_DESCRIPTION = "Index constituent recipe for one Bloomberg index ticker such as '<INDEX_TICKER> Index'. Use for bounded member lists and optional historical/as-of constituent membership; never guess index tickers.";
|
|
924
|
+
var RESOLVE_ISINS_DESCRIPTION = "Resolve raw ISIN strings to Bloomberg securities through the core ISIN recipe. Do not add /isin/ prefixes in this tool; pass the exact ISIN strings supplied by the user.";
|
|
925
|
+
var ISSUER_ISINS_DESCRIPTION = "Issuer/bond ISIN workflow for supplied bond ISIN strings. Use for issuer-level ISIN discovery starting from known bond ISINs.";
|
|
926
|
+
var ETF_HOLDINGS_DESCRIPTION = "ETF holdings recipe for one ETF ticker such as '<ETF_TICKER> <MARKET_SECTOR>'. Use when the user asks for ETF constituents or holdings and wants the bounded holdings result. Resolve a supplied ISIN/CUSIP with xbbg_resolve_isins first; never guess the ticker.";
|
|
927
|
+
var STREAM_SNAPSHOT_DESCRIPTION = "Bounded live market-data snapshot from //blp/mktdata. Collects at most maxUpdates updates until timeout/done, then always unsubscribes; use for finite observations, not open subscriptions.";
|
|
928
|
+
var MKTBAR_SNAPSHOT_DESCRIPTION = "Bounded live market-bar snapshot from //blp/mktbar for one ticker. Collects at most maxUpdates updates until timeout/done, then always unsubscribes.";
|
|
929
|
+
var DEPTH_SNAPSHOT_DESCRIPTION = "Bounded live market-depth snapshot from //blp/mktdepthdata for one ticker. Collects at most maxUpdates updates until timeout/done, then always unsubscribes.";
|
|
930
|
+
var EXT_TICKER_DESCRIPTION = "Ticker hygiene helpers: parse_ticker (generic futures-style tickers ending in Index, Curncy, Comdty, or Corp, or <ROOT><N> <EXCHANGE> Equity; other market sectors are rejected), normalize_tickers, filter_equity_tickers, is_specific_contract, and validate_generic_ticker.";
|
|
931
|
+
var EXT_FUTURES_DESCRIPTION = "Futures helpers for contract construction and selection: build_futures_ticker, generate_candidates, contract_index, filter_candidates_by_cycle, filter_valid_contracts, and get_futures_months.";
|
|
932
|
+
var EXT_CDX_DESCRIPTION = "CDX helpers for parsing, series rolling/resolution, and predefined info/pricing/risk BDP field bundles.";
|
|
933
|
+
var EXT_CURRENCY_DESCRIPTION = "Currency planning helpers: build FX pairs, test same-currency requests, and find currencies needing conversion.";
|
|
934
|
+
var EXT_BQL_BUILDER_DESCRIPTION = "BQL builders for preferred stocks, corporate bonds, and ETF holdings. Prefer to construct those bounded BQL shapes before xbbg_bql.";
|
|
935
|
+
var EXT_CHART_SPEC_DESCRIPTION = "Renderer-neutral chart spec helper for frontend generative UI. Converts bounded Bloomberg rows from bdh, bdib, holdings, depth, or already-shaped row data into a Vega-Lite JSON spec; it does not fetch Bloomberg data or render images.";
|
|
936
|
+
var EXT_MARKET_SESSION_DESCRIPTION = "Market session and timezone helpers for deriving sessions, UTC windows, market rules, exchange metadata, turnover defaults, and BQR datetime defaults.";
|
|
937
|
+
var EXT_YAS_OVERRIDES_DESCRIPTION = "Build flat Bloomberg YAS override maps for fixed-income analytics fields.";
|
|
938
|
+
var EXT_CONSTANTS_DESCRIPTION = "Static Bloomberg helper constants for date parsing/formatting, futures months, dividend types, and ETF/dividend columns.";
|
|
939
|
+
var EXT_COLUMNS_DESCRIPTION = "Column rename helpers for dividend, ETF, and earnings-shaped Bloomberg responses.";
|
|
940
|
+
var EXT_CALCULATE_DESCRIPTION = "Small numeric helper operations for Bloomberg workflows, including level percentage calculations.";
|
|
516
941
|
var stringPairSchema = z__namespace.object({
|
|
517
942
|
key: z__namespace.string().trim().min(1).describe("String pair key."),
|
|
518
943
|
value: z__namespace.string().trim().min(1).describe("String pair value.")
|
|
@@ -534,7 +959,7 @@ function optionalString(options, description) {
|
|
|
534
959
|
function tickerSchema(options) {
|
|
535
960
|
const ticker = nonEmptyString(
|
|
536
961
|
options,
|
|
537
|
-
"One Bloomberg ticker
|
|
962
|
+
"One generic futures-style Bloomberg ticker: <ROOT><N> ending in Index, Curncy, Comdty, or Corp, or <ROOT><N> <EXCHANGE> Equity. parse_ticker rejects other market sectors (Pfd, Govt, Muni, Mtge, M-Mkt) and non-futures securities."
|
|
538
963
|
);
|
|
539
964
|
const tickers = stringArray(
|
|
540
965
|
options,
|
|
@@ -550,94 +975,151 @@ function tickerSchema(options) {
|
|
|
550
975
|
]);
|
|
551
976
|
}
|
|
552
977
|
function futuresSchema(options) {
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
"
|
|
567
|
-
"
|
|
568
|
-
"
|
|
569
|
-
"
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
978
|
+
const genTicker = nonEmptyString(
|
|
979
|
+
options,
|
|
980
|
+
"Generic Bloomberg futures ticker, for example ES1 Index."
|
|
981
|
+
);
|
|
982
|
+
const year = z__namespace.number().int().describe("Contract year, for example 2024.");
|
|
983
|
+
const month = z__namespace.number().int().min(1).max(12).describe("Month number, 1-12.");
|
|
984
|
+
const day = z__namespace.number().int().min(1).max(31).describe("Day number, 1-31.");
|
|
985
|
+
return z__namespace.discriminatedUnion("operation", [
|
|
986
|
+
z__namespace.object({
|
|
987
|
+
asset: nonEmptyString(
|
|
988
|
+
options,
|
|
989
|
+
"Bloomberg asset class suffix, for example Index or Comdty."
|
|
990
|
+
),
|
|
991
|
+
monthCode: nonEmptyString(options, "Bloomberg futures month code, for example H."),
|
|
992
|
+
operation: z__namespace.literal("build_futures_ticker"),
|
|
993
|
+
prefix: nonEmptyString(options, "Futures ticker root prefix, for example ES."),
|
|
994
|
+
year: z__namespace.union([z__namespace.string().trim().min(1), z__namespace.number().int().transform(String)]).describe("Contract year, full or abbreviated, as a string or integer.")
|
|
995
|
+
}).strict(),
|
|
996
|
+
z__namespace.object({
|
|
997
|
+
count: z__namespace.number().int().positive().optional().describe("Maximum number of futures candidates to generate."),
|
|
998
|
+
day,
|
|
999
|
+
freq: optionalString(options, "Futures frequency/cycle hint."),
|
|
1000
|
+
genTicker,
|
|
1001
|
+
month,
|
|
1002
|
+
operation: z__namespace.literal("generate_candidates"),
|
|
1003
|
+
year
|
|
1004
|
+
}).strict(),
|
|
1005
|
+
z__namespace.object({ genTicker, operation: z__namespace.literal("contract_index") }).strict(),
|
|
1006
|
+
z__namespace.object({
|
|
1007
|
+
candidates: z__namespace.array(futuresCandidateSchema).min(1).max(options.maxFields).describe("Candidate futures contracts."),
|
|
1008
|
+
cycle: nonEmptyString(options, "Futures cycle code to filter candidates by."),
|
|
1009
|
+
operation: z__namespace.literal("filter_candidates_by_cycle")
|
|
1010
|
+
}).strict(),
|
|
1011
|
+
z__namespace.object({
|
|
1012
|
+
contracts: z__namespace.array(stringPairSchema).min(1).max(options.maxFields).describe("Contract pairs for validity filtering."),
|
|
1013
|
+
day,
|
|
1014
|
+
month,
|
|
1015
|
+
operation: z__namespace.literal("filter_valid_contracts"),
|
|
1016
|
+
year
|
|
1017
|
+
}).strict(),
|
|
1018
|
+
z__namespace.object({ operation: z__namespace.literal("get_futures_months") }).strict()
|
|
1019
|
+
]);
|
|
575
1020
|
}
|
|
576
1021
|
function cdxSchema(options) {
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
1022
|
+
const ticker = nonEmptyString(options, "CDX ticker, generic or specific.");
|
|
1023
|
+
const recoveryRate = z__namespace.number().min(0).max(1).optional().describe("Decimal recovery rate override, e.g. 0.4 for 40%; sent as the CDS_RR override.");
|
|
1024
|
+
return z__namespace.discriminatedUnion("operation", [
|
|
1025
|
+
z__namespace.object({ operation: z__namespace.literal("parse_cdx_ticker"), ticker }).strict(),
|
|
1026
|
+
z__namespace.object({ operation: z__namespace.literal("previous_cdx_series"), ticker }).strict(),
|
|
1027
|
+
z__namespace.object({ operation: z__namespace.literal("cdx_info"), ticker }).strict(),
|
|
1028
|
+
z__namespace.object({ operation: z__namespace.literal("cdx_pricing"), recoveryRate, ticker }).strict(),
|
|
1029
|
+
z__namespace.object({ operation: z__namespace.literal("cdx_risk"), recoveryRate, ticker }).strict(),
|
|
1030
|
+
z__namespace.object({
|
|
1031
|
+
genTicker: nonEmptyString(
|
|
1032
|
+
options,
|
|
1033
|
+
"Generic CDX ticker, for example CDX IG CDSI GEN 5Y Corp."
|
|
1034
|
+
),
|
|
1035
|
+
operation: z__namespace.literal("cdx_gen_to_specific"),
|
|
1036
|
+
series: z__namespace.number().int().positive().describe("Specific CDX series number.")
|
|
1037
|
+
}).strict()
|
|
1038
|
+
]);
|
|
591
1039
|
}
|
|
592
1040
|
function currencySchema(options) {
|
|
593
|
-
return z__namespace.
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
1041
|
+
return z__namespace.discriminatedUnion("operation", [
|
|
1042
|
+
z__namespace.object({
|
|
1043
|
+
fromCcy: nonEmptyString(options, "Source ISO currency code."),
|
|
1044
|
+
operation: z__namespace.literal("build_fx_pair"),
|
|
1045
|
+
toCcy: nonEmptyString(options, "Destination ISO currency code.")
|
|
1046
|
+
}).strict(),
|
|
1047
|
+
z__namespace.object({
|
|
1048
|
+
ccy1: nonEmptyString(options, "First ISO currency code."),
|
|
1049
|
+
ccy2: nonEmptyString(options, "Second ISO currency code."),
|
|
1050
|
+
operation: z__namespace.literal("same_currency")
|
|
1051
|
+
}).strict(),
|
|
1052
|
+
z__namespace.object({
|
|
1053
|
+
currencies: stringArray(options, "ISO currency codes to check."),
|
|
1054
|
+
operation: z__namespace.literal("currencies_needing_conversion"),
|
|
1055
|
+
target: nonEmptyString(options, "Target ISO currency code.")
|
|
1056
|
+
}).strict()
|
|
1057
|
+
]);
|
|
602
1058
|
}
|
|
603
1059
|
function bqlBuilderSchema(options) {
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
1060
|
+
const extraFields = stringArray(options, "Extra BQL fields to include.").optional();
|
|
1061
|
+
return z__namespace.discriminatedUnion("operation", [
|
|
1062
|
+
z__namespace.object({
|
|
1063
|
+
equityTicker: nonEmptyString(options, "Equity ticker for preferreds query."),
|
|
1064
|
+
extraFields,
|
|
1065
|
+
operation: z__namespace.literal("build_preferreds_query")
|
|
1066
|
+
}).strict(),
|
|
1067
|
+
z__namespace.object({
|
|
1068
|
+
activeOnly: z__namespace.boolean().optional().describe("Restrict corporate bond query to active bonds."),
|
|
1069
|
+
ccy: optionalString(options, "Currency filter for corporate bond query."),
|
|
1070
|
+
extraFields,
|
|
1071
|
+
operation: z__namespace.literal("build_corporate_bonds_query"),
|
|
1072
|
+
ticker: nonEmptyString(options, "Ticker for corporate bond query.")
|
|
1073
|
+
}).strict(),
|
|
1074
|
+
z__namespace.object({
|
|
1075
|
+
etfTicker: nonEmptyString(options, "ETF ticker for holdings query."),
|
|
1076
|
+
extraFields,
|
|
1077
|
+
operation: z__namespace.literal("build_etf_holdings_query")
|
|
1078
|
+
}).strict()
|
|
1079
|
+
]);
|
|
613
1080
|
}
|
|
614
1081
|
function marketSessionSchema(options) {
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
"
|
|
628
|
-
"
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
"
|
|
632
|
-
"
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
1082
|
+
const mic = optionalString(options, "Market Identifier Code, for example XNYS.");
|
|
1083
|
+
const exchCode = optionalString(options, "Bloomberg exchange code.");
|
|
1084
|
+
return z__namespace.discriminatedUnion("operation", [
|
|
1085
|
+
z__namespace.object({
|
|
1086
|
+
dayEnd: nonEmptyString(options, "Exchange day end time, for example 16:00."),
|
|
1087
|
+
dayStart: nonEmptyString(options, "Exchange day start time, for example 09:30."),
|
|
1088
|
+
exchCode,
|
|
1089
|
+
mic,
|
|
1090
|
+
operation: z__namespace.literal("derive_sessions")
|
|
1091
|
+
}).strict(),
|
|
1092
|
+
z__namespace.object({ exchCode, mic, operation: z__namespace.literal("get_market_rule") }).strict(),
|
|
1093
|
+
z__namespace.object({
|
|
1094
|
+
countryIso: nonEmptyString(options, "ISO country code for timezone inference."),
|
|
1095
|
+
operation: z__namespace.literal("infer_timezone")
|
|
1096
|
+
}).strict(),
|
|
1097
|
+
z__namespace.object({
|
|
1098
|
+
date: nonEmptyString(options, "Date for UTC session conversion, YYYY-MM-DD or YYYYMMDD."),
|
|
1099
|
+
endTime: nonEmptyString(options, "Session end time, for example 16:00."),
|
|
1100
|
+
exchangeTz: nonEmptyString(
|
|
1101
|
+
options,
|
|
1102
|
+
"IANA exchange timezone, for example America/New_York."
|
|
1103
|
+
),
|
|
1104
|
+
operation: z__namespace.literal("session_times_to_utc"),
|
|
1105
|
+
startTime: nonEmptyString(options, "Session start time, for example 09:30.")
|
|
1106
|
+
}).strict(),
|
|
1107
|
+
z__namespace.object({
|
|
1108
|
+
endDate: optionalString(options, "Optional end date."),
|
|
1109
|
+
operation: z__namespace.literal("default_turnover_dates"),
|
|
1110
|
+
startDate: optionalString(options, "Optional start date.")
|
|
1111
|
+
}).strict(),
|
|
1112
|
+
z__namespace.object({
|
|
1113
|
+
endDatetime: optionalString(options, "Optional end datetime."),
|
|
1114
|
+
operation: z__namespace.literal("default_bqr_datetimes"),
|
|
1115
|
+
startDatetime: optionalString(options, "Optional start datetime.")
|
|
1116
|
+
}).strict(),
|
|
1117
|
+
z__namespace.object({
|
|
1118
|
+
operation: z__namespace.literal("get_exchange_override"),
|
|
1119
|
+
ticker: nonEmptyString(options, "Ticker for exchange override lookup.")
|
|
1120
|
+
}).strict(),
|
|
1121
|
+
z__namespace.object({ operation: z__namespace.literal("list_exchange_overrides") }).strict()
|
|
1122
|
+
]);
|
|
641
1123
|
}
|
|
642
1124
|
function yasOverridesSchema(options) {
|
|
643
1125
|
return z__namespace.object({
|
|
@@ -647,94 +1129,96 @@ function yasOverridesSchema(options) {
|
|
|
647
1129
|
spread: z__namespace.number().optional().describe("YAS spread override."),
|
|
648
1130
|
yieldType: z__namespace.number().int().optional().describe("YAS yield type override."),
|
|
649
1131
|
yieldVal: z__namespace.number().optional().describe("YAS yield value override.")
|
|
650
|
-
});
|
|
1132
|
+
}).strict();
|
|
651
1133
|
}
|
|
652
1134
|
function constantsSchema(options) {
|
|
653
|
-
return z__namespace.
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
"
|
|
663
|
-
"
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
"
|
|
667
|
-
"
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
"
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
1135
|
+
return z__namespace.discriminatedUnion("operation", [
|
|
1136
|
+
z__namespace.object({
|
|
1137
|
+
dateStr: nonEmptyString(options, "Date string to parse."),
|
|
1138
|
+
operation: z__namespace.literal("parse_date")
|
|
1139
|
+
}).strict(),
|
|
1140
|
+
z__namespace.object({
|
|
1141
|
+
day: z__namespace.number().int().min(1).max(31).describe("Day number, 1-31."),
|
|
1142
|
+
fmt: optionalString(options, "Date output format."),
|
|
1143
|
+
month: z__namespace.number().int().min(1).max(12).describe("Month number, 1-12."),
|
|
1144
|
+
operation: z__namespace.literal("fmt_date"),
|
|
1145
|
+
year: z__namespace.number().int().min(1).describe("Year number.")
|
|
1146
|
+
}).strict(),
|
|
1147
|
+
z__namespace.object({
|
|
1148
|
+
monthName: nonEmptyString(options, "Month name, for example March."),
|
|
1149
|
+
operation: z__namespace.literal("get_month_code")
|
|
1150
|
+
}).strict(),
|
|
1151
|
+
z__namespace.object({
|
|
1152
|
+
code: nonEmptyString(options, "Month code, for example H."),
|
|
1153
|
+
operation: z__namespace.literal("get_month_name")
|
|
1154
|
+
}).strict(),
|
|
1155
|
+
z__namespace.object({
|
|
1156
|
+
dvdType: nonEmptyString(options, "Dividend type code or label."),
|
|
1157
|
+
operation: z__namespace.literal("get_dvd_type")
|
|
1158
|
+
}).strict(),
|
|
1159
|
+
z__namespace.object({ operation: z__namespace.literal("get_futures_months") }).strict(),
|
|
1160
|
+
z__namespace.object({ operation: z__namespace.literal("get_dvd_types") }).strict(),
|
|
1161
|
+
z__namespace.object({ operation: z__namespace.literal("get_dvd_cols") }).strict(),
|
|
1162
|
+
z__namespace.object({ operation: z__namespace.literal("get_etf_cols") }).strict()
|
|
1163
|
+
]);
|
|
674
1164
|
}
|
|
675
1165
|
function columnsSchema(options) {
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
1166
|
+
const columns = stringArray(options, "Column names to rename.");
|
|
1167
|
+
return z__namespace.discriminatedUnion("operation", [
|
|
1168
|
+
z__namespace.object({ columns, operation: z__namespace.literal("rename_dividend_columns") }).strict(),
|
|
1169
|
+
z__namespace.object({ columns, operation: z__namespace.literal("rename_etf_columns") }).strict(),
|
|
1170
|
+
z__namespace.object({
|
|
1171
|
+
dataColumns: stringArray(options, "Earnings data column names."),
|
|
1172
|
+
headerRow: z__namespace.array(stringPairSchema).min(1).max(options.maxFields).describe("Earnings header row key/value pairs."),
|
|
1173
|
+
operation: z__namespace.literal("build_earning_header_rename")
|
|
1174
|
+
}).strict()
|
|
1175
|
+
]);
|
|
682
1176
|
}
|
|
683
1177
|
function calculateSchema(options) {
|
|
684
1178
|
return z__namespace.object({
|
|
685
1179
|
levels: z__namespace.array(z__namespace.number().nullable()).min(1).max(options.maxFields).describe("Reference level values."),
|
|
686
1180
|
operation: z__namespace.literal("calculate_level_percentages").describe("Numeric helper operation to run."),
|
|
687
1181
|
values: z__namespace.array(z__namespace.number().nullable()).min(1).max(options.maxFields).describe("Observed values.")
|
|
1182
|
+
}).strict().superRefine((input, ctx) => {
|
|
1183
|
+
if (input.values.length !== input.levels.length) {
|
|
1184
|
+
ctx.addIssue({
|
|
1185
|
+
code: z__namespace.ZodIssueCode.custom,
|
|
1186
|
+
message: "values and levels must have the same length"
|
|
1187
|
+
});
|
|
1188
|
+
}
|
|
688
1189
|
});
|
|
689
1190
|
}
|
|
1191
|
+
function chartSpecSchema(options) {
|
|
1192
|
+
const chartScalar = z__namespace.union([
|
|
1193
|
+
z__namespace.string().trim().max(options.maxStringChars),
|
|
1194
|
+
z__namespace.number(),
|
|
1195
|
+
z__namespace.boolean(),
|
|
1196
|
+
z__namespace.null()
|
|
1197
|
+
]);
|
|
1198
|
+
const fieldName = nonEmptyString(options, "Input row field name.");
|
|
1199
|
+
return z__namespace.object({
|
|
1200
|
+
chart: z__namespace.enum(["line", "area", "bar", "scatter", "candlestick", "depth"]).optional().describe("Chart shape to generate. Defaults from source."),
|
|
1201
|
+
closeField: fieldName.optional().describe("Candlestick close-value field."),
|
|
1202
|
+
highField: fieldName.optional().describe("Candlestick high-value field."),
|
|
1203
|
+
labelField: fieldName.optional().describe("Categorical label field for bar charts."),
|
|
1204
|
+
lowField: fieldName.optional().describe("Candlestick low-value field."),
|
|
1205
|
+
maxPoints: z__namespace.number().int().positive().max(options.maxRows).optional().describe("Maximum rows to include in the frontend spec; defaults to all provided rows."),
|
|
1206
|
+
openField: fieldName.optional().describe("Candlestick open-value field."),
|
|
1207
|
+
priceField: fieldName.optional().describe("Market-depth price field."),
|
|
1208
|
+
renderer: z__namespace.literal("vega-lite").optional().describe("Visualization spec renderer. Currently only vega-lite is generated."),
|
|
1209
|
+
rows: z__namespace.array(z__namespace.record(chartScalar)).min(1).max(options.maxRows).describe("Chart data rows copied from a bounded Bloomberg tool result."),
|
|
1210
|
+
seriesField: fieldName.optional().describe("Optional series/color field."),
|
|
1211
|
+
sideField: fieldName.optional().describe("Market-depth bid/ask side field."),
|
|
1212
|
+
sizeField: fieldName.optional().describe("Market-depth size field."),
|
|
1213
|
+
source: z__namespace.enum(["bdh", "bdib", "holdings", "depth", "rows"]).describe("Bloomberg result shape that produced rows."),
|
|
1214
|
+
title: nonEmptyString(options, "Chart title.").optional(),
|
|
1215
|
+
valueField: fieldName.optional().describe("Primary numeric value field."),
|
|
1216
|
+
xField: fieldName.optional().describe("X-axis field."),
|
|
1217
|
+
yFields: stringArray(options, "Numeric value fields to plot.").optional()
|
|
1218
|
+
}).strict();
|
|
1219
|
+
}
|
|
690
1220
|
|
|
691
1221
|
// src/ext-tools.ts
|
|
692
|
-
function asRecord(value) {
|
|
693
|
-
return value;
|
|
694
|
-
}
|
|
695
|
-
function requireString(toolName, input, field) {
|
|
696
|
-
const value = input[field];
|
|
697
|
-
if (typeof value !== "string" || value.trim().length === 0) {
|
|
698
|
-
throw new TypeError(`${toolName}: ${field} is required and must be a non-empty string`);
|
|
699
|
-
}
|
|
700
|
-
return value.trim();
|
|
701
|
-
}
|
|
702
|
-
function requireNumber(toolName, input, field) {
|
|
703
|
-
const value = input[field];
|
|
704
|
-
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
705
|
-
throw new TypeError(`${toolName}: ${field} is required and must be a finite number`);
|
|
706
|
-
}
|
|
707
|
-
return value;
|
|
708
|
-
}
|
|
709
|
-
function requireInteger(toolName, input, field) {
|
|
710
|
-
const value = requireNumber(toolName, input, field);
|
|
711
|
-
if (!Number.isInteger(value)) {
|
|
712
|
-
throw new TypeError(`${toolName}: ${field} must be an integer`);
|
|
713
|
-
}
|
|
714
|
-
return value;
|
|
715
|
-
}
|
|
716
|
-
function requireYearString(toolName, input, field) {
|
|
717
|
-
const value = input[field];
|
|
718
|
-
if (typeof value === "number" && Number.isInteger(value)) {
|
|
719
|
-
return String(value);
|
|
720
|
-
}
|
|
721
|
-
if (typeof value === "string" && value.trim().length > 0) {
|
|
722
|
-
return value.trim();
|
|
723
|
-
}
|
|
724
|
-
throw new TypeError(`${toolName}: ${field} is required and must be a year string or integer`);
|
|
725
|
-
}
|
|
726
|
-
function requireStringArray(toolName, input, field) {
|
|
727
|
-
const value = input[field];
|
|
728
|
-
if (!Array.isArray(value) || value.length === 0) {
|
|
729
|
-
throw new TypeError(`${toolName}: ${field} is required and must be a non-empty string array`);
|
|
730
|
-
}
|
|
731
|
-
return value.map((entry) => {
|
|
732
|
-
if (typeof entry !== "string" || entry.trim().length === 0) {
|
|
733
|
-
throw new TypeError(`${toolName}: ${field} entries must be non-empty strings`);
|
|
734
|
-
}
|
|
735
|
-
return entry.trim();
|
|
736
|
-
});
|
|
737
|
-
}
|
|
738
1222
|
function resultString(resolver, name, value) {
|
|
739
1223
|
return createToolResult(name, value, resolver.options.maxRows, resolver.options.maxStringChars);
|
|
740
1224
|
}
|
|
@@ -747,6 +1231,7 @@ var EXT_TOOL_DEFINITIONS = Object.freeze([
|
|
|
747
1231
|
{ create: extCdxWithResolver, name: "xbbg_ext_cdx" },
|
|
748
1232
|
{ create: extCurrencyWithResolver, name: "xbbg_ext_currency" },
|
|
749
1233
|
{ create: extBqlBuilderWithResolver, name: "xbbg_ext_bql_builder" },
|
|
1234
|
+
{ create: extChartSpecWithResolver, name: "xbbg_ext_chart_spec" },
|
|
750
1235
|
{ create: extMarketSessionWithResolver, name: "xbbg_ext_market_session" },
|
|
751
1236
|
{ create: extYasOverridesWithResolver, name: "xbbg_ext_yas_overrides" },
|
|
752
1237
|
{ create: extConstantsWithResolver, name: "xbbg_ext_constants" },
|
|
@@ -756,43 +1241,42 @@ var EXT_TOOL_DEFINITIONS = Object.freeze([
|
|
|
756
1241
|
var BLOOMBERG_EXT_TOOL_NAMES = Object.freeze(
|
|
757
1242
|
EXT_TOOL_DEFINITIONS.map((definition) => definition.name)
|
|
758
1243
|
);
|
|
1244
|
+
function extChartSpecWithResolver(resolver) {
|
|
1245
|
+
const name = "xbbg_ext_chart_spec";
|
|
1246
|
+
return createBloombergStructuredTool(
|
|
1247
|
+
async (input) => {
|
|
1248
|
+
try {
|
|
1249
|
+
return await Promise.resolve(resultString(resolver, name, createChartSpec(input)));
|
|
1250
|
+
} catch (error) {
|
|
1251
|
+
throwWithToolContext(name, error);
|
|
1252
|
+
}
|
|
1253
|
+
},
|
|
1254
|
+
{
|
|
1255
|
+
responseFormat: "content_and_artifact",
|
|
1256
|
+
description: EXT_CHART_SPEC_DESCRIPTION,
|
|
1257
|
+
name,
|
|
1258
|
+
schema: chartSpecSchema(resolver.options)
|
|
1259
|
+
}
|
|
1260
|
+
);
|
|
1261
|
+
}
|
|
759
1262
|
function extTickerWithResolver(resolver) {
|
|
760
1263
|
const name = "xbbg_ext_ticker";
|
|
761
1264
|
return createBloombergStructuredTool(
|
|
762
1265
|
async (input) => {
|
|
763
1266
|
try {
|
|
764
1267
|
const core = await resolver.getCore();
|
|
765
|
-
const args = asRecord(input);
|
|
766
1268
|
switch (input.operation) {
|
|
767
1269
|
case "parse_ticker":
|
|
768
|
-
return resultString(
|
|
769
|
-
resolver,
|
|
770
|
-
name,
|
|
771
|
-
core.ext.parseTicker(requireString(name, args, "ticker"))
|
|
772
|
-
);
|
|
1270
|
+
return resultString(resolver, name, core.ext.parseTicker(input.ticker));
|
|
773
1271
|
case "normalize_tickers":
|
|
774
|
-
return resultString(
|
|
775
|
-
resolver,
|
|
776
|
-
name,
|
|
777
|
-
core.ext.normalizeTickers(requireStringArray(name, args, "tickers"))
|
|
778
|
-
);
|
|
1272
|
+
return resultString(resolver, name, core.ext.normalizeTickers(input.tickers));
|
|
779
1273
|
case "filter_equity_tickers":
|
|
780
|
-
return resultString(
|
|
781
|
-
resolver,
|
|
782
|
-
name,
|
|
783
|
-
core.ext.filterEquityTickers(requireStringArray(name, args, "tickers"))
|
|
784
|
-
);
|
|
1274
|
+
return resultString(resolver, name, core.ext.filterEquityTickers(input.tickers));
|
|
785
1275
|
case "is_specific_contract":
|
|
786
|
-
return resultString(
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
);
|
|
791
|
-
case "validate_generic_ticker": {
|
|
792
|
-
const ticker = requireString(name, args, "ticker");
|
|
793
|
-
core.ext.validateGenericTicker(ticker);
|
|
794
|
-
return resultString(resolver, name, { ticker, valid: true });
|
|
795
|
-
}
|
|
1276
|
+
return resultString(resolver, name, core.ext.isSpecificContract(input.ticker));
|
|
1277
|
+
case "validate_generic_ticker":
|
|
1278
|
+
core.ext.validateGenericTicker(input.ticker);
|
|
1279
|
+
return resultString(resolver, name, { ticker: input.ticker, valid: true });
|
|
796
1280
|
}
|
|
797
1281
|
} catch (error) {
|
|
798
1282
|
throwWithToolContext(name, error);
|
|
@@ -812,63 +1296,39 @@ function extFuturesWithResolver(resolver) {
|
|
|
812
1296
|
async (input) => {
|
|
813
1297
|
try {
|
|
814
1298
|
const core = await resolver.getCore();
|
|
815
|
-
const args = asRecord(input);
|
|
816
1299
|
switch (input.operation) {
|
|
817
1300
|
case "build_futures_ticker":
|
|
818
1301
|
return resultString(
|
|
819
1302
|
resolver,
|
|
820
1303
|
name,
|
|
821
|
-
core.ext.buildFuturesTicker(
|
|
822
|
-
requireString(name, args, "prefix"),
|
|
823
|
-
requireString(name, args, "monthCode"),
|
|
824
|
-
requireYearString(name, args, "year"),
|
|
825
|
-
requireString(name, args, "asset")
|
|
826
|
-
)
|
|
1304
|
+
core.ext.buildFuturesTicker(input.prefix, input.monthCode, input.year, input.asset)
|
|
827
1305
|
);
|
|
828
1306
|
case "generate_candidates":
|
|
829
1307
|
return resultString(
|
|
830
1308
|
resolver,
|
|
831
1309
|
name,
|
|
832
1310
|
core.ext.generateFuturesCandidates(
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
1311
|
+
input.genTicker,
|
|
1312
|
+
input.year,
|
|
1313
|
+
input.month,
|
|
1314
|
+
input.day,
|
|
837
1315
|
input.freq,
|
|
838
1316
|
input.count
|
|
839
1317
|
)
|
|
840
1318
|
);
|
|
841
1319
|
case "contract_index":
|
|
842
|
-
return resultString(
|
|
843
|
-
resolver,
|
|
844
|
-
name,
|
|
845
|
-
core.ext.contractIndex(requireString(name, args, "genTicker"))
|
|
846
|
-
);
|
|
1320
|
+
return resultString(resolver, name, core.ext.contractIndex(input.genTicker));
|
|
847
1321
|
case "filter_candidates_by_cycle":
|
|
848
|
-
if (input.candidates === void 0) {
|
|
849
|
-
throw new TypeError(`${name}: candidates is required`);
|
|
850
|
-
}
|
|
851
1322
|
return resultString(
|
|
852
1323
|
resolver,
|
|
853
1324
|
name,
|
|
854
|
-
core.ext.filterCandidatesByCycle(
|
|
855
|
-
input.candidates,
|
|
856
|
-
requireString(name, args, "cycle")
|
|
857
|
-
)
|
|
1325
|
+
core.ext.filterCandidatesByCycle(input.candidates, input.cycle)
|
|
858
1326
|
);
|
|
859
1327
|
case "filter_valid_contracts":
|
|
860
|
-
if (input.contracts === void 0) {
|
|
861
|
-
throw new TypeError(`${name}: contracts is required`);
|
|
862
|
-
}
|
|
863
1328
|
return resultString(
|
|
864
1329
|
resolver,
|
|
865
1330
|
name,
|
|
866
|
-
core.ext.filterValidContracts(
|
|
867
|
-
input.contracts,
|
|
868
|
-
requireInteger(name, args, "year"),
|
|
869
|
-
requireInteger(name, args, "month"),
|
|
870
|
-
requireInteger(name, args, "day")
|
|
871
|
-
)
|
|
1331
|
+
core.ext.filterValidContracts(input.contracts, input.year, input.month, input.day)
|
|
872
1332
|
);
|
|
873
1333
|
case "get_futures_months":
|
|
874
1334
|
return resultString(resolver, name, core.ext.getFuturesMonths());
|
|
@@ -888,41 +1348,31 @@ function extFuturesWithResolver(resolver) {
|
|
|
888
1348
|
function extCdxWithResolver(resolver) {
|
|
889
1349
|
const name = "xbbg_ext_cdx";
|
|
890
1350
|
return createBloombergStructuredTool(
|
|
891
|
-
async (input) => {
|
|
1351
|
+
async (input, config) => {
|
|
892
1352
|
try {
|
|
893
|
-
|
|
1353
|
+
config?.signal?.throwIfAborted();
|
|
894
1354
|
if (input.operation === "cdx_info" || input.operation === "cdx_pricing" || input.operation === "cdx_risk") {
|
|
895
1355
|
const engine = await resolver.getEngine();
|
|
896
|
-
const ticker = requireString(name, args, "ticker");
|
|
897
1356
|
const fields = input.operation === "cdx_info" ? CDX_INFO_FIELDS : input.operation === "cdx_pricing" ? CDX_PRICING_FIELDS : CDX_RISK_FIELDS;
|
|
898
|
-
const result = await engine.bdp([ticker], fields, {
|
|
1357
|
+
const result = await engine.bdp([input.ticker], fields, {
|
|
899
1358
|
backend: "json",
|
|
900
|
-
overrides: recoveryOverrides(
|
|
1359
|
+
overrides: recoveryOverrides(
|
|
1360
|
+
input.operation === "cdx_pricing" || input.operation === "cdx_risk" ? input.recoveryRate : void 0
|
|
1361
|
+
)
|
|
901
1362
|
});
|
|
902
1363
|
return resultString(resolver, name, result);
|
|
903
1364
|
}
|
|
904
1365
|
const core = await resolver.getCore();
|
|
905
1366
|
switch (input.operation) {
|
|
906
1367
|
case "parse_cdx_ticker":
|
|
907
|
-
return resultString(
|
|
908
|
-
resolver,
|
|
909
|
-
name,
|
|
910
|
-
core.ext.parseCdxTicker(requireString(name, args, "ticker"))
|
|
911
|
-
);
|
|
1368
|
+
return resultString(resolver, name, core.ext.parseCdxTicker(input.ticker));
|
|
912
1369
|
case "previous_cdx_series":
|
|
913
|
-
return resultString(
|
|
914
|
-
resolver,
|
|
915
|
-
name,
|
|
916
|
-
core.ext.previousCdxSeries(requireString(name, args, "ticker"))
|
|
917
|
-
);
|
|
1370
|
+
return resultString(resolver, name, core.ext.previousCdxSeries(input.ticker));
|
|
918
1371
|
case "cdx_gen_to_specific":
|
|
919
1372
|
return resultString(
|
|
920
1373
|
resolver,
|
|
921
1374
|
name,
|
|
922
|
-
core.ext.cdxGenToSpecific(
|
|
923
|
-
requireString(name, args, "genTicker"),
|
|
924
|
-
requireInteger(name, args, "series")
|
|
925
|
-
)
|
|
1375
|
+
core.ext.cdxGenToSpecific(input.genTicker, input.series)
|
|
926
1376
|
);
|
|
927
1377
|
}
|
|
928
1378
|
} catch (error) {
|
|
@@ -943,34 +1393,16 @@ function extCurrencyWithResolver(resolver) {
|
|
|
943
1393
|
async (input) => {
|
|
944
1394
|
try {
|
|
945
1395
|
const core = await resolver.getCore();
|
|
946
|
-
const args = asRecord(input);
|
|
947
1396
|
switch (input.operation) {
|
|
948
1397
|
case "build_fx_pair":
|
|
949
|
-
return resultString(
|
|
950
|
-
resolver,
|
|
951
|
-
name,
|
|
952
|
-
core.ext.buildFxPair(
|
|
953
|
-
requireString(name, args, "fromCcy"),
|
|
954
|
-
requireString(name, args, "toCcy")
|
|
955
|
-
)
|
|
956
|
-
);
|
|
1398
|
+
return resultString(resolver, name, core.ext.buildFxPair(input.fromCcy, input.toCcy));
|
|
957
1399
|
case "same_currency":
|
|
958
|
-
return resultString(
|
|
959
|
-
resolver,
|
|
960
|
-
name,
|
|
961
|
-
core.ext.sameCurrency(
|
|
962
|
-
requireString(name, args, "ccy1"),
|
|
963
|
-
requireString(name, args, "ccy2")
|
|
964
|
-
)
|
|
965
|
-
);
|
|
1400
|
+
return resultString(resolver, name, core.ext.sameCurrency(input.ccy1, input.ccy2));
|
|
966
1401
|
case "currencies_needing_conversion":
|
|
967
1402
|
return resultString(
|
|
968
1403
|
resolver,
|
|
969
1404
|
name,
|
|
970
|
-
core.ext.currenciesNeedingConversion(
|
|
971
|
-
requireStringArray(name, args, "currencies"),
|
|
972
|
-
requireString(name, args, "target")
|
|
973
|
-
)
|
|
1405
|
+
core.ext.currenciesNeedingConversion(input.currencies, input.target)
|
|
974
1406
|
);
|
|
975
1407
|
}
|
|
976
1408
|
} catch (error) {
|
|
@@ -991,23 +1423,19 @@ function extBqlBuilderWithResolver(resolver) {
|
|
|
991
1423
|
async (input) => {
|
|
992
1424
|
try {
|
|
993
1425
|
const core = await resolver.getCore();
|
|
994
|
-
const args = asRecord(input);
|
|
995
1426
|
switch (input.operation) {
|
|
996
1427
|
case "build_preferreds_query":
|
|
997
1428
|
return resultString(
|
|
998
1429
|
resolver,
|
|
999
1430
|
name,
|
|
1000
|
-
core.ext.buildPreferredsQuery(
|
|
1001
|
-
requireString(name, args, "equityTicker"),
|
|
1002
|
-
input.extraFields
|
|
1003
|
-
)
|
|
1431
|
+
core.ext.buildPreferredsQuery(input.equityTicker, input.extraFields)
|
|
1004
1432
|
);
|
|
1005
1433
|
case "build_corporate_bonds_query":
|
|
1006
1434
|
return resultString(
|
|
1007
1435
|
resolver,
|
|
1008
1436
|
name,
|
|
1009
1437
|
core.ext.buildCorporateBondsQuery(
|
|
1010
|
-
|
|
1438
|
+
input.ticker,
|
|
1011
1439
|
input.ccy,
|
|
1012
1440
|
input.extraFields,
|
|
1013
1441
|
input.activeOnly
|
|
@@ -1017,10 +1445,7 @@ function extBqlBuilderWithResolver(resolver) {
|
|
|
1017
1445
|
return resultString(
|
|
1018
1446
|
resolver,
|
|
1019
1447
|
name,
|
|
1020
|
-
core.ext.buildEtfHoldingsQuery(
|
|
1021
|
-
requireString(name, args, "etfTicker"),
|
|
1022
|
-
input.extraFields
|
|
1023
|
-
)
|
|
1448
|
+
core.ext.buildEtfHoldingsQuery(input.etfTicker, input.extraFields)
|
|
1024
1449
|
);
|
|
1025
1450
|
}
|
|
1026
1451
|
} catch (error) {
|
|
@@ -1041,36 +1466,26 @@ function extMarketSessionWithResolver(resolver) {
|
|
|
1041
1466
|
async (input) => {
|
|
1042
1467
|
try {
|
|
1043
1468
|
const core = await resolver.getCore();
|
|
1044
|
-
const args = asRecord(input);
|
|
1045
1469
|
switch (input.operation) {
|
|
1046
1470
|
case "derive_sessions":
|
|
1047
1471
|
return resultString(
|
|
1048
1472
|
resolver,
|
|
1049
1473
|
name,
|
|
1050
|
-
core.ext.deriveSessions(
|
|
1051
|
-
requireString(name, args, "dayStart"),
|
|
1052
|
-
requireString(name, args, "dayEnd"),
|
|
1053
|
-
input.mic,
|
|
1054
|
-
input.exchCode
|
|
1055
|
-
)
|
|
1474
|
+
core.ext.deriveSessions(input.dayStart, input.dayEnd, input.mic, input.exchCode)
|
|
1056
1475
|
);
|
|
1057
1476
|
case "get_market_rule":
|
|
1058
1477
|
return resultString(resolver, name, core.ext.getMarketRule(input.mic, input.exchCode));
|
|
1059
1478
|
case "infer_timezone":
|
|
1060
|
-
return resultString(
|
|
1061
|
-
resolver,
|
|
1062
|
-
name,
|
|
1063
|
-
core.ext.inferTimezone(requireString(name, args, "countryIso"))
|
|
1064
|
-
);
|
|
1479
|
+
return resultString(resolver, name, core.ext.inferTimezone(input.countryIso));
|
|
1065
1480
|
case "session_times_to_utc":
|
|
1066
1481
|
return resultString(
|
|
1067
1482
|
resolver,
|
|
1068
1483
|
name,
|
|
1069
1484
|
core.ext.sessionTimesToUtc(
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1485
|
+
input.startTime,
|
|
1486
|
+
input.endTime,
|
|
1487
|
+
input.exchangeTz,
|
|
1488
|
+
input.date
|
|
1074
1489
|
)
|
|
1075
1490
|
);
|
|
1076
1491
|
case "default_turnover_dates":
|
|
@@ -1086,11 +1501,7 @@ function extMarketSessionWithResolver(resolver) {
|
|
|
1086
1501
|
core.ext.defaultBqrDatetimes(input.startDatetime, input.endDatetime)
|
|
1087
1502
|
);
|
|
1088
1503
|
case "get_exchange_override":
|
|
1089
|
-
return resultString(
|
|
1090
|
-
resolver,
|
|
1091
|
-
name,
|
|
1092
|
-
core.ext.getExchangeOverride(requireString(name, args, "ticker"))
|
|
1093
|
-
);
|
|
1504
|
+
return resultString(resolver, name, core.ext.getExchangeOverride(input.ticker));
|
|
1094
1505
|
case "list_exchange_overrides":
|
|
1095
1506
|
return resultString(resolver, name, core.ext.listExchangeOverrides());
|
|
1096
1507
|
}
|
|
@@ -1142,45 +1553,23 @@ function extConstantsWithResolver(resolver) {
|
|
|
1142
1553
|
async (input) => {
|
|
1143
1554
|
try {
|
|
1144
1555
|
const core = await resolver.getCore();
|
|
1145
|
-
const args = asRecord(input);
|
|
1146
1556
|
switch (input.operation) {
|
|
1147
1557
|
case "parse_date":
|
|
1148
|
-
return resultString(
|
|
1149
|
-
resolver,
|
|
1150
|
-
name,
|
|
1151
|
-
core.ext.parseDate(requireString(name, args, "dateStr"))
|
|
1152
|
-
);
|
|
1558
|
+
return resultString(resolver, name, core.ext.parseDate(input.dateStr));
|
|
1153
1559
|
case "fmt_date":
|
|
1154
1560
|
return resultString(
|
|
1155
1561
|
resolver,
|
|
1156
1562
|
name,
|
|
1157
|
-
core.ext.fmtDate(
|
|
1158
|
-
requireInteger(name, args, "year"),
|
|
1159
|
-
requireInteger(name, args, "month"),
|
|
1160
|
-
requireInteger(name, args, "day"),
|
|
1161
|
-
input.fmt
|
|
1162
|
-
)
|
|
1563
|
+
core.ext.fmtDate(input.year, input.month, input.day, input.fmt)
|
|
1163
1564
|
);
|
|
1164
1565
|
case "get_month_code":
|
|
1165
|
-
return resultString(
|
|
1166
|
-
resolver,
|
|
1167
|
-
name,
|
|
1168
|
-
core.ext.getMonthCode(requireString(name, args, "monthName"))
|
|
1169
|
-
);
|
|
1566
|
+
return resultString(resolver, name, core.ext.getMonthCode(input.monthName));
|
|
1170
1567
|
case "get_month_name":
|
|
1171
|
-
return resultString(
|
|
1172
|
-
resolver,
|
|
1173
|
-
name,
|
|
1174
|
-
core.ext.getMonthName(requireString(name, args, "code"))
|
|
1175
|
-
);
|
|
1568
|
+
return resultString(resolver, name, core.ext.getMonthName(input.code));
|
|
1176
1569
|
case "get_futures_months":
|
|
1177
1570
|
return resultString(resolver, name, core.ext.getFuturesMonths());
|
|
1178
1571
|
case "get_dvd_type":
|
|
1179
|
-
return resultString(
|
|
1180
|
-
resolver,
|
|
1181
|
-
name,
|
|
1182
|
-
core.ext.getDvdType(requireString(name, args, "dvdType"))
|
|
1183
|
-
);
|
|
1572
|
+
return resultString(resolver, name, core.ext.getDvdType(input.dvdType));
|
|
1184
1573
|
case "get_dvd_types":
|
|
1185
1574
|
return resultString(resolver, name, core.ext.getDvdTypes());
|
|
1186
1575
|
case "get_dvd_cols":
|
|
@@ -1206,31 +1595,16 @@ function extColumnsWithResolver(resolver) {
|
|
|
1206
1595
|
async (input) => {
|
|
1207
1596
|
try {
|
|
1208
1597
|
const core = await resolver.getCore();
|
|
1209
|
-
const args = asRecord(input);
|
|
1210
1598
|
switch (input.operation) {
|
|
1211
1599
|
case "rename_dividend_columns":
|
|
1212
|
-
return resultString(
|
|
1213
|
-
resolver,
|
|
1214
|
-
name,
|
|
1215
|
-
core.ext.renameDividendColumns(requireStringArray(name, args, "columns"))
|
|
1216
|
-
);
|
|
1600
|
+
return resultString(resolver, name, core.ext.renameDividendColumns(input.columns));
|
|
1217
1601
|
case "rename_etf_columns":
|
|
1218
|
-
return resultString(
|
|
1219
|
-
resolver,
|
|
1220
|
-
name,
|
|
1221
|
-
core.ext.renameEtfColumns(requireStringArray(name, args, "columns"))
|
|
1222
|
-
);
|
|
1602
|
+
return resultString(resolver, name, core.ext.renameEtfColumns(input.columns));
|
|
1223
1603
|
case "build_earning_header_rename":
|
|
1224
|
-
if (input.headerRow === void 0) {
|
|
1225
|
-
throw new TypeError(`${name}: headerRow is required`);
|
|
1226
|
-
}
|
|
1227
1604
|
return resultString(
|
|
1228
1605
|
resolver,
|
|
1229
1606
|
name,
|
|
1230
|
-
core.ext.buildEarningHeaderRename(
|
|
1231
|
-
input.headerRow,
|
|
1232
|
-
requireStringArray(name, args, "dataColumns")
|
|
1233
|
-
)
|
|
1607
|
+
core.ext.buildEarningHeaderRename(input.headerRow, input.dataColumns)
|
|
1234
1608
|
);
|
|
1235
1609
|
}
|
|
1236
1610
|
} catch (error) {
|
|
@@ -1250,9 +1624,6 @@ function extCalculateWithResolver(resolver) {
|
|
|
1250
1624
|
return createBloombergStructuredTool(
|
|
1251
1625
|
async (input) => {
|
|
1252
1626
|
try {
|
|
1253
|
-
if (input.values.length !== input.levels.length) {
|
|
1254
|
-
throw new TypeError(`${name}: values and levels must have the same length`);
|
|
1255
|
-
}
|
|
1256
1627
|
const core = await resolver.getCore();
|
|
1257
1628
|
return resultString(
|
|
1258
1629
|
resolver,
|
|
@@ -1301,6 +1672,9 @@ function createExtColumnsTool(options = {}) {
|
|
|
1301
1672
|
function createExtCalculateTool(options = {}) {
|
|
1302
1673
|
return extCalculateWithResolver(createCoreResolver(options));
|
|
1303
1674
|
}
|
|
1675
|
+
function createExtChartSpecTool(options = {}) {
|
|
1676
|
+
return extChartSpecWithResolver(createCoreResolver(options));
|
|
1677
|
+
}
|
|
1304
1678
|
function createBloombergExtToolsForResolver(resolver) {
|
|
1305
1679
|
return EXT_TOOL_DEFINITIONS.filter(
|
|
1306
1680
|
(definition) => !isToolDisabled(resolver.options, definition.name)
|
|
@@ -1321,6 +1695,9 @@ var ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}$/u;
|
|
|
1321
1695
|
var BBG_DATE_RE = /^\d{8}$/u;
|
|
1322
1696
|
var AMBIGUOUS_DATE_RE = /^\d{1,2}[-/]\d{1,2}[-/]\d{2,4}([T \D]|$)/u;
|
|
1323
1697
|
var ISO_DATE_TIME_RE = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:?\d{2})?$/u;
|
|
1698
|
+
var MIN_NUMERIC_BBG_DATE = 19000101;
|
|
1699
|
+
var MAX_NUMERIC_BBG_DATE = 29991231;
|
|
1700
|
+
var MIN_EPOCH_MS = 1e11;
|
|
1324
1701
|
var primitiveSchema = z__namespace.union([
|
|
1325
1702
|
z__namespace.string().transform((value) => value.trim()),
|
|
1326
1703
|
z__namespace.number(),
|
|
@@ -1335,18 +1712,30 @@ function dateFromParts(year, month, day) {
|
|
|
1335
1712
|
return formatted;
|
|
1336
1713
|
}
|
|
1337
1714
|
function dateToBbg(value) {
|
|
1338
|
-
const
|
|
1339
|
-
if (Number.isNaN(
|
|
1715
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
1716
|
+
if (Number.isNaN(date.getTime())) {
|
|
1340
1717
|
throw new TypeError("Invalid date value; expected YYYY-MM-DD, YYYYMMDD, Date, or epoch ms");
|
|
1341
1718
|
}
|
|
1342
|
-
const year = String(
|
|
1343
|
-
const month = String(
|
|
1344
|
-
const day = String(
|
|
1719
|
+
const year = String(date.getUTCFullYear()).padStart(4, "0");
|
|
1720
|
+
const month = String(date.getUTCMonth() + 1).padStart(2, "0");
|
|
1721
|
+
const day = String(date.getUTCDate()).padStart(2, "0");
|
|
1345
1722
|
return `${year}${month}${day}`;
|
|
1346
1723
|
}
|
|
1724
|
+
function numericDateToBbg(value, unit) {
|
|
1725
|
+
if (Number.isFinite(value) && value >= MIN_EPOCH_MS) {
|
|
1726
|
+
return new Date(value);
|
|
1727
|
+
}
|
|
1728
|
+
throw new TypeError(
|
|
1729
|
+
`Ambiguous numeric ${unit} ${String(value)}; use "YYYY-MM-DD" text or epoch milliseconds`
|
|
1730
|
+
);
|
|
1731
|
+
}
|
|
1347
1732
|
function normalizeDate(value) {
|
|
1348
|
-
if (
|
|
1349
|
-
|
|
1733
|
+
if (typeof value === "number") {
|
|
1734
|
+
if (Number.isInteger(value) && value >= MIN_NUMERIC_BBG_DATE && value <= MAX_NUMERIC_BBG_DATE) {
|
|
1735
|
+
const text2 = String(value);
|
|
1736
|
+
return dateFromParts(text2.slice(0, 4), text2.slice(4, 6), text2.slice(6, 8));
|
|
1737
|
+
}
|
|
1738
|
+
return dateToBbg(numericDateToBbg(value, "date"));
|
|
1350
1739
|
}
|
|
1351
1740
|
const text = value.trim();
|
|
1352
1741
|
if (text.length === 0) {
|
|
@@ -1364,12 +1753,13 @@ function normalizeDate(value) {
|
|
|
1364
1753
|
throw new TypeError(`Invalid date ${JSON.stringify(text)}; use YYYY-MM-DD or YYYYMMDD`);
|
|
1365
1754
|
}
|
|
1366
1755
|
function normalizeDateTime(value) {
|
|
1367
|
-
if (
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1756
|
+
if (typeof value === "number") {
|
|
1757
|
+
if (Number.isInteger(value) && value >= MIN_NUMERIC_BBG_DATE && value <= MAX_NUMERIC_BBG_DATE) {
|
|
1758
|
+
throw new TypeError(
|
|
1759
|
+
`Invalid numeric datetime ${String(value)}; include an explicit time component such as "2024-01-02T09:30:00"`
|
|
1760
|
+
);
|
|
1371
1761
|
}
|
|
1372
|
-
return
|
|
1762
|
+
return numericDateToBbg(value, "datetime").toISOString();
|
|
1373
1763
|
}
|
|
1374
1764
|
const text = value.trim();
|
|
1375
1765
|
if (text.length === 0) {
|
|
@@ -1399,8 +1789,15 @@ function nonEmptyString2(tool2, field, maxChars, example) {
|
|
|
1399
1789
|
function stringArray2(tool2, field, maxItems, maxChars, example) {
|
|
1400
1790
|
return z__namespace.array(nonEmptyString2(tool2, field, maxChars, example)).min(1, `${tool2}: ${field} must contain at least one non-empty string. Example: ${example}`).max(maxItems, `${tool2}: ${field} can contain at most ${maxItems} values`);
|
|
1401
1791
|
}
|
|
1792
|
+
function normalizationIssue(context, tool2, field, error) {
|
|
1793
|
+
context.addIssue({
|
|
1794
|
+
code: "custom",
|
|
1795
|
+
message: `${tool2}: ${field}: ${error instanceof Error ? error.message : String(error)}`
|
|
1796
|
+
});
|
|
1797
|
+
return z__namespace.NEVER;
|
|
1798
|
+
}
|
|
1402
1799
|
function primitiveMap(tool2, field) {
|
|
1403
|
-
return z__namespace.record(z__namespace.string().min(1), primitiveSchema).optional().transform((value) => {
|
|
1800
|
+
return z__namespace.record(z__namespace.string().min(1), primitiveSchema).optional().transform((value, context) => {
|
|
1404
1801
|
if (value === void 0) {
|
|
1405
1802
|
return void 0;
|
|
1406
1803
|
}
|
|
@@ -1408,10 +1805,15 @@ function primitiveMap(tool2, field) {
|
|
|
1408
1805
|
for (const [key, entry] of Object.entries(value)) {
|
|
1409
1806
|
const normalizedKey = key.trim();
|
|
1410
1807
|
if (normalizedKey.length === 0) {
|
|
1411
|
-
|
|
1808
|
+
return normalizationIssue(context, tool2, field, new TypeError("contains an empty key"));
|
|
1412
1809
|
}
|
|
1413
1810
|
if (typeof entry === "string" && entry.length === 0) {
|
|
1414
|
-
|
|
1811
|
+
return normalizationIssue(
|
|
1812
|
+
context,
|
|
1813
|
+
tool2,
|
|
1814
|
+
field,
|
|
1815
|
+
new TypeError(`${normalizedKey} must not be an empty string`)
|
|
1816
|
+
);
|
|
1415
1817
|
}
|
|
1416
1818
|
normalized[normalizedKey] = entry;
|
|
1417
1819
|
}
|
|
@@ -1419,12 +1821,18 @@ function primitiveMap(tool2, field) {
|
|
|
1419
1821
|
});
|
|
1420
1822
|
}
|
|
1421
1823
|
function dateField(tool2, field) {
|
|
1422
|
-
return z__namespace.union([z__namespace.string(), z__namespace.
|
|
1824
|
+
return z__namespace.union([z__namespace.string(), z__namespace.number()]).transform((value, context) => {
|
|
1825
|
+
try {
|
|
1826
|
+
return normalizeDate(value);
|
|
1827
|
+
} catch (error) {
|
|
1828
|
+
return normalizationIssue(context, tool2, field, error);
|
|
1829
|
+
}
|
|
1830
|
+
}).describe(
|
|
1423
1831
|
`${field} date. Use YYYY-MM-DD or Bloomberg-native YYYYMMDD, never ambiguous MM/DD/YYYY.`
|
|
1424
1832
|
);
|
|
1425
1833
|
}
|
|
1426
1834
|
function dateTimeField(tool2, field) {
|
|
1427
|
-
return z__namespace.union([z__namespace.string(), z__namespace.
|
|
1835
|
+
return z__namespace.union([z__namespace.string(), z__namespace.number()]).superRefine((value, context) => {
|
|
1428
1836
|
if (typeof value !== "string") {
|
|
1429
1837
|
return;
|
|
1430
1838
|
}
|
|
@@ -1435,7 +1843,13 @@ function dateTimeField(tool2, field) {
|
|
|
1435
1843
|
message: `${tool2}: ${field} datetime requires an explicit time component; use ISO 8601 such as YYYY-MM-DDT09:30:00`
|
|
1436
1844
|
});
|
|
1437
1845
|
}
|
|
1438
|
-
}).transform((value) =>
|
|
1846
|
+
}).transform((value, context) => {
|
|
1847
|
+
try {
|
|
1848
|
+
return normalizeDateTime(value);
|
|
1849
|
+
} catch (error) {
|
|
1850
|
+
return normalizationIssue(context, tool2, field, error);
|
|
1851
|
+
}
|
|
1852
|
+
}).describe(`${field} datetime. Use ISO 8601 with an explicit time component.`);
|
|
1439
1853
|
}
|
|
1440
1854
|
function referenceFormat(tool2) {
|
|
1441
1855
|
return z__namespace.enum(REFERENCE_FORMATS, {
|
|
@@ -1478,7 +1892,7 @@ function createBdpSchema(options) {
|
|
|
1478
1892
|
options.maxStringChars,
|
|
1479
1893
|
'["<TICKER> <MARKET_SECTOR>"]'
|
|
1480
1894
|
).describe(
|
|
1481
|
-
"
|
|
1895
|
+
"Securities exactly as the user supplied them: '<TICKER> <MARKET_SECTOR>' for Bloomberg tickers, '/isin/<ISIN>' for raw ISINs, '/cusip/<CUSIP>' for raw CUSIPs. Never invent, guess, or convert identifiers into tickers."
|
|
1482
1896
|
),
|
|
1483
1897
|
validateFields: z__namespace.boolean().optional().describe("Override field validation for this request.")
|
|
1484
1898
|
});
|
|
@@ -1510,7 +1924,7 @@ function createBdhSchema(options) {
|
|
|
1510
1924
|
options.maxStringChars,
|
|
1511
1925
|
'["<TICKER> <MARKET_SECTOR>"]'
|
|
1512
1926
|
).describe(
|
|
1513
|
-
"
|
|
1927
|
+
"Securities exactly as the user supplied them: '<TICKER> <MARKET_SECTOR>' for Bloomberg tickers, '/isin/<ISIN>' for raw ISINs, '/cusip/<CUSIP>' for raw CUSIPs. Never invent, guess, or convert identifiers into tickers."
|
|
1514
1928
|
),
|
|
1515
1929
|
start: dateField(tool2, "start").describe("Required start date. Use YYYY-MM-DD or YYYYMMDD."),
|
|
1516
1930
|
validateFields: z__namespace.boolean().optional().describe("Override field validation for this request.")
|
|
@@ -1530,7 +1944,6 @@ function createBdsSchema(options) {
|
|
|
1530
1944
|
field: nonEmptyString2(tool2, "field", options.maxStringChars, "<BULK_FIELD>").describe(
|
|
1531
1945
|
"Exactly one Bloomberg bulk/table field supplied by the user."
|
|
1532
1946
|
),
|
|
1533
|
-
format: referenceFormat(tool2).describe("JSON output shape. Usually omit."),
|
|
1534
1947
|
kwargs: primitiveMap(tool2, "kwargs").describe(
|
|
1535
1948
|
"Advanced Bloomberg request kwargs as flat string/number/boolean values only."
|
|
1536
1949
|
),
|
|
@@ -1544,7 +1957,7 @@ function createBdsSchema(options) {
|
|
|
1544
1957
|
options.maxStringChars,
|
|
1545
1958
|
'["<INDEX_TICKER> <MARKET_SECTOR>"]'
|
|
1546
1959
|
).describe(
|
|
1547
|
-
"
|
|
1960
|
+
"Securities exactly as the user supplied them: '<TICKER> <MARKET_SECTOR>' for Bloomberg tickers, '/isin/<ISIN>' for raw ISINs, '/cusip/<CUSIP>' for raw CUSIPs. Never invent, guess, or convert identifiers into tickers."
|
|
1548
1961
|
),
|
|
1549
1962
|
validateFields: z__namespace.boolean().optional().describe("Override field validation for this request.")
|
|
1550
1963
|
});
|
|
@@ -1571,7 +1984,7 @@ function createBdibSchema(options) {
|
|
|
1571
1984
|
options.maxStringChars,
|
|
1572
1985
|
"<TICKER> <MARKET_SECTOR>"
|
|
1573
1986
|
).describe(
|
|
1574
|
-
"One
|
|
1987
|
+
"One security exactly as the user supplied it: '<TICKER> <MARKET_SECTOR>', '/isin/<ISIN>', or '/cusip/<CUSIP>'. Never invent, guess, or convert identifiers into tickers."
|
|
1575
1988
|
)
|
|
1576
1989
|
});
|
|
1577
1990
|
}
|
|
@@ -1610,14 +2023,13 @@ function createBdtickSchema(options) {
|
|
|
1610
2023
|
options.maxStringChars,
|
|
1611
2024
|
"<TICKER> <MARKET_SECTOR>"
|
|
1612
2025
|
).describe(
|
|
1613
|
-
"One
|
|
2026
|
+
"One security exactly as the user supplied it: '<TICKER> <MARKET_SECTOR>', '/isin/<ISIN>', or '/cusip/<CUSIP>'. Never invent, guess, or convert identifiers into tickers."
|
|
1614
2027
|
)
|
|
1615
2028
|
});
|
|
1616
2029
|
}
|
|
1617
2030
|
function createBqlSchema(options) {
|
|
1618
2031
|
const tool2 = "xbbg_bql";
|
|
1619
2032
|
return z__namespace.object({
|
|
1620
|
-
format: referenceFormat(tool2).describe("JSON output shape. Usually omit."),
|
|
1621
2033
|
kwargs: primitiveMap(tool2, "kwargs").describe(
|
|
1622
2034
|
"Advanced Bloomberg request kwargs as flat string/number/boolean values only."
|
|
1623
2035
|
),
|
|
@@ -1656,7 +2068,6 @@ function createBqrSchema(options) {
|
|
|
1656
2068
|
function createBsrchSchema(options) {
|
|
1657
2069
|
const tool2 = "xbbg_bsrch";
|
|
1658
2070
|
return z__namespace.object({
|
|
1659
|
-
format: referenceFormat(tool2).describe("JSON output shape. Usually omit."),
|
|
1660
2071
|
kwargs: primitiveMap(tool2, "kwargs").describe(
|
|
1661
2072
|
"Search-grid kwargs as flat string/number/boolean values only."
|
|
1662
2073
|
),
|
|
@@ -1679,7 +2090,6 @@ function createBfldsSchema(options) {
|
|
|
1679
2090
|
fields: stringArray2(tool2, "fields", options.maxFields, options.maxStringChars, '["<FIELD>"]').optional().describe(
|
|
1680
2091
|
"Specific field mnemonics to inspect. Provide either fields or searchSpec, not both."
|
|
1681
2092
|
),
|
|
1682
|
-
format: referenceFormat(tool2).describe("JSON output shape. Usually omit."),
|
|
1683
2093
|
kwargs: primitiveMap(tool2, "kwargs").describe(
|
|
1684
2094
|
"Advanced Bloomberg request kwargs as flat string/number/boolean values only."
|
|
1685
2095
|
),
|
|
@@ -1707,7 +2117,6 @@ function createBeqsSchema(options) {
|
|
|
1707
2117
|
const tool2 = "xbbg_beqs";
|
|
1708
2118
|
return z__namespace.object({
|
|
1709
2119
|
asof: dateField(tool2, "asof").optional().describe("Optional as-of date for the screen."),
|
|
1710
|
-
format: referenceFormat(tool2).describe("JSON output shape. Usually omit."),
|
|
1711
2120
|
group: nonEmptyString2(tool2, "group", options.maxStringChars, "<BEQS_GROUP>").optional().describe("Bloomberg BEQS group when required by the screen."),
|
|
1712
2121
|
kwargs: primitiveMap(tool2, "kwargs").describe(
|
|
1713
2122
|
"Advanced BEQS request kwargs as flat string/number/boolean values only."
|
|
@@ -1741,7 +2150,9 @@ function createYasSchema(options) {
|
|
|
1741
2150
|
options.maxSecurities,
|
|
1742
2151
|
options.maxStringChars,
|
|
1743
2152
|
'["/isin/<ISIN> <MARKET_SECTOR>"]'
|
|
1744
|
-
).describe(
|
|
2153
|
+
).describe(
|
|
2154
|
+
"Fixed-income securities exactly as the user supplied them: '<TICKER> <MARKET_SECTOR>' or identifier syntax such as '/isin/<ISIN> <MARKET_SECTOR>'. Never invent or guess tickers."
|
|
2155
|
+
),
|
|
1745
2156
|
yieldType: z__namespace.number().int().optional().describe("Optional YAS yield type."),
|
|
1746
2157
|
yieldVal: z__namespace.number().optional().describe("Optional YAS yield value input.")
|
|
1747
2158
|
});
|
|
@@ -1754,8 +2165,10 @@ function createPreferredsSchema(options) {
|
|
|
1754
2165
|
"equityTicker",
|
|
1755
2166
|
options.maxStringChars,
|
|
1756
2167
|
"<ISSUER_TICKER> <MARKET_SECTOR>"
|
|
1757
|
-
).describe(
|
|
1758
|
-
|
|
2168
|
+
).describe(
|
|
2169
|
+
"The issuer's common equity ticker as '<TICKER> <MARKET_SECTOR>', never a preferred ('Pfd') ticker and never a guessed one. Resolve a supplied ISIN/CUSIP with xbbg_resolve_isins first."
|
|
2170
|
+
),
|
|
2171
|
+
fields: z__namespace.array(nonEmptyString2(tool2, "fields", options.maxStringChars, '["<FIELD>"]')).max(options.maxFields, `${tool2}: fields can contain at most ${options.maxFields} values`).transform((fields) => fields.length === 0 ? void 0 : fields).optional().describe("Optional fields to include in the preferreds recipe result.")
|
|
1759
2172
|
});
|
|
1760
2173
|
}
|
|
1761
2174
|
function createCorporateBondsSchema(options) {
|
|
@@ -1769,7 +2182,9 @@ function createCorporateBondsSchema(options) {
|
|
|
1769
2182
|
"ticker",
|
|
1770
2183
|
options.maxStringChars,
|
|
1771
2184
|
"<ISSUER_TICKER> <MARKET_SECTOR>"
|
|
1772
|
-
).describe(
|
|
2185
|
+
).describe(
|
|
2186
|
+
"The issuer/company equity ticker as '<TICKER> <MARKET_SECTOR>' supplied by the user. Resolve a supplied ISIN/CUSIP with xbbg_resolve_isins first; never guess tickers."
|
|
2187
|
+
)
|
|
1773
2188
|
});
|
|
1774
2189
|
}
|
|
1775
2190
|
function createIndexMembersSchema(options) {
|
|
@@ -1782,7 +2197,9 @@ function createIndexMembersSchema(options) {
|
|
|
1782
2197
|
"index",
|
|
1783
2198
|
options.maxStringChars,
|
|
1784
2199
|
"<INDEX_TICKER> <MARKET_SECTOR>"
|
|
1785
|
-
).describe(
|
|
2200
|
+
).describe(
|
|
2201
|
+
"One Bloomberg index ticker as '<INDEX_TICKER> <MARKET_SECTOR>' supplied by the user; never guess index tickers."
|
|
2202
|
+
)
|
|
1786
2203
|
});
|
|
1787
2204
|
}
|
|
1788
2205
|
function createResolveIsinsSchema(options) {
|
|
@@ -1817,7 +2234,9 @@ function createEtfHoldingsSchema(options) {
|
|
|
1817
2234
|
"etfTicker",
|
|
1818
2235
|
options.maxStringChars,
|
|
1819
2236
|
"<ETF_TICKER> <MARKET_SECTOR>"
|
|
1820
|
-
).describe(
|
|
2237
|
+
).describe(
|
|
2238
|
+
"One Bloomberg ETF ticker as '<ETF_TICKER> <MARKET_SECTOR>' supplied by the user. Resolve a supplied ISIN/CUSIP with xbbg_resolve_isins first; never guess tickers."
|
|
2239
|
+
),
|
|
1821
2240
|
fields: stringArray2(tool2, "fields", options.maxFields, options.maxStringChars, '["<FIELD>"]').optional().describe("Optional fields to include in the ETF holdings recipe result.")
|
|
1822
2241
|
});
|
|
1823
2242
|
}
|
|
@@ -1826,7 +2245,7 @@ function snapshotControlFields(tool2, options) {
|
|
|
1826
2245
|
allFields: z__namespace.boolean().optional().describe("Request all Bloomberg fields when supported."),
|
|
1827
2246
|
conflate: z__namespace.boolean().optional().describe("Enable Bloomberg conflated streaming when supported."),
|
|
1828
2247
|
drain: z__namespace.boolean().optional().describe(
|
|
1829
|
-
"
|
|
2248
|
+
"Flush buffered backlog while closing the subscription. The subscription always closes; collected output stays bounded either way. Defaults to false."
|
|
1830
2249
|
),
|
|
1831
2250
|
flushThreshold: z__namespace.number().int().positive().optional().describe("Optional stream flush threshold."),
|
|
1832
2251
|
maxUpdates: z__namespace.number().int(`${tool2}: maxUpdates must be a positive integer.`).positive(`${tool2}: maxUpdates must be greater than zero.`).max(
|
|
@@ -1861,7 +2280,9 @@ function createStreamSnapshotSchema(options) {
|
|
|
1861
2280
|
options.maxSecurities,
|
|
1862
2281
|
options.maxStringChars,
|
|
1863
2282
|
'["<TICKER> <MARKET_SECTOR>"]'
|
|
1864
|
-
).describe(
|
|
2283
|
+
).describe(
|
|
2284
|
+
"Securities to observe, exactly as the user supplied them: '<TICKER> <MARKET_SECTOR>', '/isin/<ISIN>', or '/cusip/<CUSIP>'. Never invent or guess tickers."
|
|
2285
|
+
),
|
|
1865
2286
|
...snapshotControlFields(tool2, options)
|
|
1866
2287
|
});
|
|
1867
2288
|
}
|
|
@@ -1874,7 +2295,9 @@ function createMktbarSnapshotSchema(options) {
|
|
|
1874
2295
|
"ticker",
|
|
1875
2296
|
options.maxStringChars,
|
|
1876
2297
|
"<TICKER> <MARKET_SECTOR>"
|
|
1877
|
-
).describe(
|
|
2298
|
+
).describe(
|
|
2299
|
+
"One security to observe, exactly as the user supplied it: '<TICKER> <MARKET_SECTOR>', '/isin/<ISIN>', or '/cusip/<CUSIP>'. Never invent or guess tickers."
|
|
2300
|
+
),
|
|
1878
2301
|
...snapshotControlFields(tool2, options)
|
|
1879
2302
|
});
|
|
1880
2303
|
}
|
|
@@ -1887,7 +2310,9 @@ function createDepthSnapshotSchema(options) {
|
|
|
1887
2310
|
"ticker",
|
|
1888
2311
|
options.maxStringChars,
|
|
1889
2312
|
"<TICKER> <MARKET_SECTOR>"
|
|
1890
|
-
).describe(
|
|
2313
|
+
).describe(
|
|
2314
|
+
"One security to observe, exactly as the user supplied it: '<TICKER> <MARKET_SECTOR>', '/isin/<ISIN>', or '/cusip/<CUSIP>'. Never invent or guess tickers."
|
|
2315
|
+
),
|
|
1891
2316
|
...snapshotControlFields(tool2, options)
|
|
1892
2317
|
});
|
|
1893
2318
|
}
|
|
@@ -1897,17 +2322,24 @@ function resultString2(resolver, name, value) {
|
|
|
1897
2322
|
return createToolResult(name, value, resolver.options.maxRows, resolver.options.maxStringChars);
|
|
1898
2323
|
}
|
|
1899
2324
|
var STREAM_TIMEOUT = /* @__PURE__ */ Symbol("stream_timeout");
|
|
2325
|
+
var STREAM_ABORTED = /* @__PURE__ */ Symbol("stream_aborted");
|
|
2326
|
+
function abortError(signal) {
|
|
2327
|
+
const reason = signal?.reason;
|
|
2328
|
+
return reason instanceof Error ? reason : new Error("Tool call aborted");
|
|
2329
|
+
}
|
|
1900
2330
|
function streamOptions(input) {
|
|
1901
2331
|
return {
|
|
1902
2332
|
allFields: input.allFields,
|
|
1903
2333
|
conflate: input.conflate,
|
|
1904
|
-
fields: input.fields,
|
|
1905
2334
|
flushThreshold: input.flushThreshold,
|
|
1906
2335
|
options: input.options,
|
|
1907
2336
|
overflowPolicy: input.overflowPolicy,
|
|
1908
2337
|
streamCapacity: input.streamCapacity
|
|
1909
2338
|
};
|
|
1910
2339
|
}
|
|
2340
|
+
function singleTickerStreamOptions(input) {
|
|
2341
|
+
return { ...streamOptions(input), fields: input.fields };
|
|
2342
|
+
}
|
|
1911
2343
|
function isRecord(value) {
|
|
1912
2344
|
return typeof value === "object" && value !== null;
|
|
1913
2345
|
}
|
|
@@ -1963,42 +2395,55 @@ function normalizeStreamUpdate(value) {
|
|
|
1963
2395
|
const rows = rowsFromArrowTable(value);
|
|
1964
2396
|
return rows === void 0 ? jsonCompatible(value) : rows.map(jsonCompatible);
|
|
1965
2397
|
}
|
|
1966
|
-
async function nextWithinTimeout(iterator, deadlineMs) {
|
|
2398
|
+
async function nextWithinTimeout(iterator, deadlineMs, signal) {
|
|
2399
|
+
if (signal?.aborted === true) {
|
|
2400
|
+
return STREAM_ABORTED;
|
|
2401
|
+
}
|
|
1967
2402
|
const remainingMs = deadlineMs - Date.now();
|
|
1968
2403
|
if (remainingMs <= 0) {
|
|
1969
2404
|
return STREAM_TIMEOUT;
|
|
1970
2405
|
}
|
|
1971
2406
|
const nextPromise = iterator.next();
|
|
1972
2407
|
let timer;
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
2408
|
+
let onAbort;
|
|
2409
|
+
const racers = [
|
|
2410
|
+
nextPromise,
|
|
2411
|
+
new Promise((resolve) => {
|
|
2412
|
+
timer = setTimeout(() => resolve(STREAM_TIMEOUT), remainingMs);
|
|
2413
|
+
})
|
|
2414
|
+
];
|
|
2415
|
+
if (signal !== void 0) {
|
|
2416
|
+
racers.push(
|
|
2417
|
+
new Promise((resolve) => {
|
|
2418
|
+
onAbort = () => resolve(STREAM_ABORTED);
|
|
2419
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
2420
|
+
})
|
|
2421
|
+
);
|
|
2422
|
+
}
|
|
2423
|
+
const result = await Promise.race(racers);
|
|
1977
2424
|
if (timer !== void 0) {
|
|
1978
2425
|
clearTimeout(timer);
|
|
1979
2426
|
}
|
|
1980
|
-
if (
|
|
2427
|
+
if (signal !== void 0 && onAbort !== void 0) {
|
|
2428
|
+
signal.removeEventListener("abort", onAbort);
|
|
2429
|
+
}
|
|
2430
|
+
if (result === STREAM_TIMEOUT || result === STREAM_ABORTED) {
|
|
1981
2431
|
void nextPromise.catch(() => void 0);
|
|
1982
2432
|
}
|
|
1983
2433
|
return result;
|
|
1984
2434
|
}
|
|
1985
|
-
async function
|
|
1986
|
-
try {
|
|
1987
|
-
await subscription.unsubscribe(drain);
|
|
1988
|
-
} catch (error) {
|
|
1989
|
-
if (priorError === void 0) {
|
|
1990
|
-
throw error;
|
|
1991
|
-
}
|
|
1992
|
-
}
|
|
1993
|
-
}
|
|
1994
|
-
async function collectSnapshot(subscription, input) {
|
|
2435
|
+
async function collectSnapshot(subscription, input, signal) {
|
|
1995
2436
|
const updates = [];
|
|
1996
2437
|
const deadlineMs = Date.now() + input.timeoutMs;
|
|
1997
2438
|
let reason = "max_updates";
|
|
2439
|
+
let failed = false;
|
|
1998
2440
|
let caught;
|
|
1999
2441
|
try {
|
|
2000
2442
|
while (updates.length < input.maxUpdates) {
|
|
2001
|
-
const next = await nextWithinTimeout(subscription, deadlineMs);
|
|
2443
|
+
const next = await nextWithinTimeout(subscription, deadlineMs, signal);
|
|
2444
|
+
if (next === STREAM_ABORTED) {
|
|
2445
|
+
throw abortError(signal);
|
|
2446
|
+
}
|
|
2002
2447
|
if (next === STREAM_TIMEOUT) {
|
|
2003
2448
|
reason = "timeout";
|
|
2004
2449
|
break;
|
|
@@ -2009,26 +2454,34 @@ async function collectSnapshot(subscription, input) {
|
|
|
2009
2454
|
}
|
|
2010
2455
|
updates.push(normalizeStreamUpdate(next.value));
|
|
2011
2456
|
}
|
|
2012
|
-
return {
|
|
2013
|
-
maxUpdates: input.maxUpdates,
|
|
2014
|
-
reason,
|
|
2015
|
-
timeoutMs: input.timeoutMs,
|
|
2016
|
-
updateCount: updates.length,
|
|
2017
|
-
updates
|
|
2018
|
-
};
|
|
2019
2457
|
} catch (error) {
|
|
2458
|
+
failed = true;
|
|
2020
2459
|
caught = error;
|
|
2021
|
-
throw error;
|
|
2022
|
-
} finally {
|
|
2023
|
-
await unsubscribeSnapshot(subscription, input.drain === true, caught);
|
|
2024
2460
|
}
|
|
2461
|
+
const drain = input.drain === true && signal?.aborted !== true;
|
|
2462
|
+
let unsubscribeError;
|
|
2463
|
+
try {
|
|
2464
|
+
await subscription.unsubscribe(drain);
|
|
2465
|
+
} catch (error) {
|
|
2466
|
+
if (!failed) {
|
|
2467
|
+
unsubscribeError = error instanceof Error ? error.message : String(error);
|
|
2468
|
+
}
|
|
2469
|
+
}
|
|
2470
|
+
if (failed) {
|
|
2471
|
+
throw caught;
|
|
2472
|
+
}
|
|
2473
|
+
return {
|
|
2474
|
+
maxUpdates: input.maxUpdates,
|
|
2475
|
+
reason,
|
|
2476
|
+
timeoutMs: input.timeoutMs,
|
|
2477
|
+
updateCount: updates.length,
|
|
2478
|
+
updates,
|
|
2479
|
+
...unsubscribeError === void 0 ? {} : { unsubscribeError }
|
|
2480
|
+
};
|
|
2025
2481
|
}
|
|
2026
2482
|
function validationSetting(resolver, value) {
|
|
2027
2483
|
return value ?? resolver.options.validateFields;
|
|
2028
2484
|
}
|
|
2029
|
-
function enabledTool(resolver, name, creator) {
|
|
2030
|
-
return isToolDisabled(resolver.options, name) ? [] : [creator(resolver)];
|
|
2031
|
-
}
|
|
2032
2485
|
function bdpWithResolver(resolver) {
|
|
2033
2486
|
const name = "xbbg_bdp";
|
|
2034
2487
|
return createBloombergStructuredTool(
|
|
@@ -2092,7 +2545,6 @@ function bdsWithResolver(resolver) {
|
|
|
2092
2545
|
const engine = await resolver.getEngine();
|
|
2093
2546
|
const result = await engine.bds(input.securities, [input.field], {
|
|
2094
2547
|
backend: "json",
|
|
2095
|
-
format: input.format,
|
|
2096
2548
|
kwargs: input.kwargs,
|
|
2097
2549
|
overrides: input.overrides,
|
|
2098
2550
|
validateFields: validationSetting(resolver, input.validateFields)
|
|
@@ -2182,7 +2634,6 @@ function bqlWithResolver(resolver) {
|
|
|
2182
2634
|
const engine = await resolver.getEngine();
|
|
2183
2635
|
const result = await engine.bql(input.query, {
|
|
2184
2636
|
backend: "json",
|
|
2185
|
-
format: input.format,
|
|
2186
2637
|
kwargs: input.kwargs
|
|
2187
2638
|
});
|
|
2188
2639
|
return resultString2(resolver, name, result);
|
|
@@ -2206,7 +2657,6 @@ function bsrchWithResolver(resolver) {
|
|
|
2206
2657
|
const engine = await resolver.getEngine();
|
|
2207
2658
|
const result = await engine.bsrch(input.searchSpec, {
|
|
2208
2659
|
backend: "json",
|
|
2209
|
-
format: input.format,
|
|
2210
2660
|
kwargs: input.kwargs,
|
|
2211
2661
|
overrides: input.overrides
|
|
2212
2662
|
});
|
|
@@ -2258,7 +2708,6 @@ function bfldsWithResolver(resolver) {
|
|
|
2258
2708
|
const result = await engine.bflds({
|
|
2259
2709
|
backend: "json",
|
|
2260
2710
|
fields: input.fields,
|
|
2261
|
-
format: input.format,
|
|
2262
2711
|
kwargs: input.kwargs,
|
|
2263
2712
|
searchSpec: input.searchSpec
|
|
2264
2713
|
});
|
|
@@ -2284,7 +2733,6 @@ function beqsWithResolver(resolver) {
|
|
|
2284
2733
|
const result = await engine.beqs(input.screen, {
|
|
2285
2734
|
asof: input.asof,
|
|
2286
2735
|
backend: "json",
|
|
2287
|
-
format: input.format,
|
|
2288
2736
|
group: input.group,
|
|
2289
2737
|
kwargs: input.kwargs,
|
|
2290
2738
|
overrides: input.overrides,
|
|
@@ -2469,11 +2917,13 @@ function etfHoldingsWithResolver(resolver) {
|
|
|
2469
2917
|
function streamSnapshotWithResolver(resolver) {
|
|
2470
2918
|
const name = "xbbg_stream_snapshot";
|
|
2471
2919
|
return createBloombergStructuredTool(
|
|
2472
|
-
async (input) => {
|
|
2920
|
+
async (input, config) => {
|
|
2921
|
+
const signal = config?.signal;
|
|
2473
2922
|
try {
|
|
2474
2923
|
const engine = await resolver.getEngine();
|
|
2924
|
+
signal?.throwIfAborted();
|
|
2475
2925
|
const subscription = await engine.stream(input.tickers, input.fields, streamOptions(input));
|
|
2476
|
-
const result = await collectSnapshot(subscription, input);
|
|
2926
|
+
const result = await collectSnapshot(subscription, input, signal);
|
|
2477
2927
|
return resultString2(resolver, name, result);
|
|
2478
2928
|
} catch (error) {
|
|
2479
2929
|
throwWithToolContext(name, error);
|
|
@@ -2490,11 +2940,13 @@ function streamSnapshotWithResolver(resolver) {
|
|
|
2490
2940
|
function mktbarSnapshotWithResolver(resolver) {
|
|
2491
2941
|
const name = "xbbg_mktbar_snapshot";
|
|
2492
2942
|
return createBloombergStructuredTool(
|
|
2493
|
-
async (input) => {
|
|
2943
|
+
async (input, config) => {
|
|
2944
|
+
const signal = config?.signal;
|
|
2494
2945
|
try {
|
|
2495
2946
|
const engine = await resolver.getEngine();
|
|
2496
|
-
|
|
2497
|
-
const
|
|
2947
|
+
signal?.throwIfAborted();
|
|
2948
|
+
const subscription = await engine.mktbar(input.ticker, singleTickerStreamOptions(input));
|
|
2949
|
+
const result = await collectSnapshot(subscription, input, signal);
|
|
2498
2950
|
return resultString2(resolver, name, result);
|
|
2499
2951
|
} catch (error) {
|
|
2500
2952
|
throwWithToolContext(name, error);
|
|
@@ -2511,11 +2963,13 @@ function mktbarSnapshotWithResolver(resolver) {
|
|
|
2511
2963
|
function depthSnapshotWithResolver(resolver) {
|
|
2512
2964
|
const name = "xbbg_depth_snapshot";
|
|
2513
2965
|
return createBloombergStructuredTool(
|
|
2514
|
-
async (input) => {
|
|
2966
|
+
async (input, config) => {
|
|
2967
|
+
const signal = config?.signal;
|
|
2515
2968
|
try {
|
|
2516
2969
|
const engine = await resolver.getEngine();
|
|
2517
|
-
|
|
2518
|
-
const
|
|
2970
|
+
signal?.throwIfAborted();
|
|
2971
|
+
const subscription = await engine.depth(input.ticker, singleTickerStreamOptions(input));
|
|
2972
|
+
const result = await collectSnapshot(subscription, input, signal);
|
|
2519
2973
|
return resultString2(resolver, name, result);
|
|
2520
2974
|
} catch (error) {
|
|
2521
2975
|
throwWithToolContext(name, error);
|
|
@@ -2589,29 +3043,32 @@ function createMktbarSnapshotTool(options = {}) {
|
|
|
2589
3043
|
function createDepthSnapshotTool(options = {}) {
|
|
2590
3044
|
return depthSnapshotWithResolver(createCoreResolver(options));
|
|
2591
3045
|
}
|
|
3046
|
+
var CORE_TOOL_DEFINITIONS = Object.freeze([
|
|
3047
|
+
{ create: bdpWithResolver, name: "xbbg_bdp" },
|
|
3048
|
+
{ create: bdhWithResolver, name: "xbbg_bdh" },
|
|
3049
|
+
{ create: bdsWithResolver, name: "xbbg_bds" },
|
|
3050
|
+
{ create: bdibWithResolver, name: "xbbg_bdib" },
|
|
3051
|
+
{ create: bdtickWithResolver, name: "xbbg_bdtick" },
|
|
3052
|
+
{ create: bqlWithResolver, name: "xbbg_bql" },
|
|
3053
|
+
{ create: bsrchWithResolver, name: "xbbg_bsrch" },
|
|
3054
|
+
{ create: bqrWithResolver, name: "xbbg_bqr" },
|
|
3055
|
+
{ create: bfldsWithResolver, name: "xbbg_bflds" },
|
|
3056
|
+
{ create: beqsWithResolver, name: "xbbg_beqs" },
|
|
3057
|
+
{ create: yasWithResolver, name: "xbbg_yas" },
|
|
3058
|
+
{ create: preferredsWithResolver, name: "xbbg_preferreds" },
|
|
3059
|
+
{ create: corporateBondsWithResolver, name: "xbbg_corporate_bonds" },
|
|
3060
|
+
{ create: indexMembersWithResolver, name: "xbbg_index_members" },
|
|
3061
|
+
{ create: resolveIsinsWithResolver, name: "xbbg_resolve_isins" },
|
|
3062
|
+
{ create: issuerIsinsWithResolver, name: "xbbg_issuer_isins" },
|
|
3063
|
+
{ create: etfHoldingsWithResolver, name: "xbbg_etf_holdings" },
|
|
3064
|
+
{ create: streamSnapshotWithResolver, name: "xbbg_stream_snapshot" },
|
|
3065
|
+
{ create: mktbarSnapshotWithResolver, name: "xbbg_mktbar_snapshot" },
|
|
3066
|
+
{ create: depthSnapshotWithResolver, name: "xbbg_depth_snapshot" }
|
|
3067
|
+
]);
|
|
2592
3068
|
function createBloombergToolsForResolver(resolver) {
|
|
2593
|
-
return
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
...enabledTool(resolver, "xbbg_bds", bdsWithResolver),
|
|
2597
|
-
...enabledTool(resolver, "xbbg_bdib", bdibWithResolver),
|
|
2598
|
-
...enabledTool(resolver, "xbbg_bdtick", bdtickWithResolver),
|
|
2599
|
-
...enabledTool(resolver, "xbbg_bql", bqlWithResolver),
|
|
2600
|
-
...enabledTool(resolver, "xbbg_bsrch", bsrchWithResolver),
|
|
2601
|
-
...enabledTool(resolver, "xbbg_bqr", bqrWithResolver),
|
|
2602
|
-
...enabledTool(resolver, "xbbg_bflds", bfldsWithResolver),
|
|
2603
|
-
...enabledTool(resolver, "xbbg_beqs", beqsWithResolver),
|
|
2604
|
-
...enabledTool(resolver, "xbbg_yas", yasWithResolver),
|
|
2605
|
-
...enabledTool(resolver, "xbbg_preferreds", preferredsWithResolver),
|
|
2606
|
-
...enabledTool(resolver, "xbbg_corporate_bonds", corporateBondsWithResolver),
|
|
2607
|
-
...enabledTool(resolver, "xbbg_index_members", indexMembersWithResolver),
|
|
2608
|
-
...enabledTool(resolver, "xbbg_resolve_isins", resolveIsinsWithResolver),
|
|
2609
|
-
...enabledTool(resolver, "xbbg_issuer_isins", issuerIsinsWithResolver),
|
|
2610
|
-
...enabledTool(resolver, "xbbg_etf_holdings", etfHoldingsWithResolver),
|
|
2611
|
-
...enabledTool(resolver, "xbbg_stream_snapshot", streamSnapshotWithResolver),
|
|
2612
|
-
...enabledTool(resolver, "xbbg_mktbar_snapshot", mktbarSnapshotWithResolver),
|
|
2613
|
-
...enabledTool(resolver, "xbbg_depth_snapshot", depthSnapshotWithResolver)
|
|
2614
|
-
];
|
|
3069
|
+
return CORE_TOOL_DEFINITIONS.filter(
|
|
3070
|
+
(definition) => !isToolDisabled(resolver.options, definition.name)
|
|
3071
|
+
).map((definition) => definition.create(resolver));
|
|
2615
3072
|
}
|
|
2616
3073
|
function createBloombergTools(options = {}) {
|
|
2617
3074
|
return createBloombergToolsForResolver(createCoreResolver(options));
|
|
@@ -2629,6 +3086,7 @@ function createAllBloombergTools(options = {}) {
|
|
|
2629
3086
|
exports.BLOOMBERG_EXT_TOOL_NAMES = BLOOMBERG_EXT_TOOL_NAMES;
|
|
2630
3087
|
exports.BLOOMBERG_TOOL_INSTRUCTIONS = BLOOMBERG_TOOL_INSTRUCTIONS;
|
|
2631
3088
|
exports.BLOOMBERG_TOOL_NAMES = BLOOMBERG_TOOL_NAMES;
|
|
3089
|
+
exports.DEFAULT_ENGINE_REQUEST_TIMEOUT_MS = DEFAULT_ENGINE_REQUEST_TIMEOUT_MS;
|
|
2632
3090
|
exports.createAllBloombergTools = createAllBloombergTools;
|
|
2633
3091
|
exports.createBdhTool = createBdhTool;
|
|
2634
3092
|
exports.createBdibTool = createBdibTool;
|
|
@@ -2648,6 +3106,7 @@ exports.createEtfHoldingsTool = createEtfHoldingsTool;
|
|
|
2648
3106
|
exports.createExtBqlBuilderTool = createExtBqlBuilderTool;
|
|
2649
3107
|
exports.createExtCalculateTool = createExtCalculateTool;
|
|
2650
3108
|
exports.createExtCdxTool = createExtCdxTool;
|
|
3109
|
+
exports.createExtChartSpecTool = createExtChartSpecTool;
|
|
2651
3110
|
exports.createExtColumnsTool = createExtColumnsTool;
|
|
2652
3111
|
exports.createExtConstantsTool = createExtConstantsTool;
|
|
2653
3112
|
exports.createExtCurrencyTool = createExtCurrencyTool;
|
|
@@ -2663,5 +3122,6 @@ exports.createResolveIsinsTool = createResolveIsinsTool;
|
|
|
2663
3122
|
exports.createStreamSnapshotTool = createStreamSnapshotTool;
|
|
2664
3123
|
exports.createYasTool = createYasTool;
|
|
2665
3124
|
exports.getBloombergToolInstructions = getBloombergToolInstructions;
|
|
3125
|
+
exports.toolParameterJsonSchema = toolParameterJsonSchema;
|
|
2666
3126
|
//# sourceMappingURL=index.js.map
|
|
2667
3127
|
//# sourceMappingURL=index.js.map
|