Python library that loads the tickerforge-spec YAML tree from the tickerforge-spec-data package on PyPI (same content as the crates.io tickerforge-spec-data crate) and generates/parses derivatives tickers.
pip install tickerforgetickerforge depends on tickerforge-spec-data from PyPI (declared in pyproject.toml).
By default, TickerForge / TickerParser use the spec bundled in the tickerforge-spec-data package from PyPI. Pass spec_path only to override.
from tickerforge import TickerForge
forge = TickerForge()
ticker = forge.generate("IND", date="2025-04-01")
print(ticker) # e.g. INDM25Custom spec directory:
forge = TickerForge(spec_path="/path/to/tickerforge-spec/spec")parse_ticker accepts full tickers (INDM26, PETRA30, IBOVK26C120000) or root symbols (IND). It parses both futures and options and returns a unified ParsedTicker.
Full tickers derive year/month directly from the string β no reference_date required.
Root symbols resolve the front-month contract via the generator; reference_date defaults to today when omitted.
from tickerforge import TickerParser, parse_ticker
# Futures β full ticker
parsed = parse_ticker("INDM26")
print(parsed.symbol, parsed.year, parsed.month) # IND 2026 6
print(parsed.tick_size, parsed.ctr_std) # 5.0 5
print(parsed.asset_type) # "future"
# Futures β root symbol
parsed = parse_ticker("IND")
parsed = parse_ticker("IND", reference_date="2026-06-01")
# CME futures
parsed = parse_ticker("ESM26")
print(parsed.symbol, parsed.exchange) # ES CME
# B3 equity option: equity_root("PETR4") = "PETR" β "PETRA30"
parsed = parse_ticker("PETRA30")
print(parsed.asset_type) # "option"
print(parsed.option_type) # "call"
print(parsed.underlying) # "PETR4"
print(parsed.month) # 1 (A = January)
print(parsed.strike) # "30"
print(parsed.year) # None (equity options have no year)
print(parsed.exchange) # "B3"
# B3 index option
parsed = parse_ticker("IBOVK26C120000")
print(parsed.underlying, parsed.month, parsed.year, parsed.strike) # IBOV 5 2026 120000
# B3 dollar option
parsed = parse_ticker("DOLK26C5000")
print(parsed.option_type, parsed.strike) # call 5000
# DOL future vs DOL option β no ambiguity
parse_ticker("DOLK26") # β future
parse_ticker("DOLK26C5000") # β option
# Exchange filter
parsed = parse_ticker("ESM26", exchange="CME")
# AmbiguousTickerError raised if a ticker matches multiple markets;
# pass exchange= to disambiguate
# Using TickerParser (reuses a loaded spec)
parser = TickerParser()
parsed = parser.parse("DOLK26")
parsed = parser.parse("DOLK26C5000", exchange="B3")TickerParser.builder() provides a fluent API for configuration and one-shot parsing:
from tickerforge import TickerParser
# Build a reusable parser (default spec)
parser = TickerParser.builder().build()
parsed = parser.parse("INDM26")
# Build a reusable parser (custom spec)
parser = TickerParser.builder().spec_path("/path/to/spec").build()
# One-shot parse β full ticker
parsed = TickerParser.builder().ticker("INDM26").parse()
# One-shot parse β option with exchange filter
parsed = TickerParser.builder().ticker("PETRA30").exchange("B3").parse()
# One-shot parse β root symbol with date
parsed = (
TickerParser.builder()
.ticker("IND")
.reference_date("2026-06-01")
.parse()
)
# One-shot parse β custom spec + date
parsed = (
TickerParser.builder()
.spec_path("/path/to/spec")
.ticker("IND")
.reference_date("2026-06-01")
.parse()
)The builder enforces that parse() is only available after ticker() has been called.
load_spec() returns a repository of contracts and equities. Each ContractSpec includes tick size and (after load) regular session times and exchange timezone, plus helpers that use the bundled default spec unless you pass spec=β¦:
from tickerforge import load_spec
spec = load_spec()
# Loading a cash equity
petr4 = spec.equities["PETR4"]
petr4.contract_multiplier # 1.0
petr4.regular_session().start # "10:00"
# Loading a future
dol = spec.get_contract("DOL")
dol.tick_size
dol.regular_session_start_end() # e.g. ("09:00", "18:30")
dol.exchange_timezone
# `dol.sessions` is an ordered list of `SessionSegment`; in YAML, sessions are a map keyed by
# band name (`regular`, β¦) and each key is copied into `SessionSegment.name` at load time.
# Front-month ticker β default bundled spec (omit `spec`)
dol.trading_symbol_today()
dol.trading_symbol_for("2026-03-15")
# Same helpers with an explicit `SpecRepository` (e.g. custom `load_spec(path)`)
dol.trading_symbol_today(spec=spec)
dol.trading_symbol_for("2026-03-15", spec=spec)Repeated calls with the default path reload the spec each time; for hot paths, pass spec= once.
- Loading exchanges, contract cycles, expiration rules, futures, options, and equities from all
contracts/**/*.yamlandequities/**/*.yaml(B3, CME, β¦) - Validating loaded structures with Pydantic models
- Resolving contract months by cycle
- Resolving expiration dates with spec-driven exchange calendars
- Rule-based holiday definitions (fixed dates, Easter offsets, nth-weekday) loaded from
spec/schedules/ - Fallback to
exchange_calendarswhen no spec schedule exists - Generating futures tickers from
{symbol}{month_code}{yy}-style templates - Multi-asset parsing: futures and options (B3 equity, index, dollar, interest-rate; CME futures) via a single
parse_tickercall AmbiguousTickerErrorwhen a ticker matches multiple markets;exchange=parameter to disambiguateParsedTicker.asset_type,option_type,strike,underlying,exchangefields for options- Golden calendar validation for B3 WIN/IND/DOL (2023--2026)
Tests load YAML and fixtures from a spec/ directory at the project rootβthe same tree bundled into the tickerforge-spec-data wheel from that repoβs root. Clone the spec repo once:
git clone --depth 1 https://github.com/mesias/tickerforge-spec.git /tmp/tickerforge-spec
cp -r /tmp/tickerforge-spec/spec .
pytest