DEV Community

Sarah-Anne Ndlovu
Sarah-Anne Ndlovu

Posted on

Building DiamondScope: reverse-engineering South African diamond pricing in TypeScript

The Rapaport wholesale diamond price list is paywalled and trade-only. South African retail buyers cannot translate any quote they receive to its underlying wholesale cost. The result: chain retail jewellers can mark stones up 100 to 150 percent over the manufacturer-direct price and the buyer has no way to spot it.

I just shipped a free open-source tool that fixes that asymmetry. It is at naturaldiamond.co.za/diamondscope/ and the engine is on GitHub at awenroswer2443-dot/diamondscope-engine.

This post is a quick technical writeup on the engine design.

The thesis

Most diamond pricing tools are: input filter, then show inventory. DiamondScope flips that: input a chain-retail price, output the spec inferred behind it and the channel-spread breakdown.

Given a spec (shape, carat, colour, clarity, cut) the engine returns:

  1. The Rapaport-equivalent ZAR baseline.
  2. The expected price across manufacturer-direct, boutique retail, and chain retail.
  3. Per-retailer quotes for the major South African jewellers.
  4. Adjacent-spec deltas (drop one colour grade, save R7,400).
  5. Editorial commentary.
  6. A confidence indicator for the baseline.

It runs entirely client-side. No backend.

The math

The core baseline is a single per-stone Rapaport-equivalent ZAR value for a 1.00 ct round brilliant, G colour, SI1 clarity, GIA Excellent cut. All other specs scale from there.

const RAPAPORT_BASELINE_ZAR = 100_000;

export function rapaportZAR(spec: DiamondSpec): number {
  const caratCoeff = interpolateCaratCoefficient(spec.carat);
  const colourMult = COLOUR_MULTIPLIER[spec.colour];
  const clarityMult = CLARITY_MULTIPLIER[spec.clarity];
  const cutMult = CUT_MULTIPLIER[spec.cut];
  const shapeMult = SHAPE_MULTIPLIER[spec.shape];
  return Math.round(
    RAPAPORT_BASELINE_ZAR * caratCoeff * colourMult * clarityMult * cutMult * shapeMult,
  );
}
Enter fullscreen mode Exit fullscreen mode

Carat coefficient anchors are calibrated from published per-spec ranges on naturaldiamond.co.za/1-carat-diamond-price-south-africa/, the 2-carat page, and the 3-carat page. Between anchors, linear interpolation.

Colour, clarity, cut, and shape multipliers are calibrated against the same published ranges, then validated against a hand-checked sample.

Channel premiums

The three channels each get a multiplier:

  • Manufacturer-direct: 0.55 to 0.75 of Rap (mid 0.65). RAP-minus 25 to 45 percent.
  • Boutique retail: 0.80 to 1.05 of Rap (mid 0.92). RAP-minus 5 to 20 percent.
  • Chain retail: 0.55 to 1.20 of Rap (mid 0.85). Highly variable.

Chain retail variance is structural. Chain retailers often drop the cut grade from Excellent to Very Good at the same nominal price point, which compresses the headline price toward the manufacturer-direct number even though the stone is quietly worse.

Per-retailer premiums

The engine ships with nine calibrated South African retailer entries (Prodiam, Nungu, Jack Friedman, Charles Greig, Shimansky, Browns, American Swiss, Sterns, NWJ). Each has an ofRapaport multiplier and channel classification. The data is in SA_RETAILER_PREMIUMS and gets refreshed quarterly.

URL state encoding

Every DiamondScope result is shareable. The spec is encoded in URL query params so any link regenerates the same result on the recipient's device. The page hydrates from URL on load:

const query = new URLSearchParams(window.location.search);
const fromQuery = parseSpecFromQuery(query);
if (fromQuery) state.spec = fromQuery;
Enter fullscreen mode Exit fullscreen mode

Why TypeScript

The pricing data is highly enum-shaped (4 colour grades, 9 clarity grades, 4 cut grades, 10 shapes). TypeScript's literal-type unions catch every grade lookup miss at compile time. The data files essentially document themselves through their type definitions.

Source

Feedback welcome. Especially on the calibration data; if you have ground-truth manufacturer-direct quotes that differ from the engine's estimates, open an issue with the spec and the actual quote and I will tune the coefficients.

Top comments (0)