synthetic-ohlcv 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.
- synthetic_ohlcv-0.1.0/.gitignore +12 -0
- synthetic_ohlcv-0.1.0/PKG-INFO +78 -0
- synthetic_ohlcv-0.1.0/README.md +55 -0
- synthetic_ohlcv-0.1.0/pyproject.toml +78 -0
- synthetic_ohlcv-0.1.0/src/synthetic_ohlcv/__init__.py +44 -0
- synthetic_ohlcv-0.1.0/src/synthetic_ohlcv/config.py +94 -0
- synthetic_ohlcv-0.1.0/src/synthetic_ohlcv/controls.py +492 -0
- synthetic_ohlcv-0.1.0/src/synthetic_ohlcv/generator.py +298 -0
- synthetic_ohlcv-0.1.0/src/synthetic_ohlcv/io.py +94 -0
- synthetic_ohlcv-0.1.0/src/synthetic_ohlcv/server.py +94 -0
- synthetic_ohlcv-0.1.0/src/synthetic_ohlcv/templates/app.js +425 -0
- synthetic_ohlcv-0.1.0/src/synthetic_ohlcv/templates/index.html +354 -0
- synthetic_ohlcv-0.1.0/tests/test_config_and_controls.py +50 -0
- synthetic_ohlcv-0.1.0/tests/test_generator.py +141 -0
- synthetic_ohlcv-0.1.0/tests/test_io.py +40 -0
- synthetic_ohlcv-0.1.0/tests/test_server.py +126 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: synthetic-ohlcv
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Interactive synthetic OHLCV kline generator for learnable trading experiments.
|
|
5
|
+
Keywords: fastapi,klines,ohlcv,synthetic-data,trading
|
|
6
|
+
Classifier: Development Status :: 3 - Alpha
|
|
7
|
+
Classifier: Framework :: FastAPI
|
|
8
|
+
Classifier: Intended Audience :: Developers
|
|
9
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering
|
|
15
|
+
Classifier: Topic :: Software Development :: Testing
|
|
16
|
+
Requires-Python: >=3.11
|
|
17
|
+
Requires-Dist: fastapi>=0.136.1
|
|
18
|
+
Requires-Dist: numpy<3,>=2.3.0
|
|
19
|
+
Requires-Dist: polars>=1.40.1
|
|
20
|
+
Requires-Dist: pydantic>=2.13.3
|
|
21
|
+
Requires-Dist: uvicorn>=0.46.0
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# Synthetic Klines
|
|
25
|
+
|
|
26
|
+
Standalone synthetic OHLCV kline generator for learnable trading experiments.
|
|
27
|
+
|
|
28
|
+
Requires Python 3.11 or newer.
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
Install from PyPI with `pip`:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
python -m pip install synthetic-ohlcv
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Or install with `uv`:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
uv pip install synthetic-ohlcv
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Run The App
|
|
45
|
+
|
|
46
|
+
After installation, run:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
synthetic-ohlcv
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Open `http://127.0.0.1:8100`.
|
|
53
|
+
|
|
54
|
+
For local development, you can also run:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
uv run synthetic-ohlcv
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Use a custom port when needed:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
uv run synthetic-ohlcv --port 8110
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Python API
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
from synthetic_ohlcv import SyntheticKlinesConfig, make_synthetic_ohlcv
|
|
70
|
+
|
|
71
|
+
frame = make_synthetic_ohlcv(SyntheticKlinesConfig(rows=4_000, seed=43))
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Generated datasets contain exactly:
|
|
75
|
+
|
|
76
|
+
```text
|
|
77
|
+
timestamp, open, high, low, close, volume, turnover
|
|
78
|
+
```
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Synthetic Klines
|
|
2
|
+
|
|
3
|
+
Standalone synthetic OHLCV kline generator for learnable trading experiments.
|
|
4
|
+
|
|
5
|
+
Requires Python 3.11 or newer.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
Install from PyPI with `pip`:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
python -m pip install synthetic-ohlcv
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Or install with `uv`:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
uv pip install synthetic-ohlcv
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Run The App
|
|
22
|
+
|
|
23
|
+
After installation, run:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
synthetic-ohlcv
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Open `http://127.0.0.1:8100`.
|
|
30
|
+
|
|
31
|
+
For local development, you can also run:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
uv run synthetic-ohlcv
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Use a custom port when needed:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
uv run synthetic-ohlcv --port 8110
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Python API
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from synthetic_ohlcv import SyntheticKlinesConfig, make_synthetic_ohlcv
|
|
47
|
+
|
|
48
|
+
frame = make_synthetic_ohlcv(SyntheticKlinesConfig(rows=4_000, seed=43))
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Generated datasets contain exactly:
|
|
52
|
+
|
|
53
|
+
```text
|
|
54
|
+
timestamp, open, high, low, close, volume, turnover
|
|
55
|
+
```
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling>=1.28"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "synthetic-ohlcv"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Interactive synthetic OHLCV kline generator for learnable trading experiments."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
keywords = ["ohlcv", "synthetic-data", "trading", "klines", "fastapi"]
|
|
12
|
+
classifiers = [
|
|
13
|
+
"Development Status :: 3 - Alpha",
|
|
14
|
+
"Framework :: FastAPI",
|
|
15
|
+
"Intended Audience :: Developers",
|
|
16
|
+
"Intended Audience :: Financial and Insurance Industry",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Programming Language :: Python :: 3.11",
|
|
19
|
+
"Programming Language :: Python :: 3.12",
|
|
20
|
+
"Programming Language :: Python :: 3.13",
|
|
21
|
+
"Topic :: Scientific/Engineering",
|
|
22
|
+
"Topic :: Software Development :: Testing",
|
|
23
|
+
]
|
|
24
|
+
dependencies = [
|
|
25
|
+
"fastapi>=0.136.1",
|
|
26
|
+
"numpy>=2.3.0,<3",
|
|
27
|
+
"polars>=1.40.1",
|
|
28
|
+
"pydantic>=2.13.3",
|
|
29
|
+
"uvicorn>=0.46.0",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.scripts]
|
|
33
|
+
synthetic-ohlcv = "synthetic_ohlcv.server:main"
|
|
34
|
+
|
|
35
|
+
[dependency-groups]
|
|
36
|
+
dev = [
|
|
37
|
+
"httpx>=0.28.1",
|
|
38
|
+
"pytest>=9.0.3",
|
|
39
|
+
"pytest-cov>=7.0.0",
|
|
40
|
+
"ruff>=0.15.12",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
[tool.hatch.build.targets.sdist]
|
|
44
|
+
include = [
|
|
45
|
+
"/README.md",
|
|
46
|
+
"/src",
|
|
47
|
+
"/tests",
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
[tool.hatch.build.targets.wheel]
|
|
51
|
+
packages = ["src/synthetic_ohlcv"]
|
|
52
|
+
|
|
53
|
+
[tool.ruff]
|
|
54
|
+
line-length = 100
|
|
55
|
+
target-version = "py311"
|
|
56
|
+
|
|
57
|
+
[tool.ruff.lint]
|
|
58
|
+
select = ["E", "F", "I", "B", "UP", "RUF"]
|
|
59
|
+
|
|
60
|
+
[tool.ruff.format]
|
|
61
|
+
quote-style = "double"
|
|
62
|
+
indent-style = "space"
|
|
63
|
+
line-ending = "lf"
|
|
64
|
+
|
|
65
|
+
[tool.pytest.ini_options]
|
|
66
|
+
testpaths = ["tests"]
|
|
67
|
+
pythonpath = ["src"]
|
|
68
|
+
addopts = [
|
|
69
|
+
"--cov=synthetic_ohlcv",
|
|
70
|
+
"--cov-branch",
|
|
71
|
+
"--cov-report=term-missing",
|
|
72
|
+
"--cov-fail-under=100",
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
[tool.coverage.report]
|
|
76
|
+
exclude_also = [
|
|
77
|
+
"if __name__ == .__main__.:",
|
|
78
|
+
]
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""Independent synthetic OHLCV kline generator and local preview app."""
|
|
2
|
+
|
|
3
|
+
from synthetic_ohlcv.config import (
|
|
4
|
+
CycleComponent,
|
|
5
|
+
JumpShockConfig,
|
|
6
|
+
MeanReversionConfig,
|
|
7
|
+
RegimeShiftConfig,
|
|
8
|
+
SyntheticKlinesConfig,
|
|
9
|
+
VolatilityClusterConfig,
|
|
10
|
+
)
|
|
11
|
+
from synthetic_ohlcv.controls import (
|
|
12
|
+
CONFIG_CONTROL_PATHS,
|
|
13
|
+
ControlGroup,
|
|
14
|
+
ControlOption,
|
|
15
|
+
ControlSpec,
|
|
16
|
+
control_schema,
|
|
17
|
+
control_schema_payload,
|
|
18
|
+
)
|
|
19
|
+
from synthetic_ohlcv.generator import (
|
|
20
|
+
KLINE_COLUMNS,
|
|
21
|
+
make_synthetic_ohlcv,
|
|
22
|
+
make_synthetic_ohlcv_with_metadata,
|
|
23
|
+
)
|
|
24
|
+
from synthetic_ohlcv.io import SaveResult, save_synthetic_ohlcv
|
|
25
|
+
|
|
26
|
+
__all__ = [
|
|
27
|
+
"CONFIG_CONTROL_PATHS",
|
|
28
|
+
"KLINE_COLUMNS",
|
|
29
|
+
"ControlGroup",
|
|
30
|
+
"ControlOption",
|
|
31
|
+
"ControlSpec",
|
|
32
|
+
"CycleComponent",
|
|
33
|
+
"JumpShockConfig",
|
|
34
|
+
"MeanReversionConfig",
|
|
35
|
+
"RegimeShiftConfig",
|
|
36
|
+
"SaveResult",
|
|
37
|
+
"SyntheticKlinesConfig",
|
|
38
|
+
"VolatilityClusterConfig",
|
|
39
|
+
"control_schema",
|
|
40
|
+
"control_schema_payload",
|
|
41
|
+
"make_synthetic_ohlcv",
|
|
42
|
+
"make_synthetic_ohlcv_with_metadata",
|
|
43
|
+
"save_synthetic_ohlcv",
|
|
44
|
+
]
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Literal
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
|
5
|
+
|
|
6
|
+
DEFAULT_INTERVAL_MS = 15 * 60 * 1000
|
|
7
|
+
DEFAULT_START_TIMESTAMP = 1_609_459_200_000
|
|
8
|
+
DEFAULT_EXPORT_DIR = Path("exports")
|
|
9
|
+
|
|
10
|
+
CycleKind = Literal["sine", "cosine"]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class BaseConfig(BaseModel):
|
|
14
|
+
model_config = ConfigDict(extra="forbid")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class CycleComponent(BaseConfig):
|
|
18
|
+
kind: CycleKind = "sine"
|
|
19
|
+
amplitude: float = Field(default=0.0014, ge=0.0)
|
|
20
|
+
period: int = Field(default=96, ge=2)
|
|
21
|
+
phase: float = 0.0
|
|
22
|
+
decay: float = Field(default=0.0, ge=0.0)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class RegimeShiftConfig(BaseConfig):
|
|
26
|
+
enabled: bool = False
|
|
27
|
+
count: int = Field(default=3, ge=1, le=20)
|
|
28
|
+
amplitude: float = Field(default=0.00025, ge=0.0)
|
|
29
|
+
transition_steps: int = Field(default=48, ge=1)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class VolatilityClusterConfig(BaseConfig):
|
|
33
|
+
enabled: bool = False
|
|
34
|
+
strength: float = Field(default=0.35, ge=0.0)
|
|
35
|
+
persistence: float = Field(default=0.92, ge=0.0, lt=1.0)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class JumpShockConfig(BaseConfig):
|
|
39
|
+
enabled: bool = False
|
|
40
|
+
probability: float = Field(default=0.002, ge=0.0, le=1.0)
|
|
41
|
+
scale: float = Field(default=0.006, ge=0.0)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class MeanReversionConfig(BaseConfig):
|
|
45
|
+
enabled: bool = False
|
|
46
|
+
strength: float = Field(default=0.025, ge=0.0, le=1.0)
|
|
47
|
+
window: int = Field(default=96, ge=2)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def default_cycles() -> list[CycleComponent]:
|
|
51
|
+
return [
|
|
52
|
+
CycleComponent(kind="sine", amplitude=0.0014, period=96, phase=0.0),
|
|
53
|
+
CycleComponent(kind="cosine", amplitude=0.00045, period=672, phase=0.75),
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class SyntheticKlinesConfig(BaseConfig):
|
|
58
|
+
rows: int = Field(default=4_000, ge=2, le=100_000)
|
|
59
|
+
seed: int = 43
|
|
60
|
+
base_price: float = Field(default=10_000.0, gt=0.0)
|
|
61
|
+
start_timestamp: int = Field(default=DEFAULT_START_TIMESTAMP, ge=0)
|
|
62
|
+
interval_ms: int = Field(default=DEFAULT_INTERVAL_MS, gt=0)
|
|
63
|
+
|
|
64
|
+
linear_bias: float = 0.00002
|
|
65
|
+
noise_std: float = Field(default=0.0008, ge=0.0)
|
|
66
|
+
gap_noise_std: float = Field(default=0.00012, ge=0.0)
|
|
67
|
+
wick_scale: float = Field(default=0.55, ge=0.0)
|
|
68
|
+
range_multiplier: float = Field(default=1.35, ge=0.0)
|
|
69
|
+
|
|
70
|
+
base_volume: float = Field(default=1_000.0, gt=0.0)
|
|
71
|
+
volume_noise_std: float = Field(default=0.12, ge=0.0)
|
|
72
|
+
volume_return_sensitivity: float = Field(default=0.35, ge=0.0)
|
|
73
|
+
volume_range_sensitivity: float = Field(default=0.20, ge=0.0)
|
|
74
|
+
volume_volatility_sensitivity: float = Field(default=0.20, ge=0.0)
|
|
75
|
+
|
|
76
|
+
cycles: list[CycleComponent] = Field(default_factory=default_cycles)
|
|
77
|
+
regime_shift: RegimeShiftConfig = Field(default_factory=RegimeShiftConfig)
|
|
78
|
+
volatility_cluster: VolatilityClusterConfig = Field(default_factory=VolatilityClusterConfig)
|
|
79
|
+
jump_shocks: JumpShockConfig = Field(default_factory=JumpShockConfig)
|
|
80
|
+
mean_reversion: MeanReversionConfig = Field(default_factory=MeanReversionConfig)
|
|
81
|
+
|
|
82
|
+
@field_validator("linear_bias")
|
|
83
|
+
@classmethod
|
|
84
|
+
def validate_finite_linear_bias(cls, value: float) -> float:
|
|
85
|
+
if not -1.0 < value < 1.0:
|
|
86
|
+
raise ValueError("linear_bias must be between -1.0 and 1.0")
|
|
87
|
+
return value
|
|
88
|
+
|
|
89
|
+
@model_validator(mode="after")
|
|
90
|
+
def validate_component_scale(self) -> "SyntheticKlinesConfig":
|
|
91
|
+
max_cycle_amplitude = max((cycle.amplitude for cycle in self.cycles), default=0.0)
|
|
92
|
+
if max_cycle_amplitude >= 1.0:
|
|
93
|
+
raise ValueError("cycle amplitude must be smaller than 1.0")
|
|
94
|
+
return self
|