SPB Git forge

spb/hfmarketdata

Public

Open high-frequency market data platform — FirstRate full-history downloader, DuckDB/Parquet lake, open REST API and React docs platform (www.hfmarketdata.io)

127commits 1branches 0releases
24.7 MBsize
maindefault branch
11 days agolast push
JavaScript 53.7% Python 38.3% CSS 4.6% TypeScript 3.1%
3.0 KB · 83 lines python
Raw Blame History
1"""Unit tests — contract symbol parsing and root aliases."""2from __future__ import annotations34import pytest5from core.errors import ApiError6from futures.symbols import (7    ALIASES_OF_ROOT,8    ROOT_ALIASES,9    canonical_symbol,10    expand_year,11    normalize_root,12    parse_symbol,13    symbol_from_file_stem,14)151617@pytest.mark.parametrize("raw, root, mc, year", [18    ("ESZ25", "ES", "Z", 2025),19    ("ESZ2025", "ES", "Z", 2025),20    ("ES_Z25", "ES", "Z", 2025),21    ("ES-Z25", "ES", "Z", 2025),22    ("esz25", "ES", "Z", 2025),23    ("  esz2025 ", "ES", "Z", 2025),24    ("CLF26", "CL", "F", 2026),25    ("M2KH25", "M2K", "H", 2025),26    ("FDAXZ2024", "FDAX", "Z", 2024),27    ("SR3Z24", "SR3", "Z", 2024),28    ("ZKZ25", "ZK", "Z", 2025),       # root ending with a month letter29    ("HHZ25", "HH", "Z", 2025),30    ("CZ25", "C", "Z", 2025),          # 1-char root (London cocoa)31    ("USZ24", "US", "Z", 2024),32    ("ESZ99", "ES", "Z", 1999),33    ("ESZ79", "ES", "Z", 2079),34    ("ESZ80", "ES", "Z", 1980),35])36def test_parse_symbol(raw, root, mc, year):37    cs = parse_symbol(raw)38    assert (cs.root, cs.month_code, cs.year) == (root, mc, year)39    assert cs.short == f"{root}{mc}{year % 100:02d}"40    assert cs.long == f"{root}{mc}{year}"41    assert cs.file_stem == f"{root}_{mc}{year % 100:02d}"424344@pytest.mark.parametrize("raw, root", [45    ("6EZ25", "E6"), ("6JZ25", "J1"), ("6BZ25", "B6"), ("6AZ25", "A6"), ("6CZ25", "AD"), ("6SZ25", "E1"),46    ("6NZ25", "N6"), ("6MZ25", "MP"), ("6LZ25", "BR"), ("6ZZ25", "T6"), ("ZBZ25", "US"), ("E6Z25", "E6"),47])48def test_aliases_resolve_to_lake_roots(raw, root):49    assert parse_symbol(raw).root == root50    assert canonical_symbol(raw) == f"{root}Z25"515253def test_alias_tables_are_consistent():54    for alias, root in ROOT_ALIASES.items():55        assert alias in ALIASES_OF_ROOT[root]56        assert normalize_root(alias) == root57        assert normalize_root(alias.lower()) == root58    assert normalize_root("es") == "ES"59    assert "6E" in ALIASES_OF_ROOT["E6"] and "ZB" in ALIASES_OF_ROOT["US"]606162@pytest.mark.parametrize("bad", ["", "ES", "ESA25", "ESZ5", "ESZ2025X", "TOOLONGZ25", "ES Z 25", "Z25", "ES25", "ESZ125",63                                 "ES_Z_25", "ÉSZ25", "BOGUS", "ESZ1800"])64def test_invalid_symbols_raise_400(bad):65    with pytest.raises(ApiError) as e:66        parse_symbol(bad)67    assert e.value.status == 400 and e.value.code == "INVALID_CONTRACT_SYMBOL"68    assert e.value.payload()["error"]["docs"].endswith("#invalid_contract_symbol")697071def test_expand_year():72    assert expand_year(0) == 2000 and expand_year(79) == 2079 and expand_year(80) == 1980 and expand_year(99) == 199973    assert expand_year(2031) == 2031747576def test_symbol_from_file_stem():77    cs = symbol_from_file_stem("ES_Z24_1day")78    assert cs is not None and cs.short == "ESZ24" and cs.year == 202479    assert symbol_from_file_stem("ES_Z24").short == "ESZ24"80    assert symbol_from_file_stem("ES_1day") is None81    assert symbol_from_file_stem("AAPL") is None82    assert symbol_from_file_stem("ES_ZZ4_1day") is None83