forexia-cot 1.0.0__py3-none-any.whl
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.
forexia_cot/__init__.py
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"""CFTC Commitments of Traders (COT) positions for FX futures and gold.
|
|
2
|
+
|
|
3
|
+
Weekly legacy and TFF reports since 2010 for EUR, GBP, JPY, CHF, CAD, AUD, NZD,
|
|
4
|
+
MXN, the US dollar index and gold, read from github.com/ForexiaPro/cot-data.
|
|
5
|
+
Standard library only; pandas is optional.
|
|
6
|
+
|
|
7
|
+
CFTC Commitments of Traders (public domain). Compiled by Forexia:
|
|
8
|
+
https://forexiapro.com/cot-report/
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import json
|
|
14
|
+
import urllib.request
|
|
15
|
+
from typing import Any, Callable, Optional
|
|
16
|
+
|
|
17
|
+
__version__ = "1.0.0"
|
|
18
|
+
__all__ = ["BASE", "MARKETS", "REPORTS", "COT_REPORT", "market_of", "get_cot", "latest", "markets", "cot_frame"]
|
|
19
|
+
|
|
20
|
+
BASE = "https://raw.githubusercontent.com/ForexiaPro/cot-data/main/data"
|
|
21
|
+
MARKETS = ("EUR", "GBP", "JPY", "CHF", "CAD", "AUD", "NZD", "MXN", "USD", "XAU")
|
|
22
|
+
REPORTS = ("legacy", "tff")
|
|
23
|
+
COT_REPORT = "https://forexiapro.com/cot-report/?via=cot-data"
|
|
24
|
+
|
|
25
|
+
_ALIASES = {"GOLD": "XAU", "XAUUSD": "XAU", "DXY": "USD", "DX": "USD", "USDX": "USD", "EURO": "EUR"}
|
|
26
|
+
|
|
27
|
+
Fetch = Callable[[str], str]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _fetch(url: str) -> str:
|
|
31
|
+
req = urllib.request.Request(url, headers={"User-Agent": f"forexia-cot-python/{__version__}"})
|
|
32
|
+
with urllib.request.urlopen(req, timeout=30) as res:
|
|
33
|
+
return res.read().decode("utf-8")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _get(path: str, fetch: Optional[Fetch] = None, base: str = BASE) -> Any:
|
|
37
|
+
return json.loads((fetch or _fetch)(f"{base}{path}"))
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def market_of(name: str) -> str:
|
|
41
|
+
"""A market id from what people type: "eur", "EURUSD", "USDJPY", "gold", "DXY"."""
|
|
42
|
+
s = "".join(c for c in str(name).upper() if c.isalpha())
|
|
43
|
+
if s in MARKETS:
|
|
44
|
+
return s
|
|
45
|
+
if s in _ALIASES:
|
|
46
|
+
return _ALIASES[s]
|
|
47
|
+
if len(s) == 6:
|
|
48
|
+
a, b = s[:3], s[3:]
|
|
49
|
+
if a == "USD" and b in MARKETS:
|
|
50
|
+
return b
|
|
51
|
+
if b == "USD" and a in MARKETS:
|
|
52
|
+
return a
|
|
53
|
+
raise ValueError(f'unknown market "{name}" (one of {", ".join(MARKETS)})')
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _rows(file: dict) -> list[dict[str, Any]]:
|
|
57
|
+
cols = file["columns"]
|
|
58
|
+
return [dict(zip(cols, r)) for r in file["rows"]]
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def get_cot(market: str, report: str = "legacy", since: Optional[str] = None, fetch: Optional[Fetch] = None, base: str = BASE) -> list[dict[str, Any]]:
|
|
62
|
+
"""Every weekly report of a market since 2010, oldest first.
|
|
63
|
+
|
|
64
|
+
``report`` is ``"legacy"`` (non-commercial, commercial, non-reportable) or
|
|
65
|
+
``"tff"`` (dealer, asset manager, leveraged funds, other reportable,
|
|
66
|
+
non-reportable; not for gold). ``since`` keeps rows on or after a date
|
|
67
|
+
(YYYY-MM-DD). Positions are contracts in the future's terms: long EUR is
|
|
68
|
+
long the euro, long JPY is long the yen (short USDJPY).
|
|
69
|
+
"""
|
|
70
|
+
mid = market_of(market)
|
|
71
|
+
if report not in REPORTS:
|
|
72
|
+
raise ValueError(f'unknown report "{report}" (legacy or tff)')
|
|
73
|
+
if report == "tff" and mid == "XAU":
|
|
74
|
+
raise ValueError("gold is not in the TFF report; use legacy")
|
|
75
|
+
rows = _rows(_get(f"/{report}/{mid}.json", fetch, base))
|
|
76
|
+
return [r for r in rows if since is None or r["date"] >= since]
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def latest(fetch: Optional[Fetch] = None, base: str = BASE) -> dict[str, Any]:
|
|
80
|
+
"""The latest report of every market: net, weekly change and share of open interest of each group."""
|
|
81
|
+
return _get("/latest.json", fetch, base)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def markets(fetch: Optional[Fetch] = None, base: str = BASE) -> list[dict[str, Any]]:
|
|
85
|
+
"""The markets, their CFTC codes and the dates each report covers."""
|
|
86
|
+
return _get("/markets.json", fetch, base)["markets"]
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def cot_frame(market: str, report: str = "legacy", since: Optional[str] = None, fetch: Optional[Fetch] = None):
|
|
90
|
+
"""The reports as a pandas DataFrame indexed by date (needs pandas)."""
|
|
91
|
+
import pandas as pd # optional
|
|
92
|
+
|
|
93
|
+
df = pd.DataFrame(get_cot(market, report, since, fetch))
|
|
94
|
+
df["date"] = pd.to_datetime(df["date"])
|
|
95
|
+
return df.set_index("date")
|
forexia_cot/__main__.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""forexia-cot: this week's positioning, or one market's last weeks."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
from . import COT_REPORT, get_cot, latest
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def _fmt(x) -> str:
|
|
11
|
+
return "" if x is None else f"{x:,}" if isinstance(x, int) else str(x)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def main(argv: list[str] | None = None) -> int:
|
|
15
|
+
args = sys.argv[1:] if argv is None else argv
|
|
16
|
+
if args:
|
|
17
|
+
rows = get_cot(args[0], args[1] if len(args) > 1 else "legacy")[-8:]
|
|
18
|
+
group = "noncommercial" if "noncommercial_net" in rows[-1] else "leveraged_funds"
|
|
19
|
+
label = "net " + group.replace("_", " ")
|
|
20
|
+
print(f"{'date':<12}{label:>22}{'% of OI':>10}")
|
|
21
|
+
for r in rows:
|
|
22
|
+
print(f"{r['date']:<12}{_fmt(r[group + '_net']):>22}{_fmt(r[group + '_net_pct_oi']):>10}")
|
|
23
|
+
else:
|
|
24
|
+
data = latest()
|
|
25
|
+
print(f"COT report of {data['report_date']} (non-commercial, legacy)")
|
|
26
|
+
print(f"{'market':<8}{'net':>12}{'1w':>10}{'% of OI':>10}")
|
|
27
|
+
for m in data["markets"]:
|
|
28
|
+
nc = m["legacy"]["noncommercial"]
|
|
29
|
+
print(f"{m['id']:<8}{_fmt(nc['net']):>12}{_fmt(nc['net_change_1w']):>10}{_fmt(nc['net_pct_oi']):>10}")
|
|
30
|
+
print(f"\nForexia's COT index and weekly reading: {COT_REPORT}")
|
|
31
|
+
return 0
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
if __name__ == "__main__":
|
|
35
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: forexia-cot
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: CFTC Commitments of Traders (COT) data for FX futures and gold, legacy and TFF reports: positions, net and net as a share of open interest. Weekly, since 2010.
|
|
5
|
+
Project-URL: Homepage, https://github.com/ForexiaPro/cot-data
|
|
6
|
+
Project-URL: Source, https://github.com/ForexiaPro/cot-data/tree/main/python
|
|
7
|
+
Project-URL: COT report, https://forexiapro.com/cot-report/?via=cot-data
|
|
8
|
+
Author: Forexia
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: cftc,commitments of traders,cot,cot report,forex,futures,gold,positioning
|
|
12
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Office/Business :: Financial
|
|
16
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
17
|
+
Requires-Python: >=3.9
|
|
18
|
+
Provides-Extra: pandas
|
|
19
|
+
Requires-Dist: pandas; extra == 'pandas'
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# forexia-cot
|
|
23
|
+
|
|
24
|
+
The CFTC's weekly **Commitments of Traders (COT)** report for FX futures, the US dollar index and gold: **positions only** (long, short, net, net as a share of open interest), legacy and TFF reports, weekly since 2010. Reads the files of [github.com/ForexiaPro/cot-data](https://github.com/ForexiaPro/cot-data), updated every Friday after the CFTC's release.
|
|
25
|
+
|
|
26
|
+
Standard library only. pandas is optional.
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
pip install forexia-cot
|
|
30
|
+
forexia-cot # this week's table: net non-commercial, weekly change, % of open interest
|
|
31
|
+
forexia-cot gbp # the pound's last eight weeks
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
import forexia_cot as cot
|
|
36
|
+
|
|
37
|
+
cot.get_cot("EUR") # every legacy report since 2010, oldest first (a list of dicts)
|
|
38
|
+
cot.get_cot("USDJPY", report="tff") # the yen future's TFF groups
|
|
39
|
+
cot.get_cot("gold", since="2024-01-01")
|
|
40
|
+
cot.latest() # this week, every market and group
|
|
41
|
+
|
|
42
|
+
df = cot.cot_frame("EUR") # pip install "forexia-cot[pandas]"
|
|
43
|
+
df.noncommercial_net.plot()
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Markets: `EUR`, `GBP`, `JPY`, `CHF`, `CAD`, `AUD`, `NZD`, `MXN`, `USD` (the dollar index), `XAU` (gold; legacy only). `EURUSD`, `USDJPY`, `gold` and `DXY` work too.
|
|
47
|
+
|
|
48
|
+
Columns: `date` (the Tuesday the positions were counted), `open_interest`, then for each group `_long`, `_short`, `_net`, `_net_pct_oi` (net as a share of open interest, in per cent); non-commercial also has `_spreading`. Legacy groups: `noncommercial`, `commercial`, `nonreportable`. TFF groups: `dealer`, `asset_manager`, `leveraged_funds`, `other_reportable`, `nonreportable`. Positions are contracts in the future's terms: long `JPY` is long the yen, so short USDJPY.
|
|
49
|
+
|
|
50
|
+
For Forexia's COT index and weekly reading of these positions, see [forexiapro.com/cot-report](https://forexiapro.com/cot-report/?via=cot-data).
|
|
51
|
+
|
|
52
|
+
## Licence
|
|
53
|
+
|
|
54
|
+
The code is MIT. The figures are the CFTC's Commitments of Traders (public domain), compiled by Forexia: [forexiapro.com/cot-report](https://forexiapro.com/cot-report/?via=cot-data).
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
Part of the Forexia network: [InterestRateDecision.com](https://interestratedecision.com/?via=cot-data) · [Forexia Academy](https://forexiapro.com/?via=cot-data) · [TradingSignalBot](https://tradingsignalbot.com/?via=cot-data) · [PropSim](https://github.com/PropSim-Enterprise) · [OpenCharts](https://github.com/dylanpersonguy/OpenCharts)
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
forexia_cot/__init__.py,sha256=jJDpVeOsgFqLoPgiSfrkqGSDD-5rNgb-bp0CgsxBFOQ,3893
|
|
2
|
+
forexia_cot/__main__.py,sha256=xC5U46JBTmoLD_9PmSv4f6IVVY0NCmX-eGgxlW53wHM,1323
|
|
3
|
+
forexia_cot-1.0.0.dist-info/METADATA,sha256=ES5CHp_Aa-vNHntmkESfQ-EHzTtMJH9zKbjIY7Lk6KA,3361
|
|
4
|
+
forexia_cot-1.0.0.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
|
|
5
|
+
forexia_cot-1.0.0.dist-info/entry_points.txt,sha256=yXehXfZggVpSEitilzAE6Jinla1ZDEDYDGXrlYh_ddM,58
|
|
6
|
+
forexia_cot-1.0.0.dist-info/licenses/LICENSE,sha256=aLgD8_vL8T83utXdti9eLTRTIXrBWbblBifs-2D80kM,1102
|
|
7
|
+
forexia_cot-1.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Forexia (forexiapro.com)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|