@luisjpf/alpaca-sdk 0.2.0 → 0.2.7

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 ADDED
@@ -0,0 +1,337 @@
1
+ # Alpaca SDK for TypeScript
2
+
3
+ [![CI](https://github.com/luisjpf/alpaca-sdk-ts/actions/workflows/ci.yml/badge.svg)](https://github.com/luisjpf/alpaca-sdk-ts/actions/workflows/ci.yml)
4
+ [![npm version](https://img.shields.io/npm/v/@luisjpf/alpaca-sdk.svg)](https://www.npmjs.com/package/@luisjpf/alpaca-sdk)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.5-blue.svg)](https://www.typescriptlang.org/)
7
+ [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D18-green.svg)](https://nodejs.org/)
8
+
9
+ Modern, type-safe TypeScript SDK for Alpaca's Trading, Broker, and Market Data APIs.
10
+
11
+ ## Features
12
+
13
+ - **Type-safe**: Auto-generated types from OpenAPI specs
14
+ - **Universal**: Works in Node.js 18+, Deno, Bun, browsers, and edge runtimes
15
+ - **Minimal**: Native `fetch`, zero HTTP dependencies
16
+ - **Tree-shakeable**: Import only what you need
17
+ - **WebSocket Streaming**: Real-time market data and trade updates
18
+ - **Modern**: ESM-first with CommonJS compatibility
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ # Full SDK (recommended)
24
+ pnpm add @luisjpf/alpaca-sdk
25
+
26
+ # Or individual packages
27
+ pnpm add @luisjpf/trading
28
+ pnpm add @luisjpf/market-data
29
+ pnpm add @luisjpf/broker
30
+ pnpm add @luisjpf/streaming
31
+ ```
32
+
33
+ ## Quick Start
34
+
35
+ ```typescript
36
+ import { createAlpacaClient } from '@luisjpf/alpaca-sdk'
37
+
38
+ const alpaca = createAlpacaClient({
39
+ keyId: process.env.ALPACA_KEY_ID!,
40
+ secretKey: process.env.ALPACA_SECRET_KEY!,
41
+ paper: true, // Use paper trading
42
+ })
43
+
44
+ // Get account info
45
+ const account = await alpaca.trading.account.get()
46
+
47
+ // Place an order
48
+ const order = await alpaca.trading.orders.create({
49
+ symbol: 'AAPL',
50
+ qty: '10',
51
+ side: 'buy',
52
+ type: 'market',
53
+ time_in_force: 'day',
54
+ })
55
+
56
+ // Get market data
57
+ const bars = await alpaca.marketData.stocks.getSymbolBars('AAPL', {
58
+ start: '2024-01-01',
59
+ end: '2024-01-31',
60
+ timeframe: '1Day',
61
+ })
62
+ ```
63
+
64
+ ## Packages
65
+
66
+ | Package | Description |
67
+ | ---------------------- | ----------------------------------------------- |
68
+ | `@luisjpf/alpaca-sdk` | Complete SDK with all APIs |
69
+ | `@luisjpf/trading` | Trading API (orders, positions, account) |
70
+ | `@luisjpf/market-data` | Market Data API (stocks, crypto, options, news) |
71
+ | `@luisjpf/broker` | Broker API (sub-accounts, funding, KYC) |
72
+ | `@luisjpf/streaming` | WebSocket clients for real-time data |
73
+ | `@luisjpf/core` | Shared utilities (auth, errors, types) |
74
+
75
+ ## Configuration
76
+
77
+ ```typescript
78
+ import { createTradingClient } from '@luisjpf/trading'
79
+
80
+ const client = createTradingClient({
81
+ keyId: 'YOUR_API_KEY',
82
+ secretKey: 'YOUR_SECRET_KEY',
83
+ paper: true, // default: true
84
+ timeout: 30_000, // default: 30s
85
+ maxRetries: 2, // default: 2
86
+ baseUrl: 'custom-url', // optional override
87
+ })
88
+ ```
89
+
90
+ ## Error Handling
91
+
92
+ ### Automatic Retries
93
+
94
+ The SDK automatically retries failed requests for:
95
+
96
+ - **429 Rate Limit** - Uses `retry-after` header or exponential backoff
97
+ - **500+ Server Errors** - Uses exponential backoff with jitter
98
+
99
+ ```typescript
100
+ const client = createTradingClient({
101
+ keyId: 'YOUR_API_KEY',
102
+ secretKey: 'YOUR_SECRET_KEY',
103
+ maxRetries: 2, // default: 2 (set to 0 to disable)
104
+ timeout: 30_000, // default: 30s
105
+ })
106
+ ```
107
+
108
+ ### Error Classes
109
+
110
+ All errors extend `AlpacaError` and can be caught with `instanceof`:
111
+
112
+ ```typescript
113
+ import {
114
+ AlpacaError,
115
+ AuthenticationError,
116
+ RateLimitError,
117
+ InsufficientFundsError,
118
+ ForbiddenError,
119
+ NotFoundError,
120
+ ValidationError,
121
+ MarketClosedError,
122
+ ServerError,
123
+ } from '@luisjpf/core'
124
+
125
+ try {
126
+ await client.orders.create({ ... })
127
+ } catch (error) {
128
+ if (error instanceof RateLimitError) {
129
+ // Auto-retried, but still failed after maxRetries
130
+ console.log(`Rate limited. Retry after ${error.retryAfter}s`)
131
+ } else if (error instanceof InsufficientFundsError) {
132
+ console.log('Not enough buying power')
133
+ } else if (error instanceof AuthenticationError) {
134
+ console.log('Invalid API credentials')
135
+ } else if (error instanceof ValidationError) {
136
+ console.log('Invalid order parameters')
137
+ } else if (error instanceof MarketClosedError) {
138
+ console.log('Market is closed')
139
+ } else if (error instanceof NotFoundError) {
140
+ console.log('Resource not found')
141
+ } else if (error instanceof AlpacaError) {
142
+ // Base class for all Alpaca errors
143
+ console.log(`Error ${error.code}: ${error.message}`)
144
+ }
145
+ }
146
+ ```
147
+
148
+ ### Error Classes Reference
149
+
150
+ | Error Class | Status | Description |
151
+ | ------------------------ | ------ | ---------------------------------- |
152
+ | `AuthenticationError` | 401 | Invalid API credentials |
153
+ | `ForbiddenError` | 403 | Insufficient permissions |
154
+ | `InsufficientFundsError` | 403 | Not enough buying power |
155
+ | `MarketClosedError` | 403 | Market is currently closed |
156
+ | `NotFoundError` | 404 | Resource not found |
157
+ | `ValidationError` | 422 | Invalid request parameters |
158
+ | `RateLimitError` | 429 | Rate limit exceeded (auto-retried) |
159
+ | `ServerError` | 500+ | Server error (auto-retried) |
160
+
161
+ ### Error Properties
162
+
163
+ All errors include:
164
+
165
+ ```typescript
166
+ interface AlpacaError {
167
+ message: string // Human-readable error message
168
+ code: number // Alpaca error code
169
+ status: number // HTTP status code
170
+ requestId?: string // Request ID for support
171
+ }
172
+
173
+ // RateLimitError also includes:
174
+ interface RateLimitError extends AlpacaError {
175
+ retryAfter?: number // Seconds until retry (from retry-after header)
176
+ }
177
+ ```
178
+
179
+ ### Type Guards
180
+
181
+ For type-safe error handling without `instanceof`:
182
+
183
+ ```typescript
184
+ import {
185
+ isAuthenticationError,
186
+ isRateLimitError,
187
+ isInsufficientFundsError,
188
+ isValidationError,
189
+ isNotFoundError,
190
+ isMarketClosedError,
191
+ isServerError,
192
+ } from '@luisjpf/core'
193
+
194
+ try {
195
+ await client.orders.create({ ... })
196
+ } catch (error) {
197
+ if (error instanceof AlpacaError) {
198
+ const apiError = error.toApiError()
199
+
200
+ if (isRateLimitError(apiError)) {
201
+ console.log(`Retry after ${apiError.retryAfter}s`)
202
+ } else if (isInsufficientFundsError(apiError)) {
203
+ console.log('Not enough buying power')
204
+ }
205
+ }
206
+ }
207
+ ```
208
+
209
+ ## WebSocket Streaming
210
+
211
+ Real-time market data and trade updates via WebSocket.
212
+
213
+ ### Stock Data Streaming
214
+
215
+ ```typescript
216
+ import { createStockStream } from '@luisjpf/streaming'
217
+
218
+ const stream = createStockStream({
219
+ keyId: 'YOUR_API_KEY',
220
+ secretKey: 'YOUR_SECRET_KEY',
221
+ feed: 'iex', // 'iex' (free), 'sip' (paid), or 'delayed_sip'
222
+ })
223
+
224
+ // Register handlers
225
+ stream.onTrade((trade) => {
226
+ console.log(`Trade: ${trade.S} @ $${trade.p}`)
227
+ })
228
+
229
+ stream.onQuote((quote) => {
230
+ console.log(`Quote: ${quote.S} bid: $${quote.bp} ask: $${quote.ap}`)
231
+ })
232
+
233
+ stream.onBar((bar) => {
234
+ console.log(`Bar: ${bar.S} O:${bar.o} H:${bar.h} L:${bar.l} C:${bar.c}`)
235
+ })
236
+
237
+ stream.onConnect(() => console.log('Connected!'))
238
+ stream.onError((err) => console.error('Error:', err))
239
+
240
+ // Connect and subscribe
241
+ stream.connect()
242
+ stream.subscribeForTrades(['AAPL', 'MSFT', 'GOOGL'])
243
+ stream.subscribeForQuotes(['AAPL'])
244
+ stream.subscribeForBars(['AAPL'])
245
+ ```
246
+
247
+ ### Crypto Data Streaming
248
+
249
+ ```typescript
250
+ import { createCryptoStream } from '@luisjpf/streaming'
251
+
252
+ const stream = createCryptoStream({
253
+ keyId: 'YOUR_API_KEY',
254
+ secretKey: 'YOUR_SECRET_KEY',
255
+ location: 'us', // 'us' (Alpaca), 'us-1' (Kraken US), 'eu-1' (Kraken EU)
256
+ })
257
+
258
+ stream.onTrade((trade) => {
259
+ console.log(`Crypto Trade: ${trade.S} @ $${trade.p}`)
260
+ })
261
+
262
+ stream.connect()
263
+ stream.subscribeForTrades(['BTC/USD', 'ETH/USD'])
264
+ ```
265
+
266
+ ### Trade Updates Streaming
267
+
268
+ ```typescript
269
+ import { createTradeUpdatesStream } from '@luisjpf/streaming'
270
+
271
+ const stream = createTradeUpdatesStream({
272
+ keyId: 'YOUR_API_KEY',
273
+ secretKey: 'YOUR_SECRET_KEY',
274
+ paper: true, // true for paper trading, false for live
275
+ })
276
+
277
+ stream.onTradeUpdate((update) => {
278
+ console.log(`Order ${update.event}: ${JSON.stringify(update.order)}`)
279
+ })
280
+
281
+ stream.connect()
282
+ stream.subscribe()
283
+ ```
284
+
285
+ ### Stock Feed Types
286
+
287
+ | Feed | Description | Subscription |
288
+ | ------------- | ----------------------------- | ----------------- |
289
+ | `iex` | IEX Exchange data only | Free (Basic plan) |
290
+ | `sip` | Full consolidated market data | Algo Trader Plus |
291
+ | `delayed_sip` | 15-minute delayed SIP data | Free |
292
+
293
+ ### Crypto Locations
294
+
295
+ | Location | Exchange | Notes |
296
+ | -------- | --------- | ------------------------- |
297
+ | `us` | Alpaca | Default, recommended |
298
+ | `us-1` | Kraken US | Available in 23 US states |
299
+ | `eu-1` | Kraken EU | European markets |
300
+
301
+ ## Development
302
+
303
+ ```bash
304
+ # Install dependencies
305
+ pnpm install
306
+
307
+ # Generate types from OpenAPI specs
308
+ pnpm generate:types
309
+
310
+ # Build all packages
311
+ pnpm build
312
+
313
+ # Run tests
314
+ pnpm test
315
+
316
+ # Run tests with coverage
317
+ pnpm test:coverage
318
+
319
+ # Lint code
320
+ pnpm lint
321
+
322
+ # Type check
323
+ pnpm typecheck
324
+ ```
325
+
326
+ ## Requirements
327
+
328
+ - Node.js >= 18.0.0 (for native `fetch`)
329
+ - pnpm >= 9.0.0
330
+
331
+ ## Contributing
332
+
333
+ Contributions are welcome! Please feel free to submit a Pull Request.
334
+
335
+ ## License
336
+
337
+ MIT