File size: 2,683 Bytes
3a3a58f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
"""Resolve ticker / CIK / accession → full company identity."""
import re
from eugene.cache import cached
from eugene.sources.sec_api import fetch_tickers, fetch_submissions

ACCESSION_RE = re.compile(r"^\d{10}-\d{2}-\d{6}$")
CIK_RE = re.compile(r"^\d{1,10}$")


@cached(ttl=86400)
def _load_ticker_map() -> dict:
    """Build ticker → {cik, company} lookup from SEC."""
    data = fetch_tickers()
    result = {}
    for entry in data.values():
        result[entry["ticker"].upper()] = {
            "cik": str(entry["cik_str"]).zfill(10),
            "company": entry["title"],
        }
    return result


def resolve(identifier: str) -> dict:
    """
    Resolve any identifier to {ticker, cik, company, sic, fiscal_year_end}.
    
    Accepts:
      - Ticker: AAPL
      - CIK: 320193 or 0000320193
      - Accession: 0000320193-24-000123
    """
    identifier = identifier.strip()

    # --- Accession number ---
    if ACCESSION_RE.match(identifier):
        cik = identifier.split("-")[0]
        try:
            subs = fetch_submissions(cik)
            tickers = subs.get("tickers", [])
            return {
                "ticker": tickers[0] if tickers else None,
                "cik": cik,
                "company": subs.get("name", ""),
                "sic": subs.get("sic", ""),
                "fiscal_year_end": subs.get("fiscalYearEnd", ""),
                "accession": identifier,
            }
        except Exception as e:
            return {"error": f"Could not resolve accession {identifier}: {e}"}

    # --- CIK (pure digits) ---
    if CIK_RE.match(identifier):
        cik = identifier.zfill(10)
        try:
            subs = fetch_submissions(cik)
            tickers = subs.get("tickers", [])
            return {
                "ticker": tickers[0] if tickers else None,
                "cik": cik,
                "company": subs.get("name", ""),
                "sic": subs.get("sic", ""),
                "fiscal_year_end": subs.get("fiscalYearEnd", ""),
            }
        except Exception as e:
            return {"error": f"Could not resolve CIK {identifier}: {e}"}

    # --- Ticker ---
    ticker = identifier.upper().replace(" ", "")
    ticker_map = _load_ticker_map()
    if ticker not in ticker_map:
        return {"error": f"Unknown ticker: {ticker}"}

    entry = ticker_map[ticker]
    cik = entry["cik"]
    try:
        subs = fetch_submissions(cik)
    except Exception:
        subs = {}

    return {
        "ticker": ticker,
        "cik": cik,
        "company": entry.get("company", subs.get("name", "")),
        "sic": subs.get("sic", ""),
        "fiscal_year_end": subs.get("fiscalYearEnd", ""),
    }