plotPricesAndVolume = (product) => {
const scopedPrices = prices.filter(
(d) => d.product == product && isWithinTimestampRange(d)
);
const scopedTrades = trades.filter(
(d) => d.symbol == product && isWithinTimestampRange(d)
);
const scopedTidyPrices = tidyPrices.filter(
(d) => d.product == product && isWithinTimestampRange(d)
);
return Plot.plot({
title: `${product} price and order depth`,
width,
height: 300,
caption:
"Hover for tooltip. Trades fill color indicates buyer, stroke color indicates seller.",
y: {
label: "price"
},
color: {
label: "volume",
legend: true,
scheme: "BuRd"
},
symbol: {
domain: ["volume", "SUBMISSION buy", "SUBMISSION sell", "Other trades"],
legend: true
},
marks: [
Plot.lineY(scopedPrices, {
x: "timestamp",
y: "bid_price_1",
z: null,
tip: true,
stroke: "bid_volume_1"
}),
Plot.lineY(scopedPrices, {
x: "timestamp",
y: "ask_price_1",
z: null,
tip: true,
stroke: (d) => -d.ask_volume_1
}),
Plot.dot(scopedTidyPrices, {
x: "timestamp",
y: "price",
fill: "volume",
symbol: (d) => "volume"
}),
obviousTrades
? Plot.ruleX(scopedTrades, {
x: "timestamp",
stroke: (d) => traderColorScale.apply(d.seller),
filter: (d) =>
d.buyer === "SUBMISSION" || d.seller === "SUBMISSION",
tip: true,
channels: {
buyer: "buyer",
seller: "seller",
quantity: "quantity"
}
})
: undefined,
showTrades != "None"
? Plot.dot(scopedTrades, {
x: "timestamp",
y: "price",
stroke: (d) => traderColorScale.apply(d.seller),
fill: (d) => traderColorScale.apply(d.buyer),
symbol: (d) =>
d.buyer === "SUBMISSION"
? "SUBMISSION buy"
: d.seller === "SUBMISSION"
? "SUBMISSION sell"
: "Other trades",
filter: (d) =>
showTrades === "Just SUBMISSION"
? d.buyer === "SUBMISSION" || d.seller === "SUBMISSION"
: true,
tip: true,
channels: {
buyer: "buyer",
seller: "seller",
quantity: "quantity"
}
})
: undefined,
Plot.lineY(
scopedPrices,
Plot.windowY({
x: "timestamp",
y: "mid_price",
k: kMovingAverage,
reduce: "mean"
})
)
]
});
}