Source code for openbasket.pipelines.ingest.nodes
"""Download raw source files."""
from __future__ import annotations
from pathlib import Path
import pandas as pd
from ...datasets import connection
from ...sources import ishares, nport, sec, spdr
[docs]
def download_nport(quarters: list[str], raw_dir: str, overwrite: bool = False) -> pd.DataFrame:
"""Download the N-PORT ZIP for each quarter (``2026q3`` style) unless cached."""
rows = []
for q in quarters:
q = q.lower()
dest = Path(raw_dir) / f"{q}_nport.zip"
sec.download(sec.NPORT_URL.format(quarter=q), dest, overwrite=overwrite)
rows.append({"quarter": q, "zip_path": str(dest), "bytes": dest.stat().st_size})
return pd.DataFrame(rows)
[docs]
def nport_to_parquet(raw_manifest: pd.DataFrame, parquet_dir: str) -> pd.DataFrame:
"""Convert the tables the pipeline needs to Parquet, one folder per quarter."""
rows = []
for r in raw_manifest.itertuples(index=False):
rows += nport.zip_to_parquet(connection(), Path(r.zip_path), r.quarter, Path(parquet_dir))
return pd.DataFrame(rows)
[docs]
def download_fund_tickers() -> pd.DataFrame:
"""SEC's fund and ETF share-class tickers with their series IDs."""
return sec.fund_tickers()
[docs]
def download_issuer_products(ishares_sites: list[str], spdr_regions: list[str]) -> pd.DataFrame:
"""Every iShares and SPDR fund on the given regional sites, keyed by share-class ISIN."""
frames = [ishares.products(s).assign(issuer="ishares") for s in ishares_sites]
frames += [spdr.products(r) for r in spdr_regions]
return pd.concat(frames, ignore_index=True).drop_duplicates("isin")