# Period Calculation

Learn how Best Price and Peak Price periods work, and how to configure them for your needs.

> **Entity ID tip:** `<home_name>` is a placeholder for your Tibber home display name in Home Assistant. Entity IDs are derived from the displayed name (localized), so the exact slug may differ. **Can't find a sensor?** Use the **[Entity Reference (All Languages)](sensor-reference.md)** to search by name in your language.

## Table of Contents

-   [Quick Start](#quick-start)
-   [How It Works](#how-it-works)
-   [Configuration Guide](#configuration-guide)
-   [Understanding Relaxation](#understanding-relaxation) → [Full Guide](period-relaxation.md)
-   [Common Scenarios](#common-scenarios)
-   [Troubleshooting](#troubleshooting)
-   [Advanced Topics](#advanced-topics)

---

## Quick Start

### What Are Price Periods?

The integration finds time windows when electricity is especially **cheap** (Best Price) or **expensive** (Peak Price):

-   <EntityRef id="best_price_period">Best Price Periods</EntityRef> 🟢 - When to run your dishwasher, charge your EV, or heat water
-   <EntityRef id="peak_price_period">Peak Price Periods</EntityRef> 🔴 - When to reduce consumption or defer non-essential loads

### Default Behavior

Out of the box, the integration:

1. **Best Price**: Finds cheapest 1-hour+ windows that are at least 5% below the daily average
2. **Peak Price**: Finds most expensive 30-minute+ windows that are at least 5% above the daily average
3. **Relaxation**: Automatically loosens filters if not enough periods are found

**Most users don't need to change anything!** The defaults work well for typical use cases.

<details>
<summary>ℹ️ Why do Best Price and Peak Price have different defaults?</summary>

The integration sets different **initial defaults** because the features serve different purposes:

**Best Price (60 min, 15% flex):**
- Longer duration ensures appliances can complete their cycles
- Stricter flex (15%) focuses on genuinely cheap times
- Use case: Running dishwasher, EV charging, water heating

**Peak Price (30 min, 20% flex):**
- Shorter duration acceptable for early warnings
- More flexible (20%) catches price spikes earlier
- Use case: Alerting to expensive periods, even brief ones

**You can adjust all these values** in the configuration if the defaults don't fit your use case. The asymmetric defaults simply provide good starting points for typical scenarios.
</details>

### Example Timeline

```
00:00 ████████████████ Best Price Period (cheap prices)
04:00 ░░░░░░░░░░░░░░░░ Normal
08:00 ████████████████ Peak Price Period (expensive prices)
12:00 ░░░░░░░░░░░░░░░░ Normal
16:00 ████████████████ Peak Price Period (expensive prices)
20:00 ████████████████ Best Price Period (cheap prices)
```

---

## How It Works

### The Basic Idea

Each day, the integration analyzes all 96 quarter-hourly price intervals and identifies **continuous time ranges** that meet specific criteria.

```mermaid
flowchart TD
    A["96 intervals per day"] --> B{"① Flexibility<br/><small>Close to MIN/MAX?</small>"}
    B -->|Yes| C{"② Distance<br/><small>Meaningfully different<br/>from average?</small>"}
    B -->|No| X1["❌ excluded"]
    C -->|Yes| D{"③ Duration<br/><small>≥ 60 min?</small>"}
    C -->|No| X2["❌ excluded"]
    D -->|Yes| E{"④ Level filter<br/><small>(optional)</small>"}
    D -->|No| X3["❌ too short"]
    E -->|Pass| F["⑤ Spike smoothing"]
    E -->|Fail| X4["❌ filtered"]
    F --> G["✅ Period found"]

    style A fill:#e6f7ff,stroke:#00b9e7,stroke-width:2px
    style G fill:#e6fff5,stroke:#00c853,stroke-width:2px
    style X1 fill:#fff0f0,stroke:#ff5252,stroke-width:1px,color:#999
    style X2 fill:#fff0f0,stroke:#ff5252,stroke-width:1px,color:#999
    style X3 fill:#fff0f0,stroke:#ff5252,stroke-width:1px,color:#999
    style X4 fill:#fff0f0,stroke:#ff5252,stroke-width:1px,color:#999
```

Think of it like this:

1. **Find potential windows** - Times close to the daily MIN (Best Price) or MAX (Peak Price)
2. **Filter by quality** - Ensure they're meaningfully different from average
3. **Check duration** - Must be long enough to be useful
4. **Apply preferences** - Optional: only show stable prices, avoid mediocre times

### Step-by-Step Process

#### 1. Define the Search Range (Flexibility)

**Best Price:** How much MORE than the daily minimum can a price be?

```
Daily MIN: 20 ct/kWh
Flexibility: 15% (default)
→ Search for times ≤ 23 ct/kWh (20 + 15%)
```

**Peak Price:** How much LESS than the daily maximum can a price be?

```
Daily MAX: 40 ct/kWh
Flexibility: -15% (default)
→ Search for times ≥ 34 ct/kWh (40 - 15%)
```

**Why flexibility?** Prices rarely stay at exactly MIN/MAX. Flexibility lets you capture realistic time windows.

#### 2. Ensure Quality (Distance from Average)

Periods must be meaningfully different from the daily average:

```
Daily AVG: 30 ct/kWh
Minimum distance: 5% (default)

Best Price: Must be ≤ 28.5 ct/kWh (30 - 5%)
Peak Price: Must be ≥ 31.5 ct/kWh (30 + 5%)
```

**Why?** This prevents marking mediocre times as "best" just because they're slightly below average.

#### 3. Check Duration

Periods must be long enough to be practical:

```
Default: 60 minutes minimum

45-minute period → Discarded
90-minute period → Kept ✓
```

#### 4. Apply Optional Filters

You can optionally require:

-   **Absolute quality** (level filter) - "Only show if prices are CHEAP/EXPENSIVE (not just below/above average)"

#### 5. Automatic Price Spike Smoothing

Isolated price spikes are automatically detected and smoothed to prevent unnecessary period fragmentation:

```
Original prices: 18, 19, 35, 20, 19 ct   ← 35 ct is an isolated outlier
Smoothed:        18, 19, 19, 20, 19 ct   ← Spike replaced with trend prediction

Result: Continuous period 00:00-01:15 instead of split periods
```

**Important:**
-   Original prices are always preserved (min/max/avg show real values)
-   Smoothing only affects which intervals are combined into periods
-   The attribute `period_interval_smoothed_count` shows if smoothing was active

### Visual Example

**Timeline for a typical day:**

```
Hour:  00  01  02  03  04  05  06  07  08  09  10  11  12  13  14  15  16  17  18  19  20  21  22  23
Price: 18  19  20  28  29  30  35  34  33  32  30  28  25  24  26  28  30  32  31  22  21  20  19  18

Daily MIN: 18 ct | Daily MAX: 35 ct | Daily AVG: 26 ct

Best Price (15% flex = ≤20.7 ct):
       ████████                                                                        ████████████████
       00:00-03:00 (3h)                                                               19:00-24:00 (5h)

Peak Price (-15% flex = ≥29.75 ct):
                              ████████████████████████
                              06:00-11:00 (5h)
```

---

## Configuration Guide

### Basic Settings

#### Flexibility

**What:** How far from MIN/MAX to search for periods
**Default:** 15% (Best Price), -15% (Peak Price)
**Range:** 0-100%

```yaml
best_price_flex: 15 # Can be up to 15% more expensive than daily MIN
peak_price_flex: -15 # Can be up to 15% less expensive than daily MAX
```

**When to adjust:**

-   **Increase (20-25%)** → Find more/longer periods
-   **Decrease (5-10%)** → Find only the very best/worst times

**💡 Tip:** Very high flexibility (>30%) is rarely useful. **Recommendation:** Start with 15-20% and enable relaxation – it adapts automatically to each day's price pattern.

#### Minimum Period Length

**What:** How long a period must be to show it
**Default:** 60 minutes (Best Price), 30 minutes (Peak Price)
**Range:** 15-240 minutes

```yaml
best_price_min_period_length: 60
peak_price_min_period_length: 30
```

**When to adjust:**

-   **Increase (90-120 min)** → Only show longer periods (e.g., for heat pump cycles)
-   **Decrease (30-45 min)** → Show shorter windows (e.g., for quick tasks)

#### Distance from Average

**What:** How much better than average a period must be
**Default:** 5%
**Range:** 0-20%

```yaml
best_price_min_distance_from_avg: 5
peak_price_min_distance_from_avg: 5
```

**When to adjust:**

-   **Increase (5-10%)** → Only show clearly better times
-   **Decrease (0-1%)** → Show any time below/above average

**ℹ️ Note:** Both flexibility and distance filters must be satisfied. When using high flexibility values (>30%), the distance filter may become the limiting factor. For best results, use moderate flexibility (15-20%) with relaxation enabled.

### Optional Filters

#### Level Filter (Absolute Quality)

**What:** Only show periods with CHEAP/EXPENSIVE intervals (not just below/above average)
**Default:** `any` (disabled)
**Options:** `any` | `cheap` | `very_cheap` (Best Price) | `expensive` | `very_expensive` (Peak Price)

```yaml
best_price_max_level: any      # Show any period below average
best_price_max_level: cheap    # Only show if at least one interval is CHEAP
```

**Use case:** "Only notify me when prices are objectively cheap/expensive"

**ℹ️ Volatility Thresholds:** The level filter also supports volatility-based levels (`volatility_low`, `volatility_medium`, `volatility_high`). These use **fixed internal thresholds** (LOW < 10%, MEDIUM < 20%, HIGH ≥ 20%) that are separate from the sensor volatility thresholds you configure in the UI. This separation ensures that changing sensor display preferences doesn't affect period calculation behavior.

#### Gap Tolerance (for Level Filter)

**What:** Allow some "mediocre" intervals within an otherwise good period
**Default:** 0 (strict)
**Range:** 0-10

```yaml
best_price_max_level: cheap
best_price_max_level_gap_count: 2 # Allow up to 2 NORMAL intervals per period
```

**Use case:** "Don't split periods just because one interval isn't perfectly CHEAP"

### Tweaking Strategy: What to Adjust First?

When you're not happy with the default behavior, adjust settings in this order:

#### 1. **Start with Relaxation (Easiest)**

If you're not finding enough periods:

```yaml
enable_min_periods_best: true   # Already default!
min_periods_best: 2             # Already default!
relaxation_attempts_best: 11    # Already default!
```

**Why start here?** Relaxation automatically finds the right balance for each day. Much easier than manual tuning.

#### 2. **Adjust Period Length (Simple)**

If periods are too short/long for your use case:

```yaml
best_price_min_period_length: 90  # Increase from 60 for longer periods
# OR
best_price_min_period_length: 45  # Decrease from 60 for shorter periods
```

**Safe to change:** This only affects duration, not price selection logic.

#### 3. **Fine-tune Flexibility (Moderate)**

If you consistently want more/fewer periods:

```yaml
best_price_flex: 20  # Increase from 15% for more periods
# OR
best_price_flex: 10  # Decrease from 15% for stricter selection
```

**⚠️ Watch out:** Values >25% may conflict with distance filter. Use relaxation instead.

#### 4. **Adjust Distance from Average (Advanced)**

Only if periods seem "mediocre" (not really cheap/expensive):

```yaml
best_price_min_distance_from_avg: 10  # Increase from 5% for stricter quality
```

**⚠️ Careful:** High values (>10%) can make it impossible to find periods on flat price days.

#### 5. **Enable Level Filter (Expert)**

Only if you want absolute quality requirements:

```yaml
best_price_max_level: cheap  # Only show objectively CHEAP periods
```

**⚠️ Very strict:** Many days may have zero qualifying periods. **Always enable relaxation when using this!**

### Common Mistakes to Avoid

❌ **Don't increase flexibility to >30% manually** → Use relaxation instead
❌ **Don't combine high distance (>10%) with strict level filter** → Too restrictive
❌ **Don't disable relaxation with strict filters** → You'll get zero periods on some days
❌ **Don't change all settings at once** → Adjust one at a time and observe results

✅ **Do use defaults + relaxation** → Works for 90% of cases
✅ **Do adjust one setting at a time** → Easier to understand impact
✅ **Do check sensor attributes** → Shows why periods were/weren't found

---

## Understanding Relaxation

Sometimes strict filters find too few periods. **Relaxation automatically loosens filters** until a minimum number of periods is found — enabled by default.

**Key benefits:**
- Each day gets exactly the flexibility it needs (per-day independence)
- Uses a matrix approach: N flex levels × 2 filter combinations
- Stops as soon as enough periods are found

**→ [Full Relaxation Guide](period-relaxation.md)** — How it works, the adaptive matrix, choosing attempts, and diagnostics.

---

## Common Scenarios

### Scenario 1: Simple Best Price (Default)

**Goal:** Find the cheapest time each day to run dishwasher

**Configuration:**

```yaml
# Use defaults - no configuration needed!
best_price_flex: 15 # (default)
best_price_min_period_length: 60 # (default)
best_price_min_distance_from_avg: 5 # (default)
```

**What you get:**

-   1-3 periods per day with prices ≤ MIN + 15%
-   Each period at least 1 hour long
-   All periods at least 5% cheaper than daily average

**Automation example:**

```yaml
automation:
    - trigger:
          - platform: state
            entity_id: binary_sensor.<home_name>_best_price_period
            to: "on"
      action:
          - service: switch.turn_on
            target:
                entity_id: switch.dishwasher
```

---

## Troubleshooting

### Fewer Periods Than Configured

**Symptom:** You configured `min_periods_best: 2` but the sensor shows fewer periods on some days, and the attributes contain `flat_days_detected: 1` or `relaxation_incomplete: true`.

**If `flat_days_detected` is present:**

This is **expected behavior** on days with very uniform electricity prices. When prices vary by less than ~10% across the day (e.g. on sunny spring days with high solar generation), there is no meaningful second "cheap window" – all hours are equally cheap. The integration automatically reduces the target to 1 period for that day.

```yaml
min_periods_configured: 2
periods_found_total: 1
flat_days_detected: 1    # Uniform prices today → 1 period is the right answer
```

You don't need to change anything. This is the integration protecting you from artificial periods.

**If `relaxation_incomplete` is present (without `flat_days_detected`):**

Relaxation tried all configured attempts but couldn't reach your target. Options:

1. **Increase relaxation attempts** (tries more flexibility levels before giving up)
   ```yaml
   relaxation_attempts_best: 12  # Default: 11
   ```

2. **Reduce minimum period count**
   ```yaml
   min_periods_best: 1  # Only require 1 period per day
   ```

3. **Check filter settings** – very strict `best_price_min_distance_from_avg` values block relaxation

---

### No Periods Found

**Symptom:** `binary_sensor.<home_name>_best_price_period` never turns "on"

**Common Solutions:**

1. **Check if relaxation is enabled**
   ```yaml
   enable_min_periods_best: true  # Should be true (default)
   min_periods_best: 2  # Try to find at least 2 periods
   ```

2. **If still no periods, check filters**
   - Look at sensor attributes: `relaxation_active` and `relaxation_level`
   - If relaxation exhausted all attempts: Filters too strict or flat price day

3. **Try increasing flexibility slightly**
   ```yaml
   best_price_flex: 20  # Increase from default 15%
   ```

4. **Or reduce period length requirement**
   ```yaml
   best_price_min_period_length: 45  # Reduce from default 60 minutes
   ```

### Periods Split Into Small Pieces

**Symptom:** Many short periods instead of one long period

**Common Solutions:**

1. **If using level filter, add gap tolerance**
   ```yaml
   best_price_max_level: cheap
   best_price_max_level_gap_count: 2  # Allow 2 NORMAL intervals
   ```

2. **Slightly increase flexibility**
   ```yaml
   best_price_flex: 20  # From 15% → captures wider price range
   ```

3. **Check for price spikes**
   - Automatic smoothing should handle this
   - Check attribute: `period_interval_smoothed_count`
   - If 0: Not isolated spikes, but real price levels

### Understanding Sensor Attributes

**Key attributes to check:**

<details>
<summary>Show YAML: Sensor attribute reference for best_price_period</summary>

```yaml
# Entity: binary_sensor.<home_name>_best_price_period

# When "on" (period active):
start: "2025-11-11T02:00:00+01:00"  # Period start time
end: "2025-11-11T05:00:00+01:00"    # Period end time
duration_minutes: 180                # Duration in minutes
price_mean: 18.5                     # Arithmetic mean price in the period
price_median: 18.3                   # Median price in the period
rating_level: "LOW"                  # All intervals have LOW rating

# Relaxation info (shows if filter loosening was needed):
relaxation_active: true              # This day needed relaxation
relaxation_level: "price_diff_18.0%+level_any"  # Found at 18% flex, level filter removed

# Calculation summary (always shown – diagnostic overview of this calculation run):
min_periods_configured: 2           # What you configured as target
periods_found_total: 3              # What was actually found across all days

# Optional (only shown when relevant):
period_interval_smoothed_count: 2    # Number of price spikes smoothed
period_interval_level_gap_count: 1   # Number of "mediocre" intervals tolerated
flat_days_detected: 1               # Days where prices were so flat that 1 period is enough
relaxation_incomplete: true         # Some days couldn't reach the configured target
```

</details>

#### What the diagnostic attributes mean

**`min_periods_configured` / `periods_found_total`**

These two values together quickly show whether the calculation achieved its goal:

```yaml
min_periods_configured: 2   # You asked for 2 periods per day
periods_found_total: 6      # 3 days × 2 periods = fully satisfied ✅
```

```yaml
min_periods_configured: 2
periods_found_total: 5      # 3 days, but one day got only 1 period
```

Note that `periods_found_total` counts **all periods across today and tomorrow** – so 4 on a two-day view means 2 per day on average.

**`flat_days_detected`**

This is the most important diagnostic for days with very uniform prices (e.g. sunny spring/summer days with high solar generation):

```yaml
min_periods_configured: 2
periods_found_total: 1
flat_days_detected: 1       # ← This explains why you got 1 instead of 2
```

When prices barely change across the day – typically a variation of less than 10% – the integration automatically reduces the target from your configured value to 1. There is no meaningful second "best price window" when all prices are essentially equal.

**This is expected and correct behavior**, not a problem. It prevents the sensor from generating artificial periods that don't represent genuinely cheaper windows.

**`relaxation_incomplete`**

This flag appears when even after all relaxation attempts, at least one day could not reach the configured minimum number of periods:

```yaml
min_periods_configured: 2
periods_found_total: 1
relaxation_incomplete: true  # ← Relaxation tried everything, still short
```

This is most common on very flat days (see above) or with very strict filter settings. If you see this repeatedly on normal days, consider:
- Reducing `min_periods_best` to 1
- Increasing `relaxation_attempts_best`
- Checking if your `best_price_min_distance_from_avg` is too high

### Midnight Price Classification Changes

**Symptom:** A Best Price period at 23:45 suddenly changes to Peak Price at 00:00 (or vice versa), even though the absolute price barely changed.

**Why This Happens:**

This is **mathematically correct behavior** caused by how electricity prices are set in the day-ahead market:

**Market Timing:**
- The EPEX SPOT Day-Ahead auction closes at **12:00 CET** each day
- **All prices** for the next day (00:00-23:45) are set at this moment
- Late-day intervals (23:45) are priced **~36 hours before delivery**
- Early-day intervals (00:00) are priced **~12 hours before delivery**

**Why Prices Jump at Midnight:**
1. **Forecast Uncertainty:** Weather, demand, and renewable generation forecasts are more uncertain 36 hours ahead than 12 hours ahead
2. **Risk Buffer:** Late-day prices include a risk premium for this uncertainty
3. **Independent Days:** Each day has its own min/max/avg calculated from its 96 intervals
4. **Relative Classification:** Periods are classified based on their **position within the day's price range**, not absolute prices

**Example:**

<details>
<summary>Show YAML: How identical prices can flip between best/peak across midnight</summary>

```yaml
# Day 1 (low volatility, narrow range)
Price range: 18-22 ct/kWh (4 ct span)
Daily average: 20 ct/kWh
23:45: 18.5 ct/kWh → 7.5% below average → BEST PRICE ✅

# Day 2 (low volatility, narrow range)
Price range: 17-21 ct/kWh (4 ct span)
Daily average: 19 ct/kWh
00:00: 18.6 ct/kWh → 2.1% below average → PEAK PRICE ❌

# Observation: Absolute price barely changed (18.5 → 18.6 ct)
# But relative position changed dramatically:
# - Day 1: Near the bottom of the range
# - Day 2: Near the middle/top of the range
```

</details>

**When This Occurs:**
- **Low-volatility days:** When price span is narrow (< 5 ct/kWh)
- **Stable weather:** Similar conditions across multiple days
- **Market transitions:** Switching between high/low demand seasons

**How to Detect:**

Check the volatility sensors to understand if a period flip is meaningful:

```yaml
# Check daily volatility (available in integration)
sensor.<home_name>_today_s_price_volatility: 8.2%     # Low volatility
sensor.<home_name>_tomorrow_s_price_volatility: 7.9%  # Also low

# Low volatility (< 15%) means:
# - Small absolute price differences between periods
# - Classification changes may not be economically significant
# - Consider ignoring period classification on such days
```

**Handling in Automations:**

You can make your automations volatility-aware:

<details>
<summary>Show YAML: 3 automation strategies for volatility-aware period control</summary>

```yaml
# Option 1: Only act on high-volatility days
automation:
  - alias: "Dishwasher - Best Price (High Volatility Only)"
    trigger:
      - platform: state
        entity_id: binary_sensor.<home_name>_best_price_period
        to: "on"
    condition:
      - condition: numeric_state
        entity_id: sensor.<home_name>_today_s_price_volatility
        above: 15  # Only act if volatility > 15%
    action:
      - service: switch.turn_on
        entity_id: switch.dishwasher

# Option 2: Check absolute price, not just classification
automation:
  - alias: "Heat Water - Cheap Enough"
    trigger:
      - platform: state
        entity_id: binary_sensor.<home_name>_best_price_period
        to: "on"
    condition:
      - condition: numeric_state
        entity_id: sensor.<home_name>_current_electricity_price
        below: 20  # Absolute threshold: < 20 ct/kWh
    action:
      - service: switch.turn_on
        entity_id: switch.water_heater

# Option 3: Use per-period day volatility (available on period sensors)
automation:
  - alias: "EV Charging - Volatility-Aware"
    trigger:
      - platform: state
        entity_id: binary_sensor.<home_name>_best_price_period
        to: "on"
    condition:
      # Check if the period's day has meaningful volatility
      - condition: template
        value_template: >
          {{ state_attr('binary_sensor.<home_name>_best_price_period', 'day_volatility_%') | float(0) > 15 }}
    action:
      - service: switch.turn_on
        entity_id: switch.ev_charger
```

</details>

**Available Per-Period Attributes:**

Each period sensor exposes day volatility and price statistics:

```yaml
binary_sensor.<home_name>_best_price_period:
  day_volatility_%: 8.2         # Volatility % of the period's day
  day_price_min: 1800.0          # Minimum price of the day (ct/kWh)
  day_price_max: 2200.0          # Maximum price of the day (ct/kWh)
  day_price_span: 400.0          # Difference (max - min) in ct
```

These attributes allow automations to check: "Is the classification meaningful on this particular day?"

**Summary:**
- ✅ **Expected behavior:** Periods are evaluated per-day, midnight is a natural boundary
- ✅ **Market reality:** Late-day prices have more uncertainty than early-day prices
- ✅ **Solution:** Use volatility sensors, absolute price thresholds, or per-period day volatility attributes

---

## Advanced Topics

For advanced configuration patterns and technical deep-dive, see:

-   [Automation Examples](./automation-examples.md) - Real-world automation patterns
-   [Actions](./actions.md) - Using the `tibber_prices.get_chartdata` action for custom visualizations

### Quick Reference

**Configuration Parameters:**

| Parameter                          | Default | Range            | Purpose                        |
| ---------------------------------- | ------- | ---------------- | ------------------------------ |
| `best_price_flex`                  | 15%     | 0-100%           | Search range from daily MIN    |
| `best_price_min_period_length`     | 60 min  | 15-240           | Minimum duration               |
| `best_price_min_distance_from_avg` | 5%      | 0-20%            | Quality threshold              |
| `best_price_max_level`             | any     | any/cheap/vcheap | Absolute quality               |
| `best_price_max_level_gap_count`   | 0       | 0-10             | Gap tolerance                  |
| `enable_min_periods_best`          | true    | true/false       | Enable relaxation              |
| `min_periods_best`                 | 2       | 1-10             | Target periods per day         |
| `relaxation_attempts_best`         | 11      | 1-12             | Flex levels (attempts) per day |

**Peak Price:** Same parameters with `peak_price_*` prefix (defaults: flex=-15%, same otherwise)

### Price Levels Reference

The Tibber API provides price levels for each 15-minute interval:

**Levels (based on trailing 24h average):**

-   `VERY_CHEAP` - Significantly below average
-   `CHEAP` - Below average
-   `NORMAL` - Around average
-   `EXPENSIVE` - Above average
-   `VERY_EXPENSIVE` - Significantly above average
