fintech-algorithms
Using a coding agent? Give it the skill: npx skills add IslamBaraka90/Fintech-Algorithms-Library What it does →

Share-Class Relationship Mapping

Same Issuer Does Not Mean Same Security

Install and import#

bash
npm install fintech-algorithms
ts
import { calculate } from "fintech-algorithms/corporate-actions-and-security-master-data/identity-continuity/share-class-relationship-mapping";

Signature#

calculate(data)

Relates share classes of one issuer — GOOG and GOOGL, voting and non-voting lines. Index membership, float and liquidity screens all need to know these are one company, and naive de-duplication by name gets it wrong.

Parameters#

NameTypeNotes
data{ query: object; entities: Entity[]; relationships: Relationship[] }relationships carries the declared links between classes rather than inferring them from name similarity, which fails on exactly the cases that matter.

Returns#

{ query, root, state, sameIssuerShareClassIds, comparison, resolvedRelationships, diagnostics }

Every class of the same issuer, with the comparison basis used and diagnostics for links that could not be resolved.

Errors#

  • When the query entity is unknown — reported as a state rather than thrown

Complexity: time O(relationships), space O(classes).

Worked example#

verified This is the worked example published in the article, replayed by the test suite on every run. The output cannot drift.

Input#

data
{
  "query": {
    "rootEntityId": "SYN-CLASS-FOUNDER",
    "validAt": "2026-03-01T12:00:00Z",
    "knownAt": "2026-03-05T12:00:00Z",
    "compareShareClassIds": ["SYN-CLASS-FOUNDER", "SYN-CLASS-PUBLIC"]
  },
  "entities": [
    {
      "entityId": "SYN-ISSUER-ALPHA",
      "entityType": "ISSUER",
      "label": "Synthetic Alpha Holdings"
    },
    {
      "entityId": "SYN-INSTRUMENT-COMMON",
      "entityType": "LEGAL_INSTRUMENT",
      "label": "Synthetic Alpha Common Equity"
    },
    {
      "entityId": "SYN-INSTRUMENT-PREFERRED",
      "entityType": "LEGAL_INSTRUMENT",
      "label": "Synthetic Alpha Preferred Equity"
    }
  ],
  "relationships": [
    {
      "assertionId": "R-ISSUE-COMMON",
      "revisionNumber": 1,
      "status": "ACTIVE",
      "relationshipType": "ISSUED_BY",
      "sourceEntityId": "SYN-INSTRUMENT-COMMON",
      "targetEntityId": "SYN-ISSUER-ALPHA",
      "effectiveFrom": "2026-01-01T00:00:00Z",
      "effectiveTo": null,
      "observedAt": "2025-12-15T09:00:00Z",
      "availableAt": "2025-12-15T10:00:00Z",
      "source": {
        "sourceId": "SYN-CHARTER-1",
        "sourceType": "synthetic_charter",
        "documentDate": "2025-12-15",
        "locator": "Article IV"
      },
      "terms": {
        "basis": "legal-issuer"
      },
      "unsupportedTerms": []
    },
    {
      "assertionId": "R-ISSUE-PREF",
      "revisionNumber": 1,
      "status": "ACTIVE",
      "relationshipType": "ISSUED_BY",
      "sourceEntityId": "SYN-INSTRUMENT-PREFERRED",
      "targetEntityId": "SYN-ISSUER-ALPHA",
      "effectiveFrom": "2026-01-01T00:00:00Z",
      "effectiveTo": null,
      "observedAt": "2025-12-15T09:00:00Z",
      "availableAt": "2025-12-15T10:00:00Z",
      "source": {
        "sourceId": "SYN-CHARTER-1",
        "sourceType": "synthetic_charter",
        "documentDate": "2025-12-15",
        "locator": "Article IV"
      },
      "terms": {
        "basis": "legal-issuer"
      },
      "unsupportedTerms": []
    },
    {
      "assertionId": "R-CLASS-FOUNDER",
      "revisionNumber": 1,
      "status": "ACTIVE",
      "relationshipType": "CLASS_OF",
      "sourceEntityId": "SYN-CLASS-FOUNDER",
      "targetEntityId": "SYN-INSTRUMENT-COMMON",
      "effectiveFrom": "2026-01-01T00:00:00Z",
      "effectiveTo": null,
      "observedAt": "2025-12-15T09:00:00Z",
      "availableAt": "2025-12-15T10:00:00Z",
      "source": {
        "sourceId": "SYN-CHARTER-1",
        "sourceType": "synthetic_charter",
        "documentDate": "2025-12-15",
        "locator": "Article IV.1"
      },
      "terms": {
        "classCode": "F"
      },
      "unsupportedTerms": []
    }
  ]
}

Call#

calculate(data)

Returns#

object with 4 fields: state, sameIssuerShareClassIds, comparison, diagnostics

{
  "state": "RESOLVED",
  "sameIssuerShareClassIds": ["SYN-CLASS-FOUNDER", "SYN-CLASS-PREFERRED", "SYN-CLASS-PUBLIC"],
  "comparison": {
    "votingRightsRatioLeftToRight": {
      "status": "ESTABLISHED",
      "numerator": 10,
      "denominator": 1,
      "unit": "votes_per_share"
    },
    "economicRightsRatioLeftToRight": {
      "status": "ESTABLISHED",
      "numerator": 1,
      "denominator": 1,
      "unit": "distribution_units_per_share"
    },
    "equalEconomics": true,
    "conversion": {
      "status": "ESTABLISHED",
      "direction": "SYN-CLASS-FOUNDER->SYN-CLASS-PUBLIC",
      "relationshipType": "CONVERTS_TO",
      "ratio": {
        "numerator": 1,
        "denominator": 1
      },
      "unit": "target_shares_per_source_share",
      "conditions": ["qualifying_transfer"]
    },
    "fungibility": {
      "status": "NOT_ESTABLISHED"
    },
    "priceConvertibility": "NOT_ESTABLISHED"
  },
  "diagnostics": {
    "excludedFutureRevisionCount": 1,
    "cancelledAssertionIds": ["R-LIST-OLD"]
  }
}

Diagrams#

Share-Class Relationship Mapping — article hero
Share-Class Relationship Mapping — failure guard
Share-Class Relationship Mapping — worked example

Calculation flow#

Bitemporal relationship resolution
flowchart TD
    A[Typed entities and relationship revisions] --> B{Contract valid?}
    B -->|No| X[Reject input]
    B -->|Yes| C[Group by stable assertion ID]
    C --> D[Keep revisions available by knownAt]
    D --> E[Select highest available revision]
    E --> F{Cancelled?}
    F -->|Yes| G[Record cancellation]
    F -->|No| H{Interval contains validAt?}
    H -->|No| I[Exclude from resolved graph]
    H -->|Yes| J[Add typed edge with source and terms]
    J --> K{Conflicts or unsupported terms?}
    K -->|Conflict| L[Resolver result is CONFLICT]
    K -->|Unsupported| M[Resolver result is INCOMPLETE]
    K -->|No| N[Resolver result is RESOLVED]
    N --> O[Compare explicit unit-compatible rights]
    O --> P[Return graph and diagnostics]
Assertion and resolution lifecycle
stateDiagram-v2
    [*] --> Observed
    Observed --> Available: source enters system
    Available --> Effective: valid interval contains validAt
    Available --> Future: effectiveFrom after validAt
    Available --> Expired: effectiveTo at or before validAt
    Available --> Cancelled: latest available revision cancels assertion
    Effective --> Resolved: terms supported and consistent
    Effective --> Incomplete: unsupported contract term
    Effective --> Conflict: incompatible active assertions
    Future --> [*]
    Expired --> [*]
    Cancelled --> [*]
    Resolved --> [*]
    Incomplete --> [*]
    Conflict --> [*]

How it works#

This page states the contract — how to call it correctly. The article explains the concept: why it works, and where it breaks.

Read the article →

References#

  • Alphabet Inc. 2025 Annual Report on Form 10-K — Alphabet Inc.; filed with the U.S. Securities and Exchange Commission
  • Financial Instrument Global Identifier Specification, version 1.2 — Object Management Group
  • ISO 6166:2021, Financial services — International securities identification number — International Organization for Standardization
  • Alphabet Inc. Amended and Restated Certificate of Incorporation — Alphabet Inc.
  • Evidence classification

The rest of the Identity Continuity family#