Skip to main content

Interactive synthetic OHLCV kline generator for learnable trading experiments.

Project description

Synthetic Klines

synthetic-ohlcv is a Python synthetic OHLCV data generator for controlled trading ML experiments, time-series pipeline tests, and reproducible market-like candlestick data. It generates synthetic kline datasets with valid open, high, low, close, volume, and turnover columns, returns data as a Polars DataFrame, and includes a local FastAPI and Plotly preview app for interactive scenario design.

The package is designed for experiments where you want to know whether a model, feature pipeline, or backtest harness can recover a known synthetic signal. It is not intended to prove that a strategy will work on real exchange data.

Features

  • Generate reproducible synthetic OHLCV and kline data with a fixed random seed.
  • Create valid candlestick data with ordered timestamps and coherent high/low/open/close values.
  • Tune learnable components such as trend bias, cyclic returns, return noise, candle gaps, wicks, volume response, regime shifts, volatility clustering, jump shocks, and mean reversion.
  • Export datasets to Parquet, CSV, and JSON metadata.
  • Use a small Python API for notebooks, scripts, tests, and ML experiments.
  • Run a local FastAPI app with Plotly candlestick and volume charts for visual inspection.

Installation

Install from PyPI with pip:

python -m pip install synthetic-ohlcv

Or install with uv:

uv pip install synthetic-ohlcv

Requires Python 3.11 or newer.

Quickstart

from synthetic_ohlcv import SyntheticKlinesConfig, make_synthetic_ohlcv

config = SyntheticKlinesConfig(rows=4_000, seed=43)
frame = make_synthetic_ohlcv(config)

print(frame.head())

The returned object is a Polars DataFrame, so it can be written, filtered, converted, or joined with normal Polars APIs.

Dataset Schema

Generated datasets contain exactly these columns:

Column Meaning
timestamp Candle open timestamp in milliseconds.
open Candle open price.
high Candle high price.
low Candle low price.
close Candle close price.
volume Synthetic traded volume.
turnover Synthetic traded value, computed from volume and typical candle price.

Run The Preview App

After installation, run:

synthetic-ohlcv

Open http://127.0.0.1:8100.

For local development, you can also run:

uv run synthetic-ohlcv

Use a custom host or port when needed:

synthetic-ohlcv --host 127.0.0.1 --port 8110
uv run synthetic-ohlcv --port 8110

The app lets you adjust generation controls, preview synthetic candlestick and volume charts, and save the resulting dataset.

Python Examples

Reproducible Data

Use the same configuration and seed to generate the same dataset again.

from synthetic_ohlcv import SyntheticKlinesConfig, make_synthetic_ohlcv

config = SyntheticKlinesConfig(rows=1_000, seed=123)

left = make_synthetic_ohlcv(config)
right = make_synthetic_ohlcv(config)

assert left.equals(right)

Save Parquet, CSV, And Metadata

from synthetic_ohlcv import SyntheticKlinesConfig, save_synthetic_ohlcv

result = save_synthetic_ohlcv(
    config=SyntheticKlinesConfig(rows=5_000, seed=7),
    dataset_name="cycle_debug_run",
    output_dir="exports",
)

print(result.parquet_path)
print(result.csv_path)
print(result.metadata_path)

This writes:

exports/cycle_debug_run.parquet
exports/cycle_debug_run.csv
exports/cycle_debug_run.metadata.json

Inspect Generation Metadata

Use metadata to understand the generated scenario and summarize the synthetic components.

from synthetic_ohlcv import SyntheticKlinesConfig, make_synthetic_ohlcv_with_metadata

frame, metadata = make_synthetic_ohlcv_with_metadata(
    SyntheticKlinesConfig(rows=2_000, seed=21)
)

print(metadata["summary"]["total_return"])
print(metadata["components"]["returns"]["cycles"])

Metadata is useful for diagnostics and experiment tracking. Do not feed it into a model unless you are intentionally building a supervised synthetic task with known generation labels.

Flat Null Benchmark

Start with a flat dataset when validating that a training loop, feature store, or backtest harness does not invent signal where no signal exists.

from synthetic_ohlcv import (
    JumpShockConfig,
    MeanReversionConfig,
    RegimeShiftConfig,
    SyntheticKlinesConfig,
    VolatilityClusterConfig,
    make_synthetic_ohlcv,
)

config = SyntheticKlinesConfig(
    rows=1_000,
    base_price=500.0,
    linear_bias=0.0,
    noise_std=0.0,
    gap_noise_std=0.0,
    wick_scale=0.0,
    range_multiplier=0.0,
    volume_noise_std=0.0,
    volume_return_sensitivity=0.0,
    volume_range_sensitivity=0.0,
    volume_volatility_sensitivity=0.0,
    cycles=[],
    regime_shift=RegimeShiftConfig(enabled=False, amplitude=0.0),
    volatility_cluster=VolatilityClusterConfig(enabled=False, strength=0.0),
    jump_shocks=JumpShockConfig(enabled=False, probability=0.0, scale=0.0),
    mean_reversion=MeanReversionConfig(enabled=False, strength=0.0),
)

frame = make_synthetic_ohlcv(config)

Harder Market-Like Scenario

Combine multiple components to create a less stationary synthetic benchmark.

from synthetic_ohlcv import (
    CycleComponent,
    JumpShockConfig,
    MeanReversionConfig,
    RegimeShiftConfig,
    SyntheticKlinesConfig,
    VolatilityClusterConfig,
    make_synthetic_ohlcv_with_metadata,
)

config = SyntheticKlinesConfig(
    rows=10_000,
    seed=99,
    cycles=[
        CycleComponent(kind="sine", amplitude=0.0010, period=96),
        CycleComponent(kind="cosine", amplitude=0.0007, period=672, phase=0.5, decay=0.2),
    ],
    regime_shift=RegimeShiftConfig(enabled=True, count=4, amplitude=0.0002),
    volatility_cluster=VolatilityClusterConfig(enabled=True, strength=0.5),
    jump_shocks=JumpShockConfig(enabled=True, probability=0.01, scale=0.003),
    mean_reversion=MeanReversionConfig(enabled=True, strength=0.01, window=72),
)

frame, metadata = make_synthetic_ohlcv_with_metadata(config)

Guidance For ML Experiments

  • Start with a flat null benchmark, then move to an easy cyclic scenario, then add noise, nonstationarity, jumps, and volatility clustering.
  • Keep the seed fixed while debugging feature engineering, data loading, and model training.
  • Change seeds and scenario parameters when checking robustness.
  • Split by timestamp, not by shuffled rows, to avoid time-series leakage.
  • Use the same scenario across models when comparing architecture or feature changes.
  • Track the JSON metadata next to model runs so you can explain which synthetic signals were present.
  • Treat synthetic results as controlled evidence about your pipeline or model behavior, not as evidence of live trading profitability.

When To Use This

synthetic-ohlcv is useful for:

  • ML pipeline smoke tests with realistic OHLCV-shaped data.
  • Signal-recovery experiments where the target pattern is intentionally generated.
  • Overfitting and leakage diagnostics.
  • Backtest and data-loader fixtures.
  • Notebook examples that should not depend on external exchange APIs.
  • Reproducible benchmarks for feature engineering and model iteration.

Limitations

Synthetic candles are not real markets. This package does not simulate an order book, bid/ask spread, exchange latency, slippage, liquidation cascades, market impact, cross-asset correlation, or real participant behavior. Use real exchange data and realistic execution assumptions before drawing conclusions about trading performance.

Development

Install development dependencies with uv, then run the tests:

uv sync
uv run pytest

The test suite verifies schema invariants, reproducibility, export behavior, FastAPI routes, and the configured coverage gate.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

synthetic_ohlcv-0.1.3.tar.gz (21.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

synthetic_ohlcv-0.1.3-py3-none-any.whl (21.3 kB view details)

Uploaded Python 3

File details

Details for the file synthetic_ohlcv-0.1.3.tar.gz.

File metadata

  • Download URL: synthetic_ohlcv-0.1.3.tar.gz
  • Upload date:
  • Size: 21.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for synthetic_ohlcv-0.1.3.tar.gz
Algorithm Hash digest
SHA256 010504592c6560f12fb6907f167cbde5369ccfd1e427b7fde265492594e92de2
MD5 fc609c6591b217e86a24b8ac089c815f
BLAKE2b-256 0e7c04b3aa7d5da2ba6f802845bb3d09b3affab19c457062e1f0c58781dd4b7f

See more details on using hashes here.

File details

Details for the file synthetic_ohlcv-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: synthetic_ohlcv-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 21.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for synthetic_ohlcv-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 d5f64c3dd8a3d3f183ada940223f65ba46b9857b4bd73434d5d63c349bc0fbfb
MD5 963f766181feabf6527c411257e59c29
BLAKE2b-256 9d105a7c0054c42b1cda1896ef0c70364753f519b3efb968683100d35722ed99

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page