cotmetrics
Turn raw COT (Commitments of Traders) data into positioning metrics and trading
signals — the positioning index, concentration / clustering / position-size,
reversal signals, and the CotIndexer that assembles per-instrument weekly panels.
Split out of the cot-analyzer dashboard so the metrics layer installs without the
Dash/Plotly UI stack. Reads prices and COT from the shared
cotdata store.
Install
pip install cotmetrics
This pulls in cotdata, the data layer beneath
it. cotmetrics computes metrics over a populated cotdata store — point
COTDATA_STORE at one before you can read real prices/COT (see
cotdata for how to build the store). Optional
extras: pip install "cotmetrics[options]" (max-pain options snapshots via yfinance).
Use
import cotmetrics # flat metric fns, side-effect-free import
from cotmetrics.indexer import get_indexer, boot_options_update
from cotmetrics.signals import append_trading_signals
cotmetrics.calculate_cot_index(...)
import cotmetrics is side-effect-free. get_indexer() constructs (and caches) the
CotIndexer, which loads the store on first use; the daily options fetch runs only
when you call boot_options_update() explicitly.
Config / paths
| env | meaning | default |
|---|---|---|
COTDATA_STORE |
shared price/COT store (from cotdata) | required |
COTMETRICS_CACHE |
derived per-instrument parquet cache | ~/.cache/cotmetrics |
COTMETRICS_CITPY |
CIT PY research notes (dated .md/.txt), persistent data not a cache. Point it at the generating tool's output dir, never inside COTDATA_STORE |
~/.local/share/cotmetrics/citpy |
COTMETRICS_PARAMS |
instrument/params config | packaged sample params.yaml |
COTMETRICS_DATA |
working dir for real_test_data (fixture) exports | <cache>/../cotmetrics_data |
The packaged params.yaml is a small generic sample (a handful of well-known
symbols, untuned 52-week lookbacks) so cotmetrics runs out of the box. For a real
instrument universe and any tuned parameters, set COTMETRICS_PARAMS to your own
config file.
Scheduling (weekly COT refresh + email)
COT data is produced by cotdata, not here. cotmetrics only reads the shared store, so
refresh COT on the schedule cotdata documents (see the "Scheduling on Linux (cron)"
section of the cotdata README:
cotdata-update --cot-all, run through the CFTC's Friday ~3:30pm ET release window).
scripts/cron_update.sh wraps that refresh and emails the weekly report only when the
COT report date actually advances. It takes its config from the environment (no paths
baked in), so point the crontab at it:
# Friday afternoon (times in ET): refresh COT, email the report only if new data landed.
*/2 15-16 * * 5 COTDATA_STORE=/path/to/store /path/to/cotmetrics/scripts/cron_update.sh >> /path/to/cot.log 2>&1
| env | meaning | default |
|---|---|---|
COTDATA_STORE |
shared cotdata store | required |
COTDATA_UPDATE |
the cotdata-update binary |
cotdata-update on PATH |
The script reads status.json's newest_data.cot_legacy before and after the update and
runs scripts/generate-weekly-report-email.sh only on a change, so re-running across the
release window is a harmless no-op until the CFTC zip lands.
This route suits a box that produces COT. It runs cotdata-update itself, so on a
box whose store is a replica fed by a producer push, it would make a second producer
racing that push. Such a box has no download to trigger on, and should instead let the
consuming app send: cot-analyzer's store poller notices status.json advancing and
calls cotmetrics.weekly_email in-process, guarded by an opt-in flag and a ledger so it
sends once per COT week. Sending in-process also means the email inherits the app's own
COTMETRICS_PARAMS, which is worth more than it sounds: unset, that silently resolves
to the 6-symbol SAMPLE universe, and an email covering six markets looks exactly like an
email covering forty-seven.
Sending it directly
scripts/generate-weekly-report-email.py sends one now, and is a thin CLI over
cotmetrics.weekly_email.send_weekly_matrix_email. It reads three variables from the
environment of the process invoking it and loads no .env of its own:
| env | meaning |
|---|---|
EMAIL_USER |
the sending account |
RECEIVER_EMAIL_USER |
where the report goes |
EMAIL_PASSWORD |
an app password, not the account password |
The subject line names the COT week the matrix carries, not the day the send ran.
Development (from source)
Developed alongside its sibling repos in a shared workspace, with cotdata installed
editable rather than from PyPI:
git clone https://github.com/mspinola/cotmetrics
pip install -e ../cotdata -e ".[options,dev]"
export COTDATA_STORE=~/code/cotdata_store # shared data store
pytest
Docs
- Two properties of positioning series that break naive statistics on them. Percentile exceedances arrive in episodes, so a count of them is not a sample size; and correlating positioning levels is spurious, because the series is near unit-root. Worth reading before computing a standard error, a p-value, or a correlation on anything this package emits.
License
MIT — see LICENSE.
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 cotmetrics-0.4.0.tar.gz.
File metadata
- Download URL: cotmetrics-0.4.0.tar.gz
- Upload date:
- Size: 173.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
111e452045d8e95f3bb4e5d639aa3b2494aff150cac54154899f08210ab1429f
|
|
| MD5 |
f4c83070e9d9e811ec461d23d6f833b4
|
|
| BLAKE2b-256 |
cc90122ea5f6b000247b6879e6513e2c721bf77d8aff0689fc079fdaad679d0c
|
Provenance
The following attestation bundles were made for cotmetrics-0.4.0.tar.gz:
Publisher:
release.yml on mspinola/cotmetrics
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cotmetrics-0.4.0.tar.gz -
Subject digest:
111e452045d8e95f3bb4e5d639aa3b2494aff150cac54154899f08210ab1429f - Sigstore transparency entry: 2568836201
- Sigstore integration time:
-
Permalink:
mspinola/cotmetrics@0c04e8c1facf5f627897eea5795ce0a64ede1700 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/mspinola
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0c04e8c1facf5f627897eea5795ce0a64ede1700 -
Trigger Event:
push
-
Statement type:
File details
Details for the file cotmetrics-0.4.0-py3-none-any.whl.
File metadata
- Download URL: cotmetrics-0.4.0-py3-none-any.whl
- Upload date:
- Size: 130.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
92e17e47595b54c3c7c8856c02607f572f64bd6308c543b3d7c56ae57ea98cfe
|
|
| MD5 |
8739f010f200bbbc285129f3ff72e599
|
|
| BLAKE2b-256 |
aba72c7cb8cd6b809ac1e63c7ca2b40594cda3e7d3ca03bfaeb2b018bccacb10
|
Provenance
The following attestation bundles were made for cotmetrics-0.4.0-py3-none-any.whl:
Publisher:
release.yml on mspinola/cotmetrics
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cotmetrics-0.4.0-py3-none-any.whl -
Subject digest:
92e17e47595b54c3c7c8856c02607f572f64bd6308c543b3d7c56ae57ea98cfe - Sigstore transparency entry: 2568836233
- Sigstore integration time:
-
Permalink:
mspinola/cotmetrics@0c04e8c1facf5f627897eea5795ce0a64ede1700 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/mspinola
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0c04e8c1facf5f627897eea5795ce0a64ede1700 -
Trigger Event:
push
-
Statement type: