Máquina de estados con histéresis por confirmación: un estado nuevo solo se commitea tras sostenerse N observaciones consecutivas. Anti-flapping para clasificadores ruidosos. Sin dependencias.
Project description
hysteresis-state
Una máquina de estados con histéresis por confirmación, en Python puro y sin dependencias, para que un clasificador ruidoso no haga flapping.
El problema
Tienes una señal que a cada observación te dice en qué estado estás —un
clasificador de régimen, un sensor de conectividad, un detector de modo, un
semáforo de salud— pero cerca de los umbrales oscila: OK, CAÍDO, OK, CAÍDO.
Y cada cambio dispara algo caro o peligroso: una alerta, un failover, entrar o
salir del mercado. No quieres actuar en cada tembleque.
La regla
Un estado nuevo solo se commitea tras sostenerse confirmations
observaciones consecutivas. Si el candidato cambia o revierte antes, la cuenta se
reinicia. El estado vigente es estable; los parpadeos se ignoran.
from hysteresis_state import HysteresisState
estado = HysteresisState("OK", confirmations=3)
for lectura in stream: # p.ej. "OK" / "CAIDO"
actual = estado.update(lectura) # solo cambia tras 3 lecturas seguidas
if estado.changed: # ¿esta lectura provocó la transición?
alertar(actual)
OK, CAÍDO, OK, CAÍDO, OK no cambia nada: ningún candidato se sostuvo. Hacen
falta tres CAÍDO seguidos para commitear el cambio.
Instalación
pip install hysteresis-state
Sin dependencias. Requiere Python ≥ 3.9.
Histéresis asimétrica
A menudo quieres cambiar rápido hacia un estado seguro y despacio de vuelta al
arriesgado. Pasa un invocable (desde, hacia) -> int:
# 1 confirmación para caer a "CAIDO", 5 para volver a "OK"
conf = lambda desde, hacia: 1 if hacia == "CAIDO" else 5
estado = HysteresisState("OK", confirmations=conf)
estado.update("CAIDO") # cae al instante
# ...hacen falta 5 "OK" seguidos para volver
Es el patrón de un disyuntor: salta a la primera, se rearma con cautela.
Qué puedes inspeccionar
estado.state # el estado committeado (estable)
estado.candidate # el candidato a la espera, o None
estado.progress # observaciones consecutivas acumuladas del candidato
estado.changed # ¿la última update() committeó una transición?
estado.reset() # descarta el candidato pendiente
estado.reset("NUEVO") # además fija el estado, sin exigir confirmación
Los estados pueden ser cualquier valor comparable, no solo strings: enteros, enums, tuplas.
confirmations=1 es "sin histéresis"
Con una sola confirmación, cada observación distinta cambia el estado en el acto. Útil como caso base o para desactivar el suavizado por configuración sin ramificar el código.
De dónde viene
Salió del cerebro de régimen de un bot de trading, donde los umbrales de mercado (tendencia / rango / caos) parpadeaban y cada cambio congelaba o reactivaba la operativa. El mecanismo no dice nada de mercados: es anti-flapping para cualquier señal discreta. Por eso se extrajo como librería.
Tests
pip install "hysteresis-state[test]"
pytest
15 tests que cubren el conteo exacto, el flapping, el reinicio del candidato, la
histéresis asimétrica y los casos límite. Verificados por mutación (cambiar el
>= del commit por > rompe los tests que debe romper).
Licencia
Apache-2.0.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hysteresis_state-0.1.0.tar.gz.
File metadata
- Download URL: hysteresis_state-0.1.0.tar.gz
- Upload date:
- Size: 9.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fb8d2af51c439352bee80fa925966177c5acedf2876f4f293fff0f3f38abae29
|
|
| MD5 |
dd8b34574128e1088334bfac81a96bb4
|
|
| BLAKE2b-256 |
b63bc7c2bb5b5ef085f335cd5fcc3adc3472638d62ed93edc6259e50dd5910a3
|
Provenance
The following attestation bundles were made for hysteresis_state-0.1.0.tar.gz:
Publisher:
publish.yml on isazajuancarlos/hysteresis-state
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hysteresis_state-0.1.0.tar.gz -
Subject digest:
fb8d2af51c439352bee80fa925966177c5acedf2876f4f293fff0f3f38abae29 - Sigstore transparency entry: 2192033272
- Sigstore integration time:
-
Permalink:
isazajuancarlos/hysteresis-state@3aa70e10a91e4260f0e49864bfe2d66f24dc3c1e -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/isazajuancarlos
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3aa70e10a91e4260f0e49864bfe2d66f24dc3c1e -
Trigger Event:
push
-
Statement type:
File details
Details for the file hysteresis_state-0.1.0-py3-none-any.whl.
File metadata
- Download URL: hysteresis_state-0.1.0-py3-none-any.whl
- Upload date:
- Size: 9.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9133d5c94f9d95daaf1dfaeb6db582bf73308db615413378feb48fbd1c377fd0
|
|
| MD5 |
7bad8e6437ecf88bbc6d689953d38679
|
|
| BLAKE2b-256 |
281c9fc121ab3ce9904b545bc668d03364e8bea693f9befa90fb4844b80dd9c6
|
Provenance
The following attestation bundles were made for hysteresis_state-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on isazajuancarlos/hysteresis-state
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hysteresis_state-0.1.0-py3-none-any.whl -
Subject digest:
9133d5c94f9d95daaf1dfaeb6db582bf73308db615413378feb48fbd1c377fd0 - Sigstore transparency entry: 2192033313
- Sigstore integration time:
-
Permalink:
isazajuancarlos/hysteresis-state@3aa70e10a91e4260f0e49864bfe2d66f24dc3c1e -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/isazajuancarlos
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3aa70e10a91e4260f0e49864bfe2d66f24dc3c1e -
Trigger Event:
push
-
Statement type: