quantlab.dataset.sharadar.stock#
Sharadar daily price panel with permatickers as the symbol axis.
Sharadar is the primary US-equity vendor (ADR 0023). Its price tables (SEP for
stocks) are keyed by ticker, and when a delisted company’s ticker is reused
Sharadar renames that company’s whole history to a suffixed ticker. The
ticker is therefore not a stable axis. The permaticker, Sharadar’s
unchanging integer id of one share class, is: it appears only in the TICKERS
table, which maps each (table, ticker) to its permaticker.
SharadarStockDataset converts the raw tier (the vendor’s own rows, pulled
by quantlab.acquisition.sharadar.client into parquet under
<download-dir>/sharadar/) into a dense (timestamp, symbol) Zarr panel
whose symbol coordinate is the int64 permaticker. Each raw row is mapped
through the TICKERS rows of its own table, so a ticker of a fund never maps a
stock, and as of its raw file’s own pull, so a security whose ticker changed
after a file was pulled keeps its rows (quantlab.dataset.sharadar.permatickers:
the file’s TICKERS snapshot, current TICKERS, the ACTIONS ticker changes,
then the store’s ticker sidecar). The conversion refuses a ticker TICKERS
maps to two permatickers, and two rows of one permaticker on one date,
rather than guess which company a row belongs to. A row no permaticker is
found for is left out with a warning and listed in
<store>.unmapped.json (unmapped_path()), so a daily update completes;
those bars are missing from the store.
The panel holds raw (unadjusted) prices, so a later dividend or split never rewrites a stored row:
closeis SEP’scloseunadj;open/high/loware SEP’s split-adjusted values timescloseunadj / close, andvolumeis SEP’s split-adjusted volume divided by that ratio (Sharadar’s own imputation of the raw values).
Sharadar’s adjusted columns (close and the other split-adjusted values,
closeadj) and lastupdated are not stored: the vendor rewrites them over
the whole history on every ex-date. quantlab builds its own adjusted prices
instead, from the raw prices and the dividend, spinoff-value and split events
of the ACTIONS table, with the CRSP panel’s convention and names (adjOpen, adjHigh,
adjLow, adjClose, adjVolume, divCash, splitFactor; see
SharadarStockDataset._adjust). The panel therefore carries the same
twelve daily variables as a CRSP or Tiingo panel, and a factor, label or
backtest reads it without knowing the vendor. Like a CRSP panel it also
carries cumfacshr, the cumulative share adjustment factor: 1.0 on each
permaticker’s first stored bar and divided by splitFactor on every bar
since, so cumfacshr[t-1] / cumfacshr[t] == splitFactor[t] with
cumfacshr[t-1] the permaticker’s last earlier stored value. Only such
ratios are meaningful; an executor books a holder’s split from them. A bar without a fill price
is untradable (the MarketDataset default), and so is a bar Sharadar
carries forward through a trading halt: volume 0 and the previous close
repeated (SharadarStockDataset.tradable_bars). delisting_bars is the
default: a delisted security is settled at its last close, with no delisting
return imputed (Sharadar gives none).
Every conversion, an update included, also writes the ticker sidecar
<store>.sharadar_tickers.json beside the store from TICKERS and ACTIONS
(quantlab.dataset.sharadar.tickers), and ticker_lookup() reads it, so
a backtest shows each permaticker as the ticker and company in use that day.
Examples#
>>> config = SharadarDatasetConfig(
... zarr_file_path="/data/market/sharadar/sharadar_sep_1d/sharadar_sep_1d.zarr",
... raw_data_dir_path="/data/downloads/sharadar",
... )
>>> SharadarStockDataset(config).from_raw_data().save()
>>> panel = SharadarStockDataset(config).panel("2024-01-02", "2024-01-05")
>>> sorted(panel.data_vars)
['adjClose', 'adjHigh', 'adjLow', 'adjOpen', 'adjVolume', 'anomaly_flag', 'close', 'cumfacshr', 'divCash', 'high', 'low', 'open', 'splitFactor', 'volume']
Classes
Dense daily panel of raw OHLCV from a Sharadar price table, keyed by permaticker. |