|
| 1 | +# XBRL Query Functionality |
| 2 | + |
| 3 | +You can query the facts inside an XBRL instance using the XBRL query API. This allows you to get access to specific financial data, filter results and perform analysis on the financial facts contained within a single XBRL filing. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +XBRL query functionality is built around two main classes: |
| 8 | +- `FactsView` - Provides access to raw XBRL facts from a single filing |
| 9 | +- `FactQuery` - Enables complex filtering and analysis of those facts |
| 10 | + |
| 11 | +## Basic Usage |
| 12 | + |
| 13 | +### Accessing Facts |
| 14 | + |
| 15 | +```python |
| 16 | +from edgar import * |
| 17 | +from edgar.xbrl import XBRL |
| 18 | + |
| 19 | +# Get an XBRL filing |
| 20 | +company = Company("AAPL") |
| 21 | +filing = company.latest("10-K") |
| 22 | +xb = filing.xbrl() |
| 23 | +``` |
| 24 | + |
| 25 | +### Access the facts view |
| 26 | + |
| 27 | +The `FactsView` provides direct access to the facts in the XBRL instance: |
| 28 | +```python |
| 29 | +facts = xb.facts |
| 30 | +print(f"Total facts: {len(facts)}") |
| 31 | +``` |
| 32 | + |
| 33 | +## Querying Facts |
| 34 | + |
| 35 | +To query facts use the `query()` method on the `XBRL` instance and one of the `by_` functions e.g. `by_text()`. This returns a `FactQuery` object that allows you to filter and manipulate the facts. |
| 36 | + |
| 37 | +```python |
| 38 | +# Start a query |
| 39 | +results = (xb.query() |
| 40 | + .by_concept("us-gaap:PaymentsToAcquireAvailableForSaleSecuritiesDebt") |
| 41 | + ) |
| 42 | +``` |
| 43 | + |
| 44 | + |
| 45 | + |
| 46 | +The result is an `edgar.xbrl.facts.FactQuery` object that contains the filtered facts. You can see from the rich display the available columns of whichg a few are selected by default. |
| 47 | + |
| 48 | +You can also convert the results to a DataFrame for easier manipulation including selecting which columns you want to view: |
| 49 | + |
| 50 | +```python |
| 51 | +df = results.to_dataframe('concept', 'label', 'value', 'period_end') |
| 52 | +``` |
| 53 | + |
| 54 | +## Filtering Facts |
| 55 | + |
| 56 | +### By Concept |
| 57 | + |
| 58 | +```python |
| 59 | +# Find revenue-related facts |
| 60 | +revenue_query = xb.query().by_concept("us-gaap:Revenues") |
| 61 | +revenue_facts = revenue_query.execute() |
| 62 | + |
| 63 | +``` |
| 64 | + |
| 65 | +### By Label |
| 66 | + |
| 67 | +You can filter facts by their labels, which are human-readable names associated with the concepts. |
| 68 | +```python |
| 69 | +# Search by label text |
| 70 | +revenue_query = xb.query().by_label("Revenue") |
| 71 | +``` |
| 72 | +To specify exact matches or partial matches, use the `exact` parameter: |
| 73 | + |
| 74 | +```python |
| 75 | +sales_query = xb.query().by_label("Revenue", exact=False) |
| 76 | +``` |
| 77 | + |
| 78 | +### By Value |
| 79 | + |
| 80 | +```python |
| 81 | +# Facts with values above $1 billion |
| 82 | +large_values = xb.query().by_value(lambda x: x > 1_000_000_000) |
| 83 | + |
| 84 | +# Facts within a range |
| 85 | +range_query = xb.query().by_value(lambda x: 100_000 <= x <= 1_000_000) |
| 86 | +``` |
| 87 | + |
| 88 | + |
| 89 | +### By Statement Type |
| 90 | + |
| 91 | +```python |
| 92 | +# Facts from specific statements |
| 93 | +income_facts = xb.query().by_statement_type("IncomeStatement") |
| 94 | +balance_facts = xb.query().by_statement_type("BalanceSheet") |
| 95 | +``` |
| 96 | + |
| 97 | +## Method Chaining |
| 98 | + |
| 99 | +Combine multiple filters using method chaining: |
| 100 | + |
| 101 | +```python |
| 102 | +# Complex query with multiple filters |
| 103 | +complex_query = (xbrl.query() |
| 104 | + .by_statement("IncomeStatement") |
| 105 | + .by_label("Revenue") |
| 106 | + .by_value(lambda x: x > 1_000_000) |
| 107 | + .sort_by('value', ascending=False) |
| 108 | + .limit(10)) |
| 109 | + |
| 110 | +results = complex_query.execute() |
| 111 | +``` |
| 112 | + |
| 113 | +## Data Transformations |
| 114 | + |
| 115 | +### Sorting |
| 116 | + |
| 117 | +```python |
| 118 | +# Sort by value (descending) |
| 119 | +sorted_query = xbrl.query().sort_by('value', ascending=False) |
| 120 | + |
| 121 | +# Sort by concept name |
| 122 | +concept_sorted = xbrl.query().sort_by('concept') |
| 123 | +``` |
| 124 | + |
| 125 | +### Limiting Results |
| 126 | + |
| 127 | +```python |
| 128 | +# Get top 10 results |
| 129 | +top_10 = xbrl.query().limit(10) |
| 130 | + |
| 131 | +# Pagination |
| 132 | +page_1 = xbrl.query().limit(20) |
| 133 | +page_2 = xbrl.query().offset(20).limit(20) |
| 134 | +``` |
| 135 | + |
| 136 | +## Working with Results |
| 137 | + |
| 138 | +### DataFrame Output |
| 139 | + |
| 140 | +```python |
| 141 | +# Get specific columns |
| 142 | +df = query.to_dataframe('concept', 'label', 'value', 'period_end') |
| 143 | + |
| 144 | +# All available columns |
| 145 | +full_df = query.to_dataframe() |
| 146 | + |
| 147 | +# Column information |
| 148 | +print("Available columns:", df.columns.tolist()) |
| 149 | +``` |
| 150 | + |
| 151 | +### Fact Structure |
| 152 | + |
| 153 | +Each fact contains the following key information: |
| 154 | + |
| 155 | +```python |
| 156 | +fact = results[0] |
| 157 | +print(f"Concept: {fact['concept']}") |
| 158 | +print(f"Label: {fact['label']}") |
| 159 | +print(f"Value: {fact['value']}") |
| 160 | +print(f"Period: {fact['period_end']}") |
| 161 | +print(f"Units: {fact['units']}") |
| 162 | +print(f"Decimals: {fact['decimals']}") |
| 163 | +``` |
| 164 | + |
| 165 | +## Advanced Filtering |
| 166 | + |
| 167 | +### Dimensions |
| 168 | + |
| 169 | +```python |
| 170 | +# Facts with specific dimensions |
| 171 | +dimensional_query = xbrl.query().by_dimension("ProductOrServiceAxis", "ProductMember") |
| 172 | + |
| 173 | +# Facts with any value for a dimension |
| 174 | +any_product_dim = xbrl.query().by_dimension("ProductOrServiceAxis") |
| 175 | + |
| 176 | +# Facts with NO dimensions (undimensioned facts) |
| 177 | +undimensioned_facts = xbrl.query().by_dimension(None) |
| 178 | + |
| 179 | +# Multiple dimensions |
| 180 | +multi_dim = xbrl.query().by_dimensions({ |
| 181 | + "ProductOrServiceAxis": "ProductMember", |
| 182 | + "GeographyAxis": "USMember" |
| 183 | +}) |
| 184 | +``` |
| 185 | + |
| 186 | + |
| 187 | +## Performance Tips |
| 188 | + |
| 189 | +1. **Use specific filters**: Filter early to reduce data processing |
| 190 | +2. **Limit results**: Use `.limit()` for large datasets |
| 191 | +3. **Cache queries**: Store frequently used queries |
| 192 | +4. **Select columns**: Use `to_dataframe()` with specific columns |
| 193 | + |
| 194 | +```python |
| 195 | +# Efficient query pattern |
| 196 | +efficient_query = (xb.query() |
| 197 | + .by_statement("IncomeStatement") # Filter first |
| 198 | + .by_value(lambda x: x > 0) # Remove zeros |
| 199 | + .limit(100) # Limit results |
| 200 | + .to_dataframe('concept', 'value')) # Select columns |
| 201 | +``` |
| 202 | + |
| 203 | +## Examples |
| 204 | + |
| 205 | +### Finding Revenue Information |
| 206 | + |
| 207 | +```python |
| 208 | +# All revenue-related facts |
| 209 | +revenue_facts = (xb.query() |
| 210 | + .by_label("revenue", exact=False) |
| 211 | + .sort_by('value', ascending=False) |
| 212 | + .execute()) |
| 213 | + |
| 214 | +for fact in revenue_facts: |
| 215 | + print(f"{fact['label']}: ${fact['value']:,}") |
| 216 | +``` |
| 217 | + |
| 218 | +### Comparing Quarterly Data |
| 219 | + |
| 220 | +```python |
| 221 | +# Get quarterly revenue data |
| 222 | +quarterly_revenue = (xb.query() |
| 223 | + .by_concept("us-gaap:Revenues") |
| 224 | + .by_period_type("duration") |
| 225 | + .sort_by('period_end') |
| 226 | + .to_dataframe('period_end', 'value')) |
| 227 | + |
| 228 | +print(quarterly_revenue) |
| 229 | +``` |
| 230 | + |
| 231 | +### Balance Sheet Analysis |
| 232 | + |
| 233 | +```python |
| 234 | +# Major balance sheet items |
| 235 | +balance_items = (xb.query() |
| 236 | + .by_statement("BalanceSheet") |
| 237 | + .by_value(lambda x: x > 1_000_000_000) # > $1B |
| 238 | + .sort_by('value', ascending=False) |
| 239 | + .to_dataframe('label', 'value')) |
| 240 | + |
| 241 | +print("Major Balance Sheet Items (> $1B):") |
| 242 | +print(balance_items) |
| 243 | +``` |
| 244 | + |
| 245 | +This query system provides a flexible and powerful way to explore XBRL data, enabling detailed financial analysis and data extraction from individual filings. |
0 commit comments