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.
@@ -0,0 +1,12 @@
1
+ .venv/
2
+ .vscode/
3
+ __pycache__/
4
+ .pytest_cache/
5
+ .ruff_cache/
6
+ .coverage
7
+ htmlcov/
8
+ dist/
9
+ *.egg-info/
10
+ *.py[cod]
11
+ .DS_Store
12
+ exports/*
@@ -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