Files
2025-12-09 12:13:01 +01:00

119 lines
4.1 KiB
Python

"""Parser for 13F primary document XML format."""
from datetime import datetime
from decimal import Decimal
from functools import lru_cache
from edgar._party import Address
from edgar.thirteenf.models import (
FilingManager,
OtherManager,
CoverPage,
SummaryPage,
Signature,
PrimaryDocument13F
)
from edgar.xmltools import child_text, find_element
__all__ = ['parse_primary_document_xml']
@lru_cache(maxsize=8)
def parse_primary_document_xml(primary_document_xml: str):
"""
Parse the primary 13F XML document.
Args:
primary_document_xml: XML content of the primary document
Returns:
PrimaryDocument13F: Parsed primary document data
"""
root = find_element(primary_document_xml, "edgarSubmission")
# Header data
header_data = root.find("headerData")
filer_info = header_data.find("filerInfo")
report_period = datetime.strptime(child_text(filer_info, "periodOfReport"), "%m-%d-%Y")
# Form Data
form_data = root.find("formData")
cover_page_el = form_data.find("coverPage")
report_calendar_or_quarter = child_text(form_data, "reportCalendarOrQuarter")
report_type = child_text(cover_page_el, "reportType")
# Filing Manager
filing_manager_el = cover_page_el.find("filingManager")
# Address
address_el = filing_manager_el.find("address")
address = Address(
street1=child_text(address_el, "street1"),
street2=child_text(address_el, "street2"),
city=child_text(address_el, "city"),
state_or_country=child_text(address_el, "stateOrCountry"),
zipcode=child_text(address_el, "zipCode")
)
filing_manager = FilingManager(name=child_text(filing_manager_el, "name"), address=address)
# Other managers
other_manager_info_el = cover_page_el.find("otherManagersInfo")
other_managers = [
OtherManager(
cik=child_text(other_manager_el, "cik"),
name=child_text(other_manager_el, "name"),
file_number=child_text(other_manager_el, "form13FFileNumber")
)
for other_manager_el in other_manager_info_el.find_all("otherManager")
] if other_manager_info_el else []
# Summary Page
summary_page_el = form_data.find("summaryPage")
if summary_page_el:
other_included_managers_count = child_text(summary_page_el,
"otherIncludedManagersCount")
if other_included_managers_count:
other_included_managers_count = int(other_included_managers_count)
total_holdings = child_text(summary_page_el, "tableEntryTotal")
if total_holdings:
total_holdings = int(total_holdings)
total_value = child_text(summary_page_el, "tableValueTotal")
if total_value:
total_value = Decimal(total_value)
else:
other_included_managers_count = 0
total_holdings = 0
total_value = 0
# Signature Block
signature_block_el = form_data.find("signatureBlock")
signature = Signature(
name=child_text(signature_block_el, "name"),
title=child_text(signature_block_el, "title"),
phone=child_text(signature_block_el, "phone"),
city=child_text(signature_block_el, "city"),
signature=child_text(signature_block_el, "signature"),
state_or_country=child_text(signature_block_el, "stateOrCountry"),
date=child_text(signature_block_el, "signatureDate")
)
parsed_primary_doc = PrimaryDocument13F(
report_period=report_period,
cover_page=CoverPage(
filing_manager=filing_manager,
report_calendar_or_quarter=report_calendar_or_quarter,
report_type=report_type,
other_managers=other_managers
),
signature=signature,
summary_page=SummaryPage(
other_included_managers_count=other_included_managers_count or 0,
total_holdings=total_holdings or 0,
total_value=total_value or 0
),
additional_information=child_text(cover_page_el, "additionalInformation")
)
return parsed_primary_doc