← back to Govarbitrage

src/engines/valuation.test.ts

86 lines

import { describe, expect, it } from "vitest";
import { computeValuation } from "./valuation";

describe("computeValuation", () => {
  it("derives a full valuation ladder from a retail anchor", () => {
    const v = computeValuation({
      newRetail: 20000,
      condition: "USED_GOOD",
      quantity: 1,
      demandScore: 70,
      identificationConfidence: 0.9,
      comparableCount: 6,
    });

    // Used-good sits at ~46% of retail.
    expect(v.usedSoldPrice).toBeCloseTo(9200, 0);
    expect(v.usedAskingPrice).toBeGreaterThan(v.usedSoldPrice);
    expect(v.usedLow).toBeLessThan(v.usedSoldPrice);
    expect(v.usedHigh).toBeGreaterThan(v.usedSoldPrice);
    // Channel ordering: liquidation < wholesale < used.
    expect(v.liquidationValue).toBeLessThan(v.wholesaleValue);
    expect(v.wholesaleValue).toBeLessThan(v.usedSoldPrice);
    // Longer horizon fetches more than a fire sale.
    expect(v.value90Day).toBeGreaterThan(v.sellTodayValue);
    expect(v.expectedSalePrice).toBeGreaterThan(0);
  });

  it("scales expected sale price by quantity", () => {
    const one = computeValuation({
      newRetail: 500,
      condition: "LIKE_NEW",
      quantity: 1,
      demandScore: 50,
      identificationConfidence: 0.6,
    });
    const ten = computeValuation({
      newRetail: 500,
      condition: "LIKE_NEW",
      quantity: 10,
      demandScore: 50,
      identificationConfidence: 0.6,
    });
    expect(ten.expectedSalePrice).toBeCloseTo(one.expectedSalePrice * 10, 0);
  });

  it("gives higher confidence with more comparables and better ID", () => {
    const weak = computeValuation({
      newRetail: 1000,
      condition: "UNKNOWN",
      quantity: 1,
      demandScore: 40,
      identificationConfidence: 0.2,
      comparableCount: 0,
    });
    const strong = computeValuation({
      newRetail: 1000,
      condition: "USED_GOOD",
      quantity: 1,
      demandScore: 40,
      identificationConfidence: 0.95,
      comparableCount: 8,
    });
    expect(strong.confidenceScore).toBeGreaterThan(weak.confidenceScore);
    expect(strong.confidenceScore).toBeLessThanOrEqual(100);
  });

  it("rewards high demand with faster sale and higher probability", () => {
    const lowDemand = computeValuation({
      newRetail: 1000,
      condition: "USED_GOOD",
      quantity: 1,
      demandScore: 10,
      identificationConfidence: 0.7,
    });
    const highDemand = computeValuation({
      newRetail: 1000,
      condition: "USED_GOOD",
      quantity: 1,
      demandScore: 95,
      identificationConfidence: 0.7,
    });
    expect(highDemand.daysUntilSold).toBeLessThan(lowDemand.daysUntilSold);
    expect(highDemand.probabilityOfSale).toBeGreaterThan(lowDemand.probabilityOfSale);
  });
});