Files
investor-flow/app/src/__tests__/volumeProfile.test.ts
T

54 lines
1.7 KiB
TypeScript
Raw Normal View History

import { describe, it } from "node:test";
import assert from "node:assert/strict";
import { buildVolumeProfile } from "../lib/volumeProfile.ts";
describe("buildVolumeProfile", () => {
it("returns empty for no candles", () => {
const r = buildVolumeProfile([]);
assert.equal(r.bins.length, 0);
assert.equal(r.totalVolume, 0);
assert.equal(r.pocMid, null);
});
it("returns empty for zero volume", () => {
const r = buildVolumeProfile([{ h: 10, l: 9, v: 0 }]);
assert.equal(r.bins.length, 0);
});
it("preserves total volume across bins", () => {
const candles = [
{ h: 12, l: 10, v: 100 },
{ h: 11, l: 9, v: 200 },
{ h: 14, l: 13, v: 50 },
];
const r = buildVolumeProfile(candles, { bins: 10 });
const sum = r.bins.reduce((a, b) => a + b.volume, 0);
assert.ok(Math.abs(sum - 350) < 1e-6, `sum=${sum}`);
assert.equal(r.totalVolume, 350);
});
it("poc is the max volume bin mid", () => {
// All volume at the high end
const candles = [
{ h: 20, l: 19, v: 1000 },
{ h: 11, l: 10, v: 10 },
];
const r = buildVolumeProfile(candles, { bins: 8 });
assert.ok(r.pocMid != null);
const maxBin = r.bins.reduce((a, b) => (b.volume > a.volume ? b : a));
assert.equal(r.pocMid, maxBin.mid);
assert.ok(r.pocMid! >= 15, `poc should sit high, got ${r.pocMid}`);
});
it("sets vah/val around value area", () => {
const candles = Array.from({ length: 20 }, (_, i) => ({
h: 100 + i * 0.5,
l: 99 + i * 0.5,
v: i === 10 ? 500 : 20,
}));
const r = buildVolumeProfile(candles, { bins: 16, valueAreaPct: 0.7 });
assert.ok(r.vah != null && r.val != null);
assert.ok(r.vah! >= r.val!);
});
});