Skip to main content

chart-lookalike-transform

Find the affine transform — vertical scale a, offset b, and optional inversion — that best maps a candidate ticker's price series onto a chart shape you already recognize, then screen a list of tickers by how well they "look like" that setup.

A chart's shape is invariant to vertical scale and shift: $10 → $11 over a month traces the same curve as $100 → $110. So to ask "does NVDA right now look like the cup-and-handle I'm watching for?" you fit

reference ≈ a · candidate + b          (a < 0 ⇒ candidate is the mirror image)

by least squares (closed form), report the fit quality as a 0..1 similarity, and overlay the transformed candidate on the reference with moving-average indicators.

This is not dynamic time warping — the time axis is held fixed, so "lookalike" means the literal same shape over the same window, just rescaled vertically. (DTW would match shapes that drift in time; deliberately out of scope.)

Install

pip install -e ".[test]"      # includes matplotlib for plotting + pytest
# or, runtime only:
pip install -e .              # numpy only; add ".[plot]" for PNG overlays

Python ≥ 3.10. Core dependency is just NumPy; matplotlib is optional (only for --plot).

Quick start (no network)

Everything works offline against deterministic synthetic data via --offline (or CHART_LOOKALIKE_API=mock), so you can try it instantly:

# List the built-in reference shapes.
chart-lookalike shapes

# Fit one ticker to a recognized shape and print the transform.
chart-lookalike match AAPL --shape cup-with-handle --offline

# Screen a basket, keep the best 5, and use a real ticker as the reference shape.
chart-lookalike screen AAPL MSFT NVDA TSLA AMD --ref-ticker NVDA --offline --top 5

# Write a PNG overlay (transformed candidate + reference + SMAs).
chart-lookalike match TSLA --shape v-bottom --offline --plot match.png

Drop --offline to pull live daily closes from Yahoo Finance (no API key needed). The data layer is provider-pluggable behind the CHART_LOOKALIKE_API env var.

Reference shapes

Three ways to specify the target shape (choose exactly one):

Flag Meaning
--shape <name> a built-in shape (chart-lookalike shapes lists them)
--ref-csv <path> a file of reference prices (one number per line, or date,close rows — the last numeric field per line is used)
--ref-ticker <sym> use another ticker's own series as the target shape

Built-in shapes: v-bottom, inverse-v-top, cup, cup-with-handle, head-and-shoulders, uptrend, downtrend, double-bottom.

How the fit works

For a reference t and candidate c (resampled to a common length), the least-squares affine fit has a closed form:

a = cov(c, t) / var(c)
b = mean(t) − a · mean(c)

When inversion is allowed, the mirror candidate −c is also fit and the lower-residual solution wins (a negative a ⇒ inverted = True). Fit quality:

rmse       = sqrt( mean( (a·c + b − t)² ) )
similarity = clip( 1 − rmse / rms(t − mean(t)),  0, 1 )

similarity = 1.0 is a perfect shape match; 0.0 is no better than predicting a flat line at the reference's mean.

Library API

import numpy as np
from chart_lookalike import fit_affine, apply_affine, get_provider, screen
from chart_lookalike.shapes import get_shape

provider = get_provider("mock")              # or "yahoo"
series   = provider.history("AAPL", days=180)
ref      = get_shape("cup-with-handle")

fit = fit_affine(series.closes, ref)         # AffineFit(scale, offset, inverted, rmse, similarity, n)
overlay = apply_affine(series.closes, fit)   # candidate mapped onto the reference's units

ranked = screen(ref, ["AAPL", "MSFT", "NVDA"], provider, top=3)
for r in ranked:
    print(r.symbol, round(r.similarity, 3), "inverted" if r.fit.inverted else "")

Live-data dependency & testing

The Yahoo provider hits query1.finance.yahoo.com/v8/finance/chart at runtime — that endpoint is undocumented and rate-limited, so it is the one piece that can break outside our control. The JSON parser (parse_yahoo_chart) is split out as a pure function and unit-tested against a saved fixture (fixtures/yahoo_aapl.json, including a null-close hole and the error envelope) — the test suite never touches the network.

pytest -q

Disclaimer

This is a charting/screening aid, not investment advice. A high similarity score means two curves have a similar shape over a window — nothing about what happens next.

License

MIT — see LICENSE.

Metadata

Release files for chart-lookalike-transform 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for chart-lookalike-transform 0.1.0
File Size Uploaded Provenance
chart_lookalike_transform-0.1.0.tar.gz 24.1 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for chart-lookalike-transform 0.1.0
File Interpreter ABI Platform
chart_lookalike_transform-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 43.5 kB

Release files / chart_lookalike_transform-0.1.0.tar.gz

Download URL chart_lookalike_transform-0.1.0.tar.gz
Size 24.1 kB
Tags Source
SHA-256 checksum
How to use checksums
65dfd5786e9ea4ab9945df41bc24a74fd8acb1fe24afa0febf6eb631fbee05a8
BLAKE2b-256 checksum
How to use checksums
a2651e93ca40b851694d180a1c1c318245e6a615186b6782cf4766483b379cd6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release files / chart_lookalike_transform-0.1.0-py3-none-any.whl

Download URL chart_lookalike_transform-0.1.0-py3-none-any.whl
Size 19.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1ba7898d92082b53cff0e7b786c5ce55cae654c26626151d9fbf19fbdaab740f
BLAKE2b-256 checksum
How to use checksums
5aed06227c89621616989e2fe4c37acce31f36571416d2f39b62fbbd88589579
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Security for chart-lookalike-transform 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page