{"id":50795757,"url":"https://github.com/nilp0inter/sequential-test","last_synced_at":"2026-06-12T14:32:55.875Z","repository":{"id":346588027,"uuid":"1190652332","full_name":"nilp0inter/sequential-test","owner":"nilp0inter","description":"A Python library for sequential hypothesis testing","archived":false,"fork":false,"pushed_at":"2026-03-24T13:55:26.000Z","size":40,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-25T17:55:29.151Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nilp0inter.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-24T13:45:35.000Z","updated_at":"2026-03-24T13:55:29.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/nilp0inter/sequential-test","commit_stats":null,"previous_names":["nilp0inter/sequential-test"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/nilp0inter/sequential-test","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nilp0inter%2Fsequential-test","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nilp0inter%2Fsequential-test/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nilp0inter%2Fsequential-test/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nilp0inter%2Fsequential-test/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nilp0inter","download_url":"https://codeload.github.com/nilp0inter/sequential-test/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nilp0inter%2Fsequential-test/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34249560,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-12T02:00:06.859Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-12T14:32:55.767Z","updated_at":"2026-06-12T14:32:55.868Z","avatar_url":"https://github.com/nilp0inter.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Sequential Test\n\nA Python library for sequential hypothesis testing. Useful for A/B testing and other scenarios where you want to reach a decision as early as the data allows, without waiting for a fixed sample size.\n\n## Installation\n\n```bash\npip install sequential-test\n```\n\nRequires Python \u003e=3.10, \u003c3.13.\n\n## Dependencies\n\n- NumPy\n- SciPy\n\n## Usage\n\n```python\nfrom sequential_test import sequential_test\n```\n\n### Normal distribution (default)\n\n```python\nresult = sequential_test(x=x, y=y, sigma=1.0)\n```\n\n### Bernoulli distribution\n\n```python\nresult = sequential_test(\n    x=x,\n    y=y,\n    theta=0.0,\n    sigma=0.5,\n    distribution=\"bernoulli\",\n    alpha=0.01,\n    lower_bound=0.05,\n)\n```\n\n### Parameters\n\n| Parameter | Type | Default | Description |\n|---|---|---|---|\n| `x` | Iterable | required | Treatment observations |\n| `y` | Iterable | required | Control observations |\n| `sigma` | float | `0.0` | Known standard deviation (used for normal distribution) |\n| `theta` | float | `0.0` | Hypothesized difference under H0 |\n| `truncation` | float | `200` | Maximum number of observations for mixture variance calculation |\n| `distribution` | str | `\"normal\"` | `\"normal\"` or `\"bernoulli\"` |\n| `alpha` | float | `0.05` | Significance level |\n| `warmup_observations` | int | `100` | Observations to collect before testing begins |\n| `lower_bound` | float \\| None | `None` | Lower decision boundary for early H0 acceptance. When set, the test stops early if the likelihood ratio drops below this value. |\n\n### Result\n\n`sequential_test()` returns a `SequentialTestResult` with the following fields:\n\n| Field | Type | Description |\n|---|---|---|\n| `distribution` | str | Distribution used |\n| `number_of_observations` | int | Total observations processed |\n| `likelihood_ratios` | list[float] | Likelihood ratio at each step |\n| `stopping_time` | int | Observation at which a decision was reached |\n| `decision` | str | `\"Accept H1\"` or `\"Accept H0\"` |\n| `text` | str | Human-readable summary |\n| `alpha` | float | Significance level used |\n\n## How it works\n\n### Mixture variance\n\n$$\n\\tau^2 = \\sigma^2 \\frac{\\Phi(-b)}{\\frac{1}{b}\\phi(b)-\\Phi(-b)}\n$$\n\n### Test statistic (normal)\n\n$$\n\\tilde{\\Lambda}_n = \\sqrt{\\frac{2\\sigma^2}{2\\sigma^2 + n\\tau^2}}\\exp\\left(\\frac{n^2\\tau^2(\\bar{X}_n - \\bar{Y}_n-\\theta_0)^2}{4\\sigma^2(2\\sigma^2+n\\tau^2)}\\right)\n$$\n\n### Test statistic (Bernoulli)\n\n$$\n\\tilde{\\Lambda}_n = \\sqrt{\\frac{V_n}{V_n + n\\tau^2}}\\exp{\\left(\\frac{n^2\\tau^2(\\bar{X}_n - \\bar{Y}_n-\\theta_0)^2}{2V_n(V_n+n\\tau^2)}\\right)}\n$$\n\nThe test rejects H0 when the likelihood ratio exceeds $1/\\alpha$. If `lower_bound` is set, it accepts H0 early when the ratio drops below that threshold.\n\n### Differences from standard mSPRT\n\nThis library extends the classic mSPRT in two ways:\n\n- **Lower decision boundary** — standard mSPRT only tests against an upper threshold ($1/\\alpha$) and can only reject H0. The optional `lower_bound` parameter adds a lower threshold for early H0 acceptance, closer to a two-sided SPRT.\n- **Warmup period** — standard mSPRT evaluates from the first observation. The `warmup_observations` parameter skips a configurable number of initial observations to avoid noisy early decisions.\n\n## References\n\n1. Wald, A. (1945). Sequential Tests of Statistical Hypotheses. *The Annals of Mathematical Statistics*, 16(2), 117–186. [DOI: 10.1214/aoms/1177731118](https://doi.org/10.1214/aoms/1177731118)\n2. Robbins, H. (1970). Statistical Methods Related to the Law of the Iterated Logarithm. *The Annals of Mathematical Statistics*, 41(5), 1397–1409. [DOI: 10.1214/aoms/1177696786](https://doi.org/10.1214/aoms/1177696786)\n3. Johari, R., Koomen, P., Pekelis, L., \u0026 Walsh, D. (2022). Always Valid Inference: Continuous Monitoring of A/B Tests. *Operations Research*, 70(3), 1806–1821. [DOI: 10.1287/opre.2021.2135](https://doi.org/10.1287/opre.2021.2135)\n4. Stenberg, E. mixtureSPRT — R and C++ implementation. [GitHub](https://github.com/erik-stenberg/mixtureSPRT)\n5. Kuzminas, O. msprt — original Python implementation. [GitHub](https://github.com/ovidijusku/msprt/tree/main)\n\n## License\n\nThis project is licensed under the GPL-3.0-or-later license.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnilp0inter%2Fsequential-test","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnilp0inter%2Fsequential-test","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnilp0inter%2Fsequential-test/lists"}