feat(config_flow): add configurable hysteresis and gap tolerance for price ratings

Added UI controls for price rating stabilization parameters that were
previously hardcoded. Users can now fine-tune rating stability to match
their automation needs.

Changes:
- Added CONF_PRICE_RATING_HYSTERESIS constant (0-5%, step 0.5%, default 2%)
- Added CONF_PRICE_RATING_GAP_TOLERANCE constant (0-4 intervals, default 1)
- Extended get_price_rating_schema() with two new sliders
- Updated data_transformation.py to pass both parameters to enrichment function
- Improved descriptions in all 5 languages (de, en, nb, nl, sv) to focus on
  automation stability instead of chart appearance
- Both settings included in factory reset via get_default_options()

Hysteresis explanation: Prevents rapid state changes when prices hover near
thresholds (e.g., LOW requires price > threshold+hysteresis to leave).

Gap tolerance explanation: Merges small isolated rating blocks into dominant
neighboring blocks using "look through" algorithm (fixed in previous commit).

Impact: Users can now adjust rating stability for their specific use cases.
Lower hysteresis (0-1%) for responsive automations, higher (3-5%) for stable
long-running processes. Gap tolerance prevents brief rating spikes from
triggering unnecessary automation actions.
This commit is contained in:
Julian Pawlowski 2025-12-22 13:54:10 +00:00
parent 64cf842719
commit f57997b119
8 changed files with 114 additions and 39 deletions

View file

@ -28,6 +28,8 @@ from custom_components.tibber_prices.const import (
CONF_PEAK_PRICE_MIN_DISTANCE_FROM_AVG,
CONF_PEAK_PRICE_MIN_LEVEL,
CONF_PEAK_PRICE_MIN_PERIOD_LENGTH,
CONF_PRICE_RATING_GAP_TOLERANCE,
CONF_PRICE_RATING_HYSTERESIS,
CONF_PRICE_RATING_THRESHOLD_HIGH,
CONF_PRICE_RATING_THRESHOLD_LOW,
CONF_PRICE_TREND_THRESHOLD_FALLING,
@ -56,6 +58,8 @@ from custom_components.tibber_prices.const import (
DEFAULT_PEAK_PRICE_MIN_DISTANCE_FROM_AVG,
DEFAULT_PEAK_PRICE_MIN_LEVEL,
DEFAULT_PEAK_PRICE_MIN_PERIOD_LENGTH,
DEFAULT_PRICE_RATING_GAP_TOLERANCE,
DEFAULT_PRICE_RATING_HYSTERESIS,
DEFAULT_PRICE_RATING_THRESHOLD_HIGH,
DEFAULT_PRICE_RATING_THRESHOLD_LOW,
DEFAULT_PRICE_TREND_THRESHOLD_FALLING,
@ -73,6 +77,8 @@ from custom_components.tibber_prices.const import (
MAX_GAP_COUNT,
MAX_MIN_PERIOD_LENGTH,
MAX_MIN_PERIODS,
MAX_PRICE_RATING_GAP_TOLERANCE,
MAX_PRICE_RATING_HYSTERESIS,
MAX_PRICE_RATING_THRESHOLD_HIGH,
MAX_PRICE_RATING_THRESHOLD_LOW,
MAX_PRICE_TREND_FALLING,
@ -83,6 +89,8 @@ from custom_components.tibber_prices.const import (
MAX_VOLATILITY_THRESHOLD_VERY_HIGH,
MIN_GAP_COUNT,
MIN_PERIOD_LENGTH,
MIN_PRICE_RATING_GAP_TOLERANCE,
MIN_PRICE_RATING_HYSTERESIS,
MIN_PRICE_RATING_THRESHOLD_HIGH,
MIN_PRICE_RATING_THRESHOLD_LOW,
MIN_PRICE_TREND_FALLING,
@ -257,7 +265,7 @@ def get_display_settings_schema(options: Mapping[str, Any], currency_code: str |
def get_price_rating_schema(options: Mapping[str, Any]) -> vol.Schema:
"""Return schema for price rating thresholds configuration."""
"""Return schema for price rating configuration (thresholds and stabilization)."""
return vol.Schema(
{
vol.Optional(
@ -294,6 +302,39 @@ def get_price_rating_schema(options: Mapping[str, Any]) -> vol.Schema:
mode=NumberSelectorMode.SLIDER,
),
),
vol.Optional(
CONF_PRICE_RATING_HYSTERESIS,
default=float(
options.get(
CONF_PRICE_RATING_HYSTERESIS,
DEFAULT_PRICE_RATING_HYSTERESIS,
)
),
): NumberSelector(
NumberSelectorConfig(
min=MIN_PRICE_RATING_HYSTERESIS,
max=MAX_PRICE_RATING_HYSTERESIS,
unit_of_measurement="%",
step=0.5,
mode=NumberSelectorMode.SLIDER,
),
),
vol.Optional(
CONF_PRICE_RATING_GAP_TOLERANCE,
default=int(
options.get(
CONF_PRICE_RATING_GAP_TOLERANCE,
DEFAULT_PRICE_RATING_GAP_TOLERANCE,
)
),
): NumberSelector(
NumberSelectorConfig(
min=MIN_PRICE_RATING_GAP_TOLERANCE,
max=MAX_PRICE_RATING_GAP_TOLERANCE,
step=1,
mode=NumberSelectorMode.SLIDER,
),
),
}
)

View file

@ -44,6 +44,8 @@ CONF_BEST_PRICE_MIN_PERIOD_LENGTH = "best_price_min_period_length"
CONF_PEAK_PRICE_MIN_PERIOD_LENGTH = "peak_price_min_period_length"
CONF_PRICE_RATING_THRESHOLD_LOW = "price_rating_threshold_low"
CONF_PRICE_RATING_THRESHOLD_HIGH = "price_rating_threshold_high"
CONF_PRICE_RATING_HYSTERESIS = "price_rating_hysteresis"
CONF_PRICE_RATING_GAP_TOLERANCE = "price_rating_gap_tolerance"
CONF_AVERAGE_SENSOR_DISPLAY = "average_sensor_display" # "median" or "mean"
CONF_PRICE_TREND_THRESHOLD_RISING = "price_trend_threshold_rising"
CONF_PRICE_TREND_THRESHOLD_FALLING = "price_trend_threshold_falling"
@ -133,6 +135,10 @@ MIN_PRICE_RATING_THRESHOLD_LOW = -50 # Minimum value for low rating threshold
MAX_PRICE_RATING_THRESHOLD_LOW = -5 # Maximum value for low rating threshold (must be < HIGH)
MIN_PRICE_RATING_THRESHOLD_HIGH = 5 # Minimum value for high rating threshold (must be > LOW)
MAX_PRICE_RATING_THRESHOLD_HIGH = 50 # Maximum value for high rating threshold
MIN_PRICE_RATING_HYSTERESIS = 0.0 # Minimum hysteresis (0 = disabled)
MAX_PRICE_RATING_HYSTERESIS = 5.0 # Maximum hysteresis (5% band)
MIN_PRICE_RATING_GAP_TOLERANCE = 0 # Minimum gap tolerance (0 = disabled)
MAX_PRICE_RATING_GAP_TOLERANCE = 4 # Maximum gap tolerance (4 intervals = 1 hour)
# Volatility threshold limits
# MODERATE threshold: practical range 5% to 25% (entry point for noticeable fluctuation)
@ -328,9 +334,11 @@ def get_default_options(currency_code: str | None) -> dict[str, Any]:
CONF_VIRTUAL_TIME_OFFSET_DAYS: DEFAULT_VIRTUAL_TIME_OFFSET_DAYS,
CONF_VIRTUAL_TIME_OFFSET_HOURS: DEFAULT_VIRTUAL_TIME_OFFSET_HOURS,
CONF_VIRTUAL_TIME_OFFSET_MINUTES: DEFAULT_VIRTUAL_TIME_OFFSET_MINUTES,
# Price rating thresholds (flat - single-section step)
# Price rating settings (flat - single-section step)
CONF_PRICE_RATING_THRESHOLD_LOW: DEFAULT_PRICE_RATING_THRESHOLD_LOW,
CONF_PRICE_RATING_THRESHOLD_HIGH: DEFAULT_PRICE_RATING_THRESHOLD_HIGH,
CONF_PRICE_RATING_HYSTERESIS: DEFAULT_PRICE_RATING_HYSTERESIS,
CONF_PRICE_RATING_GAP_TOLERANCE: DEFAULT_PRICE_RATING_GAP_TOLERANCE,
# Volatility thresholds (flat - single-section step)
CONF_VOLATILITY_THRESHOLD_MODERATE: DEFAULT_VOLATILITY_THRESHOLD_MODERATE,
CONF_VOLATILITY_THRESHOLD_HIGH: DEFAULT_VOLATILITY_THRESHOLD_HIGH,

View file

@ -48,12 +48,16 @@ class TibberPricesDataTransformer:
prefixed_message = f"{self._log_prefix} {message}"
getattr(_LOGGER, level)(prefixed_message, *args, **kwargs)
def get_threshold_percentages(self) -> dict[str, int]:
"""Get threshold percentages from config options."""
def get_threshold_percentages(self) -> dict[str, int | float]:
"""Get threshold percentages, hysteresis and gap tolerance from config options."""
options = self.config_entry.options or {}
return {
"low": options.get(_const.CONF_PRICE_RATING_THRESHOLD_LOW, _const.DEFAULT_PRICE_RATING_THRESHOLD_LOW),
"high": options.get(_const.CONF_PRICE_RATING_THRESHOLD_HIGH, _const.DEFAULT_PRICE_RATING_THRESHOLD_HIGH),
"hysteresis": options.get(_const.CONF_PRICE_RATING_HYSTERESIS, _const.DEFAULT_PRICE_RATING_HYSTERESIS),
"gap_tolerance": options.get(
_const.CONF_PRICE_RATING_GAP_TOLERANCE, _const.DEFAULT_PRICE_RATING_GAP_TOLERANCE
),
}
def invalidate_config_cache(self) -> None:
@ -210,6 +214,8 @@ class TibberPricesDataTransformer:
all_intervals,
threshold_low=thresholds["low"],
threshold_high=thresholds["high"],
hysteresis=float(thresholds["hysteresis"]),
gap_tolerance=int(thresholds["gap_tolerance"]),
time=self.time,
)

View file

@ -170,15 +170,19 @@
"submit": "↩ Speichern & Zurück"
},
"current_interval_price_rating": {
"title": "📊 Preisbewertungs-Schwellenwerte",
"description": "**Konfiguriere Schwellenwerte für Preisbewertungsstufen (niedrig/normal/hoch) basierend auf dem Vergleich mit dem nachlaufenden 24-Stunden-Durchschnitt.**",
"title": "📊 Preisbewertungs-Einstellungen",
"description": "**Konfiguriere Schwellenwerte und Stabilisierung für Preisbewertungsstufen (niedrig/normal/hoch) basierend auf dem Vergleich mit dem nachlaufenden 24-Stunden-Durchschnitt.**",
"data": {
"price_rating_threshold_low": "Niedrig-Schwelle",
"price_rating_threshold_high": "Hoch-Schwelle"
"price_rating_threshold_high": "Hoch-Schwelle",
"price_rating_hysteresis": "Hysterese",
"price_rating_gap_tolerance": "Lücken-Toleranz"
},
"data_description": {
"price_rating_threshold_low": "Prozentwert, um wie viel der aktuelle Preis unter dem nachlaufenden 24-Stunden-Durchschnitt liegen muss, damit er als 'niedrig' bewertet wird. Beispiel: 5 bedeutet mindestens 5% unter Durchschnitt. Sensoren mit dieser Bewertung zeigen günstige Zeitfenster an. Standard: 5%",
"price_rating_threshold_high": "Prozentwert, um wie viel der aktuelle Preis über dem nachlaufenden 24-Stunden-Durchschnitt liegen muss, damit er als 'hoch' bewertet wird. Beispiel: 10 bedeutet mindestens 10% über Durchschnitt. Sensoren mit dieser Bewertung warnen vor teuren Zeitfenstern. Standard: 10%"
"price_rating_threshold_low": "Prozentwert, um wie viel der aktuelle Preis unter dem nachlaufenden 24-Stunden-Durchschnitt liegen muss, damit er als 'niedrig' bewertet wird. Beispiel: -10 bedeutet mindestens 10% unter Durchschnitt. Sensoren mit dieser Bewertung zeigen günstige Zeitfenster an. Standard: -10%",
"price_rating_threshold_high": "Prozentwert, um wie viel der aktuelle Preis über dem nachlaufenden 24-Stunden-Durchschnitt liegen muss, damit er als 'hoch' bewertet wird. Beispiel: 10 bedeutet mindestens 10% über Durchschnitt. Sensoren mit dieser Bewertung warnen vor teuren Zeitfenstern. Standard: 10%",
"price_rating_hysteresis": "Prozentband um die Schwellenwerte zur Vermeidung schneller Zustandswechsel. Wenn die Bewertung bereits NIEDRIG ist, muss der Preis über (Schwelle + Hysterese) steigen, um zu NORMAL zu wechseln. Ebenso muss bei HOCH der Preis unter (Schwelle - Hysterese) fallen, um den Zustand zu verlassen. Dies sorgt für Stabilität bei Automationen, die auf Bewertungsänderungen reagieren. Auf 0 setzen zum Deaktivieren. Standard: 2%",
"price_rating_gap_tolerance": "Maximale Anzahl aufeinanderfolgender Intervalle, die 'geglättet' werden können, wenn sie sich von den umgebenden Bewertungen unterscheiden. Kleine isolierte Bewertungsänderungen werden in den dominanten Nachbarblock integriert. Dies sorgt für Stabilität bei Automationen, indem kurze Bewertungsspitzen keine unnötigen Aktionen auslösen. Beispiel: 1 bedeutet, dass ein einzelnes 'normal'-Intervall umgeben von 'hoch'-Intervallen zu 'hoch' korrigiert wird. Auf 0 setzen zum Deaktivieren. Standard: 1"
},
"submit": "↩ Speichern & Zurück"
},

View file

@ -170,15 +170,19 @@
"submit": "↩ Save & Back"
},
"current_interval_price_rating": {
"title": "📊 Price Rating Thresholds",
"description": "**Configure thresholds for price rating levels (low/normal/high) based on comparison with trailing 24-hour average.**",
"title": "📊 Price Rating Settings",
"description": "**Configure thresholds and stabilization for price rating levels (low/normal/high) based on comparison with trailing 24-hour average.**",
"data": {
"price_rating_threshold_low": "Low Threshold",
"price_rating_threshold_high": "High Threshold"
"price_rating_threshold_high": "High Threshold",
"price_rating_hysteresis": "Hysteresis",
"price_rating_gap_tolerance": "Gap Tolerance"
},
"data_description": {
"price_rating_threshold_low": "Percentage below the trailing 24-hour average that the current price must be to qualify as 'low' rating. Example: 5 means at least 5% below average. Sensors with this rating indicate favorable time windows. Default: 5%",
"price_rating_threshold_high": "Percentage above the trailing 24-hour average that the current price must be to qualify as 'high' rating. Example: 10 means at least 10% above average. Sensors with this rating warn about expensive time windows. Default: 10%"
"price_rating_threshold_low": "Percentage below the trailing 24-hour average that the current price must be to qualify as 'low' rating. Example: -10 means at least 10% below average. Sensors with this rating indicate favorable time windows. Default: -10%",
"price_rating_threshold_high": "Percentage above the trailing 24-hour average that the current price must be to qualify as 'high' rating. Example: 10 means at least 10% above average. Sensors with this rating warn about expensive time windows. Default: 10%",
"price_rating_hysteresis": "Percentage band around thresholds to prevent rapid state changes. When the rating is already LOW, the price must rise above (threshold + hysteresis) to switch to NORMAL. Similarly, HIGH requires the price to fall below (threshold - hysteresis) to leave. This provides stability for automations that react to rating changes. Set to 0 to disable. Default: 2%",
"price_rating_gap_tolerance": "Maximum number of consecutive intervals that can be 'smoothed out' if they differ from surrounding ratings. Small isolated rating changes are merged into the dominant neighboring block. This provides stability for automations by preventing brief rating spikes from triggering unnecessary actions. Example: 1 means a single 'normal' interval surrounded by 'high' intervals gets corrected to 'high'. Set to 0 to disable. Default: 1"
},
"submit": "↩ Save & Back"
},

View file

@ -170,15 +170,19 @@
"submit": "↩ Lagre & tilbake"
},
"current_interval_price_rating": {
"title": "📊 Prisvurderings-terskler",
"description": "**Konfigurer terskler for prisvurderingsnivåer (lav/normal/høy) basert på sammenligning med etterfølgende 24-timers gjennomsnitt.**",
"title": "📊 Prisvurderingsinnstillinger",
"description": "**Konfigurer terskler og stabilisering for prisvurderingsnivåer (lav/normal/høy) basert på sammenligning med etterfølgende 24-timers gjennomsnitt.**",
"data": {
"price_rating_threshold_low": "Lav-terskel",
"price_rating_threshold_high": "Høy-terskel"
"price_rating_threshold_high": "Høy-terskel",
"price_rating_hysteresis": "Hysterese",
"price_rating_gap_tolerance": "Gap-toleranse"
},
"data_description": {
"price_rating_threshold_low": "Prosentverdi for hvor mye gjeldende pris må være under det etterfølgende 24-timers gjennomsnittet for å kvalifisere som 'lav' vurdering. Eksempel: 5 betyr minst 5% under gjennomsnitt. Sensorer med denne vurderingen indikerer gunstige tidsvinduer. Standard: 5%",
"price_rating_threshold_high": "Prosentverdi for hvor mye gjeldende pris må være over det etterfølgende 24-timers gjennomsnittet for å kvalifisere som 'høy' vurdering. Eksempel: 10 betyr minst 10% over gjennomsnitt. Sensorer med denne vurderingen advarer om dyre tidsvinduer. Standard: 10%"
"price_rating_threshold_low": "Prosentverdi for hvor mye gjeldende pris må være under det etterfølgende 24-timers gjennomsnittet for å kvalifisere som 'lav' vurdering. Eksempel: -10 betyr minst 10% under gjennomsnitt. Sensorer med denne vurderingen indikerer gunstige tidsvinduer. Standard: -10%",
"price_rating_threshold_high": "Prosentverdi for hvor mye gjeldende pris må være over det etterfølgende 24-timers gjennomsnittet for å kvalifisere som 'høy' vurdering. Eksempel: 10 betyr minst 10% over gjennomsnitt. Sensorer med denne vurderingen advarer om dyre tidsvinduer. Standard: 10%",
"price_rating_hysteresis": "Prosentbånd rundt terskler for å unngå raske tilstandsendringer. Når vurderingen allerede er LAV, må prisen stige over (terskel + hysterese) for å bytte til NORMAL. Tilsvarende krever HØY at prisen faller under (terskel - hysterese) for å forlate tilstanden. Dette gir stabilitet for automatiseringer som reagerer på vurderingsendringer. Sett til 0 for å deaktivere. Standard: 2%",
"price_rating_gap_tolerance": "Maksimalt antall påfølgende intervaller som kan 'jevnes ut' hvis de avviker fra omkringliggende vurderinger. Små isolerte vurderingsendringer slås sammen med den dominerende nabogruppen. Dette gir stabilitet for automatiseringer ved å forhindre at korte vurderingstopper utløser unødvendige handlinger. Eksempel: 1 betyr at et enkelt 'normal'-intervall omgitt av 'høy'-intervaller korrigeres til 'høy'. Sett til 0 for å deaktivere. Standard: 1"
},
"submit": "↩ Lagre & tilbake"
},

View file

@ -170,33 +170,37 @@
"submit": "↩ Opslaan & Terug"
},
"current_interval_price_rating": {
"title": "📊 Prijsbeoordeling Drempelwaarden",
"description": "**Configureer drempelwaarden voor prijsbeoordelingsniveaus (laag/normaal/hoog) gebaseerd op vergelijking met het voortschrijdende 24-uurs gemiddelde.**",
"title": "📊 Instellingen Prijsbeoordeling",
"description": "**Configureer drempelwaarden en stabilisatie voor prijsbeoordelingsniveaus (laag/normaal/hoog) gebaseerd op vergelijking met het voortschrijdende 24-uurs gemiddelde.**",
"data": {
"price_rating_threshold_low": "Lage Drempel",
"price_rating_threshold_high": "Hoge Drempel"
"price_rating_threshold_high": "Hoge Drempel",
"price_rating_hysteresis": "Hysterese",
"price_rating_gap_tolerance": "Gap Tolerantie"
},
"data_description": {
"price_rating_threshold_low": "Percentage onder het voortschrijdende 24-uurs gemiddelde dat de huidige prijs moet zijn om te kwalificeren als 'laag' beoordelingsniveau. Voorbeeld: 5 betekent minimaal 5% onder gemiddelde. Sensoren met deze beoordeling geven gunstige tijdvensters aan. Standaard: 5%",
"price_rating_threshold_high": "Percentage boven het voortschrijdende 24-uurs gemiddelde dat de huidige prijs moet zijn om te kwalificeren als 'hoog' beoordelingsniveau. Voorbeeld: 10 betekent minimaal 10% boven gemiddelde. Sensoren met deze beoordeling waarschuwen voor dure tijdvensters. Standaard: 10%"
"price_rating_threshold_low": "Percentage onder het voortschrijdende 24-uurs gemiddelde dat de huidige prijs moet zijn om te kwalificeren als 'laag' beoordelingsniveau. Voorbeeld: -10 betekent minimaal 10% onder gemiddelde. Sensoren met deze beoordeling geven gunstige tijdvensters aan. Standaard: -10%",
"price_rating_threshold_high": "Percentage boven het voortschrijdende 24-uurs gemiddelde dat de huidige prijs moet zijn om te kwalificeren als 'hoog' beoordelingsniveau. Voorbeeld: 10 betekent minimaal 10% boven gemiddelde. Sensoren met deze beoordeling waarschuwen voor dure tijdvensters. Standaard: 10%",
"price_rating_hysteresis": "Percentageband rond drempelwaarden om snelle toestandswijzigingen te voorkomen. Wanneer de beoordeling al LAAG is, moet de prijs boven (drempel + hysterese) stijgen om naar NORMAAL te wisselen. Evenzo vereist HOOG dat de prijs onder (drempel - hysterese) daalt om de toestand te verlaten. Dit zorgt voor stabiliteit bij automatiseringen die reageren op beoordelingswijzigingen. Stel in op 0 om uit te schakelen. Standaard: 2%",
"price_rating_gap_tolerance": "Maximaal aantal opeenvolgende intervallen dat 'gladgestreken' kan worden als ze afwijken van omringende beoordelingen. Kleine geïsoleerde beoordelingswijzigingen worden samengevoegd met het dominante naburige blok. Dit zorgt voor stabiliteit bij automatiseringen door te voorkomen dat korte beoordelingspieken onnodige acties activeren. Voorbeeld: 1 betekent dat een enkel 'normaal'-interval omringd door 'hoog'-intervallen gecorrigeerd wordt naar 'hoog'. Stel in op 0 om uit te schakelen. Standaard: 1"
},
"submit": "↩ Opslaan & Terug"
},
"best_price": {
"title": "💚 Best Price Period Settings",
"description": "**Configure settings for the Best Price Period binary sensor. This sensor is active during periods with the lowest electricity prices.**\n\n---",
"title": "💚 Beste Prijs Periode Instellingen",
"description": "**Configureer instellingen voor de Beste Prijs Periode binaire sensor. Deze sensor is actief tijdens periodes met de laagste elektriciteitsprijzen.**\n\n---",
"sections": {
"period_settings": {
"name": "Period Duration & Levels",
"description": "Configure how long periods should be and which price levels to include.",
"name": "Periode Duur & Niveaus",
"description": "Configureer hoe lang periodes moeten zijn en welke prijsniveaus moeten worden opgenomen.",
"data": {
"best_price_min_period_length": "Minimum Period Length",
"best_price_max_level": "Price Level Filter",
"best_price_max_level_gap_count": "Gap Tolerance"
"best_price_min_period_length": "Minimale Periode Lengte",
"best_price_max_level": "Prijsniveau Filter",
"best_price_max_level_gap_count": "Gat Tolerantie"
},
"data_description": {
"best_price_min_period_length": "Minimum duration for a period to be considered as 'best price'. Longer periods are more practical for running appliances like dishwashers or heat pumps. Best price periods require 60 minutes minimum (vs. 30 minutes for peak price warnings) because they should provide meaningful time windows for consumption planning, not just brief opportunities.",
"best_price_max_level": "Only show best price periods if they contain intervals with price levels ≤ selected value. For example, selecting '**Cheap**' means the period must have at least one '**Very cheap**' or '**Cheap**' interval. This ensures 'best price' periods are not just relatively cheap for the day, but actually cheap in absolute terms. Select '**Any**' to show best prices regardless of their absolute price level.",
"best_price_min_period_length": "Minimale duur voor een periode om als 'beste prijs' te worden beschouwd. Langere periodes zijn praktischer voor apparaten zoals vaatwassers of warmtepompen. Beste prijs periodes vereisen minimaal 60 minuten (versus 30 minuten voor piekprijs waarschuwingen) omdat ze betekenisvolle tijdvensters voor verbruiksplanning moeten bieden, niet alleen korte kansen.",
"best_price_max_level": "Toon alleen beste prijs periodes als ze intervallen bevatten met prijsniveaus ≤ geselecteerde waarde. Bijvoorbeeld, bij selectie '**Goedkoop**' moet de periode minimaal één '**Zeer goedkoop**' of '**Goedkoop**' interval hebben. Dit zorgt ervoor dat 'beste prijs' periodes niet alleen relatief goedkoop zijn voor de dag, maar daadwerkelijk goedkoop in absolute termen. Selecteer '**Alles**' om beste prijzen te tonen ongeacht hun absolute prijsniveau.",
"best_price_max_level_gap_count": "Maximaal aantal opeenvolgende intervallen toegestaan die precies één niveaustap afwijken van het vereiste niveau. Bijvoorbeeld: met '**Goedkoop**' filter en gat telling 1, wordt een reeks '**Goedkoop**, **Goedkoop**, **Normaal**, **Goedkoop**' geaccepteerd (**Normaal** is één stap boven **Goedkoop**). Dit voorkomt dat periodes worden gesplitst door incidentele niveauafwijkingen. **Let op:** Gat tolerantie vereist periodes ≥90 minuten (6 intervallen) om uitschieters effectief te detecteren. Standaard: 0 (strikte filtering, geen tolerantie)."
}
},
@ -1153,4 +1157,4 @@
}
},
"title": "Tibber Prijsinformatie & Beoordelingen"
}
}

View file

@ -170,15 +170,19 @@
"submit": "↩ Spara & tillbaka"
},
"current_interval_price_rating": {
"title": "📊 Prisbetygströsklar",
"description": "**Konfigurera tröskelvärden för prisbetygsnivåer (låg/normal/hög) baserat på jämförelse med glidande 24-timmars genomsnitt.**",
"title": "📊 Prisbetyginställningar",
"description": "**Konfigurera tröskelvärden och stabilisering för prisbetygsnivåer (låg/normal/hög) baserat på jämförelse med glidande 24-timmars genomsnitt.**",
"data": {
"price_rating_threshold_low": "Låg tröskel",
"price_rating_threshold_high": "Hög tröskel"
"price_rating_threshold_high": "Hög tröskel",
"price_rating_hysteresis": "Hysteres",
"price_rating_gap_tolerance": "Gap-tolerans"
},
"data_description": {
"price_rating_threshold_low": "Procentandel under det glidande 24-timmars genomsnittet som det aktuella priset måste vara för att kvalificera som 'lågt' betyg. Exempel: 5 betyder minst 5% under genomsnittet. Sensorer med detta betyg indikerar gynnsamma tidsfönster. Standard: 5%",
"price_rating_threshold_high": "Procentandel över det glidande 24-timmars genomsnittet som det aktuella priset måste vara för att kvalificera som 'högt' betyg. Exempel: 10 betyder minst 10% över genomsnittet. Sensorer med detta betyg varnar om dyra tidsfönster. Standard: 10%"
"price_rating_threshold_low": "Procentandel under det glidande 24-timmars genomsnittet som det aktuella priset måste vara för att kvalificera som 'lågt' betyg. Exempel: -10 betyder minst 10% under genomsnittet. Sensorer med detta betyg indikerar gynnsamma tidsfönster. Standard: -10%",
"price_rating_threshold_high": "Procentandel över det glidande 24-timmars genomsnittet som det aktuella priset måste vara för att kvalificera som 'högt' betyg. Exempel: 10 betyder minst 10% över genomsnittet. Sensorer med detta betyg varnar om dyra tidsfönster. Standard: 10%",
"price_rating_hysteresis": "Procentband runt tröskelvärden för att undvika snabba tillståndsändringar. När betyget redan är LÅGT måste priset stiga över (tröskel + hysteres) för att byta till NORMAL. Likaså kräver HÖGT att priset faller under (tröskel - hysteres) för att lämna tillståndet. Detta ger stabilitet för automatiseringar som reagerar på betygsändringar. Sätt till 0 för att inaktivera. Standard: 2%",
"price_rating_gap_tolerance": "Maximalt antal på varandra följande intervaller som kan 'jämnas ut' om de avviker från omgivande betyg. Små isolerade betygsändringar sammanfogas med det dominerande grannblocket. Detta ger stabilitet för automatiseringar genom att förhindra att korta betygstoppar utlöser onödiga åtgärder. Exempel: 1 betyder att ett enstaka 'normal'-intervall omgivet av 'hög'-intervaller korrigeras till 'hög'. Sätt till 0 för att inaktivera. Standard: 1"
},
"submit": "↩ Spara & tillbaka"
},