| import os |
| from sec_api import ExtractorApi |
| from functools import wraps |
| from typing import Annotated |
| from ..utils import SavePathType |
| from ..data_source import FMPUtils |
|
|
|
|
| CACHE_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), ".cache") |
|
|
|
|
| def init_sec_api(func): |
| @wraps(func) |
| def wrapper(*args, **kwargs): |
| global extractor |
| if os.environ.get("SEC_API_KEY") is None: |
| print("Please set the environment variable SEC_API_KEY to use sec_api.") |
| return None |
| else: |
| extractor = ExtractorApi(os.environ["SEC_API_KEY"]) |
| print("Sec Api initialized") |
| return func(*args, **kwargs) |
|
|
| return wrapper |
|
|
|
|
| class SECUtils: |
|
|
| @init_sec_api |
| def get_10k_section( |
| ticker_symbol: Annotated[str, "ticker symbol"], |
| fyear: Annotated[str, "fiscal year of the 10-K report"], |
| section: Annotated[ |
| str | int, |
| "Section of the 10-K report to extract, should be in [1, 1A, 1B, 2, 3, 4, 5, 6, 7, 7A, 8, 9, 9A, 9B, 10, 11, 12, 13, 14, 15]", |
| ], |
| report_address: Annotated[ |
| str, |
| "URL of the 10-K report, if not specified, will get report url from fmp api", |
| ] = None, |
| save_path: SavePathType = None, |
| ) -> str: |
| """ |
| Get a specific section of a 10-K report from the SEC API. |
| """ |
| if isinstance(section, int): |
| section = str(section) |
| if section not in [ |
| "1A", |
| "1B", |
| "7A", |
| "9A", |
| "9B", |
| ] + [str(i) for i in range(1, 16)]: |
| raise ValueError( |
| "Section must be in [1, 1A, 1B, 2, 3, 4, 5, 6, 7, 7A, 8, 9, 9A, 9B, 10, 11, 12, 13, 14, 15]" |
| ) |
|
|
| |
|
|
| |
|
|
| |
| |
| |
| |
| if report_address is None: |
| report_address = FMPUtils.get_sec_report(ticker_symbol, fyear) |
| if report_address.startswith("Link: "): |
| report_address = report_address.lstrip("Link: ").split()[0] |
| else: |
| return report_address |
| |
| cache_path = os.path.join(CACHE_PATH, f"sec_utils/{ticker_symbol}_{fyear}_{section}.txt") |
| if os.path.exists(cache_path): |
| with open(cache_path, "r") as f: |
| section_text = f.read() |
| else: |
| section_text = extractor.get_section(report_address, section, "text") |
| os.makedirs(os.path.dirname(cache_path), exist_ok=True) |
| with open(cache_path, "w") as f: |
| f.write(section_text) |
|
|
| if save_path: |
| os.makedirs(os.path.dirname(save_path), exist_ok=True) |
| with open(save_path, "w") as f: |
| f.write(section_text) |
|
|
| return section_text |
|
|