@master-chief/alpaca
Advanced tools
Comparing version 1.4.1 to 2.0.0
@@ -1,2 +0,2 @@ | ||
export { Client } from './lib/client.js'; | ||
export { Stream } from './lib/stream.js'; | ||
export { AlpacaClient } from './lib/client.js'; | ||
export { AlpacaStream } from './lib/stream.js'; |
@@ -0,9 +1,11 @@ | ||
import qs from 'qs'; | ||
import fetch from 'node-fetch'; | ||
import qs from 'qs'; | ||
import urls from './urls.js'; | ||
import limiter from 'limiter'; | ||
import urls from './urls.js'; | ||
export class Client { | ||
import { Parser } from './parser.js'; | ||
export class AlpacaClient { | ||
constructor(options) { | ||
this.options = options; | ||
this.limiter = new limiter.RateLimiter(199, 'minute'); | ||
this.limiter = new limiter.RateLimiter(200, 'minute'); | ||
this.parser = new Parser(); | ||
} | ||
@@ -16,39 +18,39 @@ async isAuthenticated() { | ||
catch { | ||
throw new Error('not authenticated'); | ||
return false; | ||
} | ||
} | ||
getAccount() { | ||
return this.request('GET', urls.rest.account, 'account'); | ||
async getAccount() { | ||
return this.parser.parseAccount(await this.request('GET', urls.rest.account, 'account')); | ||
} | ||
getOrder(params) { | ||
return this.request('GET', urls.rest.account, `orders/${params.order_id || params.client_order_id}?${qs.stringify({ | ||
async getOrder(params) { | ||
return this.parser.parseOrder(await this.request('GET', urls.rest.account, `orders/${params.order_id || params.client_order_id}?${qs.stringify({ | ||
nested: params.nested, | ||
})}`); | ||
})}`)); | ||
} | ||
getOrders(params) { | ||
return this.request('GET', urls.rest.account, `orders?${qs.stringify(params)}`); | ||
async getOrders(params) { | ||
return this.parser.parseOrders(await this.request('GET', urls.rest.account, `orders?${qs.stringify(params)}`)); | ||
} | ||
placeOrder(params) { | ||
return this.request('POST', urls.rest.account, `orders`, params); | ||
async placeOrder(params) { | ||
return this.parser.parseOrder(await this.request('POST', urls.rest.account, `orders`, params)); | ||
} | ||
replaceOrder(params) { | ||
return this.request('PATCH', urls.rest.account, `orders/${params.order_id}`, params); | ||
async replaceOrder(params) { | ||
return this.parser.parseOrder(await this.request('PATCH', urls.rest.account, `orders/${params.order_id}`, params)); | ||
} | ||
cancelOrder(params) { | ||
return this.request('DELETE', urls.rest.account, `orders/${params.order_id}`); | ||
async cancelOrder(params) { | ||
return this.parser.parseOrder(await this.request('DELETE', urls.rest.account, `orders/${params.order_id}`)); | ||
} | ||
cancelOrders() { | ||
return this.request('DELETE', urls.rest.account, `orders`); | ||
async cancelOrders() { | ||
return this.parser.parseOrders(await this.request('DELETE', urls.rest.account, `orders`)); | ||
} | ||
getPosition(params) { | ||
return this.request('GET', urls.rest.account, `positions/${params.symbol}`); | ||
async getPosition(params) { | ||
return this.parser.parsePosition(await this.request('GET', urls.rest.account, `positions/${params.symbol}`)); | ||
} | ||
getPositions() { | ||
return this.request('GET', urls.rest.account, `positions`); | ||
async getPositions() { | ||
return this.parser.parsePositions(await this.request('GET', urls.rest.account, `positions`)); | ||
} | ||
closePosition(params) { | ||
return this.request('DELETE', urls.rest.account, `positions/${params.symbol}`); | ||
async closePosition(params) { | ||
return this.parser.parseOrder(await this.request('DELETE', urls.rest.account, `positions/${params.symbol}`)); | ||
} | ||
closePositions() { | ||
return this.request('DELETE', urls.rest.account, `positions`); | ||
async closePositions() { | ||
return this.parser.parseOrders(await this.request('DELETE', urls.rest.account, `positions`)); | ||
} | ||
@@ -85,4 +87,4 @@ getAsset(params) { | ||
} | ||
getClock() { | ||
return this.request('GET', urls.rest.account, `clock`); | ||
async getClock() { | ||
return this.parser.parseClock(await this.request('GET', urls.rest.account, `clock`)); | ||
} | ||
@@ -95,4 +97,4 @@ getAccountConfigurations() { | ||
} | ||
getAccountActivities(params) { | ||
return this.request('GET', urls.rest.account, `account/activities/${params.activity_type}?${qs.stringify(params)}`); | ||
async getAccountActivities(params) { | ||
return this.parser.parseActivities(await this.request('GET', urls.rest.account, `account/activities/${params.activity_type}?${qs.stringify(params)}`)); | ||
} | ||
@@ -129,3 +131,2 @@ getPortfolioHistory(params) { | ||
return new Promise(async (resolve, reject) => { | ||
// do rate limiting | ||
if (this.options.rate_limit) { | ||
@@ -140,7 +141,6 @@ await new Promise((resolve) => this.limiter.removeTokens(1, resolve)); | ||
}, | ||
body: data ? JSON.stringify(data) : undefined, | ||
body: JSON.stringify(data), | ||
}) | ||
.then( | ||
// if json parse fails we default to an empty object | ||
async (response) => (await response.json().catch(() => false)) || {}) | ||
// if json parse fails we default to an empty object | ||
.then(async (resp) => (await resp.json().catch(() => false)) || {}) | ||
.then((json) => 'code' in json && 'message' in json ? reject(json) : resolve(json)) | ||
@@ -147,0 +147,0 @@ .catch(reject); |
import WebSocket from 'ws'; | ||
import urls from './urls.js'; | ||
import { EventEmitter } from 'events'; | ||
export class Stream extends EventEmitter { | ||
export class AlpacaStream extends EventEmitter { | ||
constructor(params) { | ||
@@ -6,0 +6,0 @@ // construct EventEmitter |
@@ -1,3 +0,3 @@ | ||
export { Client } from './lib/client.js' | ||
export { Stream } from './lib/stream.js' | ||
export { AlpacaClient } from './lib/client.js' | ||
export { AlpacaStream } from './lib/stream.js' | ||
@@ -4,0 +4,0 @@ export { |
@@ -0,7 +1,10 @@ | ||
import qs from 'qs' | ||
import fetch from 'node-fetch' | ||
import qs from 'qs' | ||
import urls from './urls.js' | ||
import limiter from 'limiter' | ||
import urls from './urls.js' | ||
import { Parser } from './parser.js' | ||
import { | ||
RawAccount, | ||
Account, | ||
@@ -15,4 +18,2 @@ Order, | ||
AccountConfigurations, | ||
NonTradeActivity, | ||
TradeActivity, | ||
PortfolioHistory, | ||
@@ -23,2 +24,6 @@ Bar, | ||
Credentials, | ||
RawOrder, | ||
RawPosition, | ||
RawActivity, | ||
Activity, | ||
} from './entities.js' | ||
@@ -51,4 +56,5 @@ | ||
export class Client { | ||
private limiter = new limiter.RateLimiter(199, 'minute') | ||
export class AlpacaClient { | ||
private limiter = new limiter.RateLimiter(200, 'minute') | ||
private parser = new Parser() | ||
@@ -68,71 +74,97 @@ constructor( | ||
} catch { | ||
throw new Error('not authenticated') | ||
return false | ||
} | ||
} | ||
getAccount(): Promise<Account> { | ||
return this.request('GET', urls.rest.account, 'account') | ||
async getAccount(): Promise<Account> { | ||
return this.parser.parseAccount( | ||
await this.request<RawAccount>('GET', urls.rest.account, 'account') | ||
) | ||
} | ||
getOrder(params: GetOrder): Promise<Order> { | ||
return this.request( | ||
'GET', | ||
urls.rest.account, | ||
`orders/${params.order_id || params.client_order_id}?${qs.stringify({ | ||
nested: params.nested, | ||
})}` | ||
async getOrder(params: GetOrder): Promise<Order> { | ||
return this.parser.parseOrder( | ||
await this.request<RawOrder>( | ||
'GET', | ||
urls.rest.account, | ||
`orders/${params.order_id || params.client_order_id}?${qs.stringify({ | ||
nested: params.nested, | ||
})}` | ||
) | ||
) | ||
} | ||
getOrders(params?: GetOrders): Promise<Order[]> { | ||
return this.request( | ||
'GET', | ||
urls.rest.account, | ||
`orders?${qs.stringify(params)}` | ||
async getOrders(params?: GetOrders): Promise<Order[]> { | ||
return this.parser.parseOrders( | ||
await this.request<RawOrder[]>( | ||
'GET', | ||
urls.rest.account, | ||
`orders?${qs.stringify(params)}` | ||
) | ||
) | ||
} | ||
placeOrder(params: PlaceOrder): Promise<Order> { | ||
return this.request('POST', urls.rest.account, `orders`, params) | ||
async placeOrder(params: PlaceOrder): Promise<Order> { | ||
return this.parser.parseOrder( | ||
await this.request<RawOrder>('POST', urls.rest.account, `orders`, params) | ||
) | ||
} | ||
replaceOrder(params: ReplaceOrder): Promise<Order> { | ||
return this.request( | ||
'PATCH', | ||
urls.rest.account, | ||
`orders/${params.order_id}`, | ||
params | ||
async replaceOrder(params: ReplaceOrder): Promise<Order> { | ||
return this.parser.parseOrder( | ||
await this.request<RawOrder>( | ||
'PATCH', | ||
urls.rest.account, | ||
`orders/${params.order_id}`, | ||
params | ||
) | ||
) | ||
} | ||
cancelOrder(params: CancelOrder): Promise<Order> { | ||
return this.request( | ||
'DELETE', | ||
urls.rest.account, | ||
`orders/${params.order_id}` | ||
async cancelOrder(params: CancelOrder): Promise<Order> { | ||
return this.parser.parseOrder( | ||
await this.request<RawOrder>( | ||
'DELETE', | ||
urls.rest.account, | ||
`orders/${params.order_id}` | ||
) | ||
) | ||
} | ||
cancelOrders(): Promise<Order[]> { | ||
return this.request('DELETE', urls.rest.account, `orders`) | ||
async cancelOrders(): Promise<Order[]> { | ||
return this.parser.parseOrders( | ||
await this.request<RawOrder[]>('DELETE', urls.rest.account, `orders`) | ||
) | ||
} | ||
getPosition(params: GetPosition): Promise<Position> { | ||
return this.request('GET', urls.rest.account, `positions/${params.symbol}`) | ||
async getPosition(params: GetPosition): Promise<Position> { | ||
return this.parser.parsePosition( | ||
await this.request<RawPosition>( | ||
'GET', | ||
urls.rest.account, | ||
`positions/${params.symbol}` | ||
) | ||
) | ||
} | ||
getPositions(): Promise<Position[]> { | ||
return this.request('GET', urls.rest.account, `positions`) | ||
async getPositions(): Promise<Position[]> { | ||
return this.parser.parsePositions( | ||
await this.request<RawPosition[]>('GET', urls.rest.account, `positions`) | ||
) | ||
} | ||
closePosition(params: ClosePosition): Promise<Order> { | ||
return this.request( | ||
'DELETE', | ||
urls.rest.account, | ||
`positions/${params.symbol}` | ||
async closePosition(params: ClosePosition): Promise<Order> { | ||
return this.parser.parseOrder( | ||
await this.request<RawOrder>( | ||
'DELETE', | ||
urls.rest.account, | ||
`positions/${params.symbol}` | ||
) | ||
) | ||
} | ||
closePositions(): Promise<Order[]> { | ||
return this.request('DELETE', urls.rest.account, `positions`) | ||
async closePositions(): Promise<Order[]> { | ||
return this.parser.parseOrders( | ||
await this.request<RawOrder[]>('DELETE', urls.rest.account, `positions`) | ||
) | ||
} | ||
@@ -210,4 +242,6 @@ | ||
getClock(): Promise<Clock> { | ||
return this.request('GET', urls.rest.account, `clock`) | ||
async getClock(): Promise<Clock> { | ||
return this.parser.parseClock( | ||
await this.request('GET', urls.rest.account, `clock`) | ||
) | ||
} | ||
@@ -230,9 +264,11 @@ | ||
getAccountActivities( | ||
async getAccountActivities( | ||
params: GetAccountActivities | ||
): Promise<Array<NonTradeActivity | TradeActivity>> { | ||
return this.request( | ||
'GET', | ||
urls.rest.account, | ||
`account/activities/${params.activity_type}?${qs.stringify(params)}` | ||
): Promise<Activity[]> { | ||
return this.parser.parseActivities( | ||
await this.request<RawActivity[]>( | ||
'GET', | ||
urls.rest.account, | ||
`account/activities/${params.activity_type}?${qs.stringify(params)}` | ||
) | ||
) | ||
@@ -279,8 +315,8 @@ } | ||
private request( | ||
private request<T = any>( | ||
method: string, | ||
url: string, | ||
endpoint: string, | ||
data?: any | ||
): Promise<any> { | ||
data?: { [key: string]: any } | ||
): Promise<T> { | ||
// modify the base url if paper is true | ||
@@ -300,8 +336,5 @@ if (this.options.paper && url == urls.rest.account) { | ||
return new Promise<any>(async (resolve, reject) => { | ||
// do rate limiting | ||
return new Promise<T>(async (resolve, reject) => { | ||
if (this.options.rate_limit) { | ||
await new Promise<void>((resolve) => | ||
this.limiter.removeTokens(1, resolve) | ||
) | ||
await new Promise((resolve) => this.limiter.removeTokens(1, resolve)) | ||
} | ||
@@ -315,8 +348,6 @@ | ||
}, | ||
body: data ? JSON.stringify(data) : undefined, | ||
body: JSON.stringify(data), | ||
}) | ||
.then( | ||
// if json parse fails we default to an empty object | ||
async (response) => (await response.json().catch(() => false)) || {} | ||
) | ||
// if json parse fails we default to an empty object | ||
.then(async (resp) => (await resp.json().catch(() => false)) || {}) | ||
.then((json) => | ||
@@ -323,0 +354,0 @@ 'code' in json && 'message' in json ? reject(json) : resolve(json) |
1182
lib/entities.ts
@@ -0,1 +1,5 @@ | ||
/** | ||
* Your Alpaca key id and secret. | ||
* Can be passed to the AlpacaClient and AlpacaStream. | ||
*/ | ||
export interface Credentials { | ||
@@ -6,3 +10,7 @@ key: string | ||
export interface Account { | ||
/** | ||
* The account information with unparsed types, exactly as Alpaca provides it. | ||
* We encourage you to use the Account interface, which has many of these fields parsed. | ||
*/ | ||
export interface RawAccount { | ||
account_blocked: boolean | ||
@@ -36,7 +44,213 @@ account_number: string | ||
/** | ||
* The following are the possible account status values. Most likely, the account status | ||
* is ACTIVE unless there is any problem. The account status may get in ACCOUNT_UPDATED | ||
* when personal information is being updated from the dashboard, in which case you may | ||
* not be allowed trading for a short period of time until the change is approved. | ||
*/ | ||
export type AccountStatus = | ||
/** | ||
* The account is onboarding. | ||
*/ | ||
| 'ONBOARDING' | ||
/** | ||
* The account application submission failed for some reason. | ||
*/ | ||
| 'SUBMISSION_FAILED' | ||
/** | ||
* The account application has been submitted for review. | ||
*/ | ||
| 'SUBMITTED' | ||
/** | ||
* The account information is being updated. | ||
*/ | ||
| 'ACCOUNT_UPDATED' | ||
/** | ||
* The final account approval is pending. | ||
*/ | ||
| 'APPROVAL_PENDING' | ||
/** | ||
* The account is active for trading. | ||
*/ | ||
| 'ACTIVE' | ||
/** | ||
* The account application has been rejected. | ||
*/ | ||
| 'REJECTED' | ||
/** | ||
* Information related to an Alpaca account, such as account status, funds, and various | ||
* flags relevant to an account's ability to trade. | ||
*/ | ||
export interface Account { | ||
/** | ||
* Get the raw data, exactly as it came from Alpaca | ||
*/ | ||
raw(): RawAccount | ||
/** | ||
* If true, the account activity by user is prohibited. | ||
*/ | ||
account_blocked: boolean | ||
/** | ||
* Account number. | ||
*/ | ||
account_number: string | ||
/** | ||
* Current available $ buying power; If multiplier = 4, this is your daytrade buying | ||
* power which is calculated as (last_equity - (last) maintenance_margin) * 4; If | ||
* multiplier = 2, buying_power = max(equity – initial_margin,0) * 2; If multiplier = 1, | ||
* buying_power = cash | ||
*/ | ||
buying_power: number | ||
/** | ||
* Cash balance | ||
*/ | ||
cash: number | ||
/** | ||
* Timestamp this account was created at | ||
*/ | ||
created_at: Date | ||
/** | ||
* "USD" | ||
*/ | ||
currency: string | ||
/** | ||
* The current number of daytrades that have been made in the last 5 trading days | ||
* (inclusive of today) | ||
*/ | ||
daytrade_count: number | ||
/** | ||
* Your buying power for day trades (continuously updated value) | ||
*/ | ||
daytrading_buying_power: number | ||
/** | ||
* Cash + long_market_value + short_market_value | ||
*/ | ||
equity: number | ||
/** | ||
* Account ID. | ||
*/ | ||
id: string | ||
/** | ||
* Reg T initial margin requirement (continuously updated value) | ||
*/ | ||
initial_margin: number | ||
/** | ||
* Equity as of previous trading day at 16:00:00 ET | ||
*/ | ||
last_equity: number | ||
/** | ||
* Your maintenance margin requirement on the previous trading day | ||
*/ | ||
last_maintenance_margin: number | ||
/** | ||
* Real-time MtM value of all long positions held in the account | ||
*/ | ||
long_market_value: number | ||
/** | ||
* Maintenance margin requirement (continuously updated value) | ||
*/ | ||
maintenance_margin: number | ||
/** | ||
* Buying power multiplier that represents account margin classification; valid values 1 | ||
* (standard limited margin account with 1x buying power), 2 (reg T margin account with | ||
* 2x intraday and overnight buying power; this is the default for all non-PDT accounts | ||
* with $2,000 or more equity), 4 (PDT account with 4x intraday buying power and 2x reg | ||
* T overnight buying power) | ||
*/ | ||
multiplier: number | ||
/** | ||
* Whether or not the account has been flagged as a pattern day trader | ||
*/ | ||
pattern_day_trader: boolean | ||
/** | ||
* Total value of cash + holding positions (This field is deprecated. It is equivalent | ||
* to the equity field.) | ||
*/ | ||
portfolio_value: number | ||
/** | ||
* Your buying power under Regulation T (your excess equity - equity minus margin | ||
* value - times your margin multiplier) | ||
*/ | ||
regt_buying_power: number | ||
/** | ||
* Real-time MtM value of all short positions held in the account | ||
*/ | ||
short_market_value: number | ||
/** | ||
* Flag to denote whether or not the account is permitted to short | ||
*/ | ||
shorting_enabled: boolean | ||
/** | ||
* Value of special memorandum account (will be used at a later date to provide | ||
* additional buying_power) | ||
*/ | ||
sma: number | ||
/** | ||
* The following are the possible account status values. Most likely, the account status | ||
* is ACTIVE unless there is any problem. The account status may get in ACCOUNT_UPDATED | ||
* when personal information is being updated from the dashboard, in which case you may | ||
* not be allowed trading for a short period of time until the change is approved. | ||
*/ | ||
status: AccountStatus | ||
/** | ||
* User setting. If true, the account is not allowed to place orders. | ||
*/ | ||
trade_suspended_by_user: boolean | ||
/** | ||
* If true, the account is not allowed to place orders. | ||
*/ | ||
trading_blocked: boolean | ||
/** | ||
* If true, the account is not allowed to request money transfers. | ||
*/ | ||
transfers_blocked: boolean | ||
} | ||
export interface AccountConfigurations { | ||
dtbp_check: string | ||
/** | ||
* both, entry, or exit. Controls Day Trading Margin Call (DTMC) checks. | ||
*/ | ||
dtbp_check: 'both' | 'entry' | 'exit' | ||
/** | ||
* If true, account becomes long-only mode. | ||
*/ | ||
no_shorting: boolean | ||
/** | ||
* If true, new orders are blocked. | ||
*/ | ||
suspend_trade: boolean | ||
trade_confirm_email: string | ||
/** | ||
* all or none. If none, emails for order fills are not sent. | ||
*/ | ||
trade_confirm_email: 'all' | 'none' | ||
} | ||
@@ -71,30 +285,122 @@ | ||
export type AssetExchange = | ||
| 'AMEX' | ||
| 'ARCA' | ||
| 'BATS' | ||
| 'NYSE' | ||
| 'NASDAQ' | ||
| 'NYSEARCA' | ||
export type AssetStatus = 'active' | 'inactive' | ||
/** | ||
* The assets API serves as the master list of assets available for trade and data | ||
* consumption from Alpaca. Assets are sorted by asset class, exchange and symbol. Some | ||
* assets are only available for data consumption via Polygon, and are not tradable with | ||
* Alpaca. These assets will be marked with the flag tradable=false. | ||
*/ | ||
export interface Asset { | ||
/** | ||
* Asset ID | ||
*/ | ||
id: string | ||
/** | ||
* "us_equity" | ||
*/ | ||
class: string | ||
exchange: string | ||
/** | ||
* AMEX, ARCA, BATS, NYSE, NASDAQ or NYSEARCA | ||
*/ | ||
exchange: AssetExchange | ||
/** | ||
* Asset symbol | ||
*/ | ||
symbol: string | ||
status: string | ||
/** | ||
* active or inactive | ||
*/ | ||
status: AssetStatus | ||
/** | ||
* Asset is tradable on Alpaca or not | ||
*/ | ||
tradable: boolean | ||
/** | ||
* Asset is marginable or not | ||
*/ | ||
marginable: boolean | ||
/** | ||
* Asset is shortable or not | ||
*/ | ||
shortable: boolean | ||
/** | ||
* Asset is easy-to-borrow or not (filtering for easy_to_borrow = True is the best way | ||
* to check whether the name is currently available to short at Alpaca). | ||
*/ | ||
easy_to_borrow: boolean | ||
} | ||
/** | ||
* Price and volume data during a particular time interval | ||
*/ | ||
export interface Bar { | ||
/** | ||
* the beginning time of this bar as a Unix epoch in seconds | ||
*/ | ||
t: number | ||
/** | ||
* open price | ||
*/ | ||
o: number | ||
/** | ||
* high price | ||
*/ | ||
h: number | ||
/** | ||
* low price | ||
*/ | ||
l: number | ||
/** | ||
* close price | ||
*/ | ||
c: number | ||
/** | ||
* volume | ||
*/ | ||
v: number | ||
} | ||
/** | ||
* Contains the time of open and close for a market on a particular day from 1970 to 2029 | ||
*/ | ||
export interface Calendar { | ||
/** | ||
* Date string in YYYY-MM-DD format | ||
*/ | ||
date: string | ||
/** | ||
* The time the market opens at on this date in HH:MM format | ||
*/ | ||
open: string | ||
/** | ||
* The time the market closes at on this date in HH:MM format | ||
*/ | ||
close: string | ||
} | ||
export interface Clock { | ||
export interface RawClock { | ||
timestamp: string | ||
@@ -106,2 +412,36 @@ is_open: boolean | ||
/** | ||
* The clock API serves the current market timestamp, whether or not the market is | ||
* currently open, as well as the times of the next market open and close. | ||
*/ | ||
export interface Clock { | ||
/** | ||
* Get the raw data, exactly as it came from Alpaca | ||
*/ | ||
raw(): RawClock | ||
/** | ||
* Current timestamp | ||
*/ | ||
timestamp: Date | ||
/** | ||
* Whether or not the market is open | ||
*/ | ||
is_open: boolean | ||
/** | ||
* Next market open timestamp | ||
*/ | ||
next_open: Date | ||
/** | ||
* Next market close timestamp | ||
*/ | ||
next_close: Date | ||
} | ||
/** | ||
* Last quote details for a symbol | ||
*/ | ||
export interface LastQuote { | ||
@@ -111,8 +451,35 @@ status: string | ||
last: { | ||
/** | ||
* the current ask price | ||
*/ | ||
askprice: number | ||
/** | ||
* the current ask size | ||
*/ | ||
asksize: number | ||
/** | ||
* the exchange code of the ask quote | ||
*/ | ||
askexchange: number | ||
/** | ||
* the current bid price | ||
*/ | ||
bidprice: number | ||
/** | ||
* the current bid size | ||
*/ | ||
bidsize: number | ||
/** | ||
* the exchange code of the bid quote | ||
*/ | ||
bidexchange: number | ||
/** | ||
* epoch timestamp in nanoseconds | ||
*/ | ||
timestamp: number | ||
@@ -122,2 +489,5 @@ } | ||
/** | ||
* Last trade details for a symbol | ||
*/ | ||
export interface LastTrade { | ||
@@ -127,9 +497,40 @@ status: string | ||
last: { | ||
/** | ||
* last trade price | ||
*/ | ||
price: number | ||
/** | ||
* last trade volume size | ||
*/ | ||
size: number | ||
/** | ||
* exchange code where the last trade was made | ||
*/ | ||
exchange: number | ||
/** | ||
* condition flag 1 | ||
*/ | ||
cond1: number | ||
/** | ||
* condition flag 2 | ||
*/ | ||
cond2: number | ||
/** | ||
* condition flag 3 | ||
*/ | ||
cond3: number | ||
/** | ||
* condition flag 4 | ||
*/ | ||
cond4: number | ||
/** | ||
* epoch timestamp in nanoseconds | ||
*/ | ||
timestamp: number | ||
@@ -139,3 +540,7 @@ } | ||
export interface Order { | ||
/** | ||
* The order entity with unparsed fields, exactly as Alpaca provides it. | ||
* We encourage you to use the Order interface, which has many of these fields parsed. | ||
*/ | ||
export interface RawOrder { | ||
id: string | ||
@@ -152,3 +557,3 @@ client_order_id: string | ||
replaced_by: string | ||
replaces: any | ||
replaces: string | ||
asset_id: string | ||
@@ -167,15 +572,363 @@ symbol: string | ||
extended_hours: boolean | ||
legs: any | ||
legs: RawOrder[] | ||
trail_price: string | ||
trail_percent: string | ||
hwm: string | ||
} | ||
export type OrderType = | ||
| 'market' | ||
| 'limit' | ||
| 'stop' | ||
| 'stop_limit' | ||
| 'trailing_stop' | ||
export type OrderSide = 'buy' | 'sell' | ||
export type OrderTimeInForce = | ||
/** | ||
* A day order is eligible for execution only on the day it is live. By default, the | ||
* order is only valid during Regular Trading Hours (9:30am - 4:00pm ET). If unfilled | ||
* after the closing auction, it is automatically canceled. If submitted after the | ||
* close, it is queued and submitted the following trading day. However, if marked as | ||
* eligible for extended hours, the order can also execute during supported extended | ||
* hours. | ||
*/ | ||
| 'day' | ||
/** | ||
* The order is good until canceled. Non-marketable GTC limit orders are subject to | ||
* price adjustments to offset corporate actions affecting the issue. We do not | ||
* currently support Do Not Reduce(DNR) orders to opt out of such price adjustments. | ||
*/ | ||
| 'gtc' | ||
/** | ||
* Use this TIF with a market/limit order type to submit "market on open" (MOO) and | ||
* "limit on open" (LOO) orders. This order is eligible to execute only in the market | ||
* opening auction. Any unfilled orders after the open will be cancelled. OPG orders | ||
* submitted after 9:28am but before 7:00pm ET will be rejected. OPG orders submitted | ||
* after 7:00pm will be queued and routed to the following day's opening auction. On | ||
* open/on close orders are routed to the primary exchange. Such orders do not | ||
* necessarily execute exactly at 9:30am / 4:00pm ET but execute per the exchange's | ||
* auction rules. | ||
*/ | ||
| 'opg' | ||
/** | ||
* Use this TIF with a market/limit order type to submit "market on close" (MOC) and | ||
* "limit on close" (LOC) orders. This order is eligible to execute only in the market | ||
* closing auction. Any unfilled orders after the close will be cancelled. CLS orders | ||
* submitted after 3:50pm but before 7:00pm ET will be rejected. CLS orders submitted | ||
* after 7:00pm will be queued and routed to the following day's closing auction. Only | ||
* available with API v2. | ||
*/ | ||
| 'cls' | ||
/** | ||
* An Immediate Or Cancel (IOC) order requires all or part of the order to be executed | ||
* immediately. Any unfilled portion of the order is canceled. Only available with API | ||
* v2. | ||
*/ | ||
| 'ioc' | ||
/** | ||
* A Fill or Kill (FOK) order is only executed if the entire order quantity can be | ||
* filled, otherwise the order is canceled. Only available with API v2. | ||
*/ | ||
| 'fok' | ||
export type OrderStatus = | ||
/** | ||
* The order has been received by Alpaca, and routed to exchanges for execution. This | ||
* is the usual initial state of an order. | ||
*/ | ||
| 'new' | ||
/** | ||
* The order has been partially filled. | ||
*/ | ||
| 'partially_filled' | ||
/** | ||
* The order has been filled, and no further updates will occur for the order. | ||
*/ | ||
| 'filled' | ||
/** | ||
* The order is done executing for the day, and will not receive further updates until | ||
* the next trading day. | ||
*/ | ||
| 'done_for_day' | ||
/** | ||
* The order has been canceled, and no further updates will occur for the order. This | ||
* can be either due to a cancel request by the user, or the order has been canceled by | ||
* the exchanges due to its time-in-force. | ||
*/ | ||
| 'canceled' | ||
/** | ||
* The order has expired, and no further updates will occur for the order. | ||
*/ | ||
| 'expired' | ||
/** | ||
* The order was replaced by another order, or was updated due to a market event such | ||
* as corporate action. | ||
*/ | ||
| 'replaced' | ||
/** | ||
* The order is waiting to be canceled. | ||
*/ | ||
| 'pending_cancel' | ||
/** | ||
* The order is waiting to be replaced by another order. The order will reject cancel | ||
* request while in this state. | ||
*/ | ||
| 'pending_replace' | ||
/** | ||
* (Uncommon) The order has been received by Alpaca, but hasn't yet been routed to the | ||
* execution venue. This could be seen often out side of trading session hours. | ||
*/ | ||
| 'accepted' | ||
/** | ||
* (Uncommon) The order has been received by Alpaca, and routed to the exchanges, but | ||
* has not yet been accepted for execution. This state only occurs on rare occasions. | ||
*/ | ||
| 'pending_new' | ||
/** | ||
* (Uncommon) The order has been received by exchanges, and is evaluated for pricing. | ||
* This state only occurs on rare occasions. | ||
*/ | ||
| 'accepted_for_bidding' | ||
/** | ||
* (Uncommon) The order has been stopped, and a trade is guaranteed for the order, | ||
* usually at a stated price or better, but has not yet occurred. This state only | ||
* occurs on rare occasions. | ||
*/ | ||
| 'stopped' | ||
/** | ||
* (Uncommon) The order has been rejected, and no further updates will occur for the | ||
* order. This state occurs on rare occasions and may occur based on various conditions | ||
* decided by the exchanges. | ||
*/ | ||
| 'rejected' | ||
/** | ||
* (Uncommon) The order has been suspended, and is not eligible for trading. This state | ||
* only occurs on rare occasions. | ||
*/ | ||
| 'suspended' | ||
/** | ||
* (Uncommon) The order has been completed for the day (either filled or done for day), | ||
* but remaining settlement calculations are still pending. This state only occurs on | ||
* rare occasions. | ||
*/ | ||
| 'calculated' | ||
/** | ||
* An Order in Alpaca | ||
*/ | ||
export interface Order { | ||
/** | ||
* Get the raw data, exactly as it came from Alpaca | ||
*/ | ||
raw(): RawOrder | ||
/** | ||
* Order id | ||
*/ | ||
id: string | ||
/** | ||
* Client unique order id | ||
*/ | ||
client_order_id: string | ||
/** | ||
* When the order was created | ||
*/ | ||
created_at: Date | ||
/** | ||
* When the order was last updated | ||
*/ | ||
updated_at: Date | ||
/** | ||
* When the order was submitted | ||
*/ | ||
submitted_at: Date | ||
/** | ||
* When the order was filled | ||
*/ | ||
filled_at: Date | ||
/** | ||
* When the order expired | ||
*/ | ||
expired_at: Date | ||
/** | ||
* When the order was canceled | ||
*/ | ||
canceled_at: Date | ||
/** | ||
* When the order failed | ||
*/ | ||
failed_at: Date | ||
/** | ||
* When the order was last replaced | ||
*/ | ||
replaced_at: Date | ||
/** | ||
* The order ID that this order was replaced by | ||
*/ | ||
replaced_by: string | ||
/** | ||
* The order ID that this order replaces | ||
*/ | ||
replaces: string | ||
/** | ||
* Asset ID | ||
*/ | ||
asset_id: string | ||
/** | ||
* Asset symbol | ||
*/ | ||
symbol: string | ||
/** | ||
* Asset class | ||
*/ | ||
asset_class: string | ||
/** | ||
* Ordered quantity | ||
*/ | ||
qty: number | ||
/** | ||
* Filled quantity | ||
*/ | ||
filled_qty: number | ||
/** | ||
* Order type (market, limit, stop, stop_limit, trailing_stop) | ||
*/ | ||
type: OrderType | ||
/** | ||
* Buy or sell | ||
*/ | ||
side: OrderSide | ||
/** | ||
* Order Time in Force | ||
*/ | ||
time_in_force: OrderTimeInForce | ||
/** | ||
* Limit price | ||
*/ | ||
limit_price: number | ||
/** | ||
* Stop price | ||
*/ | ||
stop_price: number | ||
/** | ||
* Filled average price | ||
*/ | ||
filled_avg_price: number | ||
/** | ||
* The status of the order | ||
*/ | ||
status: OrderStatus | ||
/** | ||
* If true, eligible for execution outside regular trading hours. | ||
*/ | ||
extended_hours: boolean | ||
/** | ||
* When querying non-simple order_class orders in a nested style, an array of Order | ||
* entities associated with this order. Otherwise, null. | ||
*/ | ||
legs: Order[] | ||
/** | ||
* The dollar value away from the high water mark for trailing stop orders. | ||
*/ | ||
trail_price: number | ||
/** | ||
* The percent value away from the high water mark for trailing stop orders. | ||
*/ | ||
trail_percent: number | ||
/** | ||
* The highest (lowest) market price seen since the trailing stop order was submitted. | ||
*/ | ||
hwm: number | ||
} | ||
/** | ||
* Timeseries data for equity and profit loss information of the account | ||
*/ | ||
export interface PortfolioHistory { | ||
/** | ||
* time of each data element, left-labeled (the beginning of time window) | ||
*/ | ||
timestamp: number[] | ||
/** | ||
* equity value of the account in dollar amount as of the end of each time window | ||
*/ | ||
equity: number[] | ||
/** | ||
* profit/loss in dollar from the base value | ||
*/ | ||
profit_loss: number[] | ||
/** | ||
* profit/loss in percentage from the base value | ||
*/ | ||
profit_loss_pct: number[] | ||
/** | ||
* basis in dollar of the profit loss calculation | ||
*/ | ||
base_value: number | ||
/** | ||
* time window size of each data element | ||
*/ | ||
timeframe: string | ||
} | ||
export interface Position { | ||
/** | ||
* A position with unparsed fields, exactly as Alpaca provides it. | ||
* We encourage you to use the Position interface, which has many of these fields parsed. | ||
*/ | ||
export interface RawPosition { | ||
asset_id: string | ||
@@ -199,2 +952,94 @@ symbol: string | ||
export type PositionSide = 'long' | 'short' | ||
/** | ||
* A position in Alpaca | ||
*/ | ||
export interface Position { | ||
/** | ||
* Get the raw data, exactly as it came from Alpaca | ||
*/ | ||
raw(): RawPosition | ||
/** | ||
* Asset ID | ||
*/ | ||
asset_id: string | ||
/** | ||
* Symbol name of the asset | ||
*/ | ||
symbol: string | ||
/** | ||
* Exchange name of the asset | ||
*/ | ||
exchange: string | ||
/** | ||
* Asset class name | ||
*/ | ||
asset_class: string | ||
/** | ||
* Average entry price of the position | ||
*/ | ||
avg_entry_price: number | ||
/** | ||
* The number of shares | ||
*/ | ||
qty: number | ||
/** | ||
* long or short | ||
*/ | ||
side: PositionSide | ||
/** | ||
* Total dollar amount of the position | ||
*/ | ||
market_value: number | ||
/** | ||
* Total cost basis in dollar | ||
*/ | ||
cost_basis: number | ||
/** | ||
* Unrealized profit/loss in dollars | ||
*/ | ||
unrealized_pl: number | ||
/** | ||
* Unrealized profit/loss percent (by a factor of 1) | ||
*/ | ||
unrealized_plpc: number | ||
/** | ||
* Unrealized profit/loss in dollars for the day | ||
*/ | ||
unrealized_intraday_pl: number | ||
/** | ||
* Unrealized profit/loss percent (by a factor of 1) | ||
*/ | ||
unrealized_intraday_plpc: number | ||
/** | ||
* Current asset price per share | ||
*/ | ||
current_price: number | ||
/** | ||
* Last day's asset price per share based on the closing value of the last trading day | ||
*/ | ||
lastday_price: number | ||
/** | ||
* Percent change from last day price (by a factor of 1) | ||
*/ | ||
change_today: number | ||
} | ||
export interface Quote { | ||
@@ -225,4 +1070,172 @@ ev: string | ||
export interface TradeActivity { | ||
activity_type: string | ||
export type ActivityType = | ||
/** | ||
* Order fills (both partial and full fills) | ||
*/ | ||
| 'FILL' | ||
/** | ||
* Cash transactions (both CSD and CSR) | ||
*/ | ||
| 'TRANS' | ||
/** | ||
* Miscellaneous or rarely used activity types (All types except those in TRANS, DIV, | ||
* or FILL) | ||
*/ | ||
| 'MISC' | ||
/** | ||
* ACATS IN/OUT (Cash) | ||
*/ | ||
| 'ACATC' | ||
/** | ||
* ACATS IN/OUT (Securities) | ||
*/ | ||
| 'ACATS' | ||
/** | ||
* Cash disbursement(+) | ||
*/ | ||
| 'CSD' | ||
/** | ||
* Cash receipt(-) | ||
*/ | ||
| 'CSR' | ||
/** | ||
* Dividends | ||
*/ | ||
| 'DIV' | ||
/** | ||
* Dividend (capital gain long term) | ||
*/ | ||
| 'DIVCGL' | ||
/** | ||
* Dividend (capital gain short term) | ||
*/ | ||
| 'DIVCGS' | ||
/** | ||
* Dividend fee | ||
*/ | ||
| 'DIVFEE' | ||
/** | ||
* Dividend adjusted (Foreign Tax Withheld) | ||
*/ | ||
| 'DIVFT' | ||
/** | ||
* Dividend adjusted (NRA Withheld) | ||
*/ | ||
| 'DIVNRA' | ||
/** | ||
* Dividend return of capital | ||
*/ | ||
| 'DIVROC' | ||
/** | ||
* Dividend adjusted (Tefra Withheld) | ||
*/ | ||
| 'DIVTW' | ||
/** | ||
* Dividend (tax exempt) | ||
*/ | ||
| 'DIVTXEX' | ||
/** | ||
* Interest (credit/margin) | ||
*/ | ||
| 'INT' | ||
/** | ||
* Interest adjusted (NRA Withheld) | ||
*/ | ||
| 'INTNRA' | ||
/** | ||
* Interest adjusted (Tefra Withheld) | ||
*/ | ||
| 'INTTW' | ||
/** | ||
* Journal entry | ||
*/ | ||
| 'JNL' | ||
/** | ||
* Journal entry (cash) | ||
*/ | ||
| 'JNLC' | ||
/** | ||
* Journal entry (stock) | ||
*/ | ||
| 'JNLS' | ||
/** | ||
* Merger/Acquisition | ||
*/ | ||
| 'MA' | ||
/** | ||
* Name change | ||
*/ | ||
| 'NC' | ||
/** | ||
* Option assignment | ||
*/ | ||
| 'OPASN' | ||
/** | ||
* Option expiration | ||
*/ | ||
| 'OPEXP' | ||
/** | ||
* Option exercise | ||
*/ | ||
| 'OPXRC' | ||
/** | ||
* Pass Thru Charge | ||
*/ | ||
| 'PTC' | ||
/** | ||
* Pass Thru Rebate | ||
*/ | ||
| 'PTR' | ||
/** | ||
* Reorg CA | ||
*/ | ||
| 'REORG' | ||
/** | ||
* Symbol change | ||
*/ | ||
| 'SC' | ||
/** | ||
* Stock spinoff | ||
*/ | ||
| 'SSO' | ||
/** | ||
* Stock split | ||
*/ | ||
| 'SSP' | ||
export interface RawTradeActivity { | ||
// Only FILL | ||
activity_type: Extract<ActivityType, 'FILL'> | ||
cum_qty: string | ||
@@ -240,4 +1253,5 @@ id: string | ||
export interface NonTradeActivity { | ||
activity_type: string | ||
export interface RawNonTradeActivity { | ||
// Everything except FILL | ||
activity_type: Exclude<ActivityType, 'FILL'> | ||
id: string | ||
@@ -251,2 +1265,119 @@ date: string | ||
export type TradeActivityType = 'fill' | 'partial_fill' | ||
export type TradeActivitySide = 'buy' | 'sell' | ||
export interface TradeActivity { | ||
/** | ||
* Get the raw data, exactly as it came from Alpaca | ||
*/ | ||
raw(): RawTradeActivity | ||
/** | ||
* FILL | ||
*/ | ||
activity_type: Extract<ActivityType, 'FILL'> | ||
/** | ||
* The cumulative quantity of shares involved in the execution. | ||
*/ | ||
cum_qty: number | ||
/** | ||
* An id for the activity. Always in "::" format. Can be sent as page_token in requests | ||
* to facilitate the paging of results. | ||
*/ | ||
id: string | ||
/** | ||
* For partially_filled orders, the quantity of shares that are left to be filled. | ||
*/ | ||
leaves_qty: number | ||
/** | ||
* The per-share price that the trade was executed at. | ||
*/ | ||
price: number | ||
/** | ||
* The number of shares involved in the trade execution. | ||
*/ | ||
qty: number | ||
/** | ||
* buy or sell | ||
*/ | ||
side: TradeActivitySide | ||
/** | ||
* The symbol of the security being traded. | ||
*/ | ||
symbol: string | ||
/** | ||
* The time at which the execution occurred. | ||
*/ | ||
transaction_time: string | ||
/** | ||
* The id for the order that filled. | ||
*/ | ||
order_id: string | ||
/** | ||
* fill or partial_fill | ||
*/ | ||
type: TradeActivityType | ||
} | ||
export interface NonTradeActivity { | ||
/** | ||
* Get the raw data, exactly as it came from Alpaca | ||
*/ | ||
raw(): RawNonTradeActivity | ||
/** | ||
* Activity type | ||
*/ | ||
activity_type: Exclude<ActivityType, 'FILL'> | ||
/** | ||
* An ID for the activity, always in "::" format. Can be sent as page_token in requests | ||
* to facilitate the paging of results. | ||
*/ | ||
id: string | ||
/** | ||
* The date on which the activity occurred or on which the transaction associated with | ||
* the activity settled. | ||
*/ | ||
date: string | ||
/** | ||
* The net amount of money (positive or negative) associated with the activity. | ||
*/ | ||
net_amount: number | ||
/** | ||
* The symbol of the security involved with the activity. Not present for all activity | ||
* types. | ||
*/ | ||
symbol: string | ||
/** | ||
* For dividend activities, the number of shares that contributed to the payment. Not | ||
* present for other activity types. | ||
*/ | ||
qty: number | ||
/** | ||
* For dividend activities, the average amount paid per share. Not present for other | ||
* activity types. | ||
*/ | ||
per_share_amount: number | ||
} | ||
export type RawActivity = RawTradeActivity | RawNonTradeActivity | ||
export type Activity = TradeActivity | NonTradeActivity | ||
export interface TradeUpdate { | ||
@@ -269,8 +1400,31 @@ event: string | ||
export interface Watchlist { | ||
/** | ||
* account ID | ||
*/ | ||
account_id: string | ||
/** | ||
* the content of this watchlist, in the order as registered by the client | ||
*/ | ||
assets: Asset[] | ||
/** | ||
* When the watchlist was created | ||
*/ | ||
created_at: string | ||
/** | ||
* watchlist id | ||
*/ | ||
id: string | ||
/** | ||
* user-defined watchlist name (up to 64 characters) | ||
*/ | ||
name: string | ||
/** | ||
* When the watchlist was last updated | ||
*/ | ||
updated_at: string | ||
} |
@@ -0,1 +1,3 @@ | ||
import { OrderSide, OrderType, OrderTimeInForce } from './entities.js' | ||
export interface AddToWatchList { | ||
@@ -72,7 +74,7 @@ uuid: string | ||
export interface GetOrders { | ||
status?: string | ||
status?: 'open' | 'closed' | 'all' | ||
limit?: number | ||
after?: Date | ||
until?: Date | ||
direction?: string | ||
direction?: 'asc' | 'desc' | ||
nested?: boolean | ||
@@ -99,11 +101,11 @@ } | ||
qty: number | ||
side: 'buy' | 'sell' | ||
type: 'market' | 'limit' | 'stop' | 'stop_limit' | 'trailing_stop' | ||
time_in_force: 'day' | 'gtc' | 'opg' | 'cls' | 'ioc' | 'fok' | ||
side: OrderSide | ||
type: OrderType | ||
time_in_force: OrderTimeInForce | ||
limit_price?: number | ||
stop_price?: number | ||
extended_hours?: boolean | ||
client_order_id?: string | ||
trail_price?: number | ||
trail_percent?: number | ||
extended_hours?: boolean | ||
client_order_id?: string | ||
order_class?: 'simple' | 'bracket' | 'oco' | 'oto' | ||
@@ -127,3 +129,3 @@ take_profit?: { | ||
qty?: number | ||
time_in_force?: string | ||
time_in_force?: OrderTimeInForce | ||
limit_price?: number | ||
@@ -130,0 +132,0 @@ stop_price?: number |
@@ -7,14 +7,17 @@ import WebSocket from 'ws' | ||
export declare interface Stream { | ||
on<U extends keyof StreamEvents>(event: U, listener: StreamEvents[U]): this | ||
emit<U extends keyof StreamEvents>( | ||
export declare interface AlpacaStream { | ||
on<U extends keyof AlpacaStreamEvents>( | ||
event: U, | ||
...args: Parameters<StreamEvents[U]> | ||
listener: AlpacaStreamEvents[U] | ||
): this | ||
emit<U extends keyof AlpacaStreamEvents>( | ||
event: U, | ||
...args: Parameters<AlpacaStreamEvents[U]> | ||
): boolean | ||
} | ||
export declare interface StreamEvents { | ||
open: (connection: Stream) => void | ||
close: (connection: Stream) => void | ||
authenticated: (connection: Stream) => void | ||
export declare interface AlpacaStreamEvents { | ||
open: (connection: AlpacaStream) => void | ||
close: (connection: AlpacaStream) => void | ||
authenticated: (connection: AlpacaStream) => void | ||
error: (error: Error) => void | ||
@@ -29,3 +32,3 @@ message: (data: Object) => void | ||
export class Stream extends EventEmitter { | ||
export class AlpacaStream extends EventEmitter { | ||
private host: string | ||
@@ -32,0 +35,0 @@ private connection: WebSocket |
{ | ||
"name": "@master-chief/alpaca", | ||
"version": "1.4.1", | ||
"version": "2.0.0", | ||
"description": "a TypeScript Node.js library for the https://alpaca.markets REST API and WebSocket streams", | ||
@@ -21,7 +21,21 @@ "main": "dist/index.js", | ||
"scripts": { | ||
"build": "tsc", | ||
"test": "npm run build && $(npm bin)/ava -v" | ||
"build": "npm run clean && tsc", | ||
"clean": "rimraf dist types", | ||
"test": "npm run build && npm run test:unit", | ||
"test:unit": "jest", | ||
"test:watch": "jest --watchAll" | ||
}, | ||
"jest": { | ||
"preset": "ts-jest", | ||
"testEnvironment": "node", | ||
"roots": [ | ||
"<rootDir>/lib" | ||
], | ||
"testMatch": [ | ||
"**/tests/**/*.test.ts" | ||
] | ||
}, | ||
"author": "master-chief", | ||
"contributors": [ | ||
"lbstr", | ||
"AqilCont", | ||
@@ -38,6 +52,11 @@ "KalebMills" | ||
"devDependencies": { | ||
"@types/jest": "^26.0.14", | ||
"@types/node-fetch": "^2.5.7", | ||
"@types/qs": "^6.9.3", | ||
"@types/ws": "^7.2.4" | ||
"@types/ws": "^7.2.4", | ||
"jest": "^26.4.2", | ||
"rimraf": "^3.0.2", | ||
"ts-jest": "^26.4.0", | ||
"typescript": "^4.0.3" | ||
} | ||
} |
155
README.md
@@ -21,4 +21,5 @@ # alpaca | ||
- [x] Fully asynchronous API. | ||
- [x] Extensible `Client` and `Stream` classes. | ||
- [x] Extensible `AlpacaClient` and `AlpacaStream` classes. | ||
- [x] Built-in rate limiting. | ||
- [x] Built-in number and date parsing. | ||
- [x] A 1:1 mapping of the official Alpaca [docs](https://docs.alpaca.markets/). | ||
@@ -42,14 +43,34 @@ | ||
```typescript | ||
import { Client } from "@master-chief/alpaca"; | ||
import { AlpacaClient } from '@master-chief/alpaca' | ||
const client = new Client({ | ||
const client = new AlpacaClient({ | ||
credentials: { | ||
key: "...", | ||
secret: "...", | ||
key: '...', | ||
secret: '...', | ||
}, | ||
paper: true, | ||
rate_limit: true, | ||
}); | ||
}) | ||
``` | ||
#### Parsing | ||
Alpaca provides numbers as strings. From | ||
[their docs](https://alpaca.markets/docs/api-documentation/api-v2/#numbers): | ||
> Decimal numbers are returned as strings to preserve full precision across | ||
> platforms. When making a request, it is recommended that you also convert your | ||
> numbers to strings to avoid truncation and precision errors. | ||
This package provides numbers as `number` instead, and date strings as `Date` | ||
objects which is what most developers want out of the box. If you want the | ||
original data, as it came from Alpaca, you can call `raw()` on any entity. | ||
```javascript | ||
const account = await client.getAccount() | ||
console.log(typeof account.buying_power) // number | ||
console.log(typeof account.raw().buying_power) // string | ||
``` | ||
#### Examples | ||
@@ -93,3 +114,3 @@ | ||
```typescript | ||
await client.isAuthenticated(); | ||
await client.isAuthenticated() | ||
``` | ||
@@ -100,3 +121,3 @@ | ||
```typescript | ||
await client.getAccount(); | ||
await client.getAccount() | ||
``` | ||
@@ -108,4 +129,4 @@ | ||
await client.getOrder({ | ||
order_id: "6187635d-04e5-485b-8a94-7ce398b2b81c", | ||
}); | ||
order_id: '6187635d-04e5-485b-8a94-7ce398b2b81c', | ||
}) | ||
``` | ||
@@ -118,4 +139,4 @@ | ||
limit: 25, | ||
status: "all", | ||
}); | ||
status: 'all', | ||
}) | ||
``` | ||
@@ -127,8 +148,8 @@ | ||
await client.placeOrder({ | ||
symbol: "SPY", | ||
symbol: 'SPY', | ||
qty: 1, | ||
side: "buy", | ||
type: "market", | ||
time_in_force: "day", | ||
}); | ||
side: 'buy', | ||
type: 'market', | ||
time_in_force: 'day', | ||
}) | ||
``` | ||
@@ -140,5 +161,5 @@ | ||
await client.replaceOrder({ | ||
order_id: "69a3db8b-cc63-44da-a26a-e3cca9490308", | ||
order_id: '69a3db8b-cc63-44da-a26a-e3cca9490308', | ||
limit_price: 9.74, | ||
}); | ||
}) | ||
``` | ||
@@ -150,4 +171,4 @@ | ||
await client.cancelOrder({ | ||
order_id: "69a3db8b-cc63-44da-a26a-e3cca9490308", | ||
}); | ||
order_id: '69a3db8b-cc63-44da-a26a-e3cca9490308', | ||
}) | ||
``` | ||
@@ -158,3 +179,3 @@ | ||
```typescript | ||
await client.cancelOrders(); | ||
await client.cancelOrders() | ||
``` | ||
@@ -165,3 +186,3 @@ | ||
```typescript | ||
await client.getPosition({ symbol: "SPY" }); | ||
await client.getPosition({ symbol: 'SPY' }) | ||
``` | ||
@@ -172,3 +193,3 @@ | ||
```typescript | ||
await client.getPositions(); | ||
await client.getPositions() | ||
``` | ||
@@ -179,3 +200,3 @@ | ||
```typescript | ||
await client.closePosition({ symbol: "SPY" }); | ||
await client.closePosition({ symbol: 'SPY' }) | ||
``` | ||
@@ -186,3 +207,3 @@ | ||
```typescript | ||
await client.closePositions(); | ||
await client.closePositions() | ||
``` | ||
@@ -193,3 +214,3 @@ | ||
```typescript | ||
await client.getAsset({ asset_id_or_symbol: "SPY" }); | ||
await client.getAsset({ asset_id_or_symbol: 'SPY' }) | ||
``` | ||
@@ -200,3 +221,3 @@ | ||
```typescript | ||
await client.getAssets({ status: "active" }); | ||
await client.getAssets({ status: 'active' }) | ||
``` | ||
@@ -207,3 +228,3 @@ | ||
```typescript | ||
await client.getWatchlist({ uuid: "2000e463-6f87-41c0-a8ba-3e40cbf67128" }); | ||
await client.getWatchlist({ uuid: '2000e463-6f87-41c0-a8ba-3e40cbf67128' }) | ||
``` | ||
@@ -214,3 +235,3 @@ | ||
```typescript | ||
await client.getWatchlists(); | ||
await client.getWatchlists() | ||
``` | ||
@@ -222,5 +243,5 @@ | ||
await client.createWatchlist({ | ||
name: "my watchlist", | ||
symbols: ["SPY", "DIA", "EEM", "XLF"], | ||
}); | ||
name: 'my watchlist', | ||
symbols: ['SPY', 'DIA', 'EEM', 'XLF'], | ||
}) | ||
``` | ||
@@ -232,6 +253,6 @@ | ||
await client.updateWatchlist({ | ||
uuid: "2000e463-6f87-41c0-a8ba-3e40cbf67128", | ||
name: "new watchlist name", | ||
symbols: ["TSLA", "AAPL"], | ||
}); | ||
uuid: '2000e463-6f87-41c0-a8ba-3e40cbf67128', | ||
name: 'new watchlist name', | ||
symbols: ['TSLA', 'AAPL'], | ||
}) | ||
``` | ||
@@ -243,5 +264,5 @@ | ||
await client.addToWatchlist({ | ||
uuid: "2000e463-6f87-41c0-a8ba-3e40cbf67128", | ||
symbol: "F", | ||
}); | ||
uuid: '2000e463-6f87-41c0-a8ba-3e40cbf67128', | ||
symbol: 'F', | ||
}) | ||
``` | ||
@@ -253,5 +274,5 @@ | ||
await client.removeFromWatchlist({ | ||
uuid: "2000e463-6f87-41c0-a8ba-3e40cbf67128", | ||
symbol: "F", | ||
}); | ||
uuid: '2000e463-6f87-41c0-a8ba-3e40cbf67128', | ||
symbol: 'F', | ||
}) | ||
``` | ||
@@ -263,4 +284,4 @@ | ||
await client.deleteWatchlist({ | ||
uuid: "2000e463-6f87-41c0-a8ba-3e40cbf67128", | ||
}); | ||
uuid: '2000e463-6f87-41c0-a8ba-3e40cbf67128', | ||
}) | ||
``` | ||
@@ -271,3 +292,3 @@ | ||
```typescript | ||
await client.getCalendar({ start: new Date(), end: new Date() }); | ||
await client.getCalendar({ start: new Date(), end: new Date() }) | ||
``` | ||
@@ -278,3 +299,3 @@ | ||
```typescript | ||
await client.getClock(); | ||
await client.getClock() | ||
``` | ||
@@ -285,3 +306,3 @@ | ||
```typescript | ||
await client.getAccountConfigurations(); | ||
await client.getAccountConfigurations() | ||
``` | ||
@@ -295,3 +316,3 @@ | ||
suspend_trade: true, | ||
}); | ||
}) | ||
``` | ||
@@ -303,4 +324,4 @@ | ||
await client.getAccountActivities({ | ||
activity_type: "FILL", | ||
}); | ||
activity_type: 'FILL', | ||
}) | ||
``` | ||
@@ -312,5 +333,5 @@ | ||
await client.getPortfolioHistory({ | ||
period: "1D", | ||
timeframe: "1Min", | ||
}); | ||
period: '1D', | ||
timeframe: '1Min', | ||
}) | ||
``` | ||
@@ -322,4 +343,4 @@ | ||
await client.getBars({ | ||
symbols: ["SPY", "DIA", "XLF"], | ||
}); | ||
symbols: ['SPY', 'DIA', 'XLF'], | ||
}) | ||
``` | ||
@@ -331,4 +352,4 @@ | ||
await client.getLastTrade({ | ||
symbol: "SPY", | ||
}); | ||
symbol: 'SPY', | ||
}) | ||
``` | ||
@@ -340,4 +361,4 @@ | ||
await client.getLastQuote({ | ||
symbol: "SPY", | ||
}); | ||
symbol: 'SPY', | ||
}) | ||
``` | ||
@@ -353,11 +374,11 @@ | ||
```typescript | ||
import { Stream } from "@master-chief/alpaca"; | ||
import { AlpacaStream } from '@master-chief/alpaca' | ||
const stream = new Stream({ | ||
const stream = new AlpacaStream({ | ||
credentials: { | ||
key: "...", | ||
secret: "...", | ||
key: '...', | ||
secret: '...', | ||
}, | ||
stream: "market_data", | ||
}); | ||
stream: 'market_data', | ||
}) | ||
``` | ||
@@ -386,3 +407,3 @@ | ||
```typescript | ||
stream.subscribe(["AM.SPY"]); | ||
stream.subscribe(['AM.SPY']) | ||
``` | ||
@@ -389,0 +410,0 @@ |
@@ -1,4 +0,4 @@ | ||
export { Client } from './lib/client.js'; | ||
export { Stream } from './lib/stream.js'; | ||
export { AlpacaClient } from './lib/client.js'; | ||
export { AlpacaStream } from './lib/stream.js'; | ||
export { Account, Order, Position, Asset, Watchlist, Calendar, Clock, AccountConfigurations, NonTradeActivity, TradeActivity, PortfolioHistory, Bar, LastQuote, LastTrade, } from './lib/entities.js'; | ||
export { GetOrder, GetOrders, PlaceOrder, ReplaceOrder, CancelOrder, GetPosition, ClosePosition, GetAsset, GetAssets, GetWatchList, CreateWatchList, UpdateWatchList, AddToWatchList, RemoveFromWatchList, DeleteWatchList, GetCalendar, UpdateAccountConfigurations, GetAccountActivities, GetPortfolioHistory, GetBars, GetLastTrade, GetLastQuote, } from './lib/params.js'; |
@@ -1,4 +0,4 @@ | ||
import { Account, Order, Position, Asset, Watchlist, Calendar, Clock, AccountConfigurations, NonTradeActivity, TradeActivity, PortfolioHistory, Bar, LastQuote, LastTrade, Credentials } from './entities.js'; | ||
import { Account, Order, Position, Asset, Watchlist, Calendar, Clock, AccountConfigurations, PortfolioHistory, Bar, LastQuote, LastTrade, Credentials, Activity } from './entities.js'; | ||
import { GetOrder, GetOrders, PlaceOrder, ReplaceOrder, CancelOrder, GetPosition, ClosePosition, GetAsset, GetAssets, GetWatchList, CreateWatchList, UpdateWatchList, AddToWatchList, RemoveFromWatchList, DeleteWatchList, GetCalendar, UpdateAccountConfigurations, GetAccountActivities, GetPortfolioHistory, GetBars, GetLastTrade, GetLastQuote } from './params.js'; | ||
export declare class Client { | ||
export declare class AlpacaClient { | ||
protected options: { | ||
@@ -10,2 +10,3 @@ credentials: Credentials; | ||
private limiter; | ||
private parser; | ||
constructor(options: { | ||
@@ -41,3 +42,3 @@ credentials: Credentials; | ||
updateAccountConfigurations(params: UpdateAccountConfigurations): Promise<AccountConfigurations>; | ||
getAccountActivities(params: GetAccountActivities): Promise<Array<NonTradeActivity | TradeActivity>>; | ||
getAccountActivities(params: GetAccountActivities): Promise<Activity[]>; | ||
getPortfolioHistory(params?: GetPortfolioHistory): Promise<PortfolioHistory>; | ||
@@ -44,0 +45,0 @@ getBars(params: GetBars): Promise<Map<String, Bar[]>>; |
@@ -0,1 +1,5 @@ | ||
/** | ||
* Your Alpaca key id and secret. | ||
* Can be passed to the AlpacaClient and AlpacaStream. | ||
*/ | ||
export interface Credentials { | ||
@@ -5,3 +9,7 @@ key: string; | ||
} | ||
export interface Account { | ||
/** | ||
* The account information with unparsed types, exactly as Alpaca provides it. | ||
* We encourage you to use the Account interface, which has many of these fields parsed. | ||
*/ | ||
export interface RawAccount { | ||
account_blocked: boolean; | ||
@@ -34,7 +42,182 @@ account_number: string; | ||
} | ||
/** | ||
* The following are the possible account status values. Most likely, the account status | ||
* is ACTIVE unless there is any problem. The account status may get in ACCOUNT_UPDATED | ||
* when personal information is being updated from the dashboard, in which case you may | ||
* not be allowed trading for a short period of time until the change is approved. | ||
*/ | ||
export declare type AccountStatus = | ||
/** | ||
* The account is onboarding. | ||
*/ | ||
'ONBOARDING' | ||
/** | ||
* The account application submission failed for some reason. | ||
*/ | ||
| 'SUBMISSION_FAILED' | ||
/** | ||
* The account application has been submitted for review. | ||
*/ | ||
| 'SUBMITTED' | ||
/** | ||
* The account information is being updated. | ||
*/ | ||
| 'ACCOUNT_UPDATED' | ||
/** | ||
* The final account approval is pending. | ||
*/ | ||
| 'APPROVAL_PENDING' | ||
/** | ||
* The account is active for trading. | ||
*/ | ||
| 'ACTIVE' | ||
/** | ||
* The account application has been rejected. | ||
*/ | ||
| 'REJECTED'; | ||
/** | ||
* Information related to an Alpaca account, such as account status, funds, and various | ||
* flags relevant to an account's ability to trade. | ||
*/ | ||
export interface Account { | ||
/** | ||
* Get the raw data, exactly as it came from Alpaca | ||
*/ | ||
raw(): RawAccount; | ||
/** | ||
* If true, the account activity by user is prohibited. | ||
*/ | ||
account_blocked: boolean; | ||
/** | ||
* Account number. | ||
*/ | ||
account_number: string; | ||
/** | ||
* Current available $ buying power; If multiplier = 4, this is your daytrade buying | ||
* power which is calculated as (last_equity - (last) maintenance_margin) * 4; If | ||
* multiplier = 2, buying_power = max(equity – initial_margin,0) * 2; If multiplier = 1, | ||
* buying_power = cash | ||
*/ | ||
buying_power: number; | ||
/** | ||
* Cash balance | ||
*/ | ||
cash: number; | ||
/** | ||
* Timestamp this account was created at | ||
*/ | ||
created_at: Date; | ||
/** | ||
* "USD" | ||
*/ | ||
currency: string; | ||
/** | ||
* The current number of daytrades that have been made in the last 5 trading days | ||
* (inclusive of today) | ||
*/ | ||
daytrade_count: number; | ||
/** | ||
* Your buying power for day trades (continuously updated value) | ||
*/ | ||
daytrading_buying_power: number; | ||
/** | ||
* Cash + long_market_value + short_market_value | ||
*/ | ||
equity: number; | ||
/** | ||
* Account ID. | ||
*/ | ||
id: string; | ||
/** | ||
* Reg T initial margin requirement (continuously updated value) | ||
*/ | ||
initial_margin: number; | ||
/** | ||
* Equity as of previous trading day at 16:00:00 ET | ||
*/ | ||
last_equity: number; | ||
/** | ||
* Your maintenance margin requirement on the previous trading day | ||
*/ | ||
last_maintenance_margin: number; | ||
/** | ||
* Real-time MtM value of all long positions held in the account | ||
*/ | ||
long_market_value: number; | ||
/** | ||
* Maintenance margin requirement (continuously updated value) | ||
*/ | ||
maintenance_margin: number; | ||
/** | ||
* Buying power multiplier that represents account margin classification; valid values 1 | ||
* (standard limited margin account with 1x buying power), 2 (reg T margin account with | ||
* 2x intraday and overnight buying power; this is the default for all non-PDT accounts | ||
* with $2,000 or more equity), 4 (PDT account with 4x intraday buying power and 2x reg | ||
* T overnight buying power) | ||
*/ | ||
multiplier: number; | ||
/** | ||
* Whether or not the account has been flagged as a pattern day trader | ||
*/ | ||
pattern_day_trader: boolean; | ||
/** | ||
* Total value of cash + holding positions (This field is deprecated. It is equivalent | ||
* to the equity field.) | ||
*/ | ||
portfolio_value: number; | ||
/** | ||
* Your buying power under Regulation T (your excess equity - equity minus margin | ||
* value - times your margin multiplier) | ||
*/ | ||
regt_buying_power: number; | ||
/** | ||
* Real-time MtM value of all short positions held in the account | ||
*/ | ||
short_market_value: number; | ||
/** | ||
* Flag to denote whether or not the account is permitted to short | ||
*/ | ||
shorting_enabled: boolean; | ||
/** | ||
* Value of special memorandum account (will be used at a later date to provide | ||
* additional buying_power) | ||
*/ | ||
sma: number; | ||
/** | ||
* The following are the possible account status values. Most likely, the account status | ||
* is ACTIVE unless there is any problem. The account status may get in ACCOUNT_UPDATED | ||
* when personal information is being updated from the dashboard, in which case you may | ||
* not be allowed trading for a short period of time until the change is approved. | ||
*/ | ||
status: AccountStatus; | ||
/** | ||
* User setting. If true, the account is not allowed to place orders. | ||
*/ | ||
trade_suspended_by_user: boolean; | ||
/** | ||
* If true, the account is not allowed to place orders. | ||
*/ | ||
trading_blocked: boolean; | ||
/** | ||
* If true, the account is not allowed to request money transfers. | ||
*/ | ||
transfers_blocked: boolean; | ||
} | ||
export interface AccountConfigurations { | ||
dtbp_check: string; | ||
/** | ||
* both, entry, or exit. Controls Day Trading Margin Call (DTMC) checks. | ||
*/ | ||
dtbp_check: 'both' | 'entry' | 'exit'; | ||
/** | ||
* If true, account becomes long-only mode. | ||
*/ | ||
no_shorting: boolean; | ||
/** | ||
* If true, new orders are blocked. | ||
*/ | ||
suspend_trade: boolean; | ||
trade_confirm_email: string; | ||
/** | ||
* all or none. If none, emails for order fills are not sent. | ||
*/ | ||
trade_confirm_email: 'all' | 'none'; | ||
} | ||
@@ -66,27 +249,96 @@ export interface AccountUpdate { | ||
} | ||
export declare type AssetExchange = 'AMEX' | 'ARCA' | 'BATS' | 'NYSE' | 'NASDAQ' | 'NYSEARCA'; | ||
export declare type AssetStatus = 'active' | 'inactive'; | ||
/** | ||
* The assets API serves as the master list of assets available for trade and data | ||
* consumption from Alpaca. Assets are sorted by asset class, exchange and symbol. Some | ||
* assets are only available for data consumption via Polygon, and are not tradable with | ||
* Alpaca. These assets will be marked with the flag tradable=false. | ||
*/ | ||
export interface Asset { | ||
/** | ||
* Asset ID | ||
*/ | ||
id: string; | ||
/** | ||
* "us_equity" | ||
*/ | ||
class: string; | ||
exchange: string; | ||
/** | ||
* AMEX, ARCA, BATS, NYSE, NASDAQ or NYSEARCA | ||
*/ | ||
exchange: AssetExchange; | ||
/** | ||
* Asset symbol | ||
*/ | ||
symbol: string; | ||
status: string; | ||
/** | ||
* active or inactive | ||
*/ | ||
status: AssetStatus; | ||
/** | ||
* Asset is tradable on Alpaca or not | ||
*/ | ||
tradable: boolean; | ||
/** | ||
* Asset is marginable or not | ||
*/ | ||
marginable: boolean; | ||
/** | ||
* Asset is shortable or not | ||
*/ | ||
shortable: boolean; | ||
/** | ||
* Asset is easy-to-borrow or not (filtering for easy_to_borrow = True is the best way | ||
* to check whether the name is currently available to short at Alpaca). | ||
*/ | ||
easy_to_borrow: boolean; | ||
} | ||
/** | ||
* Price and volume data during a particular time interval | ||
*/ | ||
export interface Bar { | ||
/** | ||
* the beginning time of this bar as a Unix epoch in seconds | ||
*/ | ||
t: number; | ||
/** | ||
* open price | ||
*/ | ||
o: number; | ||
/** | ||
* high price | ||
*/ | ||
h: number; | ||
/** | ||
* low price | ||
*/ | ||
l: number; | ||
/** | ||
* close price | ||
*/ | ||
c: number; | ||
/** | ||
* volume | ||
*/ | ||
v: number; | ||
} | ||
/** | ||
* Contains the time of open and close for a market on a particular day from 1970 to 2029 | ||
*/ | ||
export interface Calendar { | ||
/** | ||
* Date string in YYYY-MM-DD format | ||
*/ | ||
date: string; | ||
/** | ||
* The time the market opens at on this date in HH:MM format | ||
*/ | ||
open: string; | ||
/** | ||
* The time the market closes at on this date in HH:MM format | ||
*/ | ||
close: string; | ||
} | ||
export interface Clock { | ||
export interface RawClock { | ||
timestamp: string; | ||
@@ -97,2 +349,31 @@ is_open: boolean; | ||
} | ||
/** | ||
* The clock API serves the current market timestamp, whether or not the market is | ||
* currently open, as well as the times of the next market open and close. | ||
*/ | ||
export interface Clock { | ||
/** | ||
* Get the raw data, exactly as it came from Alpaca | ||
*/ | ||
raw(): RawClock; | ||
/** | ||
* Current timestamp | ||
*/ | ||
timestamp: Date; | ||
/** | ||
* Whether or not the market is open | ||
*/ | ||
is_open: boolean; | ||
/** | ||
* Next market open timestamp | ||
*/ | ||
next_open: Date; | ||
/** | ||
* Next market close timestamp | ||
*/ | ||
next_close: Date; | ||
} | ||
/** | ||
* Last quote details for a symbol | ||
*/ | ||
export interface LastQuote { | ||
@@ -102,11 +383,35 @@ status: string; | ||
last: { | ||
/** | ||
* the current ask price | ||
*/ | ||
askprice: number; | ||
/** | ||
* the current ask size | ||
*/ | ||
asksize: number; | ||
/** | ||
* the exchange code of the ask quote | ||
*/ | ||
askexchange: number; | ||
/** | ||
* the current bid price | ||
*/ | ||
bidprice: number; | ||
/** | ||
* the current bid size | ||
*/ | ||
bidsize: number; | ||
/** | ||
* the exchange code of the bid quote | ||
*/ | ||
bidexchange: number; | ||
/** | ||
* epoch timestamp in nanoseconds | ||
*/ | ||
timestamp: number; | ||
}; | ||
} | ||
/** | ||
* Last trade details for a symbol | ||
*/ | ||
export interface LastTrade { | ||
@@ -116,13 +421,41 @@ status: string; | ||
last: { | ||
/** | ||
* last trade price | ||
*/ | ||
price: number; | ||
/** | ||
* last trade volume size | ||
*/ | ||
size: number; | ||
/** | ||
* exchange code where the last trade was made | ||
*/ | ||
exchange: number; | ||
/** | ||
* condition flag 1 | ||
*/ | ||
cond1: number; | ||
/** | ||
* condition flag 2 | ||
*/ | ||
cond2: number; | ||
/** | ||
* condition flag 3 | ||
*/ | ||
cond3: number; | ||
/** | ||
* condition flag 4 | ||
*/ | ||
cond4: number; | ||
/** | ||
* epoch timestamp in nanoseconds | ||
*/ | ||
timestamp: number; | ||
}; | ||
} | ||
export interface Order { | ||
/** | ||
* The order entity with unparsed fields, exactly as Alpaca provides it. | ||
* We encourage you to use the Order interface, which has many of these fields parsed. | ||
*/ | ||
export interface RawOrder { | ||
id: string; | ||
@@ -139,3 +472,3 @@ client_order_id: string; | ||
replaced_by: string; | ||
replaces: any; | ||
replaces: string; | ||
asset_id: string; | ||
@@ -154,13 +487,297 @@ symbol: string; | ||
extended_hours: boolean; | ||
legs: any; | ||
legs: RawOrder[]; | ||
trail_price: string; | ||
trail_percent: string; | ||
hwm: string; | ||
} | ||
export declare type OrderType = 'market' | 'limit' | 'stop' | 'stop_limit' | 'trailing_stop'; | ||
export declare type OrderSide = 'buy' | 'sell'; | ||
export declare type OrderTimeInForce = | ||
/** | ||
* A day order is eligible for execution only on the day it is live. By default, the | ||
* order is only valid during Regular Trading Hours (9:30am - 4:00pm ET). If unfilled | ||
* after the closing auction, it is automatically canceled. If submitted after the | ||
* close, it is queued and submitted the following trading day. However, if marked as | ||
* eligible for extended hours, the order can also execute during supported extended | ||
* hours. | ||
*/ | ||
'day' | ||
/** | ||
* The order is good until canceled. Non-marketable GTC limit orders are subject to | ||
* price adjustments to offset corporate actions affecting the issue. We do not | ||
* currently support Do Not Reduce(DNR) orders to opt out of such price adjustments. | ||
*/ | ||
| 'gtc' | ||
/** | ||
* Use this TIF with a market/limit order type to submit "market on open" (MOO) and | ||
* "limit on open" (LOO) orders. This order is eligible to execute only in the market | ||
* opening auction. Any unfilled orders after the open will be cancelled. OPG orders | ||
* submitted after 9:28am but before 7:00pm ET will be rejected. OPG orders submitted | ||
* after 7:00pm will be queued and routed to the following day's opening auction. On | ||
* open/on close orders are routed to the primary exchange. Such orders do not | ||
* necessarily execute exactly at 9:30am / 4:00pm ET but execute per the exchange's | ||
* auction rules. | ||
*/ | ||
| 'opg' | ||
/** | ||
* Use this TIF with a market/limit order type to submit "market on close" (MOC) and | ||
* "limit on close" (LOC) orders. This order is eligible to execute only in the market | ||
* closing auction. Any unfilled orders after the close will be cancelled. CLS orders | ||
* submitted after 3:50pm but before 7:00pm ET will be rejected. CLS orders submitted | ||
* after 7:00pm will be queued and routed to the following day's closing auction. Only | ||
* available with API v2. | ||
*/ | ||
| 'cls' | ||
/** | ||
* An Immediate Or Cancel (IOC) order requires all or part of the order to be executed | ||
* immediately. Any unfilled portion of the order is canceled. Only available with API | ||
* v2. | ||
*/ | ||
| 'ioc' | ||
/** | ||
* A Fill or Kill (FOK) order is only executed if the entire order quantity can be | ||
* filled, otherwise the order is canceled. Only available with API v2. | ||
*/ | ||
| 'fok'; | ||
export declare type OrderStatus = | ||
/** | ||
* The order has been received by Alpaca, and routed to exchanges for execution. This | ||
* is the usual initial state of an order. | ||
*/ | ||
'new' | ||
/** | ||
* The order has been partially filled. | ||
*/ | ||
| 'partially_filled' | ||
/** | ||
* The order has been filled, and no further updates will occur for the order. | ||
*/ | ||
| 'filled' | ||
/** | ||
* The order is done executing for the day, and will not receive further updates until | ||
* the next trading day. | ||
*/ | ||
| 'done_for_day' | ||
/** | ||
* The order has been canceled, and no further updates will occur for the order. This | ||
* can be either due to a cancel request by the user, or the order has been canceled by | ||
* the exchanges due to its time-in-force. | ||
*/ | ||
| 'canceled' | ||
/** | ||
* The order has expired, and no further updates will occur for the order. | ||
*/ | ||
| 'expired' | ||
/** | ||
* The order was replaced by another order, or was updated due to a market event such | ||
* as corporate action. | ||
*/ | ||
| 'replaced' | ||
/** | ||
* The order is waiting to be canceled. | ||
*/ | ||
| 'pending_cancel' | ||
/** | ||
* The order is waiting to be replaced by another order. The order will reject cancel | ||
* request while in this state. | ||
*/ | ||
| 'pending_replace' | ||
/** | ||
* (Uncommon) The order has been received by Alpaca, but hasn't yet been routed to the | ||
* execution venue. This could be seen often out side of trading session hours. | ||
*/ | ||
| 'accepted' | ||
/** | ||
* (Uncommon) The order has been received by Alpaca, and routed to the exchanges, but | ||
* has not yet been accepted for execution. This state only occurs on rare occasions. | ||
*/ | ||
| 'pending_new' | ||
/** | ||
* (Uncommon) The order has been received by exchanges, and is evaluated for pricing. | ||
* This state only occurs on rare occasions. | ||
*/ | ||
| 'accepted_for_bidding' | ||
/** | ||
* (Uncommon) The order has been stopped, and a trade is guaranteed for the order, | ||
* usually at a stated price or better, but has not yet occurred. This state only | ||
* occurs on rare occasions. | ||
*/ | ||
| 'stopped' | ||
/** | ||
* (Uncommon) The order has been rejected, and no further updates will occur for the | ||
* order. This state occurs on rare occasions and may occur based on various conditions | ||
* decided by the exchanges. | ||
*/ | ||
| 'rejected' | ||
/** | ||
* (Uncommon) The order has been suspended, and is not eligible for trading. This state | ||
* only occurs on rare occasions. | ||
*/ | ||
| 'suspended' | ||
/** | ||
* (Uncommon) The order has been completed for the day (either filled or done for day), | ||
* but remaining settlement calculations are still pending. This state only occurs on | ||
* rare occasions. | ||
*/ | ||
| 'calculated'; | ||
/** | ||
* An Order in Alpaca | ||
*/ | ||
export interface Order { | ||
/** | ||
* Get the raw data, exactly as it came from Alpaca | ||
*/ | ||
raw(): RawOrder; | ||
/** | ||
* Order id | ||
*/ | ||
id: string; | ||
/** | ||
* Client unique order id | ||
*/ | ||
client_order_id: string; | ||
/** | ||
* When the order was created | ||
*/ | ||
created_at: Date; | ||
/** | ||
* When the order was last updated | ||
*/ | ||
updated_at: Date; | ||
/** | ||
* When the order was submitted | ||
*/ | ||
submitted_at: Date; | ||
/** | ||
* When the order was filled | ||
*/ | ||
filled_at: Date; | ||
/** | ||
* When the order expired | ||
*/ | ||
expired_at: Date; | ||
/** | ||
* When the order was canceled | ||
*/ | ||
canceled_at: Date; | ||
/** | ||
* When the order failed | ||
*/ | ||
failed_at: Date; | ||
/** | ||
* When the order was last replaced | ||
*/ | ||
replaced_at: Date; | ||
/** | ||
* The order ID that this order was replaced by | ||
*/ | ||
replaced_by: string; | ||
/** | ||
* The order ID that this order replaces | ||
*/ | ||
replaces: string; | ||
/** | ||
* Asset ID | ||
*/ | ||
asset_id: string; | ||
/** | ||
* Asset symbol | ||
*/ | ||
symbol: string; | ||
/** | ||
* Asset class | ||
*/ | ||
asset_class: string; | ||
/** | ||
* Ordered quantity | ||
*/ | ||
qty: number; | ||
/** | ||
* Filled quantity | ||
*/ | ||
filled_qty: number; | ||
/** | ||
* Order type (market, limit, stop, stop_limit, trailing_stop) | ||
*/ | ||
type: OrderType; | ||
/** | ||
* Buy or sell | ||
*/ | ||
side: OrderSide; | ||
/** | ||
* Order Time in Force | ||
*/ | ||
time_in_force: OrderTimeInForce; | ||
/** | ||
* Limit price | ||
*/ | ||
limit_price: number; | ||
/** | ||
* Stop price | ||
*/ | ||
stop_price: number; | ||
/** | ||
* Filled average price | ||
*/ | ||
filled_avg_price: number; | ||
/** | ||
* The status of the order | ||
*/ | ||
status: OrderStatus; | ||
/** | ||
* If true, eligible for execution outside regular trading hours. | ||
*/ | ||
extended_hours: boolean; | ||
/** | ||
* When querying non-simple order_class orders in a nested style, an array of Order | ||
* entities associated with this order. Otherwise, null. | ||
*/ | ||
legs: Order[]; | ||
/** | ||
* The dollar value away from the high water mark for trailing stop orders. | ||
*/ | ||
trail_price: number; | ||
/** | ||
* The percent value away from the high water mark for trailing stop orders. | ||
*/ | ||
trail_percent: number; | ||
/** | ||
* The highest (lowest) market price seen since the trailing stop order was submitted. | ||
*/ | ||
hwm: number; | ||
} | ||
/** | ||
* Timeseries data for equity and profit loss information of the account | ||
*/ | ||
export interface PortfolioHistory { | ||
/** | ||
* time of each data element, left-labeled (the beginning of time window) | ||
*/ | ||
timestamp: number[]; | ||
/** | ||
* equity value of the account in dollar amount as of the end of each time window | ||
*/ | ||
equity: number[]; | ||
/** | ||
* profit/loss in dollar from the base value | ||
*/ | ||
profit_loss: number[]; | ||
/** | ||
* profit/loss in percentage from the base value | ||
*/ | ||
profit_loss_pct: number[]; | ||
/** | ||
* basis in dollar of the profit loss calculation | ||
*/ | ||
base_value: number; | ||
/** | ||
* time window size of each data element | ||
*/ | ||
timeframe: string; | ||
} | ||
export interface Position { | ||
/** | ||
* A position with unparsed fields, exactly as Alpaca provides it. | ||
* We encourage you to use the Position interface, which has many of these fields parsed. | ||
*/ | ||
export interface RawPosition { | ||
asset_id: string; | ||
@@ -183,2 +800,76 @@ symbol: string; | ||
} | ||
export declare type PositionSide = 'long' | 'short'; | ||
/** | ||
* A position in Alpaca | ||
*/ | ||
export interface Position { | ||
/** | ||
* Get the raw data, exactly as it came from Alpaca | ||
*/ | ||
raw(): RawPosition; | ||
/** | ||
* Asset ID | ||
*/ | ||
asset_id: string; | ||
/** | ||
* Symbol name of the asset | ||
*/ | ||
symbol: string; | ||
/** | ||
* Exchange name of the asset | ||
*/ | ||
exchange: string; | ||
/** | ||
* Asset class name | ||
*/ | ||
asset_class: string; | ||
/** | ||
* Average entry price of the position | ||
*/ | ||
avg_entry_price: number; | ||
/** | ||
* The number of shares | ||
*/ | ||
qty: number; | ||
/** | ||
* long or short | ||
*/ | ||
side: PositionSide; | ||
/** | ||
* Total dollar amount of the position | ||
*/ | ||
market_value: number; | ||
/** | ||
* Total cost basis in dollar | ||
*/ | ||
cost_basis: number; | ||
/** | ||
* Unrealized profit/loss in dollars | ||
*/ | ||
unrealized_pl: number; | ||
/** | ||
* Unrealized profit/loss percent (by a factor of 1) | ||
*/ | ||
unrealized_plpc: number; | ||
/** | ||
* Unrealized profit/loss in dollars for the day | ||
*/ | ||
unrealized_intraday_pl: number; | ||
/** | ||
* Unrealized profit/loss percent (by a factor of 1) | ||
*/ | ||
unrealized_intraday_plpc: number; | ||
/** | ||
* Current asset price per share | ||
*/ | ||
current_price: number; | ||
/** | ||
* Last day's asset price per share based on the closing value of the last trading day | ||
*/ | ||
lastday_price: number; | ||
/** | ||
* Percent change from last day price (by a factor of 1) | ||
*/ | ||
change_today: number; | ||
} | ||
export interface Quote { | ||
@@ -207,4 +898,138 @@ ev: string; | ||
} | ||
export interface TradeActivity { | ||
activity_type: string; | ||
export declare type ActivityType = | ||
/** | ||
* Order fills (both partial and full fills) | ||
*/ | ||
'FILL' | ||
/** | ||
* Cash transactions (both CSD and CSR) | ||
*/ | ||
| 'TRANS' | ||
/** | ||
* Miscellaneous or rarely used activity types (All types except those in TRANS, DIV, | ||
* or FILL) | ||
*/ | ||
| 'MISC' | ||
/** | ||
* ACATS IN/OUT (Cash) | ||
*/ | ||
| 'ACATC' | ||
/** | ||
* ACATS IN/OUT (Securities) | ||
*/ | ||
| 'ACATS' | ||
/** | ||
* Cash disbursement(+) | ||
*/ | ||
| 'CSD' | ||
/** | ||
* Cash receipt(-) | ||
*/ | ||
| 'CSR' | ||
/** | ||
* Dividends | ||
*/ | ||
| 'DIV' | ||
/** | ||
* Dividend (capital gain long term) | ||
*/ | ||
| 'DIVCGL' | ||
/** | ||
* Dividend (capital gain short term) | ||
*/ | ||
| 'DIVCGS' | ||
/** | ||
* Dividend fee | ||
*/ | ||
| 'DIVFEE' | ||
/** | ||
* Dividend adjusted (Foreign Tax Withheld) | ||
*/ | ||
| 'DIVFT' | ||
/** | ||
* Dividend adjusted (NRA Withheld) | ||
*/ | ||
| 'DIVNRA' | ||
/** | ||
* Dividend return of capital | ||
*/ | ||
| 'DIVROC' | ||
/** | ||
* Dividend adjusted (Tefra Withheld) | ||
*/ | ||
| 'DIVTW' | ||
/** | ||
* Dividend (tax exempt) | ||
*/ | ||
| 'DIVTXEX' | ||
/** | ||
* Interest (credit/margin) | ||
*/ | ||
| 'INT' | ||
/** | ||
* Interest adjusted (NRA Withheld) | ||
*/ | ||
| 'INTNRA' | ||
/** | ||
* Interest adjusted (Tefra Withheld) | ||
*/ | ||
| 'INTTW' | ||
/** | ||
* Journal entry | ||
*/ | ||
| 'JNL' | ||
/** | ||
* Journal entry (cash) | ||
*/ | ||
| 'JNLC' | ||
/** | ||
* Journal entry (stock) | ||
*/ | ||
| 'JNLS' | ||
/** | ||
* Merger/Acquisition | ||
*/ | ||
| 'MA' | ||
/** | ||
* Name change | ||
*/ | ||
| 'NC' | ||
/** | ||
* Option assignment | ||
*/ | ||
| 'OPASN' | ||
/** | ||
* Option expiration | ||
*/ | ||
| 'OPEXP' | ||
/** | ||
* Option exercise | ||
*/ | ||
| 'OPXRC' | ||
/** | ||
* Pass Thru Charge | ||
*/ | ||
| 'PTC' | ||
/** | ||
* Pass Thru Rebate | ||
*/ | ||
| 'PTR' | ||
/** | ||
* Reorg CA | ||
*/ | ||
| 'REORG' | ||
/** | ||
* Symbol change | ||
*/ | ||
| 'SC' | ||
/** | ||
* Stock spinoff | ||
*/ | ||
| 'SSO' | ||
/** | ||
* Stock split | ||
*/ | ||
| 'SSP'; | ||
export interface RawTradeActivity { | ||
activity_type: Extract<ActivityType, 'FILL'>; | ||
cum_qty: string; | ||
@@ -221,4 +1046,4 @@ id: string; | ||
} | ||
export interface NonTradeActivity { | ||
activity_type: string; | ||
export interface RawNonTradeActivity { | ||
activity_type: Exclude<ActivityType, 'FILL'>; | ||
id: string; | ||
@@ -231,2 +1056,96 @@ date: string; | ||
} | ||
export declare type TradeActivityType = 'fill' | 'partial_fill'; | ||
export declare type TradeActivitySide = 'buy' | 'sell'; | ||
export interface TradeActivity { | ||
/** | ||
* Get the raw data, exactly as it came from Alpaca | ||
*/ | ||
raw(): RawTradeActivity; | ||
/** | ||
* FILL | ||
*/ | ||
activity_type: Extract<ActivityType, 'FILL'>; | ||
/** | ||
* The cumulative quantity of shares involved in the execution. | ||
*/ | ||
cum_qty: number; | ||
/** | ||
* An id for the activity. Always in "::" format. Can be sent as page_token in requests | ||
* to facilitate the paging of results. | ||
*/ | ||
id: string; | ||
/** | ||
* For partially_filled orders, the quantity of shares that are left to be filled. | ||
*/ | ||
leaves_qty: number; | ||
/** | ||
* The per-share price that the trade was executed at. | ||
*/ | ||
price: number; | ||
/** | ||
* The number of shares involved in the trade execution. | ||
*/ | ||
qty: number; | ||
/** | ||
* buy or sell | ||
*/ | ||
side: TradeActivitySide; | ||
/** | ||
* The symbol of the security being traded. | ||
*/ | ||
symbol: string; | ||
/** | ||
* The time at which the execution occurred. | ||
*/ | ||
transaction_time: string; | ||
/** | ||
* The id for the order that filled. | ||
*/ | ||
order_id: string; | ||
/** | ||
* fill or partial_fill | ||
*/ | ||
type: TradeActivityType; | ||
} | ||
export interface NonTradeActivity { | ||
/** | ||
* Get the raw data, exactly as it came from Alpaca | ||
*/ | ||
raw(): RawNonTradeActivity; | ||
/** | ||
* Activity type | ||
*/ | ||
activity_type: Exclude<ActivityType, 'FILL'>; | ||
/** | ||
* An ID for the activity, always in "::" format. Can be sent as page_token in requests | ||
* to facilitate the paging of results. | ||
*/ | ||
id: string; | ||
/** | ||
* The date on which the activity occurred or on which the transaction associated with | ||
* the activity settled. | ||
*/ | ||
date: string; | ||
/** | ||
* The net amount of money (positive or negative) associated with the activity. | ||
*/ | ||
net_amount: number; | ||
/** | ||
* The symbol of the security involved with the activity. Not present for all activity | ||
* types. | ||
*/ | ||
symbol: string; | ||
/** | ||
* For dividend activities, the number of shares that contributed to the payment. Not | ||
* present for other activity types. | ||
*/ | ||
qty: number; | ||
/** | ||
* For dividend activities, the average amount paid per share. Not present for other | ||
* activity types. | ||
*/ | ||
per_share_amount: number; | ||
} | ||
export declare type RawActivity = RawTradeActivity | RawNonTradeActivity; | ||
export declare type Activity = TradeActivity | NonTradeActivity; | ||
export interface TradeUpdate { | ||
@@ -248,8 +1167,26 @@ event: string; | ||
export interface Watchlist { | ||
/** | ||
* account ID | ||
*/ | ||
account_id: string; | ||
/** | ||
* the content of this watchlist, in the order as registered by the client | ||
*/ | ||
assets: Asset[]; | ||
/** | ||
* When the watchlist was created | ||
*/ | ||
created_at: string; | ||
/** | ||
* watchlist id | ||
*/ | ||
id: string; | ||
/** | ||
* user-defined watchlist name (up to 64 characters) | ||
*/ | ||
name: string; | ||
/** | ||
* When the watchlist was last updated | ||
*/ | ||
updated_at: string; | ||
} |
@@ -0,1 +1,2 @@ | ||
import { OrderSide, OrderType, OrderTimeInForce } from './entities.js'; | ||
export interface AddToWatchList { | ||
@@ -59,7 +60,7 @@ uuid: string; | ||
export interface GetOrders { | ||
status?: string; | ||
status?: 'open' | 'closed' | 'all'; | ||
limit?: number; | ||
after?: Date; | ||
until?: Date; | ||
direction?: string; | ||
direction?: 'asc' | 'desc'; | ||
nested?: boolean; | ||
@@ -82,11 +83,11 @@ } | ||
qty: number; | ||
side: 'buy' | 'sell'; | ||
type: 'market' | 'limit' | 'stop' | 'stop_limit' | 'trailing_stop'; | ||
time_in_force: 'day' | 'gtc' | 'opg' | 'cls' | 'ioc' | 'fok'; | ||
side: OrderSide; | ||
type: OrderType; | ||
time_in_force: OrderTimeInForce; | ||
limit_price?: number; | ||
stop_price?: number; | ||
extended_hours?: boolean; | ||
client_order_id?: string; | ||
trail_price?: number; | ||
trail_percent?: number; | ||
extended_hours?: boolean; | ||
client_order_id?: string; | ||
order_class?: 'simple' | 'bracket' | 'oco' | 'oto'; | ||
@@ -108,3 +109,3 @@ take_profit?: { | ||
qty?: number; | ||
time_in_force?: string; | ||
time_in_force?: OrderTimeInForce; | ||
limit_price?: number; | ||
@@ -111,0 +112,0 @@ stop_price?: number; |
/// <reference types="node" /> | ||
import { EventEmitter } from 'events'; | ||
import { Credentials } from './entities.js'; | ||
export declare interface Stream { | ||
on<U extends keyof StreamEvents>(event: U, listener: StreamEvents[U]): this; | ||
emit<U extends keyof StreamEvents>(event: U, ...args: Parameters<StreamEvents[U]>): boolean; | ||
export declare interface AlpacaStream { | ||
on<U extends keyof AlpacaStreamEvents>(event: U, listener: AlpacaStreamEvents[U]): this; | ||
emit<U extends keyof AlpacaStreamEvents>(event: U, ...args: Parameters<AlpacaStreamEvents[U]>): boolean; | ||
} | ||
export declare interface StreamEvents { | ||
open: (connection: Stream) => void; | ||
close: (connection: Stream) => void; | ||
authenticated: (connection: Stream) => void; | ||
export declare interface AlpacaStreamEvents { | ||
open: (connection: AlpacaStream) => void; | ||
close: (connection: AlpacaStream) => void; | ||
authenticated: (connection: AlpacaStream) => void; | ||
error: (error: Error) => void; | ||
@@ -20,3 +20,3 @@ message: (data: Object) => void; | ||
} | ||
export declare class Stream extends EventEmitter { | ||
export declare class AlpacaStream extends EventEmitter { | ||
protected params: { | ||
@@ -23,0 +23,0 @@ credentials: Credentials; |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
127720
30
4287
392
8
2