Skip to content

Commit

Permalink
fix: bug with market depth patch parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
felipecsl committed Sep 12, 2023
1 parent 90741cd commit 46deecd
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 24 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tda-wsjson-client",
"version": "0.7.0",
"version": "0.7.1",
"description": "WebSocket client for the TD Ameritrade wsjson API",
"main": "dist/web.bundle.js",
"types": "dist/web.d.ts",
Expand Down
52 changes: 38 additions & 14 deletions src/client/services/marketDepthMessageHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@ import { RawPayloadRequest, RawPayloadResponse } from "../tdaWsJsonTypes";
import { ApiService } from "./apiService";

type MarketDepthQuote = {
name: string;
name?: string;
price?: number;
size: number;
size?: number;
index?: number;
};

type MarketDepthPatch = { op: string; path: string; value?: any };

export type RawPayloadMarketDepthResponse = {
askQuotes: MarketDepthQuote[];
bidQuotes: MarketDepthQuote[];
Expand Down Expand Up @@ -53,7 +56,7 @@ export default class MarketDepthMessageHandler
}

private parsePatchResponse(
patches?: { op: string; path: string; value?: any }[]
patches?: MarketDepthPatch[]
): MarketDepthResponse | null {
const patch = patches?.[0];
if (patch?.op === "replace" && patch?.path === "") {
Expand All @@ -66,17 +69,12 @@ export default class MarketDepthMessageHandler
const askQuotes: MarketDepthQuote[] = [];
patches
?.filter(({ op }) => op === "replace")
.forEach(({ path, value }) => {
const pathParts = path.split("/");
const name = pathParts[2];
const prop = pathParts[3];
if (prop === "size") {
const size = value;
if (path.includes("bidQuotes")) {
bidQuotes.push({ name, size });
} else if (path.includes("askQuotes")) {
askQuotes.push({ name, size });
}
.forEach((patch) => {
const quote = parseQuote(patch);
if (patch.path.includes("bidQuotes")) {
bidQuotes.push(quote);
} else if (patch.path.includes("askQuotes")) {
askQuotes.push(quote);
} else {
console.warn("Don't know how to handle market depth patch", patch);
}
Expand All @@ -86,3 +84,29 @@ export default class MarketDepthMessageHandler

service: ApiService = "market_depth";
}

function parseQuote(patch: MarketDepthPatch): MarketDepthQuote {
const { path, value } = patch;
const pathParts = path.split("/");
const index = +pathParts[2];
const prop = pathParts[3];
const quote: MarketDepthQuote = { index };
switch (prop) {
case "size": {
quote.size = value;
break;
}
case "price": {
quote.price = value;
break;
}
case "name": {
quote.name = value;
break;
}
default:
console.warn("Don't know how to handle market depth patch", patch);
break;
}
return quote;
}
26 changes: 17 additions & 9 deletions src/example/marketDepthStateUpdater.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { MarketDepthResponse } from "../client/services/marketDepthMessageHandler";

type MarketDepthQuote = { [name: string]: { price: number; size: number } };
type MarketDepthQuote = {
[name: string]: { price?: number; size?: number; name?: string };
};

export default class MarketDepthStateUpdater {
readonly askQuotes: MarketDepthQuote = {};
Expand All @@ -10,18 +12,24 @@ export default class MarketDepthStateUpdater {

handleMessage(message: MarketDepthResponse) {
const { askQuotes, bidQuotes } = message;
askQuotes.forEach(({ name, price, size }) => {
if (price) {
this.askQuotes[name] = { price, size };
askQuotes.forEach(({ index, name, price, size }, i) => {
if (index !== undefined) {
const quote = this.askQuotes[index];
if (price !== undefined) quote.price = price;
if (name !== undefined) quote.name = name;
if (size !== undefined) quote.size = size;
} else {
this.askQuotes[name].size = size;
this.askQuotes[i] = { price, size, name };
}
});
bidQuotes.forEach(({ name, price, size }) => {
if (price) {
this.bidQuotes[name] = { price, size };
bidQuotes.forEach(({ index, name, price, size }, i) => {
if (index !== undefined) {
const quote = this.bidQuotes[index];
if (price !== undefined) quote.price = price;
if (name !== undefined) quote.name = name;
if (size !== undefined) quote.size = size;
} else {
this.bidQuotes[name].size = size;
this.bidQuotes[i] = { price, size, name };
}
});
}
Expand Down
1 change: 1 addition & 0 deletions src/example/testApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ class TestApp {
const stateUpdater = new MarketDepthStateUpdater();
logger(` --- marketDepth() requesting market depth for ${symbol} ---`);
for await (const message of this.client.marketDepth(symbol)) {
logger("message %O", message);
stateUpdater.handleMessage(message);
logger("ask quotes: %O", stateUpdater.askQuotes);
logger("bid quotes: %O", stateUpdater.bidQuotes);
Expand Down

0 comments on commit 46deecd

Please sign in to comment.