Display Rules

Display rules tell the AI exactly how to format individual data fields. No guessing, no hallucinated precision, no misplaced decimal points.

Why display rules matter

When an AI presents the number 0.1247, should it say "12.47%", "0.12", "12%", or "about 12 and a half percent"? Display rules eliminate this ambiguity. The data provider specifies the exact format, and the runtime enforces it.

Format types

The format.type field determines how a value is rendered:

percentage

Multiplies by 100 and appends %. Supports precision and sign control.

{
  "scope": ["returns.*"],
  "format": {
    "type": "percentage",
    "precision": 2,
    "sign": "always"
  }
}
// 0.1247 → "+12.47%"

currency

Formats as a monetary value with symbol and precision. The currency can be read from another field.

{
  "scope": ["price.current"],
  "format": {
    "type": "currency",
    "precision": 2,
    "currency_field": "price.currency",
    "symbol_position": "before"
  }
}
// 423.17 → "$423.17"

number

Plain numeric formatting with configurable precision, rounding, and grouping.

{
  "scope": ["market_cap"],
  "format": {
    "type": "number",
    "precision": 0,
    "grouping": true
  }
}
// 2450000000 → "2,450,000,000"

date

Formats timestamps using strftime-compatible format strings.

{
  "scope": ["last_updated"],
  "format": {
    "type": "date",
    "format": "%B %d, %Y",
    "timezone": "America/New_York"
  }
}

ordinal_scale

Renders numeric values as visual scales (star ratings, risk gauges).

{
  "scope": ["risk_rating"],
  "format": {
    "type": "ordinal_scale",
    "min": 1,
    "max": 5,
    "display_as": "★",
    "unit": "risk"
  }
}
// 3 → "★★★ (3/5 risk)"

Labels

Labels provide human-readable names for fields. They can be verbatim (must use exactly) or flexible (AI can rephrase):

"label": {
  "text": "1-Year Return",
  "verbatim": true,
  "alternatives": ["1Y Return", "One-Year Return"]
}

context_required

Lists other fields that must be presented alongside this field. If the AI shows a return figure, it might be required to also show the time period and benchmark:

"context_required": ["returns.benchmark", "returns.as_of_date"]

suppress_if

Conditionally hides a field based on another field's value. For example, suppress projected returns if the fund is closed:

"suppress_if": {
  "field": "fund_status",
  "operator": "eq",
  "value": "closed"
}