Data Citations for Financial Models

Financial models are much harder to understand when you didn't build them or haven't worked with them recently. Hardcoded values are a typical problem. Data or assumptions that come from an outside provider, file, or maybe just an off-hand management comment may be pasted into a workbook without a clear link back to their origin. With models increasingly built by agents, clear data provenance is critical for verifying and understanding model results.

Orcaset helps preserve data provenance across system boundaries. Models can retrieve data directly from external sources, and individual values can carry immutable citations identifying their origin.

Inline data retrieval

Copying data into a workbook breaks the link between the values and their source. Without detailed comments, verifying or updating those values can be difficult.

Orcaset models can instead retrieve external data directly inline as part of the model. Live links directly to the data source reduce the number of hardcoded values. Inputs can live in a database, internal data service, filing repository, or other source system, while the financial model remains focused on the calculations applied to those inputs.

Data source citations

Inline data retrieval improves the data ingestion process. Once data is in the model, Orcaset can attach custom metadata to values linking them to their source. Orcaset's resolution engine tracks all dependencies between values, so derived values can still be traced through to their originating sources.

Source metadata is fully customizable using user-defined types. Citations can contain whatever information is appropriate for the underlying data source, such as a filing accession number, reporting period, URL, database record identifier, or retrieval timestamp. Because the citation travels with the value, this context remains available when the value is inspected and can be surfaced through the model's dependency graph.

A concrete example

The citations example retrieves Q2 2026 revenue for SpaceX from the SEC API and creates a simple revenue model that grows at a constant quarterly rate. When a value from the model is resolved, the loader function fetches data from EDGAR's revenue companyconcept URL, parses the JSON response, and creates a numerical value with the source filing accession number, period frame, and URL as annotations.

Conceptually, the return value is a float subclass that adds the source metadata:

class CitedFloat(float):
    accn: str # filing ID
    frame: str  # period
    url: str  # url
class CitedFloat(float):
    accn: str # filing ID
    frame: str  # period
    url: str  # url
class CitedFloat(float):
    accn: str # filing ID
    frame: str  # period
    url: str  # url

Since the value is a float subclass, it can be used anywhere a regular float could be used. It works and type-checks with regular arithmetic operators (+, -, *, etc.) no differently than a regular float.

Whenever the Q2 2026 revenue value is accessed by a dependent value, Orcaset records a link back to the CitedFloat. This builds an indirect chain back to the origin metadata. For example, the model defines Q3 revenue as Q2 revenue * (1 + 10%). Printing the dependency tree for Q3 revenue results in:

SpaceX revenue@Period(2026-06-30, 2026-09-30) = 8595400000.0
└── SpaceX revenue.cells = <orcaset.series.Replayable object at 0x...>
    └── SpaceX revenue@Period(2026-06-30, 2026-09-30) = 8595400000.0
        └── SpaceX revenue@Period(2026-03-31, 2026-06-30) = CitedFloat(7814000000.0,
                EdgarCitation(accn='0001628280-26-052535',
                frame='CY2026Q2',
                url='https://data.sec.gov/api/xbrl/companyconcept/CIK0001181412/us-gaap/RevenueFromContractWithCustomerExcludingAssessedTax.json'

SpaceX revenue@Period(2026-06-30, 2026-09-30) = 8595400000.0
└── SpaceX revenue.cells = <orcaset.series.Replayable object at 0x...>
    └── SpaceX revenue@Period(2026-06-30, 2026-09-30) = 8595400000.0
        └── SpaceX revenue@Period(2026-03-31, 2026-06-30) = CitedFloat(7814000000.0,
                EdgarCitation(accn='0001628280-26-052535',
                frame='CY2026Q2',
                url='https://data.sec.gov/api/xbrl/companyconcept/CIK0001181412/us-gaap/RevenueFromContractWithCustomerExcludingAssessedTax.json'

SpaceX revenue@Period(2026-06-30, 2026-09-30) = 8595400000.0
└── SpaceX revenue.cells = <orcaset.series.Replayable object at 0x...>
    └── SpaceX revenue@Period(2026-06-30, 2026-09-30) = 8595400000.0
        └── SpaceX revenue@Period(2026-03-31, 2026-06-30) = CitedFloat(7814000000.0,
                EdgarCitation(accn='0001628280-26-052535',
                frame='CY2026Q2',
                url='https://data.sec.gov/api/xbrl/companyconcept/CIK0001181412/us-gaap/RevenueFromContractWithCustomerExcludingAssessedTax.json'

While not the prettiest output, it clearly shows the chain from SpaceX revenue@Period(2026-06-30, 2026-09-30) at the top down to the source annotation at the bottom.

Orcaset dependency trees are structured graphs that are easy to parse and traverse. While models may have a large number of dependency edges, their structured format makes it easy to trace values back to their origin(s).

Models built to be reviewed

Models are handed between analysts, revisited months later, and increasingly built or modified by AI agents. In each case, the person reviewing the model has less context than its original builder.

Data citations help preserve that context. They do not guarantee that a model is correct, but they make its inputs easier to verify and its calculations easier to interpret. Instead of ending at an unexplained hardcode, the audit trail can extend from a calculated output all the way back to the external source supporting it.

As agents take on more model-building work, this kind of auditability becomes increasingly important. The goal should not simply be to build models faster, but to build models whose work can be independently inspected, verified, and grounded against hallucinations.

See the complete citations and data provenance example for a deeper dive into the example's implementation.