oilpriceapi 0.9.0 → 0.9.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/dist/cjs/resources/futures.js +61 -24
- package/dist/cjs/version.js +1 -1
- package/dist/resources/futures.d.ts +112 -35
- package/dist/resources/futures.js +60 -24
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.FuturesResource = exports.FuturesContractFamily = exports.FUTURES_FAMILY_SLUGS = exports.FUTURES_CONTRACTS = void 0;
|
|
10
|
+
exports.resolveFuturesFamilySlug = resolveFuturesFamilySlug;
|
|
10
11
|
const errors_js_1 = require("../errors.js");
|
|
11
12
|
/**
|
|
12
13
|
* Ergonomic contract codes for the most-requested futures families (issue #1).
|
|
@@ -48,15 +49,34 @@ exports.FUTURES_CONTRACTS = {
|
|
|
48
49
|
* path segment used by the typed family helpers.
|
|
49
50
|
*/
|
|
50
51
|
exports.FUTURES_FAMILY_SLUGS = {
|
|
51
|
-
[exports.FUTURES_CONTRACTS.BRENT]: "ice-brent",
|
|
52
|
-
[exports.FUTURES_CONTRACTS.WTI]: "ice-wti",
|
|
53
|
-
[exports.FUTURES_CONTRACTS.GASOIL]: "ice-gasoil",
|
|
54
|
-
|
|
55
|
-
[exports.FUTURES_CONTRACTS.
|
|
56
|
-
[exports.FUTURES_CONTRACTS.
|
|
57
|
-
[exports.FUTURES_CONTRACTS.
|
|
58
|
-
[exports.FUTURES_CONTRACTS.
|
|
52
|
+
[exports.FUTURES_CONTRACTS.BRENT]: "ice-brent", // BZ
|
|
53
|
+
[exports.FUTURES_CONTRACTS.WTI]: "ice-wti", // CL
|
|
54
|
+
[exports.FUTURES_CONTRACTS.GASOIL]: "ice-gasoil", // G
|
|
55
|
+
QS: "ice-gasoil", // ICE Gasoil also trades under the QS ticker prefix
|
|
56
|
+
[exports.FUTURES_CONTRACTS.NATURAL_GAS]: "natural-gas", // NG
|
|
57
|
+
[exports.FUTURES_CONTRACTS.TTF_GAS]: "ttf-gas", // TTF
|
|
58
|
+
[exports.FUTURES_CONTRACTS.LNG_JKM]: "lng-jkm", // JKM
|
|
59
|
+
[exports.FUTURES_CONTRACTS.EUA_CARBON]: "eua-carbon", // EUA
|
|
60
|
+
[exports.FUTURES_CONTRACTS.UK_CARBON]: "uk-carbon", // UKA
|
|
59
61
|
};
|
|
62
|
+
/**
|
|
63
|
+
* Resolve a futures contract code (e.g. `"BZ"`, `"QS"`) or an already-valid
|
|
64
|
+
* family slug (e.g. `"ice-brent"`) to its `/v1/futures/{slug}` path segment.
|
|
65
|
+
*
|
|
66
|
+
* Matching is case-insensitive for codes. Returns `null` if the input maps to
|
|
67
|
+
* neither a known code nor a known family slug.
|
|
68
|
+
*/
|
|
69
|
+
function resolveFuturesFamilySlug(codeOrSlug) {
|
|
70
|
+
const trimmed = codeOrSlug.trim();
|
|
71
|
+
// Direct code match (case-insensitive — codes are upper-case).
|
|
72
|
+
const byCode = exports.FUTURES_FAMILY_SLUGS[trimmed.toUpperCase()];
|
|
73
|
+
if (byCode)
|
|
74
|
+
return byCode;
|
|
75
|
+
// Already a valid family slug?
|
|
76
|
+
const lower = trimmed.toLowerCase();
|
|
77
|
+
const isSlug = Object.values(exports.FUTURES_FAMILY_SLUGS).includes(lower);
|
|
78
|
+
return isSlug ? lower : null;
|
|
79
|
+
}
|
|
60
80
|
/**
|
|
61
81
|
* Typed helper for a single futures contract family (e.g., ICE Brent, Gasoil).
|
|
62
82
|
*
|
|
@@ -80,9 +100,12 @@ class FuturesContractFamily {
|
|
|
80
100
|
}
|
|
81
101
|
/**
|
|
82
102
|
* Get the latest price for this contract family.
|
|
103
|
+
*
|
|
104
|
+
* Latest is served from the bare slug path `GET /v1/futures/{slug}` —
|
|
105
|
+
* there is NO `/latest` suffix (that path 404s).
|
|
83
106
|
*/
|
|
84
107
|
async latest() {
|
|
85
|
-
return this.client["request"](`/v1/futures/${this.slug}
|
|
108
|
+
return this.client["request"](`/v1/futures/${this.slug}`, {});
|
|
86
109
|
}
|
|
87
110
|
/**
|
|
88
111
|
* Get historical prices for this contract family.
|
|
@@ -156,16 +179,13 @@ exports.FuturesContractFamily = FuturesContractFamily;
|
|
|
156
179
|
*
|
|
157
180
|
* const client = new OilPriceAPI({ apiKey: 'your_key' });
|
|
158
181
|
*
|
|
159
|
-
* // Get latest
|
|
160
|
-
* const latest = await client.futures.latest('CL
|
|
182
|
+
* // Get the latest curve by contract code (resolves to GET /v1/futures/ice-wti)
|
|
183
|
+
* const latest = await client.futures.latest('CL');
|
|
161
184
|
* console.log(`${latest.contract}: $${latest.price}`);
|
|
162
185
|
*
|
|
163
|
-
* //
|
|
164
|
-
* const
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
* // Get futures curve
|
|
168
|
-
* const curve = await client.futures.curve('CL');
|
|
186
|
+
* // Typed family helpers are the most ergonomic option:
|
|
187
|
+
* const brent = await client.futures.brent().latest();
|
|
188
|
+
* const curve = await client.futures.brent().curve();
|
|
169
189
|
* curve.curve.forEach(point => {
|
|
170
190
|
* console.log(`${point.months_out}mo: $${point.price}`);
|
|
171
191
|
* });
|
|
@@ -176,25 +196,42 @@ class FuturesResource {
|
|
|
176
196
|
this.client = client;
|
|
177
197
|
}
|
|
178
198
|
/**
|
|
179
|
-
* Get latest
|
|
199
|
+
* Get the latest curve/quote for a futures contract family.
|
|
180
200
|
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
201
|
+
* Accepts an ergonomic contract code (e.g. `"BZ"`, `"CL"`, `"QS"`) or a
|
|
202
|
+
* family slug (e.g. `"ice-brent"`). The code is resolved to its family slug
|
|
203
|
+
* and the request is sent to `GET /v1/futures/{slug}` — the bare slug path,
|
|
204
|
+
* with NO `/latest` suffix (the suffixed path 404s).
|
|
183
205
|
*
|
|
184
|
-
*
|
|
206
|
+
* Supported codes: BZ (Brent), CL (WTI), G/QS (Gasoil), NG (Natural Gas),
|
|
207
|
+
* TTF, JKM, EUA, UKA. Slugs: ice-brent, ice-wti, ice-gasoil, natural-gas,
|
|
208
|
+
* ttf-gas, lng-jkm, eua-carbon, uk-carbon.
|
|
209
|
+
*
|
|
210
|
+
* @param contract - Contract code (e.g. "BZ") or family slug (e.g. "ice-brent").
|
|
211
|
+
* @returns Latest futures price/curve data
|
|
212
|
+
*
|
|
213
|
+
* @throws {ValidationError} If the code/slug is empty or unrecognized.
|
|
185
214
|
* @throws {OilPriceAPIError} If API request fails
|
|
186
215
|
*
|
|
187
216
|
* @example
|
|
188
217
|
* ```typescript
|
|
189
|
-
*
|
|
190
|
-
*
|
|
218
|
+
* import { FUTURES_CONTRACTS } from 'oilpriceapi';
|
|
219
|
+
* const price = await client.futures.latest(FUTURES_CONTRACTS.BRENT); // "BZ"
|
|
220
|
+
* const wti = await client.futures.latest('ice-wti');
|
|
191
221
|
* ```
|
|
192
222
|
*/
|
|
193
223
|
async latest(contract) {
|
|
194
224
|
if (!contract || typeof contract !== "string") {
|
|
195
225
|
throw new errors_js_1.ValidationError("Contract symbol must be a non-empty string");
|
|
196
226
|
}
|
|
197
|
-
|
|
227
|
+
const slug = resolveFuturesFamilySlug(contract);
|
|
228
|
+
if (!slug) {
|
|
229
|
+
throw new errors_js_1.ValidationError(`Unknown futures contract "${contract}". Use a contract code ` +
|
|
230
|
+
`(BZ, CL, G, QS, NG, TTF, JKM, EUA, UKA) or a family slug ` +
|
|
231
|
+
`(ice-brent, ice-wti, ice-gasoil, natural-gas, ttf-gas, lng-jkm, ` +
|
|
232
|
+
`eua-carbon, uk-carbon).`);
|
|
233
|
+
}
|
|
234
|
+
return this.client["request"](`/v1/futures/${slug}`, {});
|
|
198
235
|
}
|
|
199
236
|
/**
|
|
200
237
|
* Get historical prices for a futures contract
|
package/dist/cjs/version.js
CHANGED
|
@@ -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
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED