feat(sec): A3 slice 2a — companyfacts -> snapshot parser
Pure parser (no I/O/DB) turning one issuer's companyfacts + submissions filing metadata into per-accession snapshot rows for the filing's primary period. - Period identity from end == reportDate, never fy/fp (fy/fp is the filing's context; comparatives repeat it). - Duration facts stored as cumulative YTD: pick the fact whose span matches the fiscal-period-to-date length (Q1~3mo..FY~12mo) within tolerance; no YTD-length fact -> null (never a discrete masquerading as YTD). - Balance-sheet instants at end == reportDate; shares_outstanding is the dei cover-page fact whose own end (cover date) is stored in shares_outstanding_date. - Cash and debt composites are aggregate-first and mutually exclusive (each source tag counted at most once). - Carries filing_date through submissions rows (snapshot.filed_date). Verified on REAL Apple companyfacts: 44 snapshots, 0 skipped, YTD revenue 124.3B->219.7B->313.7B->416.2B across FY2025 (Q4 derives at read time), every shares_date is the cover date != period_end. Tests: 6 fixture + 1 skip-guarded live-invariants (monotonic YTD, cover-date shares). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -270,6 +270,7 @@ def _rows_from_arrays(arrays: dict[str, list]) -> list[dict[str, Any]]:
|
||||
"accession": arrays["accessionNumber"][i],
|
||||
"form": form,
|
||||
"report_date": arrays["reportDate"][i] or None,
|
||||
"filing_date": arrays["filingDate"][i] or None,
|
||||
"acceptance_datetime": arrays["acceptanceDateTime"][i] or None,
|
||||
"is_xbrl": bool(arrays.get("isXBRL", [0] * len(forms))[i]),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user