Skip to content

Create a NumPy-backed examples section from real market workflows #64

Description

@wilsonfreitas

Summary

Create a new documentation track for NumPy-backed, reproducible examples inspired by the real-world workflows in wilsonfreitas/brazilian-securities-lectures.

The external repository is an excellent source of realistic financial workflows, but it uses the legacy bizdays API style. The goal here is not to port those notebooks verbatim. Instead, we should extract the strongest use cases, adapt them to the current NumPy-backed public API, and turn them into a first-class examples section in this repository's documentation.

This should become the canonical place where users learn how to apply bizdays to real financial problems such as curve construction, maturity adjustment, contract settlement rules, and bond cash-flow scheduling.

Relationship to existing docs work

This issue is related to the broader documentation update in #59, but it is focused specifically on the examples strategy, example design, API adaptation, and reproducible datasets needed for a high-quality examples section.

Why this matters

The external lectures repository shows that bizdays is not only a calendar utility. In practice it is used as infrastructure for:

  • maturity normalization
  • business-day counting under market conventions
  • mixed DU/DC workflows
  • contract-specific settlement rules
  • interpolation grids for yield curves
  • bond and debenture cash-flow scheduling
  • event-driven analysis over business-day sequences

That makes it ideal source material for a robust examples section. However, the current code in that repository reflects the legacy API style and notebook-era assumptions. If we copy it directly into the docs, we will document the wrong interface and carry over patterns that no longer represent the current package design.

Key decision

The new examples section must target the current NumPy-backed API only.

That means:

  • examples should use the current top-level bizdays.Calendar
  • examples should prefer the vectorized behavior already built into the NumPy-backed methods
  • examples should avoid teaching legacy .vec usage as the primary path
  • examples should use the current Calendar.load calling convention
  • examples should explain NumPy / pandas return shapes where relevant
  • examples should be reproducible without depending on live external services

Findings from the external repository

Source repository evaluated:

  • wilsonfreitas/brazilian-securities-lectures

Main source files/notebooks inspected:

  • myfuncs.py
  • Brazilian Securities 1.ipynb
  • Brazilian Securities 2.ipynb
  • Brazilian Securities 3.ipynb
  • Brazilian Securities 4.ipynb
  • Compute historical COPOM chances estimates.ipynb
  • Estimate Nelson-Siegel-Svensson Coeficients using Government Bonds.ipynb
  • data/*.parquet

Distinct bizdays use cases identified

  1. Basic business-day counting

    • Compare market calendars and actual-day calendars
    • Example shape in lectures:
      • Calendar(name='actual')
      • Calendar.load('ANBIMA.cal')
      • cal.bizdays(start, end)
    • Documentation value: excellent beginner material
  2. Settlement-date adjustment to the next business day

    • Used repeatedly to normalize futures maturities and cash-flow dates
    • Example shape in lectures:
      • series.map(cal.following)
      • cal.vec.adjust_next(...)
    • Documentation value: essential
  3. Vectorized business-day counting in pandas workflows

    • Used throughout DataFrame-based pricing pipelines
    • Example shape in lectures:
      • list(cal.vec.bizdays(df['DataRef'], df['Maturity']))
    • Documentation value: essential
  4. Curve construction from futures contracts

    • Core pattern: adjust maturity -> count DU -> derive rate -> build interpolation grid
    • Example shape in lectures:
      • DI1 curve construction
      • cal.offset(refdate, 1) for first node
      • cal.vec.offset(refdate, tenors) for interpolation grid
    • Documentation value: extremely high
  5. Contract-specific maturity rules using getdate

    • Used for contracts whose maturity is not a trivial calendar date
    • Example shape in lectures:
      • cal.getdate('first wed before 15th day', year, month)
      • cal.getdate('first wed after 15th day', year, month)
      • cal.getdate('last bizday', year, month)
      • cal.getdate('15th day', year, month)
    • Documentation value: high, especially for advanced examples
  6. Two-calendar workflows (DU vs DC)

    • ANBIMA calendar for business days / 252-day convention
    • actual calendar for calendar-day / 360-day convention
    • Appears in DDI / DOL / FRC workflows
    • Documentation value: very high, because it explains why market conventions matter
  7. Bond and debenture cash-flow scheduling

    • Coupon/fixing dates adjusted to business days
    • Discounting performed on DU
    • Documentation value: very high
  8. Business-day sequences over historical periods

    • Example shape in lectures:
      • MARKET_CALENDAR.seq('2021-09-01', '2021-11-01')
    • Used to iterate over all business days in a historical analysis window
    • Documentation value: strong advanced example
  9. Event horizon counting

    • Business days until next COPOM meeting
    • Documentation value: good macro/event-driven example

Strongest examples to adapt for this repository

These are the best candidates for the future examples section, ordered roughly from foundational to advanced:

  1. Load a calendar and count business days

    • Compare ANBIMA and actual
    • Explain 252-day vs actual-day conventions
  2. Adjust maturities in a pandas DataFrame

    • Normalize a column of contract dates to the next business day
    • Then compute DU to each maturity
  3. Build a DI curve from futures data

    • This is the strongest end-to-end workflow in the lecture material
    • Covers settlement adjustment, DU, rate derivation, and interpolation-ready outputs
  4. Use two calendars in the same pricing workflow

    • Show why one instrument may require business-day counting while another leg uses actual days
  5. Resolve contract maturity rules with getdate

    • Especially the IND example (Wednesday around the 15th)
    • Also BGI and CCM monthly rules
  6. Generate interpolation nodes with business-day offsets

    • Use business-day tenors and map them to actual maturity dates
  7. Schedule and discount bond/debenture cash flows

    • Adjust coupon dates and compute DU to each future payment
  8. Iterate over business days in a historical window

    • Use seq for event-driven analysis (e.g. COPOM window)

Required adaptation: legacy-style examples -> NumPy-backed examples

The lecture repository is valuable for use cases, but many of its code shapes should not be copied as-is.

1. Calendar loading

Legacy lecture style:

  • bizdays.Calendar.load('ANBIMA.cal')

NumPy-backed docs should use:

  • Calendar.load(name='ANBIMA')
  • Calendar.load(name='B3')
  • Calendar.load(name='Actual')
  • Calendar.load(filename='path/to/calendar.json') for custom files

Notes:

  • use the current keyword-only API
  • do not teach .cal packaged-calendar loading as the primary path
  • document packaged JSON-backed calendars and provider prefixes separately

2. Replace .vec.* as the primary teaching path

Legacy lecture style:

  • cal.vec.bizdays(...)
  • cal.vec.adjust_next(...)
  • cal.vec.offset(...)

NumPy-backed docs should prefer:

  • cal.bizdays(...)
  • cal.adjust_next(...) / cal.following(...)
  • cal.offset(...)

The NumPy-backed Calendar already accepts scalar and sequence inputs. The examples section should teach that directly.

Good pandas-facing shapes to document explicitly:

maturity = pd.to_datetime(cal.following(df['Vencimento']))
du = cal.bizdays(df['DataRef'], maturity)
curve_dates = pd.to_datetime(cal.offset(refdate, tenors))

3. Return-shape adaptation for pandas examples

The new examples should explain that the NumPy-backed API returns NumPy arrays / numpy.datetime64 values for vectorized calls.

That means pandas examples may need explicit adaptation such as:

  • pd.to_datetime(...) when assigning date arrays back into a DataFrame
  • np.asarray(...) when users want plain numeric arrays
  • avoiding unnecessary list(...) wrappers inherited from the legacy generator-based API

This is important because a straight copy of legacy notebook code may still “work” in places, but it will hide the intended idioms of the new API.

4. Prefer direct array operations over row-wise .apply(...) where possible

The lecture repo uses row-wise DataFrame.apply(...) in several places because that was a natural fit for the legacy API and notebook prototyping.

For the NumPy-backed examples, prefer:

  • column-wise operations
  • direct vectorized calls
  • precomputed arrays of years/months only when required by getdate

Row-wise .apply(...) may still be acceptable for some getdate-driven rule examples, but it should not dominate the examples section.

5. Clarify aliases and naming

The examples should explain when these names are equivalent:

  • following() == adjust_next()
  • preceding() == adjust_previous()

The lecture material heavily uses following() and adjust_next(). The docs should choose a consistent primary style and note the alias.

Proposed examples structure for the docs

Tier 1 - Foundations

  1. Count business days with built-in calendars

    • ANBIMA vs Actual
    • scalar and pandas examples
  2. Adjust dates to the next business day

    • single date and Series examples
    • explain following / adjust_next
  3. Offset dates by business days

    • T+1, T+2, and a small tenor grid

Tier 2 - Pandas workflows

  1. Compute DU for a contracts DataFrame

    • assign normalized maturity dates
    • compute DU column
  2. Generate a curve date grid from business-day tenors

    • use offset on a vector of tenors
    • convert back to pandas-friendly dates
  3. Use two calendars in one workflow

    • ANBIMA and Actual
    • show mixed DU/DC conventions clearly

Tier 3 - Market-rule examples

  1. Model DI futures settlement and term structure inputs

    • realistic but compact example derived from lecture patterns
  2. Resolve special maturities with getdate

    • IND: Wednesday around the 15th
    • BGI: last business day of month
    • CCM: 15th day rule
  3. Iterate over business days in a historical window

    • seq for event-driven analysis

Tier 4 - Fixed-income workflows

  1. Build coupon/fixing schedules on business days

    • adjust coupon dates
    • compute DU to payments
  2. Price a simple fixed-rate bond or debenture cash-flow stream

    • keep it small and reproducible
    • use business-day discounting explicitly

Data reproducibility: do we need bundled data?

Short answer

Yes for the stronger market examples; no for the foundational examples.

No external data required

These examples can and should be fully self-contained:

  • basic business-day counting
  • adjusting dates with following / adjust_next
  • simple offset examples
  • simple seq examples
  • introductory getdate examples
  • small synthetic bond schedule examples

Data required for realistic market workflows

These examples are much stronger if they use stable fixture data rather than tiny synthetic toy data:

  • DI futures curve example
  • mixed-calendar contract examples (DDI / DOL / FRC style)
  • interpolation-grid example based on real contract tenors
  • event-window examples over historical contract snapshots
  • richer bond/debenture examples if they depend on real market snapshots

Important constraint

The external lecture repository frequently depends on:

  • live HTTP requests
  • remote B3 pages
  • SGS/BCB series
  • notebook globals and helper modules

The docs for this repository should not depend on live services.

Existing upstream data

The lecture repository already contains static Parquet snapshots under data/, including:

  • data/2021-11-01.parquet
  • data/2021-11-05.parquet
  • data/contracts_2020_202111.parquet
  • data/contracts_202109_202111.parquet
  • data/contracts_202110_202111.parquet

This is a strong basis for building reproducible example fixtures.

Recommended data strategy for this repository

  1. Keep foundational examples fully inline

    • no downloads
    • no fixtures
    • fast to understand
  2. Create small curated CSV fixtures for advanced market examples

    • derive them from the upstream lecture snapshots
    • trim to the minimum columns needed for each example
    • keep each fixture purpose-specific and human-readable
  3. Prefer CSV over Parquet for documentation fixtures

    • easier for users to inspect
    • avoids introducing a pyarrow dependency just to run docs examples
    • makes it easier to show example inputs directly in the docs
  4. Document provenance clearly

    • say that the fixture was derived from brazilian-securities-lectures
    • record the upstream file name / date snapshot
    • keep a small script or notebook that regenerates the CSV from upstream data
  5. Provide an upstream link for users who want the full dataset

    • docs fixtures should stay small
    • users can still explore the full lecture repository separately

Suggested fixture candidates

Rather than shipping one large dataset, prefer a few small fixtures such as:

  • di1-contracts-2021-11-01.csv

    • enough rows to demonstrate maturity normalization, DU, and DI curve setup
  • mixed-futures-2021-11-01.csv

    • enough rows to demonstrate ANBIMA vs Actual conventions
    • include examples analogous to DDI / DOL / FRC style workflows
  • copom-window-2021-09-to-2021-11.csv

    • enough rows to demonstrate seq + event horizon counting
  • optionally bond-cashflow-sample.csv

    • only if a realistic bond/debenture example is easier to explain from a fixture than from inline synthetic cash flows

Suggested minimum columns per fixture

For contracts-style examples, the docs likely only need a subset of columns such as:

  • DataRef
  • Mercadoria
  • CDVencimento
  • Vencimento
  • PUAtual

Potentially also:

  • PUAnterior
  • Variacao

For event-window examples, keep only what is strictly necessary.

Implementation notes for the future examples work

  • Do not copy lecture notebooks into this repository as-is.
  • Extract patterns, simplify them, and rewrite them around the current API.
  • Use modern Calendar.load(name=...) examples throughout.
  • Favor array-oriented and pandas-oriented NumPy-backed usage.
  • Where a market example would otherwise become too large, split it into:
    1. a tiny conceptual example
    2. a richer fixture-backed example
  • Keep the examples section executable and deterministic if possible.
  • If notebooks are included, they should be aligned with the same examples used in the prose docs.

Acceptance criteria

  1. Add a dedicated examples section to the documentation.
  2. Base the example topics on the real workflows identified in brazilian-securities-lectures.
  3. Adapt all examples to the current NumPy-backed public API.
  4. Do not teach legacy .vec usage as the primary interface in the new examples section.
  5. Use current Calendar.load(name=...) / Calendar.load(filename=...) forms.
  6. Include at least:
    • basic calendar counting
    • pandas DU workflow
    • business-day offsets
    • getdate-based rule example
    • DI-curve-style workflow
    • dual-calendar workflow
    • business-day-sequence example
  7. Make advanced examples reproducible from static fixtures rather than live remote calls.
  8. If fixture data is added, keep it small, versioned, and documented with provenance.
  9. Clearly explain pandas/NumPy adaptation patterns where the new API differs from legacy notebook code.

Nice-to-have follow-ups

  • Add tests or lightweight validation for the examples that are intended to stay current.
  • Add a small provenance script that regenerates CSV fixtures from upstream snapshots.
  • Cross-link the examples section from the README, docs index, and API reference.

Notes on gaps not covered by the lecture repository

The lecture repository is strong on real financial workflows, but it does not cover several important topics that should still be documented elsewhere:

  • creating a Calendar from scratch
  • JSON calendar layout
  • list_calendars
  • pandas_market_calendars
  • preceding / adjust_previous
  • custom holiday / weekday configuration

Those should remain part of the broader documentation plan, but this issue is specifically about turning the lecture-derived workflows into a modern, NumPy-backed examples section.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    numpyNumPy-backed API and internals

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions