Files
OpenBB/openbb_platform/providers/sec/openbb_sec/utils/ratelimit.py
Danglewood dc4b26030f [V5] openbb-sec: Refactor for V5 (#7525)
* refactor openbb-sec for v5

* linting

* ty

* normalize compare_company_facts

* add workflows

* python 3.10 fix

* add more thorough url validation and tests

* ty check

* ty for python 3.10

* reconfigure with apps

* temp pyproject overrride

* pyproject

* pyproject

* pyproject

* codespell

* pyproject

* fix uk schema file links in schema_files

* test coverage

* test_cli

* port #7547 into this pr

* no hard coded prefix

* improve filing rendering capabilities

* fix xml text detection

* make codeql happy

* missed a file in the commit

* test coverage

* codespell

* fix flakey test

* some updates

* management_ownership --> management_profiles

* proxy statement markdown

* ruff

* fix test coverage

* more tests

* test coverage

* fix lint errors

* Add SEC adviser search, profile, and universe routes (#7559)

* Add SEC institutional data fetchers

* Add SEC filing index and Form D routes

* Add SEC investment adviser people data

* Expose SEC adviser and institutional routes

* fix(sec): address adviser review feedback

* refactor(sec): narrow adviser support to IAPD search

* feat(sec): add adviser firm and individual searches

* feat(sec): add adviser profile drill-down

* fix: repair pre-commit configuration

* feat(sec): add adviser universe route

* feat(sec): expose complete Form ADV data

---------

Co-authored-by: Danglewood <85772166+deeleeramone@users.noreply.github.com>

* fix test coverage

---------

Co-authored-by: deeleeramone <>
Co-authored-by: Theodore Aptekarev <aptekarev@gmail.com>
2026-09-24 08:47:49 -07:00

68 lines
1.9 KiB
Python

"""Process-wide rate limiter for SEC EDGAR requests."""
import asyncio
import os
import threading
import time
from typing import Any
_DEFAULT_REQUESTS_PER_SECOND = 9.0
REQUESTS_PER_SECOND_ENV_VAR = "OPENBB_SEC_REQUESTS_PER_SECOND"
_lock = threading.Lock()
_next_available = 0.0
def _requests_per_second() -> float:
"""Return the configured request rate, falling back to the default."""
raw = os.environ.get(REQUESTS_PER_SECOND_ENV_VAR)
if raw:
try:
value = float(raw)
except ValueError:
return _DEFAULT_REQUESTS_PER_SECOND
if value > 0:
return value
return _DEFAULT_REQUESTS_PER_SECOND
def _reserve_slot() -> float:
"""Reserve the next request slot; return the seconds to wait before sending."""
global _next_available # noqa: PLW0603
interval = 1.0 / _requests_per_second()
with _lock:
now = time.monotonic()
scheduled = max(now, _next_available)
_next_available = scheduled + interval
return scheduled - now
async def sec_rate_limit() -> None:
"""Await this process's next SEC request slot (async paths)."""
wait = _reserve_slot()
if wait > 0:
await asyncio.sleep(wait)
def sec_rate_limit_sync() -> None:
"""Block until this process's next SEC request slot is free (sync paths)."""
wait = _reserve_slot()
if wait > 0:
time.sleep(wait)
async def sec_amake_request(*args: Any, **kwargs: Any) -> Any:
"""Rate-limited ``amake_request`` for SEC EDGAR."""
from openbb_core.provider.utils.helpers import amake_request # noqa: PLC0415
await sec_rate_limit()
return await amake_request(*args, **kwargs)
def sec_make_request(*args: Any, **kwargs: Any) -> Any:
"""Rate-limited ``make_request`` for SEC EDGAR."""
from openbb_core.provider.utils.helpers import make_request # noqa: PLC0415
sec_rate_limit_sync()
return make_request(*args, **kwargs)