commodutil 3.10.0__tar.gz → 3.10.1__tar.gz
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.
- {commodutil-3.10.0 → commodutil-3.10.1}/PKG-INFO +1 -1
- commodutil-3.10.1/commodutil/standards/__init__.py +70 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/commodutil/standards/regions.py +9 -2
- {commodutil-3.10.0 → commodutil-3.10.1}/commodutil.egg-info/PKG-INFO +1 -1
- {commodutil-3.10.0 → commodutil-3.10.1}/tests/test_standards_regions.py +36 -6
- commodutil-3.10.0/commodutil/standards/__init__.py +0 -1
- {commodutil-3.10.0 → commodutil-3.10.1}/.coveragerc +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/.github/workflows/1_tests.yml +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/.github/workflows/2_coverage.yml +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/.github/workflows/3_linting.yml +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/.github/workflows/4_release.yml +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/.gitignore +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/.pypirc +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/azure-build-pipelines.yml +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/commodutil/__init__.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/commodutil/arb.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/commodutil/convfactors.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/commodutil/dates.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/commodutil/forward/__init__.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/commodutil/forward/calendar.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/commodutil/forward/continuous.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/commodutil/forward/fly.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/commodutil/forward/quarterly.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/commodutil/forward/spreads.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/commodutil/forward/structure.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/commodutil/forward/util.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/commodutil/forwards.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/commodutil/pandasutil.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/commodutil/standards/analysis_types.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/commodutil/standards/commodities.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/commodutil/standards/commodity_groups.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/commodutil/standards/currency.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/commodutil/standards/units.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/commodutil/stats.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/commodutil/transforms.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/commodutil.egg-info/SOURCES.txt +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/commodutil.egg-info/dependency_links.txt +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/commodutil.egg-info/requires.txt +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/commodutil.egg-info/top_level.txt +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/pyproject.toml +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/requirements-test.txt +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/requirements.txt +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/requirements_dev.txt +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/scripts/rbw_structure_scan.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/setup.cfg +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/tests/__init__.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/tests/conftest.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/tests/forward/__init__.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/tests/forward/conftest.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/tests/forward/test_calendar.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/tests/forward/test_continuous.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/tests/forward/test_fly.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/tests/forward/test_quarterly.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/tests/forward/test_spreads.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/tests/forward/test_structure.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/tests/forward/test_util.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/tests/test_arb.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/tests/test_cl.csv +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/tests/test_conv.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/tests/test_dates.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/tests/test_forwards.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/tests/test_pandasutils.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/tests/test_price_conv.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/tests/test_standards_analysis_types.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/tests/test_standards_commodities.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/tests/test_standards_commodity_groups.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/tests/test_standards_currency.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/tests/test_standards_units.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/tests/test_stats.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/tests/test_transforms.py +0 -0
- {commodutil-3.10.0 → commodutil-3.10.1}/tests/test_weekly.csv +0 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""commodutil.standards: canonical vocabularies for commodity trading.
|
|
2
|
+
|
|
3
|
+
Re-exports the public surface of each submodule so callers can write
|
|
4
|
+
`from commodutil.standards import normalize_region` instead of reaching
|
|
5
|
+
into the submodule directly.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from commodutil.standards.analysis_types import (
|
|
9
|
+
ANALYSIS_TYPES,
|
|
10
|
+
infer_analysis_type,
|
|
11
|
+
)
|
|
12
|
+
from commodutil.standards.commodities import (
|
|
13
|
+
COMMODITY_CONVERSION_MAP,
|
|
14
|
+
COMMODITY_KEYWORDS,
|
|
15
|
+
)
|
|
16
|
+
from commodutil.standards.commodity_groups import (
|
|
17
|
+
COMMODITY_GROUPS,
|
|
18
|
+
VALID_COMMODITY_GROUPS,
|
|
19
|
+
is_valid_commodity_group,
|
|
20
|
+
)
|
|
21
|
+
from commodutil.standards.currency import (
|
|
22
|
+
FRACTIONAL_CURRENCY_DIVISORS,
|
|
23
|
+
FRACTIONAL_TO_MAJOR,
|
|
24
|
+
VALID_CURRENCY_TOKENS,
|
|
25
|
+
fractional_to_major,
|
|
26
|
+
is_fractional_currency,
|
|
27
|
+
required_fx_pair,
|
|
28
|
+
split_currency_unit,
|
|
29
|
+
to_symbol,
|
|
30
|
+
)
|
|
31
|
+
from commodutil.standards.regions import (
|
|
32
|
+
REGION_PATTERNS,
|
|
33
|
+
VALID_REGIONS,
|
|
34
|
+
is_valid_region,
|
|
35
|
+
normalize_region,
|
|
36
|
+
)
|
|
37
|
+
from commodutil.standards.units import (
|
|
38
|
+
UNIT_MAP,
|
|
39
|
+
default_unit_for_commodity,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
__all__ = [
|
|
43
|
+
# analysis_types
|
|
44
|
+
"ANALYSIS_TYPES",
|
|
45
|
+
"infer_analysis_type",
|
|
46
|
+
# commodities
|
|
47
|
+
"COMMODITY_CONVERSION_MAP",
|
|
48
|
+
"COMMODITY_KEYWORDS",
|
|
49
|
+
# commodity_groups
|
|
50
|
+
"COMMODITY_GROUPS",
|
|
51
|
+
"VALID_COMMODITY_GROUPS",
|
|
52
|
+
"is_valid_commodity_group",
|
|
53
|
+
# currency
|
|
54
|
+
"FRACTIONAL_CURRENCY_DIVISORS",
|
|
55
|
+
"FRACTIONAL_TO_MAJOR",
|
|
56
|
+
"VALID_CURRENCY_TOKENS",
|
|
57
|
+
"fractional_to_major",
|
|
58
|
+
"is_fractional_currency",
|
|
59
|
+
"required_fx_pair",
|
|
60
|
+
"split_currency_unit",
|
|
61
|
+
"to_symbol",
|
|
62
|
+
# regions
|
|
63
|
+
"REGION_PATTERNS",
|
|
64
|
+
"VALID_REGIONS",
|
|
65
|
+
"is_valid_region",
|
|
66
|
+
"normalize_region",
|
|
67
|
+
# units
|
|
68
|
+
"UNIT_MAP",
|
|
69
|
+
"default_unit_for_commodity",
|
|
70
|
+
]
|
|
@@ -60,8 +60,15 @@ def normalize_region(text: Optional[str]) -> Optional[str]:
|
|
|
60
60
|
|
|
61
61
|
lower = text.lower()
|
|
62
62
|
|
|
63
|
-
#
|
|
64
|
-
|
|
63
|
+
# CARBOB short-circuit: California Reformulated Blendstock for Oxygenate
|
|
64
|
+
# Blending — Los Angeles / US West Coast, NOT NY Harbor. Must run BEFORE
|
|
65
|
+
# the RBOB check so "carbob" doesn't fall through to the NYH heuristic.
|
|
66
|
+
if re.search(r"\bcarbob\b", lower):
|
|
67
|
+
return "LA"
|
|
68
|
+
|
|
69
|
+
# RBOB convention: always NY Harbor. Use word boundary so "carbob" (which
|
|
70
|
+
# has 'a' before 'rbob' — no word boundary) does not match here.
|
|
71
|
+
if re.search(r"\brbob\b", lower):
|
|
65
72
|
return "NYH"
|
|
66
73
|
|
|
67
74
|
# Pattern-match against REGION_PATTERNS
|
|
@@ -19,6 +19,21 @@ def test_normalize_region_rbob_heuristic():
|
|
|
19
19
|
assert normalize_region("RBOB Feb25") == "NYH"
|
|
20
20
|
|
|
21
21
|
|
|
22
|
+
def test_normalize_region_carbob_is_not_nyh():
|
|
23
|
+
"""CARBOB is California gasoline (Los Angeles / USWC), NOT NY Harbor.
|
|
24
|
+
|
|
25
|
+
Regression guard against the prior substring bug where `"rbob" in lower`
|
|
26
|
+
matched "carbob" and mis-classified California gasoline as NYH. The fix
|
|
27
|
+
uses a word-boundary regex plus an explicit CARBOB short-circuit that
|
|
28
|
+
maps to "LA".
|
|
29
|
+
"""
|
|
30
|
+
assert normalize_region("CARBOB") != "NYH"
|
|
31
|
+
assert normalize_region("CARBOB") == "LA"
|
|
32
|
+
assert normalize_region("Los Angeles CARBOB") == "LA"
|
|
33
|
+
# Sanity: plain RBOB still resolves to NYH.
|
|
34
|
+
assert normalize_region("RBOB") == "NYH"
|
|
35
|
+
|
|
36
|
+
|
|
22
37
|
def test_normalize_region_rdam_substring():
|
|
23
38
|
assert normalize_region("RDam fuel oil") == "Rott"
|
|
24
39
|
|
|
@@ -106,16 +121,31 @@ def test_short_pattern_parity_with_curvemetadata():
|
|
|
106
121
|
"""Short-pattern (len <= 3) regions used to diverge between
|
|
107
122
|
normalize_region and curvemetadata.taxonomy.infer_region because
|
|
108
123
|
the latter had a `\\b` regex bug (literal backslash-b instead of
|
|
109
|
-
a word boundary). The bug was fixed in curvemetadata
|
|
110
|
-
|
|
124
|
+
a word boundary). The bug was fixed in curvemetadata 1.4.0 (commit
|
|
125
|
+
e8ba20e on the 1.2.0 release branch); this test is a regression
|
|
126
|
+
guard once that fix is published.
|
|
127
|
+
|
|
128
|
+
Skips gracefully when the installed curvemetadata still has the
|
|
129
|
+
bug (e.g. CI envs pulling curvemetadata < 1.4.0 from the package
|
|
130
|
+
index during the release-window between commodutil 3.10.0 and
|
|
131
|
+
curvemetadata 1.4.0 publishing).
|
|
111
132
|
"""
|
|
133
|
+
import pytest
|
|
134
|
+
|
|
112
135
|
try:
|
|
113
136
|
from curvemetadata.taxonomy import infer_region
|
|
114
137
|
except ImportError:
|
|
115
|
-
import pytest
|
|
116
|
-
|
|
117
138
|
pytest.skip("curvemetadata not available in this environment")
|
|
118
139
|
|
|
140
|
+
# Probe: does the installed curvemetadata have the `\b` fix? Any of
|
|
141
|
+
# the short patterns would return None if the bug is still present.
|
|
142
|
+
if infer_region("Brent NYH") is None:
|
|
143
|
+
pytest.skip(
|
|
144
|
+
"Installed curvemetadata has the pre-1.4.0 `\\b` regex bug "
|
|
145
|
+
"(short-pattern regions never match). Upgrade curvemetadata "
|
|
146
|
+
"to >=1.4.0 to enable this parity test."
|
|
147
|
+
)
|
|
148
|
+
|
|
119
149
|
# Only patterns of len <= 3 hit the previously-broken regex branch.
|
|
120
150
|
# Among the configured patterns those are: "nyh", "ara", "med", "nwe".
|
|
121
151
|
short_pattern_cases = [
|
|
@@ -132,8 +162,8 @@ def test_short_pattern_parity_with_curvemetadata():
|
|
|
132
162
|
)
|
|
133
163
|
assert infer_region(text) == expected, (
|
|
134
164
|
f"curvemetadata.infer_region({text!r}) should match {expected!r} "
|
|
135
|
-
f"(got {infer_region(text)!r}).
|
|
136
|
-
f"
|
|
165
|
+
f"(got {infer_region(text)!r}). The `\\b` fix is present (probe "
|
|
166
|
+
f"above passed) but parity broke on this input -- investigate."
|
|
137
167
|
)
|
|
138
168
|
|
|
139
169
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"""commodutil.standards: canonical vocabularies for commodity trading."""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|