oilpriceapi 0.6.0 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/README.md +418 -123
  2. package/dist/cjs/client.js +490 -0
  3. package/dist/cjs/errors.js +80 -0
  4. package/dist/cjs/index.js +82 -0
  5. package/dist/cjs/package.json +1 -0
  6. package/dist/cjs/resources/alerts.js +387 -0
  7. package/dist/cjs/resources/analytics.js +226 -0
  8. package/dist/cjs/resources/bunker-fuels.js +196 -0
  9. package/dist/cjs/resources/commodities.js +115 -0
  10. package/dist/cjs/resources/data-quality.js +144 -0
  11. package/dist/cjs/resources/data-sources.js +297 -0
  12. package/dist/cjs/resources/diesel.js +119 -0
  13. package/dist/cjs/resources/drilling.js +269 -0
  14. package/dist/cjs/resources/ei/drilling-productivity.js +108 -0
  15. package/dist/cjs/resources/ei/forecasts.js +106 -0
  16. package/dist/cjs/resources/ei/frac-focus.js +155 -0
  17. package/dist/cjs/resources/ei/index.js +98 -0
  18. package/dist/cjs/resources/ei/oil-inventories.js +97 -0
  19. package/dist/cjs/resources/ei/opec-production.js +97 -0
  20. package/dist/cjs/resources/ei/rig-counts.js +93 -0
  21. package/dist/cjs/resources/ei/well-permits.js +124 -0
  22. package/dist/cjs/resources/forecasts.js +162 -0
  23. package/dist/cjs/resources/futures.js +233 -0
  24. package/dist/cjs/resources/rig-counts.js +161 -0
  25. package/dist/cjs/resources/storage.js +166 -0
  26. package/dist/cjs/resources/webhooks.js +294 -0
  27. package/dist/cjs/types.js +2 -0
  28. package/dist/cjs/version.js +24 -0
  29. package/dist/client.d.ts +116 -5
  30. package/dist/client.js +169 -47
  31. package/dist/errors.d.ts +6 -0
  32. package/dist/errors.js +25 -16
  33. package/dist/index.d.ts +45 -6
  34. package/dist/index.js +40 -3
  35. package/dist/resources/alerts.d.ts +52 -15
  36. package/dist/resources/alerts.js +121 -109
  37. package/dist/resources/analytics.d.ts +325 -0
  38. package/dist/resources/analytics.js +222 -0
  39. package/dist/resources/bunker-fuels.d.ts +270 -0
  40. package/dist/resources/bunker-fuels.js +192 -0
  41. package/dist/resources/commodities.d.ts +148 -0
  42. package/dist/resources/commodities.js +111 -0
  43. package/dist/resources/data-quality.d.ts +229 -0
  44. package/dist/resources/data-quality.js +140 -0
  45. package/dist/resources/data-sources.d.ts +365 -0
  46. package/dist/resources/data-sources.js +293 -0
  47. package/dist/resources/diesel.d.ts +1 -1
  48. package/dist/resources/diesel.js +9 -38
  49. package/dist/resources/drilling.d.ts +403 -0
  50. package/dist/resources/drilling.js +265 -0
  51. package/dist/resources/ei/drilling-productivity.d.ts +173 -0
  52. package/dist/resources/ei/drilling-productivity.js +104 -0
  53. package/dist/resources/ei/forecasts.d.ts +177 -0
  54. package/dist/resources/ei/forecasts.js +102 -0
  55. package/dist/resources/ei/frac-focus.d.ts +212 -0
  56. package/dist/resources/ei/frac-focus.js +151 -0
  57. package/dist/resources/ei/index.d.ts +140 -0
  58. package/dist/resources/ei/index.js +88 -0
  59. package/dist/resources/ei/oil-inventories.d.ts +155 -0
  60. package/dist/resources/ei/oil-inventories.js +93 -0
  61. package/dist/resources/ei/opec-production.d.ts +146 -0
  62. package/dist/resources/ei/opec-production.js +93 -0
  63. package/dist/resources/ei/rig-counts.d.ts +131 -0
  64. package/dist/resources/ei/rig-counts.js +89 -0
  65. package/dist/resources/ei/well-permits.d.ts +178 -0
  66. package/dist/resources/ei/well-permits.js +120 -0
  67. package/dist/resources/forecasts.d.ts +200 -0
  68. package/dist/resources/forecasts.js +158 -0
  69. package/dist/resources/futures.d.ts +322 -0
  70. package/dist/resources/futures.js +229 -0
  71. package/dist/resources/rig-counts.d.ts +221 -0
  72. package/dist/resources/rig-counts.js +157 -0
  73. package/dist/resources/storage.d.ts +182 -0
  74. package/dist/resources/storage.js +162 -0
  75. package/dist/resources/webhooks.d.ts +326 -0
  76. package/dist/resources/webhooks.js +290 -0
  77. package/dist/types.d.ts +79 -8
  78. package/dist/version.d.ts +1 -1
  79. package/dist/version.js +2 -2
  80. package/package.json +17 -8
@@ -0,0 +1,387 @@
1
+ "use strict";
2
+ /**
3
+ * Price Alerts Resource
4
+ *
5
+ * Manage price alert configurations for automated notifications.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.AlertsResource = void 0;
9
+ const errors_js_1 = require("../errors.js");
10
+ /**
11
+ * Price Alerts Resource
12
+ *
13
+ * Manage automated price alert configurations with webhook notifications.
14
+ *
15
+ * **Features:**
16
+ * - Create alerts with customizable conditions
17
+ * - Monitor commodity prices automatically
18
+ * - Webhook notifications when conditions are met
19
+ * - Cooldown periods to prevent spam
20
+ * - 100 alerts per user soft limit
21
+ *
22
+ * **Example:**
23
+ * ```typescript
24
+ * import { OilPriceAPI } from 'oilpriceapi';
25
+ *
26
+ * const client = new OilPriceAPI({ apiKey: 'your_key' });
27
+ *
28
+ * // Create a price alert
29
+ * const alert = await client.alerts.create({
30
+ * name: 'Brent High Price Alert',
31
+ * commodity_code: 'BRENT_CRUDE_USD',
32
+ * condition_operator: 'greater_than',
33
+ * condition_value: 85.00,
34
+ * webhook_url: 'https://your-app.com/webhooks/price-alert',
35
+ * enabled: true,
36
+ * cooldown_minutes: 60
37
+ * });
38
+ *
39
+ * console.log(`Alert created: ${alert.name} (ID: ${alert.id})`);
40
+ *
41
+ * // List all alerts
42
+ * const alerts = await client.alerts.list();
43
+ * console.log(`You have ${alerts.length} active alerts`);
44
+ *
45
+ * // Update an alert
46
+ * const updated = await client.alerts.update(alert.id, {
47
+ * condition_value: 90.00,
48
+ * enabled: false
49
+ * });
50
+ *
51
+ * // Delete an alert
52
+ * await client.alerts.delete(alert.id);
53
+ * ```
54
+ */
55
+ class AlertsResource {
56
+ constructor(client) {
57
+ this.client = client;
58
+ }
59
+ /**
60
+ * List all price alerts for the authenticated user
61
+ *
62
+ * Returns all configured price alerts, including disabled ones.
63
+ * Alerts are sorted by creation date (newest first).
64
+ *
65
+ * @returns Array of all price alerts
66
+ *
67
+ * @throws {OilPriceAPIError} If API request fails
68
+ * @throws {AuthenticationError} If API key is invalid
69
+ * @throws {RateLimitError} If rate limit exceeded
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * const alerts = await client.alerts.list();
74
+ *
75
+ * alerts.forEach(alert => {
76
+ * console.log(`${alert.name}: ${alert.commodity_code} ${alert.condition_operator} ${alert.condition_value}`);
77
+ * console.log(` Status: ${alert.enabled ? 'Active' : 'Disabled'}`);
78
+ * console.log(` Triggers: ${alert.trigger_count}`);
79
+ * });
80
+ * ```
81
+ */
82
+ async list() {
83
+ const response = await this.client["request"]("/v1/alerts", {});
84
+ // API returns array directly, but handle both formats for compatibility
85
+ return Array.isArray(response) ? response : response.alerts || [];
86
+ }
87
+ /**
88
+ * Get a specific price alert by ID
89
+ *
90
+ * @param id - The alert ID to retrieve
91
+ * @returns The price alert details
92
+ *
93
+ * @throws {OilPriceAPIError} If API request fails
94
+ * @throws {DataNotFoundError} If alert ID not found
95
+ * @throws {AuthenticationError} If API key is invalid
96
+ *
97
+ * @example
98
+ * ```typescript
99
+ * const alert = await client.alerts.get('550e8400-e29b-41d4-a716-446655440000');
100
+ * console.log(`Alert: ${alert.name}`);
101
+ * console.log(`Condition: ${alert.commodity_code} ${alert.condition_operator} ${alert.condition_value}`);
102
+ * console.log(`Last triggered: ${alert.last_triggered_at || 'Never'}`);
103
+ * ```
104
+ */
105
+ async get(id) {
106
+ if (!id || typeof id !== "string") {
107
+ throw new errors_js_1.ValidationError("Alert ID must be a non-empty string");
108
+ }
109
+ const response = await this.client["request"](`/v1/alerts/${id}`, {});
110
+ // API returns object directly, but handle both formats for compatibility
111
+ return "alert" in response ? response.alert : response;
112
+ }
113
+ /**
114
+ * Create a new price alert
115
+ *
116
+ * Creates a price alert that monitors a commodity and triggers when
117
+ * the price meets the specified condition. Optionally sends webhook
118
+ * notifications when triggered.
119
+ *
120
+ * **Validation:**
121
+ * - name: 1-100 characters
122
+ * - commodity_code: Must be a valid commodity code
123
+ * - condition_value: Must be > 0 and <= 1,000,000
124
+ * - cooldown_minutes: Must be 0-1440 (24 hours)
125
+ * - webhook_url: Must be valid HTTPS URL if provided
126
+ *
127
+ * **Soft Limit:** 100 alerts per user
128
+ *
129
+ * @param params - Alert configuration parameters
130
+ * @returns The created price alert
131
+ *
132
+ * @throws {ValidationError} If parameters are invalid
133
+ * @throws {OilPriceAPIError} If API request fails
134
+ * @throws {AuthenticationError} If API key is invalid
135
+ *
136
+ * @example
137
+ * ```typescript
138
+ * // Alert when Brent crude exceeds $85
139
+ * const alert = await client.alerts.create({
140
+ * name: 'Brent $85 Alert',
141
+ * commodity_code: 'BRENT_CRUDE_USD',
142
+ * condition_operator: 'greater_than',
143
+ * condition_value: 85.00,
144
+ * webhook_url: 'https://myapp.com/webhook',
145
+ * enabled: true,
146
+ * cooldown_minutes: 120 // 2 hours between triggers
147
+ * });
148
+ * ```
149
+ */
150
+ async create(params) {
151
+ // Validate required fields
152
+ if (!params.name || typeof params.name !== "string") {
153
+ throw new errors_js_1.ValidationError("Alert name is required and must be a string");
154
+ }
155
+ if (params.name.length < 1 || params.name.length > 100) {
156
+ throw new errors_js_1.ValidationError("Alert name must be 1-100 characters");
157
+ }
158
+ if (!params.commodity_code || typeof params.commodity_code !== "string") {
159
+ throw new errors_js_1.ValidationError("Commodity code is required and must be a string");
160
+ }
161
+ if (!params.condition_operator) {
162
+ throw new errors_js_1.ValidationError("Condition operator is required");
163
+ }
164
+ const validOperators = [
165
+ "greater_than",
166
+ "less_than",
167
+ "equals",
168
+ "greater_than_or_equal",
169
+ "less_than_or_equal",
170
+ ];
171
+ if (!validOperators.includes(params.condition_operator)) {
172
+ throw new errors_js_1.ValidationError(`Invalid operator. Must be one of: ${validOperators.join(", ")}`);
173
+ }
174
+ if (typeof params.condition_value !== "number") {
175
+ throw new errors_js_1.ValidationError("Condition value must be a number");
176
+ }
177
+ if (params.condition_value <= 0 || params.condition_value > 1000000) {
178
+ throw new errors_js_1.ValidationError("Condition value must be greater than 0 and less than or equal to 1,000,000");
179
+ }
180
+ // Validate optional fields
181
+ if (params.webhook_url !== undefined) {
182
+ if (typeof params.webhook_url !== "string") {
183
+ throw new errors_js_1.ValidationError("Webhook URL must be a string");
184
+ }
185
+ if (params.webhook_url && !params.webhook_url.startsWith("https://")) {
186
+ throw new errors_js_1.ValidationError("Webhook URL must use HTTPS protocol");
187
+ }
188
+ }
189
+ if (params.cooldown_minutes !== undefined) {
190
+ if (typeof params.cooldown_minutes !== "number") {
191
+ throw new errors_js_1.ValidationError("Cooldown minutes must be a number");
192
+ }
193
+ if (params.cooldown_minutes < 0 || params.cooldown_minutes > 1440) {
194
+ throw new errors_js_1.ValidationError("Cooldown minutes must be between 0 and 1440 (24 hours)");
195
+ }
196
+ }
197
+ const response = await this.client["request"]("/v1/alerts", {}, {
198
+ method: "POST",
199
+ body: {
200
+ price_alert: {
201
+ name: params.name,
202
+ commodity_code: params.commodity_code,
203
+ condition_operator: params.condition_operator,
204
+ condition_value: params.condition_value,
205
+ webhook_url: params.webhook_url,
206
+ enabled: params.enabled ?? true,
207
+ cooldown_minutes: params.cooldown_minutes ?? 60,
208
+ metadata: params.metadata,
209
+ },
210
+ },
211
+ });
212
+ return "alert" in response ? response.alert : response;
213
+ }
214
+ /**
215
+ * Update an existing price alert
216
+ *
217
+ * Updates one or more fields of an existing alert. Only provided
218
+ * fields will be updated; others remain unchanged.
219
+ *
220
+ * @param id - The alert ID to update
221
+ * @param params - Fields to update (partial update supported)
222
+ * @returns The updated price alert
223
+ *
224
+ * @throws {ValidationError} If parameters are invalid
225
+ * @throws {DataNotFoundError} If alert ID not found
226
+ * @throws {OilPriceAPIError} If API request fails
227
+ *
228
+ * @example
229
+ * ```typescript
230
+ * // Disable an alert
231
+ * await client.alerts.update(alertId, { enabled: false });
232
+ *
233
+ * // Change threshold and cooldown
234
+ * await client.alerts.update(alertId, {
235
+ * condition_value: 90.00,
236
+ * cooldown_minutes: 180
237
+ * });
238
+ *
239
+ * // Update webhook URL
240
+ * await client.alerts.update(alertId, {
241
+ * webhook_url: 'https://newapp.com/webhook'
242
+ * });
243
+ * ```
244
+ */
245
+ async update(id, params) {
246
+ if (!id || typeof id !== "string") {
247
+ throw new errors_js_1.ValidationError("Alert ID must be a non-empty string");
248
+ }
249
+ // Validate fields if provided
250
+ if (params.name !== undefined) {
251
+ if (typeof params.name !== "string" ||
252
+ params.name.length < 1 ||
253
+ params.name.length > 100) {
254
+ throw new errors_js_1.ValidationError("Alert name must be 1-100 characters");
255
+ }
256
+ }
257
+ if (params.condition_operator !== undefined) {
258
+ const validOperators = [
259
+ "greater_than",
260
+ "less_than",
261
+ "equals",
262
+ "greater_than_or_equal",
263
+ "less_than_or_equal",
264
+ ];
265
+ if (!validOperators.includes(params.condition_operator)) {
266
+ throw new errors_js_1.ValidationError(`Invalid operator. Must be one of: ${validOperators.join(", ")}`);
267
+ }
268
+ }
269
+ if (params.condition_value !== undefined) {
270
+ if (typeof params.condition_value !== "number") {
271
+ throw new errors_js_1.ValidationError("Condition value must be a number");
272
+ }
273
+ if (params.condition_value <= 0 || params.condition_value > 1000000) {
274
+ throw new errors_js_1.ValidationError("Condition value must be greater than 0 and less than or equal to 1,000,000");
275
+ }
276
+ }
277
+ if (params.webhook_url !== undefined && params.webhook_url !== null) {
278
+ if (typeof params.webhook_url !== "string" ||
279
+ !params.webhook_url.startsWith("https://")) {
280
+ throw new errors_js_1.ValidationError("Webhook URL must be a valid HTTPS URL");
281
+ }
282
+ }
283
+ if (params.cooldown_minutes !== undefined) {
284
+ if (typeof params.cooldown_minutes !== "number" ||
285
+ params.cooldown_minutes < 0 ||
286
+ params.cooldown_minutes > 1440) {
287
+ throw new errors_js_1.ValidationError("Cooldown minutes must be between 0 and 1440 (24 hours)");
288
+ }
289
+ }
290
+ const response = await this.client["request"](`/v1/alerts/${id}`, {}, {
291
+ method: "PATCH",
292
+ body: { price_alert: params },
293
+ });
294
+ return "alert" in response ? response.alert : response;
295
+ }
296
+ /**
297
+ * Delete a price alert
298
+ *
299
+ * Permanently deletes a price alert. This action cannot be undone.
300
+ *
301
+ * @param id - The alert ID to delete
302
+ *
303
+ * @throws {DataNotFoundError} If alert ID not found
304
+ * @throws {OilPriceAPIError} If API request fails
305
+ *
306
+ * @example
307
+ * ```typescript
308
+ * await client.alerts.delete(alertId);
309
+ * console.log('Alert deleted successfully');
310
+ * ```
311
+ */
312
+ async delete(id) {
313
+ if (!id || typeof id !== "string") {
314
+ throw new errors_js_1.ValidationError("Alert ID must be a non-empty string");
315
+ }
316
+ await this.client["request"](`/v1/alerts/${id}`, {}, { method: "DELETE" });
317
+ }
318
+ /**
319
+ * Test an alert
320
+ *
321
+ * Triggers a test run of the alert to verify it's working correctly.
322
+ * Does not affect the alert's cooldown or trigger count.
323
+ *
324
+ * @param alertId - The alert ID to test
325
+ * @returns Test results
326
+ *
327
+ * @throws {NotFoundError} If alert not found
328
+ * @throws {OilPriceAPIError} If API request fails
329
+ *
330
+ * @example
331
+ * ```typescript
332
+ * const result = await client.alerts.test(alertId);
333
+ * console.log(`Test ${result.success ? 'passed' : 'failed'}`);
334
+ * if (result.response_time_ms) {
335
+ * console.log(`Webhook response time: ${result.response_time_ms}ms`);
336
+ * }
337
+ * ```
338
+ */
339
+ async test(alertId) {
340
+ if (!alertId || typeof alertId !== "string") {
341
+ throw new errors_js_1.ValidationError("Alert ID must be a non-empty string");
342
+ }
343
+ return this.client["request"](`/v1/alerts/${alertId}/test`, {}, { method: "POST" });
344
+ }
345
+ /**
346
+ * Get available alert triggers
347
+ *
348
+ * Returns list of supported trigger conditions and event types.
349
+ *
350
+ * @returns Array of available triggers
351
+ *
352
+ * @throws {OilPriceAPIError} If API request fails
353
+ *
354
+ * @example
355
+ * ```typescript
356
+ * const triggers = await client.alerts.triggers();
357
+ * triggers.forEach(trigger => {
358
+ * console.log(`${trigger.name}: ${trigger.description}`);
359
+ * });
360
+ * ```
361
+ */
362
+ async triggers() {
363
+ const response = await this.client["request"]("/v1/alerts/triggers", {});
364
+ return Array.isArray(response) ? response : response.triggers;
365
+ }
366
+ /**
367
+ * Get alert analytics history
368
+ *
369
+ * Returns historical analytics data for alerts including trigger frequency,
370
+ * success rates, and response times.
371
+ *
372
+ * @returns Analytics history data
373
+ *
374
+ * @throws {OilPriceAPIError} If API request fails
375
+ *
376
+ * @example
377
+ * ```typescript
378
+ * const analytics = await client.alerts.analyticsHistory();
379
+ * console.log(`Total triggers: ${analytics.total_triggers}`);
380
+ * console.log(`Success rate: ${analytics.success_rate}%`);
381
+ * ```
382
+ */
383
+ async analyticsHistory() {
384
+ return this.client["request"]("/v1/alerts/analytics_history", {});
385
+ }
386
+ }
387
+ exports.AlertsResource = AlertsResource;
@@ -0,0 +1,226 @@
1
+ "use strict";
2
+ /**
3
+ * Analytics Resource
4
+ *
5
+ * Access advanced analytics including performance metrics, statistical analysis,
6
+ * correlations, trend detection, spreads, and forecasts.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.AnalyticsResource = void 0;
10
+ const errors_js_1 = require("../errors.js");
11
+ /**
12
+ * Analytics Resource
13
+ *
14
+ * Access advanced analytics including performance metrics, statistical analysis,
15
+ * correlations, trends, spreads, and forecasts.
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * import { OilPriceAPI } from 'oilpriceapi';
20
+ *
21
+ * const client = new OilPriceAPI({ apiKey: 'your_key' });
22
+ *
23
+ * // Get performance metrics
24
+ * const perf = await client.analytics.performance({ commodity: 'WTI_USD', days: 30 });
25
+ * console.log(`30-day return: ${perf.return_percent}%`);
26
+ * console.log(`Volatility: ${perf.volatility}`);
27
+ *
28
+ * // Analyze correlation
29
+ * const corr = await client.analytics.correlation('WTI_USD', 'BRENT_CRUDE_USD', 90);
30
+ * console.log(`Correlation: ${corr.correlation}`);
31
+ * ```
32
+ */
33
+ class AnalyticsResource {
34
+ constructor(client) {
35
+ this.client = client;
36
+ }
37
+ /**
38
+ * Get performance metrics for a commodity
39
+ *
40
+ * Returns key performance indicators including returns, volatility,
41
+ * and price range over a specified period.
42
+ *
43
+ * @param options - Analysis parameters
44
+ * @returns Performance metrics
45
+ *
46
+ * @throws {OilPriceAPIError} If API request fails
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * const metrics = await client.analytics.performance({
51
+ * commodity: 'WTI_USD',
52
+ * days: 30
53
+ * });
54
+ * console.log(`Return: ${metrics.return_percent}%`);
55
+ * console.log(`Volatility: ${metrics.volatility}`);
56
+ * console.log(`High: $${metrics.high}, Low: $${metrics.low}`);
57
+ * ```
58
+ */
59
+ async performance(options) {
60
+ const params = {};
61
+ if (options?.commodity)
62
+ params.commodity = options.commodity;
63
+ if (options?.days)
64
+ params.days = options.days.toString();
65
+ return this.client["request"]("/v1/analytics/performance", params);
66
+ }
67
+ /**
68
+ * Get statistical analysis for a commodity
69
+ *
70
+ * Returns comprehensive statistical metrics including mean, median,
71
+ * standard deviation, and distribution characteristics.
72
+ *
73
+ * @param commodity - Commodity code to analyze
74
+ * @param days - Number of days to analyze (default: 30)
75
+ * @returns Statistical analysis
76
+ *
77
+ * @throws {NotFoundError} If commodity not found
78
+ * @throws {OilPriceAPIError} If API request fails
79
+ *
80
+ * @example
81
+ * ```typescript
82
+ * const stats = await client.analytics.statistics('BRENT_CRUDE_USD', 90);
83
+ * console.log(`Mean: $${stats.mean}`);
84
+ * console.log(`Std Dev: ${stats.std_dev}`);
85
+ * console.log(`Range: $${stats.min} - $${stats.max}`);
86
+ * ```
87
+ */
88
+ async statistics(commodity, days) {
89
+ if (!commodity || typeof commodity !== "string") {
90
+ throw new errors_js_1.ValidationError("Commodity code must be a non-empty string");
91
+ }
92
+ const params = { commodity };
93
+ if (days)
94
+ params.days = days.toString();
95
+ return this.client["request"]("/v1/analytics/statistics", params);
96
+ }
97
+ /**
98
+ * Analyze correlation between two commodities
99
+ *
100
+ * Calculates the Pearson correlation coefficient to measure how closely
101
+ * two commodities move together.
102
+ *
103
+ * @param commodity1 - First commodity code
104
+ * @param commodity2 - Second commodity code
105
+ * @param days - Number of days to analyze (default: 30)
106
+ * @returns Correlation analysis
107
+ *
108
+ * @throws {NotFoundError} If either commodity not found
109
+ * @throws {OilPriceAPIError} If API request fails
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * const corr = await client.analytics.correlation('WTI_USD', 'BRENT_CRUDE_USD', 90);
114
+ * console.log(`Correlation: ${corr.correlation}`);
115
+ * console.log(`Strength: ${corr.strength}`);
116
+ * console.log(`R-squared: ${corr.r_squared}`);
117
+ * ```
118
+ */
119
+ async correlation(commodity1, commodity2, days) {
120
+ if (!commodity1 || typeof commodity1 !== "string") {
121
+ throw new errors_js_1.ValidationError("First commodity code must be a non-empty string");
122
+ }
123
+ if (!commodity2 || typeof commodity2 !== "string") {
124
+ throw new errors_js_1.ValidationError("Second commodity code must be a non-empty string");
125
+ }
126
+ const params = {
127
+ commodity1,
128
+ commodity2,
129
+ };
130
+ if (days)
131
+ params.days = days.toString();
132
+ return this.client["request"]("/v1/analytics/correlation", params);
133
+ }
134
+ /**
135
+ * Analyze price trend for a commodity
136
+ *
137
+ * Detects trend direction, strength, and key levels (support/resistance).
138
+ *
139
+ * @param commodity - Commodity code to analyze
140
+ * @param days - Number of days to analyze (default: 30)
141
+ * @returns Trend analysis
142
+ *
143
+ * @throws {NotFoundError} If commodity not found
144
+ * @throws {OilPriceAPIError} If API request fails
145
+ *
146
+ * @example
147
+ * ```typescript
148
+ * const trend = await client.analytics.trend('WTI_USD', 60);
149
+ * console.log(`Trend: ${trend.trend} (strength: ${trend.strength})`);
150
+ * console.log(`Support: $${trend.support}`);
151
+ * console.log(`Resistance: $${trend.resistance}`);
152
+ * ```
153
+ */
154
+ async trend(commodity, days) {
155
+ if (!commodity || typeof commodity !== "string") {
156
+ throw new errors_js_1.ValidationError("Commodity code must be a non-empty string");
157
+ }
158
+ const params = { commodity };
159
+ if (days)
160
+ params.days = days.toString();
161
+ return this.client["request"]("/v1/analytics/trend", params);
162
+ }
163
+ /**
164
+ * Analyze spread between two commodities
165
+ *
166
+ * Calculates current spread and compares to historical patterns.
167
+ *
168
+ * @param commodity1 - First commodity code
169
+ * @param commodity2 - Second commodity code
170
+ * @returns Spread analysis
171
+ *
172
+ * @throws {NotFoundError} If either commodity not found
173
+ * @throws {OilPriceAPIError} If API request fails
174
+ *
175
+ * @example
176
+ * ```typescript
177
+ * const spread = await client.analytics.spread('BRENT_CRUDE_USD', 'WTI_USD');
178
+ * console.log(`Current spread: $${spread.spread}`);
179
+ * console.log(`Average spread: $${spread.average_spread}`);
180
+ * console.log(`Z-score: ${spread.z_score}`);
181
+ * ```
182
+ */
183
+ async spread(commodity1, commodity2) {
184
+ if (!commodity1 || typeof commodity1 !== "string") {
185
+ throw new errors_js_1.ValidationError("First commodity code must be a non-empty string");
186
+ }
187
+ if (!commodity2 || typeof commodity2 !== "string") {
188
+ throw new errors_js_1.ValidationError("Second commodity code must be a non-empty string");
189
+ }
190
+ return this.client["request"]("/v1/analytics/spread", {
191
+ commodity1,
192
+ commodity2,
193
+ });
194
+ }
195
+ /**
196
+ * Get price forecast for a commodity
197
+ *
198
+ * Returns forecasted prices with confidence intervals.
199
+ *
200
+ * @param commodity - Commodity code to forecast
201
+ * @returns Price forecast
202
+ *
203
+ * @throws {NotFoundError} If commodity not found
204
+ * @throws {OilPriceAPIError} If API request fails
205
+ *
206
+ * @example
207
+ * ```typescript
208
+ * const forecast = await client.analytics.forecast('WTI_USD');
209
+ * console.log(`Forecast model: ${forecast.model}`);
210
+ * console.log(`Horizon: ${forecast.horizon_days} days`);
211
+ *
212
+ * forecast.forecast.forEach(point => {
213
+ * console.log(`${point.date}: $${point.price} (${point.lower_bound}-${point.upper_bound})`);
214
+ * });
215
+ * ```
216
+ */
217
+ async forecast(commodity) {
218
+ if (!commodity || typeof commodity !== "string") {
219
+ throw new errors_js_1.ValidationError("Commodity code must be a non-empty string");
220
+ }
221
+ return this.client["request"]("/v1/analytics/forecast", {
222
+ commodity,
223
+ });
224
+ }
225
+ }
226
+ exports.AnalyticsResource = AnalyticsResource;