edinet-pit: point-in-time financials for Japanese equities

japanese-stocks

While building the Raspberry Pi screener, I mentioned the backtest runs on an “approximate point-in-time reconstruction.” That caveat sat there unfixed for a while. I’ve since pulled the fix out into its own library: edinet-pit.

The problem with historical financials

Pull a company’s past financials from yfinance or similar, and what comes back has already been revised and restated since the time it was first reported. Filtering by disclosure date doesn’t save you, since the values themselves changed after the fact. Feed that into a backtest and the strategy quietly receives information it couldn’t have had at the time. That’s a common way for a backtest to look better than the strategy deserves.

Reading the original disclosure

EDINET, Japan’s answer to SEC EDGAR, keeps every year’s original XBRL filing on record for free: the 有価証券報告書, or annual securities report. Each report tags the current fiscal year’s numbers separately from the restated prior year it also carries, using CurrentYear* contexts for the former and Prior1Year* for the latter. edinet-pit only reads the CurrentYear* contexts, so each year’s figures come from the report that disclosed them first. A common shortcut is to assume every filing becomes available a fixed number of days after the fiscal year closes. edinet-pit records the actual filing date, so a backtest can check whether a number was knowable as of any given date.

What it looks like

import datetime as dt
import edinet_pit as ep

docs = ep.find_annual_reports(dt.date(2023, 6, 1), dt.date(2023, 6, 30), codes={"7203"})
periods = [ep.fetch_period_for_doc(d["docID"], fallback_period_end=d["period_end"])
           for d in docs["7203"]]
fin, bs, cf = ep.build_frames([p for p in periods if p])

The output frames use yfinance’s row labels, so it drops into a pipeline already built around yfinance without much rewiring.

What it doesn’t do

It only maps the line items a backtest needs most: revenue, income, EPS, equity, and similar core figures, so niche tags aren’t covered yet. Interest-bearing debt is an approximation too. No single tag covers it, so the library sums the main loan, bond, and lease tags into one number. EDINET’s own API history only goes back to around 2016. It’s annual reports only, so quarterlies aren’t included, and amended filings are skipped on purpose to keep the original, not-yet-corrected numbers intact.

It’s zero-dependency by default: stdlib only, with pandas as an optional extra for the DataFrame output. The license is MIT. It also came out of the screener’s own pipeline, which means the code behind it already had real mileage before it became its own package. A longer writeup is in the works, with actual numbers on how much restated financials and survivorship bias distort a backtest.