Python library for market structure analysis — swings, trends, support/resistance zones, break/retest/flip signals. Works with any OHLCV DataFrame.
Project description
market-structure
Python library for market structure analysis — swings, trends, support/resistance zones, break/retest/flip signals. Works with any OHLCV DataFrame. Includes a Freqtrade integration.
Live Demo — interactive chart viewer showing market structure overlays on real price data.
Quick start
import pandas as pd
from market_structure.hydrate import hydrate
from market_structure.tsi import compute_tsi
from market_structure.atr import _compute_atr
# df: any OHLCV DataFrame with open, high, low, close, volume columns
df["tsi_hist"] = compute_tsi(df["close"])["tsi_histogram"]
helper = hydrate(df, histogram_key="tsi_hist")
atr = _compute_atr(df["high"].to_numpy(), df["low"].to_numpy(),
df["close"].to_numpy(), period=14)
for z in helper.get_support_zones(atr_arr=atr):
body_low, body_high = z.range # body-anchored (accepted price)
wick_low, wick_high = z.wick_range # wick extrema (for stop placement)
print(f"{z.anchor_wave_id} body=({body_low:.2f}, {body_high:.2f}) "
f"wick=({wick_low:.2f}, {wick_high:.2f}) double={z.is_double}")
Freqtrade integration
For Freqtrade strategies, a single call projects all 67 ms_* columns onto the DataFrame:
from market_structure.freqtrade import attach_market_structure
df = attach_market_structure(df, histogram_key="tsi_hist")
# df now has ms_support_zone_low, ms_wave_side, ms_is_trending_up, etc.
Backtest: market structure as a strategy filter
To validate the library, we ran an A/B comparison using a TSI signal-line crossover
strategy on 4h Binance futures (BTC, ETH, SOL, XRP, LTC) over 360 days in a -14.91%
market. The only difference: the "With MS" variant filters entries and exits through
the ms_* columns; the "Without" variant uses the same TSI signal and risk parameters
but skips market structure entirely.
| Metric | With MS filter | Without MS filter |
|---|---|---|
| Total profit | +39.85% | +22.59% |
| Profit factor | 1.50 | 1.21 |
| Sharpe | 0.94 | 0.58 |
| Max drawdown | 17.76% | 21.75% |
| Trades | 164 | 208 |
| Win rate | 36.0% | 31.7% |
| Stop-loss hits | 36 | 46 |
The filter blocked 44 low-quality entries (mostly would-be stop-outs), nearly doubling
profit while cutting drawdown by ~4 percentage points. Backtest data and
results for all three strategies live in
refs/freqtrade/.
Disclaimer: This is educational software, not financial advice. Past backtest performance does not guarantee future results. Parameters are curve-fit to a specific historical window. Do not trade real capital based on these examples without independent validation and risk assessment.
Documentation
- Column Reference — all 67
ms_*columns projected onto the DataFrame, with dtypes, tier descriptions, and strategy examples.
Install
pip install market-structure
The PyPI distribution is
market-structure; the import name ismarket_structure. The GitHub repo is namedpymarket-structure.
Development
This project uses uv for everything: Python version management, virtual environment, dependencies, lockfile, and dev tooling. Install uv first (one line — see the link above), then:
git clone git@github.com:fortunato/pymarket-structure.git
cd pymarket-structure
uv sync # creates .venv, installs all deps from uv.lock
uv run pre-commit install # one-time: enable git pre-commit hooks
uv run just # list all available development commands
uv run just check # run lint + format-check + type + test
That's the entire bootstrap. Everything else is described by the project files themselves:
pyproject.toml— package metadata, dependencies, ruff/pyright/pytest configurationJustfile— development commands (runuv run justfor the full menu).pre-commit-config.yaml— git hook configuration.editorconfig— editor formatting rules.python-version— pinned Python version
Tech stack
| Tool | Purpose |
|---|---|
| uv | Package manager, virtual environment, Python version manager |
| ruff | Linter + formatter (replaces black, isort, flake8, pylint) |
| pyright | Strict static type checker |
| pytest + pytest-cov | Test runner with branch coverage |
| pre-commit | Git hook framework |
| just | Task runner |
Common tasks
Once uv sync has run, the day-to-day workflow is driven by just recipes. A few highlights:
uv run just check # full CI pipeline (lint + format + type + test)
uv run just test # run all tests
uv run just test -k swing # run only tests matching a pattern
uv run just lint # ruff lint with auto-fix
uv run just fmt # ruff format
uv run just type # pyright (strict mode)
uv run just hooks # run all pre-commit hooks against every file
If your shell has the project's venv activated (
source .venv/bin/activate), you can drop theuv runprefix and just typejust check,pytest,ruff check, etc. directly. Most editors (PyCharm, VS Code) auto-activate the venv once the interpreter is configured.
Support
If this library saves you time or helps your trading, consider buying me a coffee.
License
See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file market_structure-0.1.0.tar.gz.
File metadata
- Download URL: market_structure-0.1.0.tar.gz
- Upload date:
- Size: 39.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2cfd536b100fd5826b9b3cc0f5f24f25ff01c95cee59f5cd593e317f0379e86a
|
|
| MD5 |
b0d933105ac179b6723c7e834e22c747
|
|
| BLAKE2b-256 |
ea20b6cb78c20b2578009b7e6126760b757d235646134b87aab1d64dc615cc7f
|
Provenance
The following attestation bundles were made for market_structure-0.1.0.tar.gz:
Publisher:
publish.yml on fortunato/pymarket-structure
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
market_structure-0.1.0.tar.gz -
Subject digest:
2cfd536b100fd5826b9b3cc0f5f24f25ff01c95cee59f5cd593e317f0379e86a - Sigstore transparency entry: 1337239886
- Sigstore integration time:
-
Permalink:
fortunato/pymarket-structure@3502b8ec96959ad47a9b63ae7474c17c7a2dbff7 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/fortunato
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3502b8ec96959ad47a9b63ae7474c17c7a2dbff7 -
Trigger Event:
release
-
Statement type:
File details
Details for the file market_structure-0.1.0-py3-none-any.whl.
File metadata
- Download URL: market_structure-0.1.0-py3-none-any.whl
- Upload date:
- Size: 41.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a5d6372f2c5574bf3210cbf34f720c6a0eabb553ad23f0fa1e9ec38acaef5d41
|
|
| MD5 |
de7d2eac45fdaa3cbddb5880e4f4bcf4
|
|
| BLAKE2b-256 |
ce780701077946a8794887a1806d541558af78b5eb95f0c806f580ab4b12c92c
|
Provenance
The following attestation bundles were made for market_structure-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on fortunato/pymarket-structure
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
market_structure-0.1.0-py3-none-any.whl -
Subject digest:
a5d6372f2c5574bf3210cbf34f720c6a0eabb553ad23f0fa1e9ec38acaef5d41 - Sigstore transparency entry: 1337239962
- Sigstore integration time:
-
Permalink:
fortunato/pymarket-structure@3502b8ec96959ad47a9b63ae7474c17c7a2dbff7 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/fortunato
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3502b8ec96959ad47a9b63ae7474c17c7a2dbff7 -
Trigger Event:
release
-
Statement type: