perpbrain-read 0.1.0__tar.gz
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-0.1.0/PKG-INFO +19 -0
- perpbrain_read-0.1.0/README.md +7 -0
- perpbrain_read-0.1.0/pyproject.toml +27 -0
- perpbrain_read-0.1.0/setup.cfg +4 -0
- perpbrain_read-0.1.0/src/perpbrain_read/__init__.py +5 -0
- perpbrain_read-0.1.0/src/perpbrain_read/_dist.py +30 -0
- perpbrain_read-0.1.0/src/perpbrain_read/py.typed +0 -0
- perpbrain_read-0.1.0/src/perpbrain_read/read/__init__.py +5 -0
- perpbrain_read-0.1.0/src/perpbrain_read/read/age.py +45 -0
- perpbrain_read-0.1.0/src/perpbrain_read/read/dataset.py +719 -0
- perpbrain_read-0.1.0/src/perpbrain_read/read/hl_feed.py +190 -0
- perpbrain_read-0.1.0/src/perpbrain_read/read/info.py +84 -0
- perpbrain_read-0.1.0/src/perpbrain_read/read/markets.py +36 -0
- perpbrain_read-0.1.0/src/perpbrain_read/read/parse.py +71 -0
- perpbrain_read-0.1.0/src/perpbrain_read/read/queries.py +267 -0
- perpbrain_read-0.1.0/src/perpbrain_read/read/rate_limit.py +99 -0
- perpbrain_read-0.1.0/src/perpbrain_read/read/signals.py +200 -0
- perpbrain_read-0.1.0/src/perpbrain_read/read/stream.py +133 -0
- perpbrain_read-0.1.0/src/perpbrain_read/read/ws_conn.py +224 -0
- perpbrain_read-0.1.0/src/perpbrain_read/read/zstd_raw.py +51 -0
- perpbrain_read-0.1.0/src/perpbrain_read/sim/__init__.py +12 -0
- perpbrain_read-0.1.0/src/perpbrain_read/sim/card.py +329 -0
- perpbrain_read-0.1.0/src/perpbrain_read/sim/costs.py +345 -0
- perpbrain_read-0.1.0/src/perpbrain_read/sim/defaults.py +119 -0
- perpbrain_read-0.1.0/src/perpbrain_read/sim/engine.py +1032 -0
- perpbrain_read-0.1.0/src/perpbrain_read/sim/execution.py +171 -0
- perpbrain_read-0.1.0/src/perpbrain_read/sim/fees.py +79 -0
- perpbrain_read-0.1.0/src/perpbrain_read/sim/fixed.py +335 -0
- perpbrain_read-0.1.0/src/perpbrain_read/sim/funding_adapter.py +76 -0
- perpbrain_read-0.1.0/src/perpbrain_read/sim/overfit.py +210 -0
- perpbrain_read-0.1.0/src/perpbrain_read/sim/receipt.py +739 -0
- perpbrain_read-0.1.0/src/perpbrain_read/sim/study.py +137 -0
- perpbrain_read-0.1.0/src/perpbrain_read.egg-info/PKG-INFO +19 -0
- perpbrain_read-0.1.0/src/perpbrain_read.egg-info/SOURCES.txt +56 -0
- perpbrain_read-0.1.0/src/perpbrain_read.egg-info/dependency_links.txt +1 -0
- perpbrain_read-0.1.0/src/perpbrain_read.egg-info/top_level.txt +1 -0
- perpbrain_read-0.1.0/tests/test_card.py +198 -0
- perpbrain_read-0.1.0/tests/test_costs.py +246 -0
- perpbrain_read-0.1.0/tests/test_dataset.py +289 -0
- perpbrain_read-0.1.0/tests/test_execution.py +141 -0
- perpbrain_read-0.1.0/tests/test_fees.py +48 -0
- perpbrain_read-0.1.0/tests/test_funding_adapter.py +28 -0
- perpbrain_read-0.1.0/tests/test_hl_feed.py +158 -0
- perpbrain_read-0.1.0/tests/test_numeric_parity.py +152 -0
- perpbrain_read-0.1.0/tests/test_overfit.py +76 -0
- perpbrain_read-0.1.0/tests/test_queries.py +277 -0
- perpbrain_read-0.1.0/tests/test_rate_limit.py +115 -0
- perpbrain_read-0.1.0/tests/test_read.py +20 -0
- perpbrain_read-0.1.0/tests/test_read_dist.py +21 -0
- perpbrain_read-0.1.0/tests/test_receipt.py +621 -0
- perpbrain_read-0.1.0/tests/test_signals.py +215 -0
- perpbrain_read-0.1.0/tests/test_sim.py +23 -0
- perpbrain_read-0.1.0/tests/test_sim_defaults.py +129 -0
- perpbrain_read-0.1.0/tests/test_simulate.py +794 -0
- perpbrain_read-0.1.0/tests/test_stream.py +209 -0
- perpbrain_read-0.1.0/tests/test_study.py +93 -0
- perpbrain_read-0.1.0/tests/test_ws_conn.py +222 -0
- perpbrain_read-0.1.0/tests/test_zstd_raw.py +39 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: perpbrain-read
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: PERPBRAIN read and simulation package. Must not import order or guard modules.
|
|
5
|
+
Author-email: PERPBRAIN <info@perpbrain.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/PERPBRAIN/perpbrain
|
|
8
|
+
Project-URL: Repository, https://github.com/PERPBRAIN/perpbrain
|
|
9
|
+
Project-URL: Changelog, https://github.com/PERPBRAIN/perpbrain/blob/main/CHANGELOG.md
|
|
10
|
+
Requires-Python: >=3.11
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
|
|
13
|
+
# perpbrain-read
|
|
14
|
+
|
|
15
|
+
Read and simulation only. This package must not import order or guard modules.
|
|
16
|
+
|
|
17
|
+
Simulation output is labelled `SIMULATED`. A result is verified and reproducible from its inputs. It is not advice.
|
|
18
|
+
|
|
19
|
+
This package is `0.1.0`. It is not published from this tree.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# perpbrain-read
|
|
2
|
+
|
|
3
|
+
Read and simulation only. This package must not import order or guard modules.
|
|
4
|
+
|
|
5
|
+
Simulation output is labelled `SIMULATED`. A result is verified and reproducible from its inputs. It is not advice.
|
|
6
|
+
|
|
7
|
+
This package is `0.1.0`. It is not published from this tree.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "perpbrain-read"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "PERPBRAIN read and simulation package. Must not import order or guard modules."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.11"
|
|
7
|
+
license = "MIT"
|
|
8
|
+
authors = [{ name = "PERPBRAIN", email = "info@perpbrain.com" }]
|
|
9
|
+
dependencies = []
|
|
10
|
+
|
|
11
|
+
[project.urls]
|
|
12
|
+
Homepage = "https://github.com/PERPBRAIN/perpbrain"
|
|
13
|
+
Repository = "https://github.com/PERPBRAIN/perpbrain"
|
|
14
|
+
Changelog = "https://github.com/PERPBRAIN/perpbrain/blob/main/CHANGELOG.md"
|
|
15
|
+
|
|
16
|
+
[tool.perpbrain]
|
|
17
|
+
dist-name = "perpbrain-read"
|
|
18
|
+
|
|
19
|
+
[build-system]
|
|
20
|
+
requires = ["setuptools==84.0.0"]
|
|
21
|
+
build-backend = "setuptools.build_meta"
|
|
22
|
+
|
|
23
|
+
[tool.setuptools.packages.find]
|
|
24
|
+
where = ["src"]
|
|
25
|
+
|
|
26
|
+
[tool.setuptools.package-data]
|
|
27
|
+
perpbrain_read = ["py.typed"]
|
|
@@ -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"
|
|
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
|