perpbrain-read 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- perpbrain_read/__init__.py +5 -0
- perpbrain_read/_dist.py +30 -0
- perpbrain_read/py.typed +0 -0
- perpbrain_read/read/__init__.py +5 -0
- perpbrain_read/read/age.py +45 -0
- perpbrain_read/read/dataset.py +719 -0
- perpbrain_read/read/hl_feed.py +190 -0
- perpbrain_read/read/info.py +84 -0
- perpbrain_read/read/markets.py +36 -0
- perpbrain_read/read/parse.py +71 -0
- perpbrain_read/read/queries.py +267 -0
- perpbrain_read/read/rate_limit.py +99 -0
- perpbrain_read/read/signals.py +200 -0
- perpbrain_read/read/stream.py +133 -0
- perpbrain_read/read/ws_conn.py +224 -0
- perpbrain_read/read/zstd_raw.py +51 -0
- perpbrain_read/sim/__init__.py +12 -0
- perpbrain_read/sim/card.py +329 -0
- perpbrain_read/sim/costs.py +345 -0
- perpbrain_read/sim/defaults.py +119 -0
- perpbrain_read/sim/engine.py +1032 -0
- perpbrain_read/sim/execution.py +171 -0
- perpbrain_read/sim/fees.py +79 -0
- perpbrain_read/sim/fixed.py +335 -0
- perpbrain_read/sim/funding_adapter.py +76 -0
- perpbrain_read/sim/overfit.py +210 -0
- perpbrain_read/sim/receipt.py +739 -0
- perpbrain_read/sim/study.py +137 -0
- perpbrain_read-0.1.0.dist-info/METADATA +19 -0
- perpbrain_read-0.1.0.dist-info/RECORD +32 -0
- perpbrain_read-0.1.0.dist-info/WHEEL +5 -0
- perpbrain_read-0.1.0.dist-info/top_level.txt +1 -0
perpbrain_read/_dist.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Distribution name, configured in pyproject.toml."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import tomllib
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def distribution_name(pyproject: Path | None = None) -> str:
|
|
10
|
+
"""Return the configured distribution name for the read package."""
|
|
11
|
+
path = pyproject if pyproject is not None else _default_pyproject()
|
|
12
|
+
data = tomllib.loads(path.read_text(encoding="utf-8"))
|
|
13
|
+
tool = data.get("tool")
|
|
14
|
+
project = data.get("project")
|
|
15
|
+
if not isinstance(tool, dict) or not isinstance(project, dict):
|
|
16
|
+
raise RuntimeError("pyproject is missing tool or project tables")
|
|
17
|
+
configured_table = tool.get("perpbrain")
|
|
18
|
+
if not isinstance(configured_table, dict):
|
|
19
|
+
raise RuntimeError("pyproject is missing tool.perpbrain")
|
|
20
|
+
configured = configured_table.get("dist-name")
|
|
21
|
+
project_name = project.get("name")
|
|
22
|
+
if not isinstance(configured, str) or not isinstance(project_name, str):
|
|
23
|
+
raise RuntimeError("dist-name and project.name must be strings")
|
|
24
|
+
if configured != project_name:
|
|
25
|
+
raise RuntimeError("tool.perpbrain.dist-name must match project.name")
|
|
26
|
+
return configured
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _default_pyproject() -> Path:
|
|
30
|
+
return Path(__file__).resolve().parents[2] / "pyproject.toml"
|
perpbrain_read/py.typed
ADDED
|
File without changes
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""Data age from the exchange timestamp on a payload, else the receipt time."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import time
|
|
6
|
+
from typing import TypedDict
|
|
7
|
+
|
|
8
|
+
STALE_AFTER_MS = 20_000
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class DataAge(TypedDict):
|
|
12
|
+
age_ms: int
|
|
13
|
+
stale: bool
|
|
14
|
+
as_of_ms: int
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def wall_ms() -> int:
|
|
18
|
+
return int(time.time() * 1000)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def message_time(payload: object) -> int | None:
|
|
22
|
+
if not isinstance(payload, dict):
|
|
23
|
+
return None
|
|
24
|
+
raw = payload.get("time")
|
|
25
|
+
if isinstance(raw, bool) or not isinstance(raw, int):
|
|
26
|
+
return None
|
|
27
|
+
return raw
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def make_age(as_of_ms: int, now_ms: int) -> DataAge:
|
|
31
|
+
elapsed = now_ms - as_of_ms
|
|
32
|
+
if elapsed < 0:
|
|
33
|
+
elapsed = 0
|
|
34
|
+
return {
|
|
35
|
+
"age_ms": elapsed,
|
|
36
|
+
"stale": elapsed >= STALE_AFTER_MS,
|
|
37
|
+
"as_of_ms": as_of_ms,
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def resolve_as_of(payload: object, received_ms: int) -> int:
|
|
42
|
+
stamped = message_time(payload)
|
|
43
|
+
if stamped is None:
|
|
44
|
+
return received_ms
|
|
45
|
+
return stamped
|