import Excel from "exceljs";
import { describe, expect, it } from "vitest";
import { initialTable, setSolveForTable, twoWay } from "../../grid/rowModel";
import { DEFAULT_ALL_IN, SX5E_MARKET as m, SX5E_TRF_RUN } from "../../market/sx5e";
import { buildPricerWorkbook } from "../pricerWorkbook";
const rows = setSolveForTable(
m,
initialTable(m, SX5E_TRF_RUN.map((q) => ({ expiry: q.expiry, trf: twoWay(q.bid, q.offer) })), DEFAULT_ALL_IN),
2,
"price",
);
/** Round-trips through an actual .xlsx buffer, as Excel would read it. */
async function roundTrip() {
const buffer = await buildPricerWorkbook(Excel, m, rows).xlsx.writeBuffer();
const wb = new Excel.Workbook();
await wb.xlsx.load(buffer as ArrayBuffer);
return wb.getWorksheet("Pricer")!;
}
describe("pricer workbook", () => {
it("has the market block, both header rows and one row per tenor", async () => {
const ws = await roundTrip();
expect(ws.getCell("A2").value).toBe("Valuation date");
expect(ws.getCell("B3").value).toBe(m.spot);
expect(ws.getCell("E2").value).toBe("Exported at");
expect(ws.getCell("E3").value).toBeInstanceOf(Date);
expect(ws.getCell("A5").value).toBe("Expiry");
expect(ws.getCell("D5").value).toBe("Fwd (pts)");
expect(ws.getCell("D6").value).toBe("Bid");
expect(ws.getCell("E6").value).toBe("Mark");
expect(ws.getCell("A7").value).toBe("Dec26");
expect(ws.getCell("A11").value).toBe("Dec30");
expect(ws.getCell("C9").value).toBe("Prices"); // Dec28 solves for prices
expect(ws.getCell("C7").value).toBe("Funding");
});
it("writes values as numbers, with all-in as a percentage", async () => {
const ws = await roundTrip();
// Dec27 TRF (columns J/K/L) and All In (columns V/W/X)
expect(ws.getCell("J8").value).toBeCloseTo(rows[1].trf.bid, 10);
expect(ws.getCell("K8").value).toBeCloseTo(rows[1].trf.mark, 10);
expect(ws.getCell("V8").value).toBeCloseTo(0.87, 10);
expect(ws.getCell("V8").numFmt).toBe("0.00%");
expect(ws.getCell("J8").numFmt).toBe("#,##0.00");
});
it("colours cells like the grid and outlines the solved slot", async () => {
const ws = await roundTrip();
const fill = (a: string) => (ws.getCell(a).fill as { fgColor?: { argb?: string } }).fgColor?.argb;
expect(fill("J7")).toBe("FFC9C4F3"); // Dec26 TRF bid: lit price
expect(fill("K7")).toBe("FFF6EBCF"); // mark
expect(fill("M7")).toBe("FFECF7F2"); // Dec26 Term Funding bid: solved assumption
// Dec26 solves funding: outline on top and left of Term Funding bid, none between Term and Forward Funding
expect(ws.getCell("M7").border?.top?.style).toBe("medium");
expect(ws.getCell("M7").border?.left?.style).toBe("medium");
expect(ws.getCell("O7").border?.right).toBeUndefined();
// Dec28 solves prices: its Fwd cells are outlined, its funding is not
expect(ws.getCell("D9").border?.left?.style).toBe("medium");
expect(ws.getCell("M9").border?.top).toBeUndefined();
});
});