DEV Community

Ali Gürtuna | AGProLabs
Ali Gürtuna | AGProLabs

Posted on Fully Autonomous

A dashboard metric needs units, provenance and a failure state

A dashboard can display two valid numbers and still make an invalid comparison.

Consider three synthetic observations: 500 shares, 500 futures contracts and 500 tick events. They all fit in a JavaScript number. They do not measure the same thing.

The engineering problem starts when an adapter discards metadata and hands the UI only a numeric value. A formatter adds a compact suffix, a table sorts descending, and the screen makes unlike measurements look equivalent.

This article introduces a small comparison contract. It is a standalone educational JavaScript example, not the implementation of a TradingView script or a live market feed.

A metric is more than its number

Carry the measurement definition through the ingestion, validation and rendering layers:

Field What the consumer needs to know
metric What was measured: turnover, volume, count or something else
unit Shares, contracts, quote currency, tick events, etc.
currency The denomination, or an explicit non-applicable marker
interval The aggregation window
session The session coverage used by that observation
basisId A trusted identifier for the measurement methodology
freshness Whether a separate freshness policy has established currentness

The basis identifier matters. Two sources can both say “contracts” while referring to different contract specifications. Two providers can use the same display label for different aggregation methods. A label is necessary metadata; it is not evidence of equivalent semantics.

Your adapter should assign the basis from a reviewed source contract. Do not let arbitrary user input or an untrusted payload declare two methods equivalent.

Return a state before returning a difference

The UI needs to distinguish missing evidence from a valid difference. This function returns one of three states:

  • unavailable: a number, metadata or freshness evidence is missing or invalid;
  • incomparable: both records are populated, but their declared contracts differ;
  • comparable: the declared contract matches and a finite difference can be calculated.
function compareMetric(a, b) {
  const keys = [
    "metric", "unit", "currency", "interval", "session", "basisId"
  ];
  for (const x of [a, b]) {
    if (!x || typeof x.value !== "number" ||
        !Number.isFinite(x.value)) {
      return { state: "unavailable", reason: "invalid-number" };
    }
    if (keys.some(k => typeof x[k] !== "string" || !x[k].trim())) {
      return { state: "unavailable", reason: "missing-metadata" };
    }
    if (x.freshness !== "fresh") {
      return { state: "unavailable", reason: "freshness-not-established" };
    }
  }
  const different = keys.filter(k => a[k] !== b[k]);
  if (different.length) {
    return { state: "incomparable", fields: different };
  }
  const delta = a.value - b.value;
  return Number.isFinite(delta)
    ? { state: "comparable", delta }
    : { state: "unavailable", reason: "numeric-overflow" };
}
Enter fullscreen mode Exit fullscreen mode

A real adapter must also enforce allowed metric/unit combinations and verify that the declared basis is trustworthy. This example deliberately does not fetch data, infer units or convert currencies.

Try a synthetic fixture

const baseline = {
  value: 100,
  metric: "turnover",
  unit: "quote-currency",
  currency: "USD",
  interval: "1h",
  session: "regular",
  basisId: "synthetic:quote-turnover-v1",
  freshness: "fresh"
};

compareMetric({ ...baseline, value: 120 }, baseline);
// { state: "comparable", delta: 20 }

compareMetric({ ...baseline, currency: "EUR" }, baseline);
// { state: "incomparable", fields: ["currency"] }

compareMetric({ ...baseline, freshness: "unknown" }, baseline);
// { state: "unavailable", reason: "freshness-not-established" }
Enter fullscreen mode Exit fullscreen mode

The freshness flag is an input to this contract, not a freshness detector. Production code still needs an explicit timestamp, clock-skew tolerance, calendar/session policy and age threshold. Never substitute the browser's latest refresh time for the source observation time.

The isolated example passed 11 synthetic checks: a matching basis, different currency, different unit, different methodology, different interval, different session, unknown freshness, missing metadata, null value, non-finite value and subtraction overflow. Those checks do not validate a vendor feed or prove a production dashboard is correct.

Rendering rules that preserve meaning

When the state is unavailable, show a text reason rather than a fabricated zero. When it is incomparable, retain the original values and explain the differing fields. Do not calculate a ranking from the rejected comparison.

Keep the raw value and its provenance available for inspection. Format a copy for display; rounding should not silently rewrite the measurement used by the model. A cached record should retain its original source metadata and observation time.

A compatible contract establishes only this narrow arithmetic comparison. It does not establish liquidity, execution quality, investment suitability or predictive value.

Apply this to a market-review interface

Commodity feed selection provides a practical example: cash quotes, continuous futures, dated contracts and ETFs can need different source contracts. Our commodity screening guide explains the instrument and volume-unit checks from the user side. Our relative volume versus liquidity guide covers another common interpretation error.

Disclosure: I am the founder of AGProLabs. Crypto Setup Planner is our TradingView candidate-screening product; this article's JavaScript is a separate educational example, not its source code. The article and example were prepared with AI assistance. Trading involves risk; analytical outputs do not guarantee outcomes.

Top comments (0)