oilpriceapi 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +78 -2
- package/dist/cjs/client.js +49 -0
- package/dist/cjs/index.js +4 -1
- package/dist/cjs/resources/futures.js +61 -24
- package/dist/cjs/resources/market-brief.js +9 -0
- package/dist/cjs/resources/streaming.js +3 -3
- package/dist/cjs/resources/subscriptions.js +217 -0
- package/dist/cjs/version.js +1 -1
- package/dist/client.d.ts +36 -1
- package/dist/client.js +50 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -0
- package/dist/resources/futures.d.ts +112 -35
- package/dist/resources/futures.js +60 -24
- package/dist/resources/market-brief.d.ts +72 -0
- package/dist/resources/market-brief.js +8 -0
- package/dist/resources/streaming.d.ts +2 -2
- package/dist/resources/streaming.js +3 -3
- package/dist/resources/subscriptions.d.ts +238 -0
- package/dist/resources/subscriptions.js +212 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { OilPriceAPIError, AuthenticationError, RateLimitError, NotFoundError, ServerError, TimeoutError, } from "./errors.js";
|
|
1
|
+
import { OilPriceAPIError, AuthenticationError, RateLimitError, NotFoundError, ServerError, TimeoutError, ValidationError, } from "./errors.js";
|
|
2
2
|
import { DieselResource } from "./resources/diesel.js";
|
|
3
3
|
import { AlertsResource } from "./resources/alerts.js";
|
|
4
4
|
import { CommoditiesResource } from "./resources/commodities.js";
|
|
@@ -18,6 +18,7 @@ import { SpreadsResource } from "./resources/spreads.js";
|
|
|
18
18
|
import { IndicatorsResource } from "./resources/indicators.js";
|
|
19
19
|
import { RawResource } from "./resources/raw.js";
|
|
20
20
|
import { StreamingResource } from "./resources/streaming.js";
|
|
21
|
+
import { SubscriptionsResource } from "./resources/subscriptions.js";
|
|
21
22
|
/**
|
|
22
23
|
* Official Node.js client for Oil Price API
|
|
23
24
|
*
|
|
@@ -77,6 +78,7 @@ export class OilPriceAPI {
|
|
|
77
78
|
this.indicators = new IndicatorsResource(this);
|
|
78
79
|
this.raw = new RawResource(this);
|
|
79
80
|
this.stream = new StreamingResource(this);
|
|
81
|
+
this.subscriptions = new SubscriptionsResource(this);
|
|
80
82
|
}
|
|
81
83
|
/**
|
|
82
84
|
* Log debug messages if debug mode is enabled
|
|
@@ -212,6 +214,14 @@ export class OilPriceAPI {
|
|
|
212
214
|
if (this.appName) {
|
|
213
215
|
headers["X-App-Name"] = this.appName;
|
|
214
216
|
}
|
|
217
|
+
// Per-request headers (e.g. MCP attribution X-OPA-Source / X-OPA-Tool).
|
|
218
|
+
if (options?.headers) {
|
|
219
|
+
Object.entries(options.headers).forEach(([key, value]) => {
|
|
220
|
+
if (value !== undefined && value !== null) {
|
|
221
|
+
headers[key] = value;
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
}
|
|
215
225
|
const fetchOptions = {
|
|
216
226
|
method: options?.method || "GET",
|
|
217
227
|
headers,
|
|
@@ -521,6 +531,45 @@ export class OilPriceAPI {
|
|
|
521
531
|
async getCommodity(code) {
|
|
522
532
|
return this.request(`/v1/commodities/${code}`, {});
|
|
523
533
|
}
|
|
534
|
+
/**
|
|
535
|
+
* Get a multi-commodity market brief (OilPriceAPI #3245 Phase 1a).
|
|
536
|
+
*
|
|
537
|
+
* Returns a structured summary (latest price, 24h change, freshness, and a
|
|
538
|
+
* 1-month forecast band) for each requested commodity, optionally with a
|
|
539
|
+
* natural-language narrative. Counts as a single request against your quota,
|
|
540
|
+
* like `/v1/prices/batch`. The per-tier cap on `codes` is enforced server-side.
|
|
541
|
+
*
|
|
542
|
+
* @param codes - Commodity codes (e.g. ["BRENT_CRUDE_USD", "WTI_USD"]). Shorthand
|
|
543
|
+
* codes like "WTI"/"BRENT" are accepted and resolved server-side.
|
|
544
|
+
* @param options - `{ narrative }` to request the natural-language summary.
|
|
545
|
+
* @returns The structured (and optional narrative) market brief.
|
|
546
|
+
*
|
|
547
|
+
* @throws {ValidationError} If `codes` is empty.
|
|
548
|
+
*
|
|
549
|
+
* @example
|
|
550
|
+
* ```typescript
|
|
551
|
+
* const brief = await client.getMarketBrief(['BRENT_CRUDE_USD', 'WTI_USD']);
|
|
552
|
+
* for (const c of brief.commodities) {
|
|
553
|
+
* console.log(`${c.name}: $${c.price} (${c.change_24h_pct}%)`);
|
|
554
|
+
* }
|
|
555
|
+
*
|
|
556
|
+
* // With narrative
|
|
557
|
+
* const withText = await client.getMarketBrief(['BRENT_CRUDE_USD'], { narrative: true });
|
|
558
|
+
* console.log(withText.narrative);
|
|
559
|
+
* ```
|
|
560
|
+
*/
|
|
561
|
+
async getMarketBrief(codes, options) {
|
|
562
|
+
if (!Array.isArray(codes) || codes.length === 0) {
|
|
563
|
+
throw new ValidationError("codes is required and must be a non-empty array of commodity codes");
|
|
564
|
+
}
|
|
565
|
+
const params = {
|
|
566
|
+
codes: codes.join(","),
|
|
567
|
+
};
|
|
568
|
+
if (options?.narrative) {
|
|
569
|
+
params.narrative = "true";
|
|
570
|
+
}
|
|
571
|
+
return this.request("/v1/market-brief", params);
|
|
572
|
+
}
|
|
524
573
|
/**
|
|
525
574
|
* Fetch live sample prices from the public, no-auth demo endpoint.
|
|
526
575
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -26,6 +26,9 @@ export type { MonthlyForecast, ForecastAccuracy, ArchivedForecast } from "./reso
|
|
|
26
26
|
export type { DataQualitySummary, DataQualityReportMeta, DataQualityReport, } from "./resources/data-quality.js";
|
|
27
27
|
export type { DrillingIntelligenceData, LatestDrillingData, DrillingSummary, DrillingTrend, FracSpreadData, WellPermitData, DUCWellData, CompletionData, WellsDrilledData, BasinDrillingData, } from "./resources/drilling.js";
|
|
28
28
|
export type { WellTimelineEvent, WellTimeline, RigCountRecord, RigCountByBasin, RigCountByState, HistoricalRigCount, OilInventoryRecord, OilInventorySummary, InventoryByProduct, HistoricalInventory, CushingInventory, OPECProductionRecord, TotalOPECProduction, ProductionByCountry, HistoricalProduction, TopProducer, DrillingProductivityRecord, DrillingProductivitySummary, DUCWellInventory, ProductivityByBasin, HistoricalProductivity, ProductivityTrend, ForecastRecord, ForecastSummary, PriceForecast, ProductionForecast, HistoricalForecast, ForecastComparison, WellPermitRecord, WellPermitSummary, PermitsByState, PermitsByOperator, PermitsByFormation, WellPermitSearchQuery, FracFocusRecord, FracFocusSummary, DisclosuresByState, DisclosuresByOperator, ChemicalUsage, WellChemical, FracFocusSearchQuery, } from "./resources/ei/index.js";
|
|
29
|
+
export type { MarketBrief, MarketBriefCommodity, MarketBriefForecast, MarketBriefOptions, } from "./resources/market-brief.js";
|
|
30
|
+
export type { Subscription, SubscriptionStatus, SubscriptionSource, SubscriptionInterval, CreateSubscriptionParams, SubscriptionEvent, SubscriptionEventsResult, SubscriptionEventsOptions, } from "./resources/subscriptions.js";
|
|
31
|
+
export { SubscriptionsResource, intervalToSeconds } from "./resources/subscriptions.js";
|
|
29
32
|
export type { WebhookEndpoint, CreateWebhookParams, UpdateWebhookParams, WebhookTestResponse as WebhookTestResult, WebhookEvent, } from "./resources/webhooks.js";
|
|
30
33
|
export type { DataSourceType, DataSourceStatus, DataSource, CreateDataSourceParams, UpdateDataSourceParams, DataSourceTestResponse, DataSourceLog, DataSourceHealth, CredentialRotationResponse, } from "./resources/data-sources.js";
|
|
31
34
|
export { OilPriceAPIError, AuthenticationError, RateLimitError, NotFoundError, ServerError, ValidationError, TimeoutError, } from "./errors.js";
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,7 @@ export { FUTURES_CONTRACTS, FUTURES_FAMILY_SLUGS, FuturesContractFamily, } from
|
|
|
12
12
|
export { SpreadsResource } from "./resources/spreads.js";
|
|
13
13
|
export { IndicatorsResource } from "./resources/indicators.js";
|
|
14
14
|
export { RawResource } from "./resources/raw.js";
|
|
15
|
+
export { SubscriptionsResource, intervalToSeconds } from "./resources/subscriptions.js";
|
|
15
16
|
export { OilPriceAPIError, AuthenticationError, RateLimitError, NotFoundError, ServerError, ValidationError, TimeoutError, } from "./errors.js";
|
|
16
17
|
export { DieselResource } from "./resources/diesel.js";
|
|
17
18
|
export { AlertsResource } from "./resources/alerts.js";
|
|
@@ -6,23 +6,71 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { OilPriceAPI } from "../client.js";
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* A single futures contract month within a {@link FuturesPrice} response.
|
|
10
|
+
*
|
|
11
|
+
* Returned at the top level under `front_month` and for every entry in
|
|
12
|
+
* `contracts[]`. The latest traded price is `last_price`.
|
|
13
|
+
*/
|
|
14
|
+
export interface FuturesContractMonth {
|
|
15
|
+
/** Contract code (e.g. "BRENT_FUTURES_2026_08"). */
|
|
16
|
+
code?: string;
|
|
17
|
+
/** Contract month in YYYY-MM form (e.g. "2026-08"). */
|
|
18
|
+
contract_month?: string;
|
|
19
|
+
/** Latest traded/settlement price for this contract month. */
|
|
20
|
+
last_price?: number;
|
|
21
|
+
/** Currency code (e.g. "USD"). */
|
|
22
|
+
currency?: string;
|
|
23
|
+
/** Opening price (may be returned as a string by the API). */
|
|
24
|
+
open?: number | string;
|
|
25
|
+
/** Closing price (may be returned as a string by the API). */
|
|
26
|
+
close?: number | string;
|
|
27
|
+
/** Session high. */
|
|
28
|
+
high?: number | string;
|
|
29
|
+
/** Session low. */
|
|
30
|
+
low?: number | string;
|
|
31
|
+
/** Any additional fields the API returns for a contract month. */
|
|
32
|
+
[key: string]: unknown;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Futures contract price data.
|
|
36
|
+
*
|
|
37
|
+
* `GET /v1/futures/{slug}` returns a TOP-LEVEL object (there is NO
|
|
38
|
+
* `{ status, data }` envelope). The latest price lives at
|
|
39
|
+
* `front_month.last_price`, with the full term structure in `contracts[]`.
|
|
40
|
+
*
|
|
41
|
+
* Legacy flat fields (`contract`, `price`, `currency`, `timestamp`) are kept
|
|
42
|
+
* optional for backward compatibility, but real responses populate
|
|
43
|
+
* `front_month` / `contracts` instead.
|
|
10
44
|
*/
|
|
11
45
|
export interface FuturesPrice {
|
|
12
|
-
/**
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
/**
|
|
46
|
+
/** Commodity identifier (e.g. "BRENT_FUTURES"). */
|
|
47
|
+
commodity?: string;
|
|
48
|
+
/** Data source (e.g. "ICE"). */
|
|
49
|
+
source?: string;
|
|
50
|
+
/** ISO timestamp the data was last updated. */
|
|
51
|
+
updated_at?: string;
|
|
52
|
+
/** Settlement date for the prices. */
|
|
53
|
+
settlement_date?: string;
|
|
54
|
+
/** Front-month contract — the latest price is `front_month.last_price`. */
|
|
55
|
+
front_month?: FuturesContractMonth;
|
|
56
|
+
/** Full forward term structure, one entry per contract month. */
|
|
57
|
+
contracts?: FuturesContractMonth[];
|
|
58
|
+
/** Optional warning when the returned data is stale. */
|
|
59
|
+
data_age_warning?: unknown;
|
|
60
|
+
/** Additional metadata returned by the API. */
|
|
61
|
+
metadata?: Record<string, unknown>;
|
|
62
|
+
/** @deprecated Legacy flat contract symbol — use `front_month.code`. */
|
|
63
|
+
contract?: string;
|
|
64
|
+
/** @deprecated Legacy flat price — use `front_month.last_price`. */
|
|
65
|
+
price?: number;
|
|
66
|
+
/** @deprecated Legacy formatted price string. */
|
|
17
67
|
formatted?: string;
|
|
18
|
-
/**
|
|
19
|
-
currency
|
|
20
|
-
/**
|
|
68
|
+
/** @deprecated Legacy currency — use `front_month.currency`. */
|
|
69
|
+
currency?: string;
|
|
70
|
+
/** @deprecated Legacy contract expiration date. */
|
|
21
71
|
expiration?: string;
|
|
22
|
-
/** ISO timestamp
|
|
23
|
-
timestamp
|
|
24
|
-
/** Additional metadata */
|
|
25
|
-
metadata?: Record<string, unknown>;
|
|
72
|
+
/** @deprecated Legacy ISO timestamp — use `updated_at`. */
|
|
73
|
+
timestamp?: string;
|
|
26
74
|
}
|
|
27
75
|
/**
|
|
28
76
|
* Historical futures price data
|
|
@@ -141,15 +189,25 @@ export interface FuturesCurvePoint {
|
|
|
141
189
|
contract?: string;
|
|
142
190
|
}
|
|
143
191
|
/**
|
|
144
|
-
* Futures curve data
|
|
192
|
+
* Futures curve data.
|
|
193
|
+
*
|
|
194
|
+
* `GET /v1/futures/{slug}/curve` can legitimately return a no-data response of
|
|
195
|
+
* the form `{ error: "No futures data available for curve analysis", date }`
|
|
196
|
+
* when a curve cannot be built. That is a valid state (not an HTTP error), so
|
|
197
|
+
* `curve` is optional and `error` / `date` are surfaced for callers to detect
|
|
198
|
+
* the no-data case.
|
|
145
199
|
*/
|
|
146
200
|
export interface FuturesCurveData {
|
|
147
201
|
/** Base contract */
|
|
148
|
-
contract
|
|
202
|
+
contract?: string;
|
|
149
203
|
/** ISO timestamp when curve was generated */
|
|
150
|
-
timestamp
|
|
151
|
-
/** Array of curve points */
|
|
152
|
-
curve
|
|
204
|
+
timestamp?: string;
|
|
205
|
+
/** Array of curve points (absent in the no-data response) */
|
|
206
|
+
curve?: FuturesCurvePoint[];
|
|
207
|
+
/** Present in the no-data response: "No futures data available for curve analysis". */
|
|
208
|
+
error?: string;
|
|
209
|
+
/** Date associated with the no-data response. */
|
|
210
|
+
date?: string;
|
|
153
211
|
}
|
|
154
212
|
/**
|
|
155
213
|
* Continuous contract data point
|
|
@@ -196,9 +254,10 @@ export interface FuturesSpreadHistory {
|
|
|
196
254
|
/**
|
|
197
255
|
* Slugs for the supported ICE / gas / carbon futures contract families.
|
|
198
256
|
*
|
|
199
|
-
* These map to the `GET /v1/futures/{slug}
|
|
200
|
-
*
|
|
201
|
-
* `/
|
|
257
|
+
* These map to the `GET /v1/futures/{slug}` (latest) endpoint plus the
|
|
258
|
+
* `GET /v1/futures/{slug}/...` sub-resources. Latest is the bare slug path
|
|
259
|
+
* (there is NO `/latest` suffix). Each family also supports `/historical`,
|
|
260
|
+
* `/ohlc`, `/intraday`, `/spreads`, `/curve`, and `/spread-history`.
|
|
202
261
|
*/
|
|
203
262
|
export type FuturesContractFamilySlug = "ice-brent" | "ice-gasoil" | "ice-wti" | "natural-gas" | "ttf-gas" | "lng-jkm" | "eua-carbon" | "uk-carbon";
|
|
204
263
|
/**
|
|
@@ -241,6 +300,14 @@ export declare const FUTURES_CONTRACTS: {
|
|
|
241
300
|
* path segment used by the typed family helpers.
|
|
242
301
|
*/
|
|
243
302
|
export declare const FUTURES_FAMILY_SLUGS: Record<string, FuturesContractFamilySlug>;
|
|
303
|
+
/**
|
|
304
|
+
* Resolve a futures contract code (e.g. `"BZ"`, `"QS"`) or an already-valid
|
|
305
|
+
* family slug (e.g. `"ice-brent"`) to its `/v1/futures/{slug}` path segment.
|
|
306
|
+
*
|
|
307
|
+
* Matching is case-insensitive for codes. Returns `null` if the input maps to
|
|
308
|
+
* neither a known code nor a known family slug.
|
|
309
|
+
*/
|
|
310
|
+
export declare function resolveFuturesFamilySlug(codeOrSlug: string): FuturesContractFamilySlug | null;
|
|
244
311
|
/**
|
|
245
312
|
* Typed helper for a single futures contract family (e.g., ICE Brent, Gasoil).
|
|
246
313
|
*
|
|
@@ -264,6 +331,9 @@ export declare class FuturesContractFamily {
|
|
|
264
331
|
slug: FuturesContractFamilySlug);
|
|
265
332
|
/**
|
|
266
333
|
* Get the latest price for this contract family.
|
|
334
|
+
*
|
|
335
|
+
* Latest is served from the bare slug path `GET /v1/futures/{slug}` —
|
|
336
|
+
* there is NO `/latest` suffix (that path 404s).
|
|
267
337
|
*/
|
|
268
338
|
latest(): Promise<FuturesPrice>;
|
|
269
339
|
/**
|
|
@@ -307,16 +377,13 @@ export declare class FuturesContractFamily {
|
|
|
307
377
|
*
|
|
308
378
|
* const client = new OilPriceAPI({ apiKey: 'your_key' });
|
|
309
379
|
*
|
|
310
|
-
* // Get latest
|
|
311
|
-
* const latest = await client.futures.latest('CL
|
|
380
|
+
* // Get the latest curve by contract code (resolves to GET /v1/futures/ice-wti)
|
|
381
|
+
* const latest = await client.futures.latest('CL');
|
|
312
382
|
* console.log(`${latest.contract}: $${latest.price}`);
|
|
313
383
|
*
|
|
314
|
-
* //
|
|
315
|
-
* const
|
|
316
|
-
*
|
|
317
|
-
*
|
|
318
|
-
* // Get futures curve
|
|
319
|
-
* const curve = await client.futures.curve('CL');
|
|
384
|
+
* // Typed family helpers are the most ergonomic option:
|
|
385
|
+
* const brent = await client.futures.brent().latest();
|
|
386
|
+
* const curve = await client.futures.brent().curve();
|
|
320
387
|
* curve.curve.forEach(point => {
|
|
321
388
|
* console.log(`${point.months_out}mo: $${point.price}`);
|
|
322
389
|
* });
|
|
@@ -326,18 +393,28 @@ export declare class FuturesResource {
|
|
|
326
393
|
private client;
|
|
327
394
|
constructor(client: OilPriceAPI);
|
|
328
395
|
/**
|
|
329
|
-
* Get latest
|
|
396
|
+
* Get the latest curve/quote for a futures contract family.
|
|
330
397
|
*
|
|
331
|
-
*
|
|
332
|
-
*
|
|
398
|
+
* Accepts an ergonomic contract code (e.g. `"BZ"`, `"CL"`, `"QS"`) or a
|
|
399
|
+
* family slug (e.g. `"ice-brent"`). The code is resolved to its family slug
|
|
400
|
+
* and the request is sent to `GET /v1/futures/{slug}` — the bare slug path,
|
|
401
|
+
* with NO `/latest` suffix (the suffixed path 404s).
|
|
333
402
|
*
|
|
334
|
-
*
|
|
403
|
+
* Supported codes: BZ (Brent), CL (WTI), G/QS (Gasoil), NG (Natural Gas),
|
|
404
|
+
* TTF, JKM, EUA, UKA. Slugs: ice-brent, ice-wti, ice-gasoil, natural-gas,
|
|
405
|
+
* ttf-gas, lng-jkm, eua-carbon, uk-carbon.
|
|
406
|
+
*
|
|
407
|
+
* @param contract - Contract code (e.g. "BZ") or family slug (e.g. "ice-brent").
|
|
408
|
+
* @returns Latest futures price/curve data
|
|
409
|
+
*
|
|
410
|
+
* @throws {ValidationError} If the code/slug is empty or unrecognized.
|
|
335
411
|
* @throws {OilPriceAPIError} If API request fails
|
|
336
412
|
*
|
|
337
413
|
* @example
|
|
338
414
|
* ```typescript
|
|
339
|
-
*
|
|
340
|
-
*
|
|
415
|
+
* import { FUTURES_CONTRACTS } from 'oilpriceapi';
|
|
416
|
+
* const price = await client.futures.latest(FUTURES_CONTRACTS.BRENT); // "BZ"
|
|
417
|
+
* const wti = await client.futures.latest('ice-wti');
|
|
341
418
|
* ```
|
|
342
419
|
*/
|
|
343
420
|
latest(contract: string): Promise<FuturesPrice>;
|
|
@@ -45,15 +45,34 @@ export const FUTURES_CONTRACTS = {
|
|
|
45
45
|
* path segment used by the typed family helpers.
|
|
46
46
|
*/
|
|
47
47
|
export const FUTURES_FAMILY_SLUGS = {
|
|
48
|
-
[FUTURES_CONTRACTS.BRENT]: "ice-brent",
|
|
49
|
-
[FUTURES_CONTRACTS.WTI]: "ice-wti",
|
|
50
|
-
[FUTURES_CONTRACTS.GASOIL]: "ice-gasoil",
|
|
51
|
-
|
|
52
|
-
[FUTURES_CONTRACTS.
|
|
53
|
-
[FUTURES_CONTRACTS.
|
|
54
|
-
[FUTURES_CONTRACTS.
|
|
55
|
-
[FUTURES_CONTRACTS.
|
|
48
|
+
[FUTURES_CONTRACTS.BRENT]: "ice-brent", // BZ
|
|
49
|
+
[FUTURES_CONTRACTS.WTI]: "ice-wti", // CL
|
|
50
|
+
[FUTURES_CONTRACTS.GASOIL]: "ice-gasoil", // G
|
|
51
|
+
QS: "ice-gasoil", // ICE Gasoil also trades under the QS ticker prefix
|
|
52
|
+
[FUTURES_CONTRACTS.NATURAL_GAS]: "natural-gas", // NG
|
|
53
|
+
[FUTURES_CONTRACTS.TTF_GAS]: "ttf-gas", // TTF
|
|
54
|
+
[FUTURES_CONTRACTS.LNG_JKM]: "lng-jkm", // JKM
|
|
55
|
+
[FUTURES_CONTRACTS.EUA_CARBON]: "eua-carbon", // EUA
|
|
56
|
+
[FUTURES_CONTRACTS.UK_CARBON]: "uk-carbon", // UKA
|
|
56
57
|
};
|
|
58
|
+
/**
|
|
59
|
+
* Resolve a futures contract code (e.g. `"BZ"`, `"QS"`) or an already-valid
|
|
60
|
+
* family slug (e.g. `"ice-brent"`) to its `/v1/futures/{slug}` path segment.
|
|
61
|
+
*
|
|
62
|
+
* Matching is case-insensitive for codes. Returns `null` if the input maps to
|
|
63
|
+
* neither a known code nor a known family slug.
|
|
64
|
+
*/
|
|
65
|
+
export function resolveFuturesFamilySlug(codeOrSlug) {
|
|
66
|
+
const trimmed = codeOrSlug.trim();
|
|
67
|
+
// Direct code match (case-insensitive — codes are upper-case).
|
|
68
|
+
const byCode = FUTURES_FAMILY_SLUGS[trimmed.toUpperCase()];
|
|
69
|
+
if (byCode)
|
|
70
|
+
return byCode;
|
|
71
|
+
// Already a valid family slug?
|
|
72
|
+
const lower = trimmed.toLowerCase();
|
|
73
|
+
const isSlug = Object.values(FUTURES_FAMILY_SLUGS).includes(lower);
|
|
74
|
+
return isSlug ? lower : null;
|
|
75
|
+
}
|
|
57
76
|
/**
|
|
58
77
|
* Typed helper for a single futures contract family (e.g., ICE Brent, Gasoil).
|
|
59
78
|
*
|
|
@@ -77,9 +96,12 @@ export class FuturesContractFamily {
|
|
|
77
96
|
}
|
|
78
97
|
/**
|
|
79
98
|
* Get the latest price for this contract family.
|
|
99
|
+
*
|
|
100
|
+
* Latest is served from the bare slug path `GET /v1/futures/{slug}` —
|
|
101
|
+
* there is NO `/latest` suffix (that path 404s).
|
|
80
102
|
*/
|
|
81
103
|
async latest() {
|
|
82
|
-
return this.client["request"](`/v1/futures/${this.slug}
|
|
104
|
+
return this.client["request"](`/v1/futures/${this.slug}`, {});
|
|
83
105
|
}
|
|
84
106
|
/**
|
|
85
107
|
* Get historical prices for this contract family.
|
|
@@ -152,16 +174,13 @@ export class FuturesContractFamily {
|
|
|
152
174
|
*
|
|
153
175
|
* const client = new OilPriceAPI({ apiKey: 'your_key' });
|
|
154
176
|
*
|
|
155
|
-
* // Get latest
|
|
156
|
-
* const latest = await client.futures.latest('CL
|
|
177
|
+
* // Get the latest curve by contract code (resolves to GET /v1/futures/ice-wti)
|
|
178
|
+
* const latest = await client.futures.latest('CL');
|
|
157
179
|
* console.log(`${latest.contract}: $${latest.price}`);
|
|
158
180
|
*
|
|
159
|
-
* //
|
|
160
|
-
* const
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
* // Get futures curve
|
|
164
|
-
* const curve = await client.futures.curve('CL');
|
|
181
|
+
* // Typed family helpers are the most ergonomic option:
|
|
182
|
+
* const brent = await client.futures.brent().latest();
|
|
183
|
+
* const curve = await client.futures.brent().curve();
|
|
165
184
|
* curve.curve.forEach(point => {
|
|
166
185
|
* console.log(`${point.months_out}mo: $${point.price}`);
|
|
167
186
|
* });
|
|
@@ -172,25 +191,42 @@ export class FuturesResource {
|
|
|
172
191
|
this.client = client;
|
|
173
192
|
}
|
|
174
193
|
/**
|
|
175
|
-
* Get latest
|
|
194
|
+
* Get the latest curve/quote for a futures contract family.
|
|
176
195
|
*
|
|
177
|
-
*
|
|
178
|
-
*
|
|
196
|
+
* Accepts an ergonomic contract code (e.g. `"BZ"`, `"CL"`, `"QS"`) or a
|
|
197
|
+
* family slug (e.g. `"ice-brent"`). The code is resolved to its family slug
|
|
198
|
+
* and the request is sent to `GET /v1/futures/{slug}` — the bare slug path,
|
|
199
|
+
* with NO `/latest` suffix (the suffixed path 404s).
|
|
179
200
|
*
|
|
180
|
-
*
|
|
201
|
+
* Supported codes: BZ (Brent), CL (WTI), G/QS (Gasoil), NG (Natural Gas),
|
|
202
|
+
* TTF, JKM, EUA, UKA. Slugs: ice-brent, ice-wti, ice-gasoil, natural-gas,
|
|
203
|
+
* ttf-gas, lng-jkm, eua-carbon, uk-carbon.
|
|
204
|
+
*
|
|
205
|
+
* @param contract - Contract code (e.g. "BZ") or family slug (e.g. "ice-brent").
|
|
206
|
+
* @returns Latest futures price/curve data
|
|
207
|
+
*
|
|
208
|
+
* @throws {ValidationError} If the code/slug is empty or unrecognized.
|
|
181
209
|
* @throws {OilPriceAPIError} If API request fails
|
|
182
210
|
*
|
|
183
211
|
* @example
|
|
184
212
|
* ```typescript
|
|
185
|
-
*
|
|
186
|
-
*
|
|
213
|
+
* import { FUTURES_CONTRACTS } from 'oilpriceapi';
|
|
214
|
+
* const price = await client.futures.latest(FUTURES_CONTRACTS.BRENT); // "BZ"
|
|
215
|
+
* const wti = await client.futures.latest('ice-wti');
|
|
187
216
|
* ```
|
|
188
217
|
*/
|
|
189
218
|
async latest(contract) {
|
|
190
219
|
if (!contract || typeof contract !== "string") {
|
|
191
220
|
throw new ValidationError("Contract symbol must be a non-empty string");
|
|
192
221
|
}
|
|
193
|
-
|
|
222
|
+
const slug = resolveFuturesFamilySlug(contract);
|
|
223
|
+
if (!slug) {
|
|
224
|
+
throw new ValidationError(`Unknown futures contract "${contract}". Use a contract code ` +
|
|
225
|
+
`(BZ, CL, G, QS, NG, TTF, JKM, EUA, UKA) or a family slug ` +
|
|
226
|
+
`(ice-brent, ice-wti, ice-gasoil, natural-gas, ttf-gas, lng-jkm, ` +
|
|
227
|
+
`eua-carbon, uk-carbon).`);
|
|
228
|
+
}
|
|
229
|
+
return this.client["request"](`/v1/futures/${slug}`, {});
|
|
194
230
|
}
|
|
195
231
|
/**
|
|
196
232
|
* Get historical prices for a futures contract
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Market Brief types (OilPriceAPI #3245 Phase 1a)
|
|
3
|
+
*
|
|
4
|
+
* A multi-commodity structured (+ optional narrative) market summary composed
|
|
5
|
+
* from existing price + forecast data. Served by `GET /v1/market-brief` and
|
|
6
|
+
* surfaced on the client as {@link OilPriceAPI.getMarketBrief}.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Short-horizon (1-month) point forecast for a commodity in a market brief.
|
|
10
|
+
*/
|
|
11
|
+
export interface MarketBriefForecast {
|
|
12
|
+
/** Central point estimate. */
|
|
13
|
+
point: number;
|
|
14
|
+
/** Low end of the forecast band. */
|
|
15
|
+
low: number;
|
|
16
|
+
/** High end of the forecast band. */
|
|
17
|
+
high: number;
|
|
18
|
+
/** Model confidence label (e.g. "low", "medium", "high"). */
|
|
19
|
+
confidence: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* One commodity's slice of a market brief.
|
|
23
|
+
*/
|
|
24
|
+
export interface MarketBriefCommodity {
|
|
25
|
+
/** Commodity code (e.g. "BRENT_CRUDE_USD"). */
|
|
26
|
+
code: string;
|
|
27
|
+
/** Human-readable commodity name. */
|
|
28
|
+
name: string;
|
|
29
|
+
/** Latest price. */
|
|
30
|
+
price: number;
|
|
31
|
+
/** ISO currency code (e.g. "USD"). */
|
|
32
|
+
currency: string;
|
|
33
|
+
/** Price unit (e.g. "barrel"). */
|
|
34
|
+
unit: string;
|
|
35
|
+
/** 24h percentage change. */
|
|
36
|
+
change_24h_pct: number;
|
|
37
|
+
/** 24h absolute change. */
|
|
38
|
+
change_24h_abs: number;
|
|
39
|
+
/** ISO timestamp the price was observed. */
|
|
40
|
+
as_of: string;
|
|
41
|
+
/** Upstream data source. */
|
|
42
|
+
source: string;
|
|
43
|
+
/** True when the price is stale (no fresh update). */
|
|
44
|
+
stale: boolean;
|
|
45
|
+
/** 1-month forecast band, when available. */
|
|
46
|
+
forecast_1m: MarketBriefForecast | null;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* A multi-commodity market brief.
|
|
50
|
+
*
|
|
51
|
+
* Returned by {@link OilPriceAPI.getMarketBrief}.
|
|
52
|
+
*/
|
|
53
|
+
export interface MarketBrief {
|
|
54
|
+
/** ISO timestamp the brief was generated. */
|
|
55
|
+
as_of: string;
|
|
56
|
+
/** The (resolved, canonical) codes included in the brief. */
|
|
57
|
+
codes: string[];
|
|
58
|
+
/** Per-commodity structured summary. */
|
|
59
|
+
commodities: MarketBriefCommodity[];
|
|
60
|
+
/** Optional natural-language narrative (only when `narrative: true`). */
|
|
61
|
+
narrative?: string;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Options for {@link OilPriceAPI.getMarketBrief}.
|
|
65
|
+
*/
|
|
66
|
+
export interface MarketBriefOptions {
|
|
67
|
+
/**
|
|
68
|
+
* Request a natural-language narrative alongside the structured data.
|
|
69
|
+
* Defaults to `false`.
|
|
70
|
+
*/
|
|
71
|
+
narrative?: boolean;
|
|
72
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Market Brief types (OilPriceAPI #3245 Phase 1a)
|
|
3
|
+
*
|
|
4
|
+
* A multi-commodity structured (+ optional narrative) market summary composed
|
|
5
|
+
* from existing price + forecast data. Served by `GET /v1/market-brief` and
|
|
6
|
+
* surfaced on the client as {@link OilPriceAPI.getMarketBrief}.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Real-time price streaming via the OilPriceAPI ActionCable endpoint
|
|
5
5
|
* (`wss://api.oilpriceapi.com/cable`).
|
|
6
6
|
*
|
|
7
|
-
* Streaming is a **
|
|
7
|
+
* Streaming is a **Professional plan ($99/mo) or higher** feature. Connections
|
|
8
8
|
* authenticate with your API key and subscribe to the `EnergyPricesChannel`,
|
|
9
9
|
* which pushes an initial `welcome` snapshot followed by live `price_update`
|
|
10
10
|
* and (for drilling-tier accounts) `rig_count_update` messages.
|
|
@@ -105,7 +105,7 @@ export interface WelcomeMessage {
|
|
|
105
105
|
};
|
|
106
106
|
}
|
|
107
107
|
/**
|
|
108
|
-
* Rig-count update broadcast (drilling /
|
|
108
|
+
* Rig-count update broadcast (drilling / Professional+ accounts).
|
|
109
109
|
*/
|
|
110
110
|
export interface RigCountUpdateMessage {
|
|
111
111
|
type: "rig_count_update";
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Real-time price streaming via the OilPriceAPI ActionCable endpoint
|
|
5
5
|
* (`wss://api.oilpriceapi.com/cable`).
|
|
6
6
|
*
|
|
7
|
-
* Streaming is a **
|
|
7
|
+
* Streaming is a **Professional plan ($99/mo) or higher** feature. Connections
|
|
8
8
|
* authenticate with your API key and subscribe to the `EnergyPricesChannel`,
|
|
9
9
|
* which pushes an initial `welcome` snapshot followed by live `price_update`
|
|
10
10
|
* and (for drilling-tier accounts) `rig_count_update` messages.
|
|
@@ -157,8 +157,8 @@ export class PriceStreamSubscription extends EventEmitter {
|
|
|
157
157
|
return;
|
|
158
158
|
}
|
|
159
159
|
if (transportType === "reject_subscription") {
|
|
160
|
-
this.emit("error", new Error("WebSocket subscription rejected. Streaming requires a
|
|
161
|
-
"(
|
|
160
|
+
this.emit("error", new Error("WebSocket subscription rejected. Streaming requires a Professional " +
|
|
161
|
+
"plan ($99/mo) or higher and a valid API key."));
|
|
162
162
|
return;
|
|
163
163
|
}
|
|
164
164
|
if (transportType === "disconnect") {
|