Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add market_depth service, refactor handlers #66

Merged
merged 3 commits into from
Sep 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,36 @@
# TD Ameritrade WsJson API client

This is a node and browser API client for the (undocumented) TDAmeritrade WebSocket API.
This is a node and browser API client for the (undocumented) TD Ameritrade WebSocket API.

🚧 Work in progress 🚧

# Prerequisites

- Node 16+

Create a `.env` file and set your TDAmeritrade oauth access token:
Create a `.env` file and set your TD Ameritrade oauth access token:

```
CLIENT_ID=your-client-id
ACCESS_TOKEN=your-access-token
REFRESH_TOKEN=your-refresh-token
TOKEN_EXPIRES_AT=your-token-expires-at
```

# Building for Node

```

yarn install
yarn build

```

# Running the example app

```

cd example
yarn install
yarn link tda-wsjson-client
yarn start

```

# Supported APIs
Expand All @@ -52,12 +51,13 @@ yarn start
- ✅ Option chain quotes
- ✅ Option quotes
- ✅ Order events
- ✅ Market depth

# Not yet implemented

- ❌ Instrument order events
- ❌ Alert subscription
- ❌ And many others 😀
- ❌ And many more 😀

# Usage

Expand Down
114 changes: 0 additions & 114 deletions src/client/messageTypeHelpers.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,9 @@
import {
ConnectionResponse,
ParsedWebSocketResponse,
RawPayloadResponse,
WsJsonRawMessage,
} from "./tdaWsJsonTypes";
import { ChartResponse } from "./services/chartMessageHandler";
import { QuotesResponse } from "./services/quotesMessageHandler";
import { PositionsResponse } from "./services/positionsMessageHandler";
import { PlaceOrderSnapshotResponse } from "./services/placeOrderMessageHandler";
import {
OrderEventsPatchResponse,
OrderEventsResponse,
OrderEventsSnapshotResponse,
} from "./services/orderEventsMessageHandler";
import { UserPropertiesResponse } from "./services/userPropertiesMessageHandler";
import { InstrumentSearchResponse } from "./services/instrumentSearchMessageHandler";
import { AlertsResponse } from "./types/alertTypes";
import { OptionChainResponse } from "./services/optionSeriesMessageHandler";
import { RawLoginResponse } from "./services/loginMessageHandler";
import { OptionQuotesResponse } from "./services/optionQuotesMessageHandler";
import { CancelOrderResponse } from "./services/cancelOrderMessageHandler";
import {
OptionSeriesQuotesPatchResponse,
OptionSeriesQuotesSnapshotResponse,
} from "./services/optionSeriesQuotesMessageHandler";

export function isPayloadResponse(
response: WsJsonRawMessage
Expand All @@ -45,97 +25,3 @@ export function isLoginResponse(
const { service } = header;
return service === "login";
}

export function isChartResponse(
response: ParsedWebSocketResponse
): response is ChartResponse {
return "candles" in response;
}

export function isQuotesResponse(
response: ParsedWebSocketResponse
): response is QuotesResponse {
return "quotes" in response;
}

export function isPositionsResponse(
response: ParsedWebSocketResponse
): response is PositionsResponse {
return "positions" in response;
}

export function isUserPropertiesResponse(
response: ParsedWebSocketResponse
): response is UserPropertiesResponse {
return "defaultAccountCode" in response;
}

export function isPlaceOrderResponse(
response: ParsedWebSocketResponse
): response is PlaceOrderSnapshotResponse {
return "orders" in response && response.service === "place_order";
}

export function isCancelOrderResponse(
response: ParsedWebSocketResponse
): response is CancelOrderResponse {
return "service" in response && response.service === "cancel_order";
}

export function isOrderEventsPatchResponse(
response: ParsedWebSocketResponse
): response is OrderEventsPatchResponse {
return "patches" in response && response.service === "order_events";
}

export function isOrderEventsResponse(
response: ParsedWebSocketResponse
): response is OrderEventsResponse {
const isSnapshotResponse = (
response: ParsedWebSocketResponse
): response is OrderEventsSnapshotResponse =>
"orders" in response && response.service === "order_events";

return isSnapshotResponse(response) || isOrderEventsPatchResponse(response);
}

// TODO: add support for patch responses
export function isOptionQuotesResponse(
response: ParsedWebSocketResponse
): response is OptionQuotesResponse {
return "service" in response && response.service === "quotes/options";
}

export function isOptionSeriesQuotesResponse(
response: ParsedWebSocketResponse
): response is OptionSeriesQuotesSnapshotResponse {
const isSnapshotResponse = (
response: ParsedWebSocketResponse
): response is OptionSeriesQuotesSnapshotResponse =>
"series" in response && response.service === "optionSeries/quotes";

const isPatchResponse = (
response: ParsedWebSocketResponse
): response is OptionSeriesQuotesPatchResponse =>
"patches" in response && response.service === "optionSeries/quotes";

return isSnapshotResponse(response) || isPatchResponse(response);
}

export function isAlertsResponse(
response: ParsedWebSocketResponse
): response is AlertsResponse {
return "alerts" in response;
}

export function isInstrumentsResponse(
response: ParsedWebSocketResponse
): response is InstrumentSearchResponse {
return "instruments" in response;
}

export function isOptionChainResponse(
response: ParsedWebSocketResponse
): response is OptionChainResponse {
return "series" in response && response.service === "optionSeries";
}
30 changes: 26 additions & 4 deletions src/client/mockWsJsonClient.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { WsJsonClient } from "./wsJsonClient";
import { PositionsResponse } from "./services/positionsMessageHandler";
import { RawLoginResponseBody } from "./services/loginMessageHandler";
import { AlertsResponse } from "./types/alertTypes";
import { CancelOrderResponse } from "./services/cancelOrderMessageHandler";
import {
ChartRequestParams,
Expand All @@ -26,10 +25,17 @@
import { QuotesResponse } from "./services/quotesMessageHandler";
import { InstrumentSearchResponse } from "./services/instrumentSearchMessageHandler";
import { UserPropertiesResponse } from "./services/userPropertiesMessageHandler";
import {
CancelAlertResponse,
CreateAlertResponse,
LookupAlertsResponse,
} from "./types/alertTypes";
import { MarketDepthResponse } from "./services/marketDepthMessageHandler";

export default class MockWsJsonClient implements WsJsonClient {
async *accountPositions(_: string): AsyncIterable<PositionsResponse> {

Check warning on line 36 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (16.x)

'_' is defined but never used

Check warning on line 36 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (18.x)

'_' is defined but never used

Check warning on line 36 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (19.x)

'_' is defined but never used
return yield {
service: "positions",
positions: [],
};
}
Expand All @@ -38,13 +44,14 @@
return Promise.resolve(null);
}

cancelAlert(_: number): Promise<AlertsResponse> {
cancelAlert(_: number): Promise<CancelAlertResponse> {

Check warning on line 47 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (16.x)

'_' is defined but never used

Check warning on line 47 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (18.x)

'_' is defined but never used

Check warning on line 47 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (19.x)

'_' is defined but never used
return Promise.resolve({
service: "alerts/cancel",
alerts: [],
});
}

cancelOrder(_: number): Promise<CancelOrderResponse> {

Check warning on line 54 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (16.x)

'_' is defined but never used

Check warning on line 54 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (18.x)

'_' is defined but never used

Check warning on line 54 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (19.x)

'_' is defined but never used
return Promise.resolve({
service: "cancel_order",
orderId: 123,
Expand All @@ -53,15 +60,17 @@
});
}

async *chart(_: ChartRequestParams): AsyncIterable<ChartResponse> {

Check warning on line 63 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (16.x)

'_' is defined but never used

Check warning on line 63 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (18.x)

'_' is defined but never used

Check warning on line 63 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (19.x)

'_' is defined but never used
return yield {
service: "chart",
symbol: "",
candles: [],
};
}

createAlert(_: CreateAlertRequestParams): Promise<AlertsResponse> {
createAlert(_: CreateAlertRequestParams): Promise<CreateAlertResponse> {

Check warning on line 71 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (16.x)

'_' is defined but never used

Check warning on line 71 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (18.x)

'_' is defined but never used

Check warning on line 71 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (19.x)

'_' is defined but never used
return Promise.resolve({
service: "alerts/create",
alerts: [],
});
}
Expand All @@ -80,13 +89,14 @@
return false;
}

async *lookupAlerts(): AsyncIterable<AlertsResponse> {
async *lookupAlerts(): AsyncIterable<LookupAlertsResponse> {
return yield {
service: "alerts/lookup",
alerts: [],
};
}

optionChain(_: string): Promise<OptionChainResponse> {

Check warning on line 99 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (16.x)

'_' is defined but never used

Check warning on line 99 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (18.x)

'_' is defined but never used

Check warning on line 99 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (19.x)

'_' is defined but never used
return Promise.resolve({
series: [],
service: "optionSeries",
Expand All @@ -94,15 +104,16 @@
}

optionChainDetails(
_: OptionChainDetailsRequest

Check warning on line 107 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (16.x)

'_' is defined but never used

Check warning on line 107 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (18.x)

'_' is defined but never used

Check warning on line 107 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (19.x)

'_' is defined but never used
): Promise<OptionChainDetailsResponse> {
return Promise.resolve({
service: "option_chain/get",
seriesDetails: [],
});
}

async *optionChainQuotes(
_: string

Check warning on line 116 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (16.x)

'_' is defined but never used

Check warning on line 116 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (18.x)

'_' is defined but never used

Check warning on line 116 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (19.x)

'_' is defined but never used
): AsyncIterable<OptionSeriesQuotesResponse> {
return yield {
series: [],
Expand All @@ -111,7 +122,7 @@
}

async *optionQuotes(
_: OptionQuotesRequestParams

Check warning on line 125 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (16.x)

'_' is defined but never used

Check warning on line 125 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (18.x)

'_' is defined but never used

Check warning on line 125 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (19.x)

'_' is defined but never used
): AsyncIterable<OptionQuotesResponse> {
return yield {
items: [],
Expand All @@ -120,7 +131,7 @@
}

placeOrder(
_: PlaceLimitOrderRequestParams

Check warning on line 134 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (16.x)

'_' is defined but never used

Check warning on line 134 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (18.x)

'_' is defined but never used

Check warning on line 134 in src/client/mockWsJsonClient.ts

View workflow job for this annotation

GitHub Actions / build (19.x)

'_' is defined but never used
): Promise<PlaceOrderSnapshotResponse> {
return Promise.resolve({
service: "place_order",
Expand All @@ -130,6 +141,7 @@

async *quotes(_: string[]): AsyncIterable<QuotesResponse> {
return yield {
service: "quotes",
quotes: [],
};
}
Expand All @@ -145,12 +157,14 @@

searchInstruments(_: string): Promise<InstrumentSearchResponse> {
return Promise.resolve({
service: "instrument_search",
instruments: [],
});
}

userProperties(): Promise<UserPropertiesResponse> {
return Promise.resolve({
service: "user_properties",
defaultAccountCode: "foo",
nickname: "foo",
plDisplayMethod: "foo",
Expand Down Expand Up @@ -179,4 +193,12 @@
service: "order_events",
};
}

async *marketDepth(_: string): AsyncIterable<MarketDepthResponse> {
return yield {
bidQuotes: [],
askQuotes: [],
service: "market_depth",
};
}
}
Loading