# xfinlink Python client for US equity data: prices, financial statements, computed metrics, entity resolution, search, index constituents, and insider transactions. All US-listed stocks and ETFs. API key required for full access. Free tier available. ## Install and authenticate pip install xfinlink import xfinlink as xfl xfl.set_api_key("YOUR_API_KEY") # get a free key at https://xfinlink.com/signup Call set_api_key() before any other xfl function. The Python client also reads XFINLINK_API_KEY or XFL_API_KEY from the environment. ## Quick example import xfinlink as xfl xfl.set_api_key("YOUR_API_KEY") df = xfl.prices("AAPL", start="2025-01-01", end="2025-03-31") # close = raw as-traded price; adj_close = split-adjusted (gap-free across splits) print(df[["date", "close", "adj_close", "volume"]].head()) ## Full API surface ### xfl.prices(ticker, start, end, period, interval, fields, adjust, limit, max_rows) -> pd.DataFrame def prices( ticker: str | list[str] | tuple, start: str | date | None = None, # defaults to 1 year ago end: str | date | None = None, period: str | None = None, # "1w","1mo","3mo","6mo","1y","2y","3y","5y","10y","ytd","max" interval: str = "1d", # "1d","3d","1w","1mo","3mo","6mo","1y" fields: list[str] | str | None = None, adjust: str = "split", # "split" or "none" limit: int | None = None, # default: all rows max_rows: int = 50000, ) -> pd.DataFrame Historical price data with server-side OHLCV aggregation. Max 100 tickers per call (1 on Free tier). Default interval is 1d (daily). Higher intervals aggregate from daily data: open=first day's open, high=max, low=min, close=last day's close, volume=sum. Columns returned (structural, always present): entity_id, ticker, entity_name, gics_sector, date Columns returned (data, selectable via fields=): open, high, low, close, adj_close, volume, return_daily, shares_outstanding, exchange_code, split_ratio, dividend, market_cap Default when fields is omitted: all except market_cap. close is always raw (as-traded) and is never modified by adjust. The adjust flag only controls adj_close: adjust="split" (default) includes adj_close (split-adjusted close); adjust="none" omits it. For a gap-free price series across splits, read adj_close, not close. Examples: df = xfl.prices("AAPL", start="2025-01-01", end="2025-06-30") df = xfl.prices(["AAPL", "MSFT"], start="2025-01-01") df = xfl.prices("AAPL MSFT GOOG", period="1y") df = xfl.prices("AAPL", start=date(2025, 1, 1)) df = xfl.prices("AAPL", fields=["close", "volume"]) ### xfl.fundamentals(ticker, start, end, period, period_type, version, fields, include_segments, segment_members, fiscal_year, period_end, limit, max_rows) -> pd.DataFrame def fundamentals( ticker: str | list[str] | tuple, start: str | date | None = None, # defaults to 1 year ago end: str | date | None = None, period: str | None = None, period_type: str = "all", # "annual", "quarterly", or "all" version: str = "restated", # "restated", "original", or "all" fields: list[str] | str | None = None, include_segments: bool = False, # add revenue segment breakdowns segment_members: str = "primary", # "primary" or "all" fiscal_year: int | None = None, # exact fiscal-year filter period_end: str | date | None = None, # exact period_end filter limit: int | None = None, # default: all rows max_rows: int = 10000, ) -> pd.DataFrame Financial statement data (income, balance sheet, cash flow). 147 fields (130 standard + 17 industry-specific). Max 100 tickers per call (1 on Free tier). All monetary values in millions USD. EPS and dividends_per_share in dollars. shares_outstanding in millions. Columns returned (structural, always present): entity_id, ticker, entity_name, gics_sector, period_end, period_type, fiscal_year, fiscal_period, filing_date, version, source Columns returned (data): 147 financial fields (130 standard + 17 industry-specific). See "Fundamentals fields" section below. When include_segments=True, each row also includes: segments_geographic — list of {label, value, is_primary} or null segments_product — list of {label, value, is_primary} or null segments_business — list of {label, value, is_primary} or null segment_coverage — {geographic_pct, product_pct, business_pct} or null Examples: df = xfl.fundamentals("AAPL", period_type="annual", period="5y") df = xfl.fundamentals("AAPL", period_type="quarterly", fields=["revenue", "net_income", "eps_diluted"]) df = xfl.fundamentals("AAPL", include_segments=True, period_type="annual") df = xfl.fundamentals("AAPL", fiscal_year=2024, period_type="annual") df = xfl.fundamentals("AAPL", period_end="2024-09-28") ### xfl.metrics(ticker, period_type, fields, start, end, period, limit, max_rows) -> pd.DataFrame def metrics( ticker: str | list[str] | tuple, period_type: str = "annual", # "annual" or "quarterly" only fields: list[str] | str | None = None, start: str | date | None = None, # defaults to 1 year ago end: str | date | None = None, period: str | None = None, limit: int | None = None, # default: all rows max_rows: int = 10000, ) -> pd.DataFrame 37 computed financial metrics. Max 100 tickers per call (1 on Free tier). Computed at query time from fundamentals + prices. Ratios are decimals (0.46 = 46%). market_cap and enterprise_value in millions USD. Per-share values in dollars. Columns returned (structural, always present): entity_id, ticker, entity_name, period_end, period_type Columns returned (data): 37 metrics. See "Metrics fields" section below. Note: metrics period_type only accepts "annual" or "quarterly" (not "all"). Examples: df = xfl.metrics("AAPL", period_type="annual", period="5y") df = xfl.metrics("AAPL", fields=["pe_ratio", "roe", "market_cap"]) df = xfl.metrics(["AAPL", "MSFT", "GOOGL"], fields=["pe_ratio", "market_cap"]) ### xfl.resolve(ticker, include) -> dict def resolve( ticker: str | list[str] | tuple, include: list[str] | None = None, # ["index","classifications"] or None for all ) -> dict Entity resolution. Shows every company that has used a ticker, with validity dates. Max 10 tickers per call. Returns dict with structure: result["data"]["TICKER"]["entities"] -> list of: { entity_id, name, entity_type, country, figi, cik, ticker_valid_from, ticker_valid_to, classifications: { sic_code, naics_code, gics_sector, gics_group, gics_industry, gics_subindustry }, index_membership: [{ index, added, removed }] } figi is the OpenFIGI Composite FIGI (e.g. "BBG000B9XRY4"). Null if unavailable. cik is the SEC Central Index Key (e.g. "0000320193" for Apple). Null if unavailable. result["meta"] -> { tickers_requested, tickers_resolved, tickers_unresolved, include } Examples: info = xfl.resolve("GM") entities = info["data"]["GM"]["entities"] info = xfl.resolve("AAPL", include=["classifications"]) ### xfl.search(q, gics_sector, entity_type, sic, naics, country, limit, offset) -> pd.DataFrame def search( q: str | None = None, gics_sector: str | None = None, entity_type: str | None = None, sic: str | None = None, naics: str | None = None, country: str = "US", limit: int = 50, offset: int = 0, ) -> pd.DataFrame Search for entities. Max limit: 500. Columns returned: entity_id, ticker, entity_name, entity_type, gics_sector, gics_sub_industry, sic, naics, country Examples: df = xfl.search(q="apple") df = xfl.search(gics_sector="Energy", limit=100) df = xfl.search(entity_type="etf") ### xfl.index(index_name, as_of, limit, offset) -> pd.DataFrame def index( index_name: str = "sp500", as_of: str | date | None = None, limit: int = 500, offset: int = 0, ) -> pd.DataFrame Index constituents, current or historical. Available indices: "sp500", "ndx100", "djia", "russell2000". Max limit: 1000. Columns returned: entity_id, ticker, entity_name, added_date, removed_date Examples: df = xfl.index("sp500") df = xfl.index("ndx100", as_of="2020-01-01") ### xfl.insiders(ticker, start, end, period, transaction_type, acquisition_or_disposition, ownership_type, form_type, insider_role, insider_name, min_value, include_amendments, fields, limit, max_rows) -> pd.DataFrame def insiders( ticker: str | list[str] | tuple, start: str | date | None = None, # defaults to 1 year ago end: str | date | None = None, period: str | None = None, transaction_type: str | list[str] | None = None, acquisition_or_disposition: str | None = None, # "A" or "D" ownership_type: str | None = None, # "direct" or "indirect" form_type: str | list[str] | None = None, insider_role: str | None = None, # substring, e.g. "CEO" insider_name: str | None = None, # substring min_value: float | None = None, # minimum transaction_value include_amendments: bool = False, fields: list[str] | str | None = None, limit: int | None = None, # default: all rows max_rows: int = 10000, ) -> pd.DataFrame Insider transactions from SEC Form 3/4/5 filings. One row per transaction. Quantities are split-adjusted. Coverage 1996 to present. **Pro tier only.** Columns returned (structural, always present): entity_id, ticker, entity_name, transaction_date, filing_date, form_type Columns returned (data, selectable via fields=): insider_name, insider_role, insider_role_other, transaction_code, transaction_type, acquisition_or_disposition, shares, shares_held_after, transaction_price, transaction_value, ownership_type, is_amendment, document_id, sequence_in_filing, data_quality transaction_type values: open_market_buy, open_market_sell, grant_or_award, option_exercise, tax_withholding, gift, sale_to_issuer, conversion_of_derivative, transaction_by_trust, tender_of_shares, acquisition_by_will, discretionary, expiration_of_long_derivative, exercise_of_out_of_the_money_derivative, expiration_of_short_derivative, voluntary_early_report, equity_swap, small_acquisition, reportable_transaction, deposit_into_voting_trust, decreased_holdings, other Examples: df = xfl.insiders("AAPL", period="1y") df = xfl.insiders("TSLA", transaction_type="open_market_sell") df = xfl.insiders("NVDA", insider_role="CEO", min_value=1_000_000) df = xfl.insiders("META", acquisition_or_disposition="A", insider_role="Director") ### Utility functions xfl.status() -> dict # API health check xfl.usage() -> dict # rate limit status (requires API key) xfl.llm_context() -> str # print and return this file xfl.set_api_base(url: str) # override base URL (for testing) ## Ticker input formats All ticker-accepting functions accept: "AAPL" # single string ["AAPL", "MSFT"] # list ("AAPL", "MSFT") # tuple "AAPL,MSFT" # comma-separated string "AAPL MSFT GOOG" # space-separated string ## Date input formats start and end accept: "2025-01-01" # string, YYYY-MM-DD date(2025, 1, 1) # datetime.date datetime(2025, 1, 1) # datetime.datetime pd.Timestamp("2025-01-01") # pandas Timestamp period shorthand (use period OR start/end, not both): "1w", "1mo", "3mo", "6mo", "1y", "2y", "3y", "5y", "10y", "ytd", "max" ## Worked examples ### 1. Quarterly income statement for one company import xfinlink as xfl xfl.set_api_key("YOUR_API_KEY") # period_type is case-insensitive: "annual", "quarterly", "Annual" all work df = xfl.fundamentals( "AAPL", period_type="quarterly", fields=["revenue", "gross_profit", "operating_income", "net_income", "eps_diluted"], period="2y", ) print(df[["period_end", "revenue", "net_income", "eps_diluted"]]) ### 2. Rank a sector by market cap using search + metrics import xfinlink as xfl xfl.set_api_key("YOUR_API_KEY") tech = xfl.search(gics_sector="Information Technology", limit=50) tickers = tech["ticker"].dropna().tolist() # metrics already returns entity_name — no need to merge with search results # all data endpoints accept up to 100 tickers/call (1 on Free) m = xfl.metrics(tickers, fields=["market_cap", "pe_ratio", "roe"]) latest = m.sort_values("period_end").groupby("ticker").tail(1).reset_index(drop=True) print(latest.sort_values("market_cap", ascending=False).head(20)) ### 3. Resolve an ambiguous ticker (GM pre/post bankruptcy) import xfinlink as xfl xfl.set_api_key("YOUR_API_KEY") info = xfl.resolve("GM") for entity in info["data"]["GM"]["entities"]: print(f"{entity['name']} (id={entity['entity_id']})") print(f" ticker valid: {entity['ticker_valid_from']} to {entity['ticker_valid_to']}") ### 4. Price series with cumulative return calculation import xfinlink as xfl xfl.set_api_key("YOUR_API_KEY") # adj_close is split-only adjusted (stable, no dividend component) # return_daily is total return including dividends (use this for performance) # There is no dividend-adjusted price column — compute from return_daily if needed df = xfl.prices("AAPL", period="1y", fields=["close", "adj_close", "return_daily"]) df["cum_return"] = (1 + df["return_daily"]).cumprod() - 1 print(f"Total return: {df['cum_return'].iloc[-1]:.2%}") ### 5. S&P 500 constituents with fundamentals import xfinlink as xfl xfl.set_api_key("YOUR_API_KEY") sp = xfl.index("sp500") tickers = sp["ticker"].dropna().tolist() # all data endpoints accept up to 100 tickers per call (1 on Free tier) import pandas as pd frames = [] for i in range(0, len(tickers), 100): batch = tickers[i:i+100] df = xfl.fundamentals(batch, period_type="annual", fields=["revenue", "net_income"], period="1y") frames.append(df) result = pd.concat(frames, ignore_index=True) print(result.sort_values("revenue", ascending=False).head(20)) ### 6. Quarterly cash flow analysis import xfinlink as xfl xfl.set_api_key("YOUR_API_KEY") # Quarterly cash flows are already single-quarter standalone values # (de-cumulated from SEC YTD convention at ingestion time) df = xfl.fundamentals( "AAPL", period_type="quarterly", fields=["operating_cash_flow", "free_cash_flow", "capital_expenditures", "net_income_cf"], period="2y", ) # Filter to a specific quarter q3 = df[df["fiscal_period"] == "Q3"].iloc[-1] print(f"AAPL {q3['fiscal_period']} FY{int(q3['fiscal_year'])}:") print(f" Operating cash flow: ${q3['operating_cash_flow']:,.0f}M") print(f" Free cash flow: ${q3['free_cash_flow']:,.0f}M") print(f" Capital expenditures: ${q3['capital_expenditures']:,.0f}M") ## Entity Resolution & Recycled Tickers xfinlink uses permanent entity IDs. Each company has one entity_id regardless of ticker changes. Data endpoints (prices, fundamentals, metrics) resolve any ticker to its single current holder. The resolve endpoint shows the full entity lineage including all historical holders. One entity, many tickers over time: Travelers Companies has traded as STPL, SPK, SPC, STA, and currently TRV. - /v1/fundamentals/TRV returns Travelers' full history across all of those ticker changes. One ticker, two entities (true recycling): GM has been used by two different companies — the pre-bankruptcy General Motors (delisted 2009) and the post-bankruptcy General Motors (2010-present). - /v1/prices/GM returns the current holder (post-bankruptcy GM). - /v1/resolve/GM shows both entities, each with its own ticker_valid_from / ticker_valid_to. To get a specific historical entity's data, use its most recent ticker. To discover which entity held a ticker at a specific time, use /v1/resolve/{ticker}. ## Gotchas - Default start date is 1 year ago. To get all history, pass period="max" or start="1900-01-01". - period="1y" and start="2025-01-01" cannot be combined. Use one or the other. Combining raises XfinlinkError. - adj_close is split-only backward-adjusted to the current post-split share basis. It does NOT include dividends. For total returns, use return_daily. - close is the raw as-traded price and is NEVER adjusted — not even when adjust="split". It steps across split dates (e.g. AAPL close drops from ~500 to ~129 on its 2020 4:1 split). The adjust parameter only controls whether adj_close is in the response. If you want a continuous, split-adjusted price series, read adj_close (or compound split_ratio yourself — see llms-prices.txt). Comparing a pre-split close to a recent close without adjusting will overstate the drawdown. - shares_outstanding in prices is a raw count (e.g. 15115823000). In fundamentals it is in millions (e.g. 15115.823). Different scales. - shares_outstanding, common_shares_issued, treasury_shares, weighted_avg_shares_basic, and weighted_avg_shares_diluted are as-filed — the value the company reported on the filing date, NOT retroactively split-adjusted. Example: NVDA Q1 FY2025 (period_end 2024-04-28) shows shares_outstanding = 2464M; the 10-for-1 split on 2024-06-07 is not reflected in that row. To derive split-adjusted shares for a period, multiply by the cumulative product of split_ratio from xfinlink_prices for all splits where date > period_end. - /v1/metrics market_cap is shares_outstanding × close (both at as-filed scale on period_end's trading day) — this gives the correct historical market capitalization at that point in time. - Quarterly cash flow values are single-quarter standalone (de-cumulated from SEC YTD convention at ingestion time). Q3 operating_cash_flow is Jul-Sep only, not Jan-Sep. No special handling needed. - period_only parameter is deprecated (no-op). Quarterly cash flows are already single-quarter standalone values. - metrics() only accepts period_type="annual" or "quarterly". Passing "all" will cause a server error. - Empty results return an empty DataFrame plus a UserWarning. No exception is raised. - Banks and REITs have null for cost_of_goods_sold, inventory, and accounts_receivable. These fields do not exist in financial institution filings. - Fiscal years vary: Apple ends September, Microsoft ends June, most companies end December. - All fundamentals monetary values are in millions USD. EPS and dividends_per_share are in dollars. - eps_diluted (and all per-share fundamentals fields) are as-reported — NOT retroactively adjusted for stock splits. adj_close in prices IS split-adjusted. Do not divide adj_close by eps_diluted to compute historical P/E ratios — the result will be wrong for any company with past splits. Use xfl.metrics(fields=["pe_ratio"]) instead, which correctly handles split adjustments. - Max tickers per call — prices, fundamentals, metrics: 1 on Free / 100 on Pro. insiders: 100 (Pro only). resolve: 10. - search limit max: 500. index limit max: 1000. - Rate limits: Free tier: 100 requests/day, 40/hour. Pro: 10,000/day, no request throttling. Hitting the limit returns HTTP 429 with retry_after_seconds in the response body. - The resolve, search, and index endpoints have an additional daily usage limit beyond the standard rate limit. Exceeding it returns HTTP 429 with retry_after_seconds. Limits vary by tier; contact hello@xfinlink.com for extended access. ## What xfinlink does NOT do - No intraday or real-time data. End-of-day prices only. - No options, futures, or derivatives. - No non-US equities. All data is US-listed stocks and ETFs. - No dividend-adjusted prices stored. Compute from return_daily (see example 4). - No analyst estimates, consensus, or forward-looking data. - No ETF holdings or compositions. - Index coverage: S&P 500, Nasdaq 100, Dow Jones, Russell 2000. ## Error handling import xfinlink as xfl xfl.set_api_key("YOUR_API_KEY") try: df = xfl.prices("INVALIDTICKER") except xfl.XfinlinkError as e: print(e) # "xfinlink: Ticker 'INVALIDTICKER' not found. Fix: ..." All xfinlink errors raise xfl.XfinlinkError. Common causes: - 401/403: bad API key -> "xfinlink: API key invalid or missing. Fix: call xfl.set_api_key(...)" - 404: unknown ticker -> "xfinlink: Ticker '...' not found. Fix: use xfl.search(q='...')" - 429: rate limit -> "xfinlink: Rate limit reached. Fix: wait Ns" ## Price fields (12) open, high, low, close, adj_close, volume, shares_outstanding, return_daily, market_cap, exchange_code, split_ratio, dividend Price convention: close = raw unadjusted price (what actually traded). NOT modified by the adjust parameter; steps across split dates. adj_close = split-only backward-adjusted to the current post-split share basis (no dividend adjustment, values are stable). This is the continuous, gap-free series. adjust="split" (default) includes it; adjust="none" omits it. return_daily = total daily return including dividends (decimal, 0.05 = 5%) dividend = cash dividend on ex-date, null otherwise split_ratio = split factor on split date (4.0 for 4:1), null otherwise market_cap = close * shares_outstanding (opt-in, not in default response) exchange_code = primary exchange: NYSE, NASDAQ, AMEX (nullable) adj_close is split-only backward-adjusted for all data (both historical and going-forward). Dividend payments are captured separately in the dividend field and incorporated into return_daily. adj_close values are stable — pulling the same date twice always returns the same number. Forward-adjusted prices are not stored. To derive them from an anchor date, request raw close plus split_ratio (adjust="none") and compound the split ratios forward (cumprod). Full worked example with AAPL's 2020 4:1 split: https://xfinlink.com/llms-prices.txt ## Fundamentals fields (147) Income Statement (38): revenue, cost_of_revenue, cost_of_goods_sold, gross_profit, research_and_development, selling_general_admin, selling_and_marketing, general_and_admin, stock_based_compensation, depreciation_amortization, depreciation, amortization_intangibles, depletion, restructuring_charges, impairment_charges, provision_for_credit_losses, gain_loss_on_sale_of_assets, other_operating_expenses, operating_expenses_total, operating_income, interest_expense, interest_income, income_from_equity_method_investments, other_non_operating_income, pretax_income, income_tax_expense, income_from_discontinued_operations, net_income, minority_interest_income, net_income_attributable_to_parent, preferred_dividends, net_income_available_to_common, comprehensive_income, ebit, ebitda, eps_basic, eps_diluted, dividends_per_share Balance Sheet Assets (23): cash_and_equivalents, restricted_cash, marketable_securities, short_term_investments, cash_and_short_term_investments, accounts_receivable, contract_assets, inventory, prepaid_expenses, other_current_assets, current_assets_total, property_plant_equipment_gross, accumulated_depreciation, property_plant_equipment_net, operating_lease_assets, finance_lease_assets, long_term_investments, equity_method_investments, goodwill, intangible_assets, deferred_tax_assets, other_noncurrent_assets, total_assets Balance Sheet Liabilities (19): accounts_payable, short_term_debt, current_portion_long_term_debt, operating_lease_liabilities_current, finance_lease_liabilities_current, deferred_revenue_current, accrued_liabilities, other_current_liabilities, current_liabilities_total, long_term_debt, operating_lease_liabilities_noncurrent, finance_lease_liabilities_noncurrent, deferred_revenue_noncurrent, deferred_tax_liabilities, pension_liabilities, insurance_loss_reserves, other_noncurrent_liabilities, total_liabilities, total_debt Balance Sheet Equity (10): common_stock_value, preferred_equity, additional_paid_in_capital, retained_earnings, treasury_stock, accumulated_other_comprehensive_income, temporary_equity, total_equity, minority_interest, total_equity_including_minority Cash Flow Operating (10): net_income_cf, depreciation_amortization_cf, stock_based_compensation_cf, deferred_income_taxes, change_in_accounts_receivable, change_in_inventory, change_in_accounts_payable, change_in_working_capital, other_operating_activities, operating_cash_flow Cash Flow Investing (7): capital_expenditures, acquisitions_net, proceeds_from_divestitures, purchases_of_investments, sales_of_investments, other_investing_activities, investing_cash_flow Cash Flow Financing (11): long_term_debt_issuance, long_term_debt_repayment, short_term_debt_proceeds, short_term_debt_repayments, finance_lease_principal_payments, share_issuance, share_repurchases, dividends_paid, dividends_paid_common, other_financing_activities, financing_cash_flow Cash Flow Supplemental (5): cash_taxes_paid, cash_interest_paid, effect_of_exchange_rate_on_cash, net_change_in_cash, free_cash_flow Cash flow convention: Quarterly cash flow fields are single-quarter standalone values (de-cumulated from SEC YTD convention at ingestion time). Annual values are 12-month totals. To compute YTD figures, sum Q1 through the desired quarter. Shares (5): shares_outstanding, common_shares_issued, weighted_avg_shares_basic, weighted_avg_shares_diluted, treasury_shares Classification (2): sic, naics Industry — Banking (9): bank_interest_income, bank_interest_expense, bank_net_interest_income, bank_noninterest_income, bank_noninterest_expense, bank_loans_net, bank_deposits, bank_allowance_for_credit_losses, bank_net_charge_offs Industry — Insurance (5): ins_premiums_earned, ins_losses_incurred, ins_underwriting_expense, ins_net_investment_income, ins_policy_benefits Industry — REITs (3): reit_rental_revenue, reit_ffo, reit_affo Revenue note for financials: For banks, insurance, and REITs, filing-source revenue may be significantly narrower than historical-source revenue. Historical source includes all income (net interest income, premiums, rental revenue). Filing source follows ASC 606 and reports only fee-based or contract revenue. Use bank-specific fields (bank_net_interest_income, bank_noninterest_income) or insurance fields (ins_premiums_earned) for comprehensive financial company revenue. Aliases (accepted in fields= param): inventories->inventory, current_assets->current_assets_total, current_liabilities->current_liabilities_total, deferred_revenue->deferred_revenue_current, accumulated_other_ci->accumulated_other_comprehensive_income, property_plant_equipment->property_plant_equipment_net ## Metrics fields (37) Valuation (10): market_cap, market_cap_diluted, enterprise_value, pe_ratio, ps_ratio, pb_ratio, price_to_cash_flow, ev_ebitda, earnings_yield, dividend_yield. pe_ratio is the recommended way to get P/E. It uses split-adjusted values internally. Manual P/E computation from prices + fundamentals requires careful split adjustment. Profitability (7): gross_margin, operating_margin, net_margin, ebitda_margin, roe, roa, roic Leverage (7): debt_to_equity, debt_to_assets, long_term_debt_to_equity, long_term_debt_to_assets, current_ratio, quick_ratio, interest_coverage Efficiency (2): asset_turnover, inventory_turnover Per-share (11): revenue_per_share, book_value_per_share, tangible_book_value_per_share, cash_per_share, debt_per_share, ocf_per_share, fcf_per_share, ebit_per_share, ebitda_per_share, capex_per_share, working_capital_per_share ## MCP Server URL: https://api.xfinlink.com/mcp?api_key=YOUR_KEY Tools: get_prices, get_fundamentals, get_metrics, resolve_ticker, search, get_index, get_insiders ## Detailed field references https://xfinlink.com/llms-prices.txt https://xfinlink.com/llms-fundamentals.txt https://xfinlink.com/llms-metrics.txt https://xfinlink.com/llms-resolve.txt https://xfinlink.com/llms-search.txt https://xfinlink.com/llms-index.txt https://xfinlink.com/llms-insiders.txt