610,000 Shares at One Yen — JavaScript Bug Hunt
Modelled on the Mizuho Securities J-Com order of December 8, 2005.
- Language: JavaScript
- Layer: Backend
- Difficulty: Hard
- Concepts: Money, Validation, Limits
- Modelled on: Mizuho Securities · 2005
- Visible tests: the limit check flags a price far below the last trade; the exchange receives the ticket's price and quantity
- Reward: 50 XP for a complete fix
Briefing
Modelled on the Mizuho Securities J-Com order of December 8, 2005. A trader meant to sell 1 share at ¥610,000 in the newly listed J-Com and instead entered 610,000 shares at ¥1 — far more shares than the company had issued. The system showed a warning that was overridden, the order went through, and attempts to cancel it failed; Mizuho's loss was reported at roughly ¥40 billion.
This project is a reconstruction: orders.js takes a sell ticket from the order-entry screen, checks it against the locked listing data, and hands it to the locked exchange. Its limit check only produces warnings, and the call into the exchange passes the ticket's fields in the wrong positions.
Fix enterSellOrder so the order the exchange receives is the one on the ticket and an impossible quantity is blocked outright.
Bug report
BUG-JCOM-1208 · Priority: Critical (trading loss) · Reported by: risk desk
enterSellOrder(market, ticket) — ticket is { symbol, price, quantity }:
- a symbol not in LISTINGS throws
- quantity > LISTINGS[symbol].outstanding throws Error("quantity exceeds shares outstanding") — a HARD block that nothing overrides; no order reaches the exchange (market.orders unchanged)
- otherwise the order is submitted with exactly the ticket's price and quantity (exchange.submit(market, symbol, price, quantity)) and the result is { order, warnings }, warnings from checkLimits
- a price below 70 % of lastPrice is a SOFT warning ("PRICE_FAR_BELOW_LAST"): the order is still submitted
Observed: a ticket for 1 share at 610,000 reached the exchange as 610,000 shares at 1, with a warning attached and no block.
Logs
09:27:04 [oms] JCOM SELL ticket qty=1 px=610000
09:27:04 [oms] warnings=[QTY_EXCEEDS_OUTSTANDING, PRICE_FAR_BELOW_LAST] -> submitted
09:27:05 [tse] JCOM SELL 610000 @ 1 acceptedThe code as shipped
src/trading/orders.js (editable)
var exchange = require("./exchange");
var LISTINGS = require("./listings").LISTINGS;
function checkLimits(ticket) {
var listing = LISTINGS[ticket.symbol];
var warnings = [];
if (ticket.quantity > listing.outstanding) warnings.push("QTY_EXCEEDS_OUTSTANDING");
if (ticket.price < listing.lastPrice * 0.7) warnings.push("PRICE_FAR_BELOW_LAST");
return warnings;
}
exports.checkLimits = checkLimits;
// ticket: { symbol, price, quantity } from the order-entry screen.
exports.enterSellOrder = function (market, ticket) {
var warnings = checkLimits(ticket);
var order = exchange.submit(market, ticket.symbol, ticket.quantity, ticket.price);
return { order: order, warnings: warnings };
};
Read-only context: src/trading/exchange.js, src/trading/listings.js.
Open the hunt to edit the files, run the visible tests and submit against the hidden ones. More JavaScript bug hunts.