Skip to main content

Business day axis scale for matplotlib

Project description

PyPI Python Docs License Tests MkDocs Material Ruff uv ty prek

busdayaxis

A Matplotlib scale that compresses non-business days and off-hours. Every visible unit on the axis corresponds to active time — no gaps for weekends, holidays, or overnight periods. No data preprocessing needed.

Remove weekend gaps

Full documentation at saemeon.github.io/busdayaxis

Installation

pip install busdayaxis

Quick Start

import matplotlib.pyplot as plt
import pandas as pd
import busdayaxis  # scale is registered automatically on import

dates = pd.date_range("2026-01-01", periods=10, freq="B")
values = range(len(dates))

fig, ax = plt.subplots()
ax.plot(dates, values)
ax.set_xscale("busday", bushours=(9, 17))  # compress weekends (Mon–Fri default) and off-hours (business hours: 09:00–17:00)
plt.show()

Why

Time series that only evolve on business days — prices, signals, operational metrics — look distorted on a standard calendar axis. Weekends and holidays introduce flat gaps that compress active periods and visually skew slopes. busdayaxis removes these gaps entirely.

What it provides

  • Compress weekends, holidays, and overnight gaps by adding an axis scalewith a single call:

    ax.set_xscale("busday", weekmask=..., holidays=..., busdaycal=..., bushours=...)
    
    • weekmask, holidays, busdaycal: standard numpy.is_busday parameters to configure which days are considered business days

    • bushours: define uniform or weekday-specific business hours

    • Implemented as a proper matplotlib.scale — autoscaling, shared axes, and all standard artists work without any changes to your plotting code

  • Business-day-aware DateLocator wrappers for all standard matplotlib.dates locators — automatically filter out ticks on off-days and off-hours

  • BusdayLocator base class to wrap any custom or third-party date locator with the same business-day filtering logic

  • MidBusdayLocator to place a tick at the midpoint of each business session, useful for centering day labels

  • mark_gaps to draw visual indicators (vlines or broken-axis slash marks) at every session boundary on a busday axis

  • holidays_from_exchange to build the holidays= list automatically from any exchange_calendars or pandas_market_calendars calendar object

Under the Hood

  • matplotlib internally handles dates as floating-point numbers representing days since 1970-01-01, or stated alternatively, as

    $$\text{ matplotlib-representation}=\frac{\text{hours\ since\ 1970-01-01}}{24\ \text{hours}}$$

  • busdayaxis transforms these coordinates to floating-point numbers representing

    $$\text{busdayaxis-representation} = \frac{\text{business-hours since 1970-01-01}}{24 \text{ hours}}$$

    This conversion implies that datetime values that fall on non-business days or outside of business hours will be mapped to the same coordinate as the nearest preceding business hour. For example, if business hours are defined as 9:00 to 17:00, then "1970-01-05 08:00" (Mon 08:00) is mapped to the same coordinate as "1970-01-05 09:00" (Mon 09:00), because the earlier timestamp lies outside the defined business hours.

Example: "1970-01-05 10:00" (Mon 10:00)

  • Matplotlib representation (all hours counted):

        Thu 1970-01-01   24h (00:00 - 24:00)
      + Fri 1970-01-02   24h (00:00 - 24:00)
      + Sat 1970-01-03   24h (00:00 - 24:00)
      + Sun 1970-01-04   24h (00:00 - 24:00)
      + Mon 1970-01-05   10h (00:00 - 10:00)
      ---------------------------------------
      =                 106h (Total hours since epoch)
      /                  24h
      ---------------------------------------
      =                  4.41666... (matplotlib coordinate)
    
  • Busdayaxis representation:

    • We assume here that business hours are from 9:00 to 17:00. This can be configured by setting ax.set_xscale("busday", bushours=(9, 17)).

    To get the floating-point representation of "1970-01-05 10:00" (Mon 10:00), we count the business hours that have elapsed since 1970-01-01 00:00:

        Thu 1970-01-01   8h (9:00 - 17:00)
      + Fri 1970-01-02   8h (9:00 - 17:00)
      + Sat 1970-01-03   0h
      + Sun 1970-01-04   0h
      + Mon 1970-01-05   1h (09:00 - 10:00)
      ---------------------------------------
      =                 17h (business hours since epoch)
      /                 24h
      ---------------------------------------
      =          0.708333... (busdayaxis coordinate)
    

Under the Hood

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

busdayaxis-0.2.1.tar.gz (505.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

busdayaxis-0.2.1-py3-none-any.whl (20.0 kB view details)

Uploaded Python 3

File details

Details for the file busdayaxis-0.2.1.tar.gz.

File metadata

  • Download URL: busdayaxis-0.2.1.tar.gz
  • Upload date:
  • Size: 505.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for busdayaxis-0.2.1.tar.gz
Algorithm Hash digest
SHA256 fee03685f90c17ee4acd101d702da3b8f13b4c37ea95bb3b12596426f8337156
MD5 9359848e8c65a3354ff85a8c785c7ed6
BLAKE2b-256 cb700b722ab56c0b1156871ee8dd405fd4f3c054f167b89e2de432630fabeddd

See more details on using hashes here.

File details

Details for the file busdayaxis-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: busdayaxis-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 20.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for busdayaxis-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 49cbd227fa1bf5bb8365040f82094126cb0e35b38d199177b1bf1259a9c968ab
MD5 bf1f7815b849f39a18e0752e6e1a5a18
BLAKE2b-256 f0756796cdfac24fc2143fea5b4a740efae3923e7233fbd7094f6143614060b1

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page