@adaptic/utils 0.0.359

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 (72) hide show
  1. package/README.md +824 -0
  2. package/dist/index.cjs +13641 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.mjs +13614 -0
  5. package/dist/index.mjs.map +1 -0
  6. package/dist/test.js +7336 -0
  7. package/dist/test.js.map +1 -0
  8. package/dist/types/adaptic.d.ts +18 -0
  9. package/dist/types/adaptic.d.ts.map +1 -0
  10. package/dist/types/alpaca-functions.d.ts +233 -0
  11. package/dist/types/alpaca-functions.d.ts.map +1 -0
  12. package/dist/types/alpaca-market-data-api.d.ts +371 -0
  13. package/dist/types/alpaca-market-data-api.d.ts.map +1 -0
  14. package/dist/types/alpaca-trading-api.d.ts +315 -0
  15. package/dist/types/alpaca-trading-api.d.ts.map +1 -0
  16. package/dist/types/alphavantage.d.ts +44 -0
  17. package/dist/types/alphavantage.d.ts.map +1 -0
  18. package/dist/types/crypto.d.ts +46 -0
  19. package/dist/types/crypto.d.ts.map +1 -0
  20. package/dist/types/display-manager.d.ts +24 -0
  21. package/dist/types/display-manager.d.ts.map +1 -0
  22. package/dist/types/format-tools.d.ts +54 -0
  23. package/dist/types/format-tools.d.ts.map +1 -0
  24. package/dist/types/index.d.ts +415 -0
  25. package/dist/types/index.d.ts.map +1 -0
  26. package/dist/types/logging.d.ts +12 -0
  27. package/dist/types/logging.d.ts.map +1 -0
  28. package/dist/types/market-hours.d.ts +24 -0
  29. package/dist/types/market-hours.d.ts.map +1 -0
  30. package/dist/types/market-time.d.ts +184 -0
  31. package/dist/types/market-time.d.ts.map +1 -0
  32. package/dist/types/metrics-calcs.d.ts +6 -0
  33. package/dist/types/metrics-calcs.d.ts.map +1 -0
  34. package/dist/types/misc-utils.d.ts +49 -0
  35. package/dist/types/misc-utils.d.ts.map +1 -0
  36. package/dist/types/performance-metrics.d.ts +88 -0
  37. package/dist/types/performance-metrics.d.ts.map +1 -0
  38. package/dist/types/polygon-indices.d.ts +85 -0
  39. package/dist/types/polygon-indices.d.ts.map +1 -0
  40. package/dist/types/polygon.d.ts +126 -0
  41. package/dist/types/polygon.d.ts.map +1 -0
  42. package/dist/types/price-utils.d.ts +26 -0
  43. package/dist/types/price-utils.d.ts.map +1 -0
  44. package/dist/types/technical-analysis.d.ts +90 -0
  45. package/dist/types/technical-analysis.d.ts.map +1 -0
  46. package/dist/types/test.d.ts +2 -0
  47. package/dist/types/test.d.ts.map +1 -0
  48. package/dist/types/testing/options-ws.d.ts +2 -0
  49. package/dist/types/testing/options-ws.d.ts.map +1 -0
  50. package/dist/types/time-utils.d.ts +17 -0
  51. package/dist/types/time-utils.d.ts.map +1 -0
  52. package/dist/types/types/adaptic-types.d.ts +11 -0
  53. package/dist/types/types/adaptic-types.d.ts.map +1 -0
  54. package/dist/types/types/alpaca-types.d.ts +998 -0
  55. package/dist/types/types/alpaca-types.d.ts.map +1 -0
  56. package/dist/types/types/alphavantage-types.d.ts +66 -0
  57. package/dist/types/types/alphavantage-types.d.ts.map +1 -0
  58. package/dist/types/types/index.d.ts +21 -0
  59. package/dist/types/types/index.d.ts.map +1 -0
  60. package/dist/types/types/logging-types.d.ts +10 -0
  61. package/dist/types/types/logging-types.d.ts.map +1 -0
  62. package/dist/types/types/market-time-types.d.ts +59 -0
  63. package/dist/types/types/market-time-types.d.ts.map +1 -0
  64. package/dist/types/types/metrics-types.d.ts +33 -0
  65. package/dist/types/types/metrics-types.d.ts.map +1 -0
  66. package/dist/types/types/polygon-indices-types.d.ts +190 -0
  67. package/dist/types/types/polygon-indices-types.d.ts.map +1 -0
  68. package/dist/types/types/polygon-types.d.ts +204 -0
  69. package/dist/types/types/polygon-types.d.ts.map +1 -0
  70. package/dist/types/types/ta-types.d.ts +89 -0
  71. package/dist/types/types/ta-types.d.ts.map +1 -0
  72. package/package.json +55 -0
package/README.md ADDED
@@ -0,0 +1,824 @@
1
+ # Adaptic Utilities
2
+
3
+ Last updated: 20 Feb 2025
4
+
5
+ A comprehensive utility library for financial data processing, time manipulation, and formatting.
6
+
7
+ NPM repo: https://www.npmjs.com/package/@adaptic/utils
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ npm install @adaptic/utils
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ Import the functions from the library:
18
+
19
+ ```typescript
20
+ import { adaptic } from '@adaptic/utils';
21
+ ```
22
+
23
+ ## Environment Variables
24
+
25
+ - `POLYGON_API_KEY`
26
+ - `ALPHA_VANTAGE_API_KEY`
27
+ - `ALPACA_API_KEY` - Required for crypto data and news
28
+ - `ALPACA_API_SECRET` - Required for crypto data and news
29
+ - `GOOGLE_SHEETS_CLIENT_EMAIL` - Required for Google Sheets operations
30
+ - `GOOGLE_SHEETS_PRIVATE_KEY` - Required for Google Sheets operations (with newlines preserved)
31
+ - `BACKEND_HTTPS_URL`= for the backend functions
32
+ - `NODE_ENV`='production' for backend functions to work with a remote server
33
+
34
+ ## Alpaca Functions
35
+
36
+ ### `fetchAccountDetails(accountId: string): Promise<AccountDetails>`
37
+
38
+ Asynchronously retrieves detailed information about a specific Alpaca trading account.
39
+
40
+ **Parameters:**
41
+ - `accountId: string` - The Alpaca account ID
42
+
43
+ **Returns:**
44
+ - `Promise<AccountDetails>` - Comprehensive account details including:
45
+ ```typescript
46
+ {
47
+ id: string;
48
+ account_number: string;
49
+ status: 'ONBOARDING' | 'SUBMISSION_FAILED' | 'SUBMITTED' | 'ACCOUNT_UPDATED' | 'APPROVAL_PENDING' | 'ACTIVE' | 'REJECTED';
50
+ currency: string;
51
+ cash: string;
52
+ portfolio_value: string; // deprecated, equivalent to equity
53
+ equity: string;
54
+ buying_power: string;
55
+ initial_margin: string;
56
+ maintenance_margin: string;
57
+ daytrade_count: number;
58
+ daytrading_buying_power: string;
59
+ options_buying_power: string;
60
+ options_approved_level: 0 | 1 | 2 | 3;
61
+ // ... and more fields available
62
+ }
63
+ ```
64
+
65
+ **Example:**
66
+ ```typescript
67
+ const accountDetails = await adaptic.alpaca.fetchAccountDetails('your-account-id');
68
+ console.log(`Account equity: ${accountDetails.equity}`);
69
+ ```
70
+
71
+ ### `fetchPortfolioHistory({ params, accountId, client, alpacaAccount }: FetchPortfolioHistoryProps): Promise<PortfolioHistoryResponse>`
72
+
73
+ Asynchronously retrieves historical portfolio data including equity and profit/loss information from either the Adaptic backend or directly from an Alpaca account.
74
+
75
+ **Parameters:**
76
+ - `FetchPortfolioHistoryProps`:
77
+ ```typescript
78
+ {
79
+ params: PortfolioHistoryParams; // Portfolio history query parameters
80
+ accountId?: string; // The Alpaca account ID (required if alpacaAccount not provided)
81
+ client?: ApolloClientType<NormalizedCacheObject>; // Optional Apollo client for backend queries
82
+ alpacaAccount?: types.AlpacaAccount;// Optional Alpaca account object (if provided, accountId not required)
83
+ }
84
+ ```
85
+ - `PortfolioHistoryParams`:
86
+ ```typescript
87
+ {
88
+ period?: string; // e.g., '1D', '1W', '1M', '1A', 'YTD' (YTD will be converted to '1A')
89
+ timeframe?: '1Min' | '5Min' | '15Min' | '1H' | '1D';
90
+ intraday_reporting?: 'market_hours' | 'extended_hours' | 'continuous';
91
+ start?: string; // RFC3339 format (if specified with period, period will be ignored)
92
+ end?: string; // RFC3339 format
93
+ pnl_reset?: 'per_day' | 'no_reset';
94
+ }
95
+ ```
96
+
97
+ **Returns:**
98
+ - `Promise<PortfolioHistoryResponse>`:
99
+ ```typescript
100
+ {
101
+ timestamp: number[]; // UNIX epoch format
102
+ equity: number[];
103
+ profit_loss: number[];
104
+ profit_loss_pct: number[];
105
+ base_value: number;
106
+ base_value_asof?: string;
107
+ timeframe: string;
108
+ cashflow?: Record<string, number>;
109
+ }
110
+ ```
111
+
112
+ **Example:**
113
+ ```typescript
114
+ // Using accountId
115
+ const history = await adaptic.alpaca.fetchPortfolioHistory({
116
+ accountId: 'your-account-id',
117
+ params: {
118
+ period: '1M',
119
+ timeframe: '1D'
120
+ }
121
+ });
122
+
123
+ // Using direct Alpaca account object
124
+ const history = await adaptic.alpaca.fetchPortfolioHistory({
125
+ alpacaAccount: yourAlpacaAccount,
126
+ params: {
127
+ start: '2025-01-01T00:00:00Z',
128
+ end: '2025-01-31T00:00:00Z',
129
+ timeframe: '1D'
130
+ }
131
+ });
132
+ ```
133
+
134
+ ### `adaptic.position.fetchAll(auth: AlpacaAuth): Promise<Position[]>`
135
+
136
+ Asynchronously fetches all current open positions for an Alpaca trading account.
137
+
138
+ **Parameters:**
139
+ - `auth: AlpacaAuth` - Authentication details:
140
+ ```typescript
141
+ {
142
+ adapticAccountId?: string; // Either this
143
+ alpacaApiKey?: string; // Or these two
144
+ alpacaApiSecret?: string;
145
+ }
146
+ ```
147
+
148
+ **Returns:**
149
+ - `Promise<Position[]>` - Array of positions with the following type:
150
+ ```typescript
151
+ {
152
+ asset_id: string;
153
+ symbol: string;
154
+ exchange: string;
155
+ asset_class: string;
156
+ asset_marginable: boolean;
157
+ qty: string;
158
+ qty_available: string;
159
+ avg_entry_price: string;
160
+ side: 'long' | 'short';
161
+ market_value: string;
162
+ cost_basis: string;
163
+ unrealized_pl: string;
164
+ unrealized_plpc: string;
165
+ unrealized_intraday_pl: string;
166
+ unrealized_intraday_plpc: string;
167
+ current_price: string;
168
+ lastday_price: string;
169
+ change_today: string;
170
+ }
171
+ ```
172
+
173
+ **Example:**
174
+ ```typescript
175
+ // Using adapticAccountId
176
+ const positions = await adaptic.position.fetchAll({
177
+ adapticAccountId: 'your-account-id'
178
+ });
179
+
180
+ // Using direct API keys
181
+ const positions = await adaptic.position.fetchAll({
182
+ alpacaApiKey: 'your-api-key',
183
+ alpacaApiSecret: 'your-api-secret'
184
+ });
185
+ ```
186
+
187
+ ### `adaptic.position.fetch(symbolOrAssetId: string, auth: AlpacaAuth): Promise<Position>`
188
+
189
+ Asynchronously fetches a specific position for an Alpaca trading account.
190
+
191
+ **Parameters:**
192
+ - `symbolOrAssetId: string` - The symbol or asset ID to fetch the position for
193
+ - `auth: AlpacaAuth` - Authentication details (same as above)
194
+
195
+ **Returns:**
196
+ - `Promise<Position>` - Single position details with the same type as in `fetchAll`
197
+
198
+ **Example:**
199
+ ```typescript
200
+ const position = await adaptic.position.fetch('AAPL', {
201
+ adapticAccountId: 'your-account-id'
202
+ });
203
+ ```
204
+
205
+ ### `adaptic.position.close(symbolOrAssetId: string, auth: AlpacaAuth, params?: ClosePositionParams): Promise<Order>`
206
+
207
+ Closes a specific position in an Alpaca trading account.
208
+
209
+ **Parameters:**
210
+ - `symbolOrAssetId: string` - The symbol or asset ID of the position to close
211
+ - `auth: AlpacaAuth` - Authentication details (same as above)
212
+ - `params?: ClosePositionParams` - Optional closing parameters:
213
+ ```typescript
214
+ {
215
+ qty?: number; // Quantity of shares to close (up to 9 decimal places)
216
+ percentage?: number; // Percentage of position to close (0-100, up to 9 decimal places)
217
+ }
218
+ ```
219
+
220
+ **Returns:**
221
+ - `Promise<Order>` - The order created to close the position
222
+
223
+ **Example:**
224
+ ```typescript
225
+ // Close entire position
226
+ const order = await adaptic.position.close('AAPL', {
227
+ adapticAccountId: 'your-account-id'
228
+ });
229
+
230
+ // Close 50% of position
231
+ const order = await adaptic.position.close('AAPL', {
232
+ adapticAccountId: 'your-account-id'
233
+ }, {
234
+ percentage: 50
235
+ });
236
+ ```
237
+
238
+ ### `adaptic.position.closeAll(auth: AlpacaAuth, params?: CloseAllPositionsParams): Promise<Array<{ symbol: string; status: number; body?: Order }>>`
239
+
240
+ Closes all positions in an Alpaca trading account.
241
+
242
+ **Parameters:**
243
+ - `auth: AlpacaAuth` - Authentication details (same as above)
244
+ - `params?: CloseAllPositionsParams` - Optional parameters:
245
+ ```typescript
246
+ {
247
+ cancelOrders?: boolean; // If true, cancels all open orders before closing positions
248
+ }
249
+ ```
250
+
251
+ **Returns:**
252
+ - `Promise<Array<{ symbol: string; status: number; body?: Order }>>` - Status of each position closure attempt:
253
+ - `symbol: string` - The symbol of the position
254
+ - `status: number` - HTTP status code for the attempt
255
+ - `body?: Order` - The order created to close the position (if successful)
256
+
257
+ **Example:**
258
+ ```typescript
259
+ // Close all positions
260
+ const results = await adaptic.position.closeAll({
261
+ adapticAccountId: 'your-account-id'
262
+ });
263
+
264
+ // Close all positions and cancel pending orders
265
+ const results = await adaptic.position.closeAll({
266
+ adapticAccountId: 'your-account-id'
267
+ }, {
268
+ cancelOrders: true
269
+ });
270
+ ```
271
+
272
+ ### `createOrder(params: CreateOrderParams): Promise<Order>`
273
+
274
+ Creates a new order for trading.
275
+
276
+ **Parameters:**
277
+ - `params: CreateOrderParams`:
278
+ ```typescript
279
+ {
280
+ symbol: string;
281
+ qty?: string;
282
+ notional?: string;
283
+ side: 'buy' | 'sell';
284
+ type: 'market' | 'limit' | 'stop' | 'stop_limit' | 'trailing_stop';
285
+ time_in_force: 'day' | 'gtc' | 'opg' | 'cls' | 'ioc' | 'fok';
286
+ limit_price?: string;
287
+ stop_price?: string;
288
+ trail_price?: string;
289
+ trail_percent?: string;
290
+ extended_hours?: boolean;
291
+ client_order_id?: string;
292
+ order_class?: 'simple' | 'oco' | 'oto' | 'bracket';
293
+ take_profit?: {
294
+ limit_price: string;
295
+ stop_price?: string;
296
+ order_class?: OrderClass;
297
+ };
298
+ stop_loss?: {
299
+ stop_price: string;
300
+ limit_price?: string;
301
+ order_class?: OrderClass;
302
+ };
303
+ position_intent?: 'buy_to_open' | 'buy_to_close' | 'sell_to_open' | 'sell_to_close';
304
+ }
305
+ ```
306
+
307
+ **Returns:**
308
+ - `Promise<Order>` - Created order details with full order type information
309
+
310
+ ## Crypto Functions
311
+
312
+ ### `fetchBars(params: CryptoBarsParams): Promise<CryptoBarsResponse>`
313
+
314
+ Fetches historical bar data for crypto trading pairs.
315
+
316
+ **Parameters:**
317
+ - `params: CryptoBarsParams`:
318
+ ```typescript
319
+ {
320
+ symbols: CryptoPair[];
321
+ timeframe: CryptoTimeframe; // '1Min' | '5Min' | '15Min' | '1Hour' | '1Day' | '1Week' | '1Month'
322
+ start?: Date;
323
+ end?: Date;
324
+ limit?: number;
325
+ page_token?: string;
326
+ sort?: 'asc' | 'desc';
327
+ }
328
+ ```
329
+
330
+ **Returns:**
331
+ - `Promise<CryptoBarsResponse>`:
332
+ ```typescript
333
+ {
334
+ bars: {
335
+ [symbol: string]: CryptoBar[];
336
+ };
337
+ next_page_token?: string;
338
+ }
339
+ ```
340
+ where `CryptoBar` is:
341
+ ```typescript
342
+ {
343
+ t: number; // timestamp
344
+ o: number; // open
345
+ h: number; // high
346
+ l: number; // low
347
+ c: number; // close
348
+ v: number; // volume
349
+ }
350
+ ```
351
+
352
+ ## Market Data Functions
353
+
354
+ ### `fetchPolygonPrices(symbol: string, params: object): Promise<PolygonPriceData[]>`
355
+
356
+ Fetches historical price data from Polygon.io.
357
+
358
+ **Parameters:**
359
+ - `symbol: string` - The trading symbol
360
+ - `params: object` - Query parameters for the data fetch
361
+
362
+ **Returns:**
363
+ - `Promise<PolygonPriceData[]>`:
364
+ ```typescript
365
+ {
366
+ date: string;
367
+ timeStamp: number;
368
+ open: number;
369
+ high: number;
370
+ low: number;
371
+ close: number;
372
+ vol: number;
373
+ vwap: number;
374
+ }[]
375
+ ```
376
+
377
+ ## Performance Metrics
378
+
379
+ ### `calculateBeta(returns: number[], benchmarkReturns: number[]): CalculateBetaResult`
380
+
381
+ Calculates beta and related statistics for a portfolio against a benchmark.
382
+
383
+ **Parameters:**
384
+ - `returns: number[]` - Array of portfolio returns
385
+ - `benchmarkReturns: number[]` - Array of benchmark returns
386
+
387
+ **Returns:**
388
+ - `CalculateBetaResult`:
389
+ ```typescript
390
+ {
391
+ beta: number;
392
+ covariance: number;
393
+ variance: number;
394
+ averagePortfolioReturn: number;
395
+ averageBenchmarkReturn: number;
396
+ }
397
+ ```
398
+
399
+ ### `calculateMaxDrawdown(portfolioValues: number[]): number`
400
+
401
+ Calculates the maximum drawdown from peak for a series of portfolio values.
402
+
403
+ **Parameters:**
404
+ - `portfolioValues: number[]` - Array of portfolio values over time
405
+
406
+ **Returns:**
407
+ - `number` - Maximum drawdown as a decimal (e.g., 0.25 for 25% drawdown)
408
+
409
+ ### `calculateDailyReturns(portfolioValues: number[]): number[]`
410
+
411
+ Computes daily returns from a series of portfolio values.
412
+
413
+ **Parameters:**
414
+ - `portfolioValues: number[]` - Array of portfolio values
415
+
416
+ **Returns:**
417
+ - `number[]` - Array of daily returns as decimals
418
+
419
+ ## News Functions
420
+
421
+ ### `fetchNews(params: NewsParams): Promise<NewsResponse>`
422
+
423
+ Fetches financial news articles.
424
+
425
+ **Parameters:**
426
+ - `params: NewsParams`:
427
+ ```typescript
428
+ {
429
+ start?: Date | string;
430
+ end?: Date | string;
431
+ symbols?: string | string[];
432
+ limit?: number;
433
+ sort?: 'asc' | 'desc';
434
+ page_token?: string;
435
+ }
436
+ ```
437
+
438
+ **Returns:**
439
+ - `Promise<NewsResponse>`:
440
+ ```typescript
441
+ {
442
+ news: {
443
+ id: number;
444
+ author: string;
445
+ content: string;
446
+ created_at: string;
447
+ updated_at: string;
448
+ headline: string;
449
+ source: string;
450
+ summary: string;
451
+ url: string;
452
+ symbols: string[];
453
+ images: {
454
+ size: 'large' | 'small' | 'thumb';
455
+ url: string;
456
+ }[];
457
+ }[];
458
+ next_page_token?: string;
459
+ }
460
+ ```
461
+
462
+ ## Time Utilities
463
+
464
+ ### Market Time Types
465
+
466
+ The following types are used throughout the market time utilities:
467
+
468
+ ```typescript
469
+ type Period = "1D" | "3D" | "1W" | "1M" | "3M" | "6M" | "1Y" | "YTD";
470
+ type Timeframe = "1Min" | "5Min" | "15Min" | "1H" | "1D";
471
+ type IntradayReporting = 'market_hours' | 'extended_hours' | 'continuous';
472
+ type OutputFormat = 'iso' | 'unix-seconds' | 'unix-ms';
473
+
474
+ interface MarketTimeParams {
475
+ period?: Period;
476
+ start?: Date;
477
+ end?: Date;
478
+ timezone?: string;
479
+ intraday_reporting?: IntradayReporting;
480
+ outputFormat?: OutputFormat;
481
+ }
482
+
483
+ interface PeriodDates {
484
+ start: string | number;
485
+ end: string | number;
486
+ }
487
+
488
+ interface MarketOpenCloseOptions {
489
+ date?: Date;
490
+ }
491
+
492
+ interface MarketOpenCloseResult {
493
+ marketOpen: boolean;
494
+ open: Date | null;
495
+ close: Date | null;
496
+ openExt: Date | null;
497
+ closeExt: Date | null;
498
+ }
499
+ ```
500
+
501
+ ### `createMarketTimeUtil(timezone?: string, intraday_reporting?: IntradayReporting): MarketTimeUtil`
502
+
503
+ Creates a utility for market time-related operations.
504
+
505
+ **Parameters:**
506
+ - `timezone?: string` - Optional timezone (default: 'America/New_York')
507
+ - `intraday_reporting?: IntradayReporting` - Optional intraday reporting mode:
508
+ - `'market_hours'` - Regular market hours (9:30 AM - 4:00 PM ET)
509
+ - `'extended_hours'` - Extended market hours (4:00 AM - 8:00 PM ET)
510
+ - `'continuous'` - All day, 24/7
511
+
512
+ **Returns:**
513
+ - `MarketTimeUtil` - Market time utility object
514
+
515
+ ### `getMarketOpenClose(options?: MarketOpenCloseOptions): MarketOpenCloseResult`
516
+
517
+ Gets market open/close times for both regular and extended hours for a given date.
518
+
519
+ **Parameters:**
520
+ - `options?: MarketOpenCloseOptions` - Optional parameters:
521
+ - `date?: Date` - The date to check (default: current date)
522
+
523
+ **Returns:**
524
+ - `MarketOpenCloseResult`:
525
+ ```typescript
526
+ {
527
+ marketOpen: boolean; // Whether the market is open on this date
528
+ open: Date | null; // Regular market hours open time
529
+ close: Date | null; // Regular market hours close time
530
+ openExt: Date | null; // Extended hours open time
531
+ closeExt: Date | null; // Extended hours close time
532
+ }
533
+ ```
534
+
535
+ **Example:**
536
+ ```typescript
537
+ const { marketOpen, open, close, openExt, closeExt } = adaptic.time.getMarketOpenClose({
538
+ date: new Date('2024-12-24')
539
+ });
540
+ ```
541
+
542
+ ### `getMarketStatus(options?: { date?: Date }): MarketStatus`
543
+
544
+ Gets the current market status and detailed information about market periods.
545
+
546
+ **Parameters:**
547
+ - `options?: object` - Optional parameters:
548
+ - `date?: Date` - The date to check (default: current date)
549
+
550
+ **Returns:**
551
+ - `MarketStatus`:
552
+ ```typescript
553
+ {
554
+ time: Date; // Current time
555
+ timeString: string; // Formatted time string
556
+ status: "closed" | "extended hours" | "open"; // Current market status
557
+ nextStatus: "closed" | "extended hours" | "open"; // Next market status
558
+ marketPeriod: "preMarket" | "earlyMarket" | "regularMarket" | "afterMarket" | "closed"; // Detailed market period
559
+ nextStatusTime: Date; // Time when next status begins
560
+ nextStatusTimeDifference: number; // Milliseconds until next status
561
+ nextStatusTimeString: string; // Formatted next status time
562
+ }
563
+ ```
564
+
565
+ The `marketPeriod` field indicates the specific trading period:
566
+ - `preMarket`: 4:00 AM - 9:30 AM ET
567
+ - `earlyMarket`: 9:30 AM - 10:00 AM ET
568
+ - `regularMarket`: 10:00 AM - Market Close (typically 4:00 PM ET)
569
+ - `afterMarket`: Market Close - 8:00 PM ET
570
+ - `closed`: Outside of all trading hours
571
+
572
+ **Example:**
573
+ ```typescript
574
+ const status = adaptic.time.getMarketStatus();
575
+ console.log(`Current market period: ${status.marketPeriod}`);
576
+ ```
577
+
578
+ ### `toUnixTimestamp(date: Date): number`
579
+
580
+ Converts a date to Unix timestamp.
581
+
582
+ **Parameters:**
583
+ - `date: Date` - The date to convert
584
+
585
+ **Returns:**
586
+ - `number` - Unix timestamp
587
+
588
+ ### `getTimeAgo(date: Date): string`
589
+
590
+ Returns a human-readable time difference from now.
591
+
592
+ **Parameters:**
593
+ - `date: Date` - The date to calculate from
594
+
595
+ **Returns:**
596
+ - `string` - Human-readable time difference (e.g., '1 minute ago')
597
+
598
+ ### `normalizeDate(date: Date): string`
599
+
600
+ Standardizes a date to a consistent format.
601
+
602
+ **Parameters:**
603
+ - `date: Date` - The date to standardize
604
+
605
+ **Returns:**
606
+ - `string` - Standardized date string (e.g., '2024-11-09')
607
+
608
+ ### `getDateInNY(time: number | string | { year: number; month: number; day: number }): Date`
609
+
610
+ Returns the current date in New York timezone.
611
+
612
+ **Parameters:**
613
+ - `time: number | string | { year: number; month: number; day: number }` - The time or date to convert
614
+
615
+ **Returns:**
616
+ - `Date` - Date in New York timezone
617
+
618
+ ### `getStartAndEndTimestamps(params: MarketTimeParams = {}): PeriodDates`
619
+
620
+ Generates start and end timestamps for a given period.
621
+
622
+ **Parameters:**
623
+ - `params: MarketTimeParams` - Optional parameters for the period
624
+
625
+ **Returns:**
626
+ - `PeriodDates` - Start and end timestamps for the period
627
+
628
+ ### `getStartAndEndDates(params: MarketTimeParams = {}): { start: Date; end: Date }`
629
+
630
+ Gets the start and end dates for a given period.
631
+
632
+ **Parameters:**
633
+ - `params: MarketTimeParams` - Optional parameters for the period
634
+
635
+ **Returns:**
636
+ - `{ start: Date; end: Date }` - Start and end dates for the period
637
+
638
+ ### `getLastTradingDateYYYYMMDD(): string`
639
+
640
+ Gets the last trading date in YYYY-MM-DD format.
641
+
642
+ **Returns:**
643
+ - `string` - Last trading date in YYYY-MM-DD format
644
+
645
+ ### `getLastFullTradingDate(currentDate?: Date): { date: Date; YYYYMMDD: string }`
646
+
647
+ Gets the last full trading date, considering market hours and holidays.
648
+
649
+ **Parameters:**
650
+ - `currentDate?: Date` - Optional reference date (defaults to current date)
651
+
652
+ **Returns:**
653
+ - Object containing:
654
+ - `date: Date` - The last full trading date
655
+ - `YYYYMMDD: string` - The date formatted as YYYY-MM-DD
656
+
657
+ ### `getNextMarketDay({ referenceDate?: Date }): { date: Date; yyyymmdd: string; dateISOString: string }`
658
+
659
+ Gets the next market day from a reference date.
660
+
661
+ **Parameters:**
662
+ - `referenceDate?: Date` - Optional reference date (defaults to current date)
663
+
664
+ **Returns:**
665
+ - Object containing:
666
+ - `date: Date` - The next market day (start of day in NY time)
667
+ - `yyyymmdd: string` - The date formatted as YYYY-MM-DD
668
+ - `dateISOString: string` - Full ISO date string
669
+
670
+ **Example:**
671
+ ```typescript
672
+ const nextMarketDay = adaptic.time.getNextMarketDay();
673
+ console.log(`Next market day: ${nextMarketDay.yyyymmdd}`);
674
+
675
+ // With reference date
676
+ const nextMarketDay = adaptic.time.getNextMarketDay({ referenceDate: new Date('2025-01-01') });
677
+ ```
678
+
679
+ ### `currentTimeET(): Date`
680
+
681
+ Gets the current time in Eastern Time.
682
+
683
+ **Returns:**
684
+ - `Date` - Current time in Eastern Time
685
+
686
+ ## Formatting Utilities
687
+
688
+ ### `capitalize(string: string): string`
689
+
690
+ Capitalizes the first letter of a string.
691
+
692
+ **Parameters:**
693
+ - `string: string` - The string to capitalize
694
+
695
+ **Returns:**
696
+ - `string` - Capitalized string
697
+
698
+ ### `formatEnum(enumValue: any): string`
699
+
700
+ Formats an enum value for display.
701
+
702
+ **Parameters:**
703
+ - `enumValue: any` - The enum value to format
704
+
705
+ **Returns:**
706
+ - `string` - Formatted enum value
707
+
708
+ ### `formatCurrency(value: number): string`
709
+
710
+ Formats a number as currency.
711
+
712
+ **Parameters:**
713
+ - `value: number` - The number to format
714
+
715
+ **Returns:**
716
+ - `string` - Formatted currency string
717
+
718
+ ### `formatPercentage(value: number): string`
719
+
720
+ Formats a number as a percentage.
721
+
722
+ **Parameters:**
723
+ - `value: number` - The number to format
724
+
725
+ **Returns:**
726
+ - `string` - Formatted percentage string
727
+
728
+ ## Misc utilities
729
+
730
+ ### `logIfDebug(message: string, data?: unknown, type: LogType = 'info' | 'warn' | 'error' | 'debug' | 'trace'): void`
731
+
732
+ Debug logging utility that respects environment debug flags.
733
+
734
+ **Parameters:**
735
+ - `message: string` - The log message
736
+ - `data?: unknown` - Optional data to log
737
+ - `type: LogType` - Optional log type (default: 'info')
738
+
739
+ ### `fetchWithRetry(url: string, options: RequestInit): Promise<Response>`
740
+
741
+ Fetches data from a URL with retry logic.
742
+
743
+ **Parameters:**
744
+ - `url: string` - The URL to fetch
745
+ - `options: RequestInit` - Optional fetch options
746
+
747
+ **Returns:**
748
+ - `Promise<Response>` - Fetched response
749
+
750
+ ## Alpaca API Utilities
751
+
752
+ This module provides several utility functions to interact with the Alpaca API, including fetching account details, placing orders, and retrieving market news.
753
+
754
+ ### Fetching News Articles
755
+
756
+ The `fetchNews` function retrieves news articles for specified symbols from the Alpaca API. It supports pagination and accepts various optional parameters to customize the query.
757
+
758
+ #### Usage
759
+
760
+ ```typescript
761
+ import { fetchNews } from './alpaca';
762
+
763
+ // Example: Fetch news for a single symbol or multiple symbols (comma-separated)
764
+ const symbols = "AAPL,MSFT,GOOG"; // For multiple symbols, use a comma-separated string
765
+
766
+ (async () => {
767
+ try {
768
+ // Option 1: Pass Alpaca API credentials via the auth parameter
769
+ const newsData = await fetchNews(symbols, {
770
+ auth: {
771
+ alpacaApiKey: "YOUR_API_KEY",
772
+ alpacaApiSecret: "YOUR_API_SECRET",
773
+ },
774
+ start: new Date(Date.now() - 24 * 60 * 60 * 1000), // Default: last 24 hours
775
+ end: new Date(),
776
+ limit: 10,
777
+ sort: 'desc',
778
+ });
779
+ console.log(newsData.news);
780
+
781
+ // Option 2: Rely on environment variables ALPACA_API_KEY and ALPACA_API_SECRET
782
+ const newsDataEnv = await fetchNews(symbols, {
783
+ start: new Date(Date.now() - 24 * 60 * 60 * 1000),
784
+ end: new Date(),
785
+ limit: 10,
786
+ sort: 'desc',
787
+ });
788
+ console.log(newsDataEnv.news);
789
+
790
+ // Pagination
791
+ // fetchNews automatically fetches all pages if a next_page_token is provided by the API.
792
+ // The final returned result contains all aggregated news articles along with a `nextPageToken` (if any remain).
793
+
794
+ } catch (error) {
795
+ console.error(`Error fetching news: ${error}`);
796
+ }
797
+ })();
798
+ ```
799
+
800
+ #### Parameter Details
801
+
802
+ - **symbols**: A required string listing the symbols to fetch news for. For multiple symbols, separate them with commas (e.g., "AAPL,MSFT,GOOG").
803
+ - **params.auth**: (Optional) An object of type `AlpacaAuth` containing either:
804
+ - `alpacaApiKey` and `alpacaApiSecret` for direct authentication, or
805
+ - `adapticAccountId` to look up credentials from your backend via Adaptic.
806
+
807
+ If the `auth` parameter is not provided, the function will fallback to using the environment variables `ALPACA_API_KEY` and `ALPACA_API_SECRET`.
808
+
809
+ - **params.start** and **params.end**: Specify the date range (as a Date object or string) for the news articles. Defaults to the last 24 hours if not provided.
810
+ - **params.limit**: The maximum number of articles to return per page (default is 10).
811
+ - **params.sort**: The sort order for articles. Use `'asc'` for ascending order or `'desc'` for descending order (default is `'desc'`).
812
+ - **params.page_token**: A token for pagination. This is automatically handled by `fetchNews` if more results are available.
813
+
814
+ The function consolidates all pages of results and returns an object with a `news` array (of type `SimpleNews[]`) and an optional `nextPageToken`.
815
+
816
+ ## Contributing to the Repository
817
+
818
+ Contributions are welcome! Please submit a pull request or open an issue for any enhancements or bug fixes.
819
+
820
+ ## Author
821
+
822
+ This project is a product of [Lumic.ai](https://lumic.ai).
823
+
824
+ Thanks for reading this far! Why did the trader bring a ladder to the bar? Because they heard the drinks were on the house!