UNPKG

12.1 kBMarkdownView Raw
1# alpaca
2
3![version](https://img.shields.io/github/package-json/v/117/alpaca?color=196DFF&style=flat-square)
4![code](https://img.shields.io/github/languages/code-size/117/alpaca?color=F1A42E&style=flat-square&label=size)
5![build](https://img.shields.io/github/workflow/status/117/alpaca/test?style=flat-square)
6![prettier](https://img.shields.io/static/v1?label=style&message=prettier&color=ff51bc&style=flat-square)
7
8A TypeScript Node.js library for the https://alpaca.markets REST API and
9WebSocket streams.
10
11## Contents
12
13- [Features](#features)
14- [Install](#install)
15- [Client](#client)
16- [Stream](#stream)
17- [Common Issues](#common-issues)
18- [Examples](#examples)
19- [Contributing](#contributing)
20
21## Features
22
23- [x] Fully typed.
24- [x] Fully asynchronous promise based API.
25- [x] Extensible `AlpacaClient` and `AlpacaStream` classes.
26- [x] Built-in rate limiting.
27- [x] Built-in number and date parsing.
28- [x] A 1:1 mapping of the official Alpaca [docs](https://docs.alpaca.markets/).
29- [x] Auto-transpiled modern ESM alternative.
30- [x] OAuth integration support.
31- [x] Minified and non-minified bundles.
32- [x] Various bundles provided:
33 - `alpaca.js` - ESM bundle (for node)
34 - `alpaca.bundle.js` - ESM bundle with dependencies (for node)
35 - `alpaca.browser.js` - UMD bundle (for browser)
36 - `alpaca.browser.modern.js` - ESM modern bundle (for browser)
37
38## Install
39
40From NPM:
41
42```cmd
43> npm i @master-chief/alpaca
44```
45
46From GitHub:
47
48- [CommonJS](./dist/cjs)
49- [Typescript](./src)
50- [ES](./dist/mjs)
51- [ES bundled ](./dist/alpaca.js)
52- [ES bundled with dependencies](./dist/alpaca.bundle.js)
53- [ES6 + UMD (classic)](./dist/alpaca.browser.js)
54- [ES6 + ESM (modern) ](./dist/alpaca.browser.modern.js)
55
56From these popular CDNs:
57
58- [UNPKG](https://unpkg.com/browse/@master-chief/alpaca/)
59- [JSDelivr](https://cdn.jsdelivr.net/npm/@master-chief/alpaca/)
60- [SkyPack](https://cdn.skypack.dev/@master-chief/alpaca)
61
62## Import
63
64Import with CommonJS:
65
66```typescript
67let { AlpacaClient, AlpacaStream } = require('@master-chief/alpaca');
68```
69
70Import with ESM:
71
72```typescript
73import { AlpacaClient, AlpacaStream } from '@master-chief/alpaca';
74```
75
76Import as script:
77
78```html
79<script src="https://unpkg.com/@master-chief/alpaca/dist/alpaca.browser.min.js"></script>
80```
81
82Import as module:
83
84```html
85<script type="module">
86 import alpaca from 'alpaca.browser.modern.min.js';
87</script>
88```
89
90## Client
91
92### Creating a new client
93
94If you wish to use env vars, populate these fields with `process.env` on your
95own. Paper account key detection is automatic. Using OAuth? Simply pass an
96`access_token` in the credentials object.
97
98```typescript
99const client = new AlpacaClient({
100 credentials: {
101 key: 'xxxxxx',
102 secret: 'xxxxxxxxxxxx',
103 // access_token: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
104 paper: true,
105 },
106 rate_limit: true,
107});
108```
109
110### Built-in parsing
111
112Alpaca provides numbers as strings. From
113[their docs](https://alpaca.markets/docs/api-documentation/api-v2/#numbers):
114
115> Decimal numbers are returned as strings to preserve full precision across
116> platforms. When making a request, it is recommended that you also convert your
117> numbers to strings to avoid truncation and precision errors.
118
119This package provides numbers as `number` instead, and date strings as `Date`
120objects which is what most developers want out of the box. If you want the
121original data, as it came from Alpaca, you can call `raw()` on any entity.
122
123```javascript
124const account = await client.getAccount();
125
126console.log(typeof account.buying_power); // number
127console.log(typeof account.raw().buying_power); // string
128```
129
130### Methods
131
132The following methods are available on the client.
133
134#### Account
135
136- [isAuthenticated](#isauthenticated)
137- [getAccount](#getaccount)
138- [getOrder](#getorder)
139- [getOrders](#getorders)
140- [placeOrder](#placeorder)
141- [replaceOrder](#replaceorder)
142- [cancelOrder](#cancelorder)
143- [cancelOrders](#cancelorders)
144- [getPosition](#getposition)
145- [getPositions](#getpositions)
146- [closePosition](#closePosition)
147- [closePositions](#closePositions)
148- [getAsset](#getasset)
149- [getAssets](#getassets)
150- [getWatchlist](#getwatchlist)
151- [getWatchlists](#getwatchlists)
152- [createWatchlist](#createwatchlist)
153- [updateWatchlist](#updatewatchlist)
154- [addToWatchlist](#addtowatchlist)
155- [removeFromWatchlist](#removefromwatchlist)
156- [deleteWatchlist](#deletewatchlist)
157- [getCalendar](#getcalendar)
158- [getClock](#getclock)
159- [getAccountConfigurations](#getAccountConfigurations)
160- [updateAccountConfigurations](#updateAccountConfigurations)
161- [getAccountActivities](#getAccountActivities)
162- [getPortfolioHistory](#getPortfolioHistory)
163
164#### Market Data v1
165
166- [getLastTrade_v1](#getLastTrade_v1)
167- [getLastQuote_v1](#getLastQuote_v1)
168- [getBars_v1](#getBars_v1)
169
170#### Market Data v2
171
172- [getTrades](#getTrades)
173- [getLatestTrade](#getLatestTrade)
174- [getQuotes](#getQuotes)
175- [getBars](#getBars)
176- [getSnapshot](#getSnapshot)
177- [getSnapshots](#getSnapshots)
178- [getNews](#getNews)
179
180#### isAuthenticated
181
182```typescript
183await client.isAuthenticated();
184```
185
186#### getAccount
187
188```typescript
189await client.getAccount();
190```
191
192#### getOrder
193
194```typescript
195await client.getOrder({ order_id: '6187635d-04e5-485b-8a94-7ce398b2b81c' });
196```
197
198#### getOrders
199
200```typescript
201await client.getOrders({ limit: 25, status: 'all' });
202```
203
204#### placeOrder
205
206```typescript
207await client.placeOrder({
208 symbol: 'SPY',
209 qty: 1,
210 // or
211 // notional: 100,
212 side: 'buy',
213 type: 'market',
214 time_in_force: 'day',
215});
216```
217
218#### replaceOrder
219
220```typescript
221await client.replaceOrder({
222 order_id: '69a3db8b-cc63-44da-a26a-e3cca9490308',
223 limit_price: 9.74,
224});
225```
226
227#### cancelOrder
228
229```typescript
230await client.cancelOrder({ order_id: '69a3db8b-cc63-44da-a26a-e3cca9490308' });
231```
232
233#### cancelOrders
234
235```typescript
236await client.cancelOrders();
237```
238
239#### getPosition
240
241```typescript
242await client.getPosition({ symbol: 'SPY' });
243```
244
245#### getPositions
246
247```typescript
248await client.getPositions();
249```
250
251#### closePosition
252
253```typescript
254await client.closePosition({ symbol: 'SPY' });
255```
256
257#### closePositions
258
259```typescript
260await client.closePositions();
261```
262
263#### getAsset
264
265```typescript
266await client.getAsset({ asset_id_or_symbol: 'SPY' });
267```
268
269#### getAssets
270
271```typescript
272await client.getAssets({ status: 'active' });
273```
274
275#### getWatchlist
276
277```typescript
278await client.getWatchlist({ uuid: '2000e463-6f87-41c0-a8ba-3e40cbf67128' });
279```
280
281#### getWatchlists
282
283```typescript
284await client.getWatchlists();
285```
286
287#### createWatchlist
288
289```typescript
290await client.createWatchlist({
291 name: 'my watchlist',
292 symbols: ['SPY', 'DIA', 'EEM', 'XLF'],
293});
294```
295
296#### updateWatchlist
297
298```typescript
299await client.updateWatchlist({
300 uuid: '2000e463-6f87-41c0-a8ba-3e40cbf67128',
301 name: 'new watchlist name',
302 symbols: ['TSLA', 'AAPL'],
303});
304```
305
306#### addToWatchlist
307
308```typescript
309await client.addToWatchlist({
310 uuid: '2000e463-6f87-41c0-a8ba-3e40cbf67128',
311 symbol: 'F',
312});
313```
314
315#### removeFromWatchlist
316
317```typescript
318await client.removeFromWatchlist({
319 uuid: '2000e463-6f87-41c0-a8ba-3e40cbf67128',
320 symbol: 'F',
321});
322```
323
324#### deleteWatchlist
325
326```typescript
327await client.deleteWatchlist({ uuid: '2000e463-6f87-41c0-a8ba-3e40cbf67128' });
328```
329
330#### getCalendar
331
332```typescript
333await client.getCalendar({ start: new Date(), end: new Date() });
334```
335
336#### getClock
337
338```typescript
339await client.getClock();
340```
341
342#### getAccountConfigurations
343
344```typescript
345await client.getAccountConfigurations();
346```
347
348#### updateAccountConfigurations
349
350```typescript
351await client.updateAccountConfigurations({
352 no_shorting: true,
353 suspend_trade: true,
354});
355```
356
357#### getAccountActivities
358
359```typescript
360await client.getAccountActivities({ activity_type: 'FILL' });
361```
362
363#### getPortfolioHistory
364
365```typescript
366await client.getPortfolioHistory({ period: '1D', timeframe: '1Min' });
367```
368
369#### getLastTrade_v1
370
371```typescript
372await client.getLastTrade_v1({ symbol: 'SPY' });
373```
374
375#### getLastQuote_v1
376
377```typescript
378await client.getLastQuote_v1({ symbol: 'SPY' });
379```
380
381#### getBars_v1
382
383```typescript
384await client.getBars_v1({ symbols: ['SPY', 'DIA', 'XLF'], timeframe: '1Min' });
385```
386
387#### getLatestTrade
388
389```typescript
390await client.getLatestTrade({ symbol: 'SPY' });
391```
392
393#### getTrades
394
395##### Basic
396
397```typescript
398await client.getTrades({
399 symbol: 'SPY',
400 start: new Date('2021-02-26T14:30:00.007Z'),
401 end: new Date('2021-02-26T14:35:00.007Z'),
402});
403```
404
405##### Paginated
406
407```typescript
408let trades = []
409let page_token = ''
410
411// until the next token we receive is null
412while (page_token != null) {
413 let resp = await client.getTrades({ ..., page_token })
414 trades.push(...resp.trades)
415 page_token = resp.next_page_token
416}
417
418// wooh! we have collected trades from multiple pages
419console.log(trades.length)
420```
421
422#### getQuotes
423
424##### Basic
425
426```typescript
427await client.getQuotes({
428 symbol: 'SPY',
429 start: new Date('2021-02-26T14:30:00.007Z'),
430 end: new Date('2021-02-26T14:35:00.007Z'),
431});
432```
433
434##### Paginated
435
436```typescript
437let quotes = []
438let page_token = ''
439
440// until the next token we receive is null
441while (page_token != null) {
442 let resp = await client.getQuotes({ ..., page_token })
443 quotes.push(...resp.quotes)
444 page_token = resp.next_page_token
445}
446
447// wooh! we have collected quotes from multiple pages
448console.log(quotes.length)
449```
450
451#### getBars
452
453##### Basic
454
455```typescript
456await client.getBars({
457 symbol: 'SPY',
458 start: new Date('2021-02-26T14:30:00.007Z'),
459 end: new Date('2021-02-26T14:35:00.007Z'),
460 timeframe: '1Min',
461 // page_token: "MjAyMS0wMi0wNlQxMzowOTo0Mlo7MQ=="
462});
463```
464
465##### Paginated
466
467```typescript
468let bars = []
469let page_token = ''
470
471// until the next token we receive is null
472while (page_token != null) {
473 let resp = await client.getBars({ ..., page_token })
474 bars.push(...resp.bars)
475 page_token = resp.next_page_token
476}
477
478// wooh! we have collected bars from multiple pages
479console.log(bars.length)
480```
481
482#### getSnapshot
483
484```typescript
485await client.getSnapshot({ symbol: 'SPY' });
486```
487
488#### getSnapshots
489
490```typescript
491await client.getSnapshots({ symbols: ['SPY', 'DIA'] });
492```
493
494#### getNews
495
496```typescript
497await client.getNews({ symbols: ['SPY'] });
498```
499
500## Stream
501
502### Creating a new stream
503
504If you wish to use env vars, populate these fields with `process.env` on your
505own.
506
507```typescript
508import { AlpacaStream } from '@master-chief/alpaca';
509
510const stream = new AlpacaStream({
511 credentials: {
512 key: 'xxxxxx',
513 secret: 'xxxxxxxxxxxx',
514 paper: true,
515 },
516 type: 'market_data', // or "account"
517 source: 'iex', // or "sip" depending on your subscription
518});
519```
520
521### Methods
522
523The following methods are available on the stream.
524
525- [subscribe](#subscribe)
526- [unsubscribe](#unsubscribe)
527- [on](#on)
528- [getConnection](#getConnection)
529
530### Channels
531
532| Channel | Type |
533| :-------------- | :------------ |
534| `trade_updates` | `account` |
535| `trades` | `market_data` |
536| `quotes` | `market_data` |
537| `bars` | `market_data` |
538
539#### subscribe
540
541```typescript
542stream.once('authenticated', () =>
543 stream.subscribe('bars', ['SPY', 'AAPL', 'TSLA']),
544);
545```
546
547#### unsubscribe
548
549```typescript
550stream.unsubscribe('bars', ['SPY']);
551```
552
553#### on
554
555```typescript
556stream.on('message', (message) => console.log(message));
557stream.on('trade', (trade) => console.log(trade));
558stream.on('bar', (bar) => console.log(bar));
559stream.on('quote', (quote) => console.log(quote));
560stream.on('trade_updates', (update) => console.log(update));
561stream.on('error', (error) => console.warn(error));
562```
563
564#### getConnection
565
566```typescript
567stream.getConnection();
568```
569
570## Common Issues
571
572If you are having difficulty getting Jest to work with this library, add this to your configuration:
573
574```js
575moduleNameMapper: {
576 '@master-chief/alpaca': '<rootDir>/node_modules/@master-chief/alpaca/dist/cjs/index.cjs',
577},
578```
579
580Credit to [@calvintwr](https://github.com/calvintwr) and [@wailinkyaww](https://github.com/wailinkyaww) for finding this solution.
581
582## Examples
583
584Don't know where to start? Check out our community-made examples
585[here](./example).
586
587## Contributing
588
589Feel free to contribute and PR to your 💖's content.