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.
Files changed (58) hide show
  1. perpbrain_read-0.1.0/PKG-INFO +19 -0
  2. perpbrain_read-0.1.0/README.md +7 -0
  3. perpbrain_read-0.1.0/pyproject.toml +27 -0
  4. perpbrain_read-0.1.0/setup.cfg +4 -0
  5. perpbrain_read-0.1.0/src/perpbrain_read/__init__.py +5 -0
  6. perpbrain_read-0.1.0/src/perpbrain_read/_dist.py +30 -0
  7. perpbrain_read-0.1.0/src/perpbrain_read/py.typed +0 -0
  8. perpbrain_read-0.1.0/src/perpbrain_read/read/__init__.py +5 -0
  9. perpbrain_read-0.1.0/src/perpbrain_read/read/age.py +45 -0
  10. perpbrain_read-0.1.0/src/perpbrain_read/read/dataset.py +719 -0
  11. perpbrain_read-0.1.0/src/perpbrain_read/read/hl_feed.py +190 -0
  12. perpbrain_read-0.1.0/src/perpbrain_read/read/info.py +84 -0
  13. perpbrain_read-0.1.0/src/perpbrain_read/read/markets.py +36 -0
  14. perpbrain_read-0.1.0/src/perpbrain_read/read/parse.py +71 -0
  15. perpbrain_read-0.1.0/src/perpbrain_read/read/queries.py +267 -0
  16. perpbrain_read-0.1.0/src/perpbrain_read/read/rate_limit.py +99 -0
  17. perpbrain_read-0.1.0/src/perpbrain_read/read/signals.py +200 -0
  18. perpbrain_read-0.1.0/src/perpbrain_read/read/stream.py +133 -0
  19. perpbrain_read-0.1.0/src/perpbrain_read/read/ws_conn.py +224 -0
  20. perpbrain_read-0.1.0/src/perpbrain_read/read/zstd_raw.py +51 -0
  21. perpbrain_read-0.1.0/src/perpbrain_read/sim/__init__.py +12 -0
  22. perpbrain_read-0.1.0/src/perpbrain_read/sim/card.py +329 -0
  23. perpbrain_read-0.1.0/src/perpbrain_read/sim/costs.py +345 -0
  24. perpbrain_read-0.1.0/src/perpbrain_read/sim/defaults.py +119 -0
  25. perpbrain_read-0.1.0/src/perpbrain_read/sim/engine.py +1032 -0
  26. perpbrain_read-0.1.0/src/perpbrain_read/sim/execution.py +171 -0
  27. perpbrain_read-0.1.0/src/perpbrain_read/sim/fees.py +79 -0
  28. perpbrain_read-0.1.0/src/perpbrain_read/sim/fixed.py +335 -0
  29. perpbrain_read-0.1.0/src/perpbrain_read/sim/funding_adapter.py +76 -0
  30. perpbrain_read-0.1.0/src/perpbrain_read/sim/overfit.py +210 -0
  31. perpbrain_read-0.1.0/src/perpbrain_read/sim/receipt.py +739 -0
  32. perpbrain_read-0.1.0/src/perpbrain_read/sim/study.py +137 -0
  33. perpbrain_read-0.1.0/src/perpbrain_read.egg-info/PKG-INFO +19 -0
  34. perpbrain_read-0.1.0/src/perpbrain_read.egg-info/SOURCES.txt +56 -0
  35. perpbrain_read-0.1.0/src/perpbrain_read.egg-info/dependency_links.txt +1 -0
  36. perpbrain_read-0.1.0/src/perpbrain_read.egg-info/top_level.txt +1 -0
  37. perpbrain_read-0.1.0/tests/test_card.py +198 -0
  38. perpbrain_read-0.1.0/tests/test_costs.py +246 -0
  39. perpbrain_read-0.1.0/tests/test_dataset.py +289 -0
  40. perpbrain_read-0.1.0/tests/test_execution.py +141 -0
  41. perpbrain_read-0.1.0/tests/test_fees.py +48 -0
  42. perpbrain_read-0.1.0/tests/test_funding_adapter.py +28 -0
  43. perpbrain_read-0.1.0/tests/test_hl_feed.py +158 -0
  44. perpbrain_read-0.1.0/tests/test_numeric_parity.py +152 -0
  45. perpbrain_read-0.1.0/tests/test_overfit.py +76 -0
  46. perpbrain_read-0.1.0/tests/test_queries.py +277 -0
  47. perpbrain_read-0.1.0/tests/test_rate_limit.py +115 -0
  48. perpbrain_read-0.1.0/tests/test_read.py +20 -0
  49. perpbrain_read-0.1.0/tests/test_read_dist.py +21 -0
  50. perpbrain_read-0.1.0/tests/test_receipt.py +621 -0
  51. perpbrain_read-0.1.0/tests/test_signals.py +215 -0
  52. perpbrain_read-0.1.0/tests/test_sim.py +23 -0
  53. perpbrain_read-0.1.0/tests/test_sim_defaults.py +129 -0
  54. perpbrain_read-0.1.0/tests/test_simulate.py +794 -0
  55. perpbrain_read-0.1.0/tests/test_stream.py +209 -0
  56. perpbrain_read-0.1.0/tests/test_study.py +93 -0
  57. perpbrain_read-0.1.0/tests/test_ws_conn.py +222 -0
  58. 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,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,5 @@
1
+ """Read-only and simulation toolkit. No order or guard imports."""
2
+
3
+ from perpbrain_read._dist import distribution_name
4
+
5
+ __all__ = ["distribution_name"]
@@ -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,5 @@
1
+ """Read models. Live queries live in queries.py and do not replace these stubs."""
2
+
3
+ from perpbrain_read.read.markets import book, funding, liquidations, open_interest
4
+
5
+ __all__ = ["book", "funding", "liquidations", "open_interest"]
@@ -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