@yottagraph-app/data-model-skill 0.0.39 → 0.0.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yottagraph-app/data-model-skill",
3
- "version": "0.0.39",
3
+ "version": "0.0.40",
4
4
  "description": "Data model skill documentation for AI agents - entity types, properties, and schemas from Lovelace fetch sources",
5
5
  "repository": {
6
6
  "type": "git",
@@ -0,0 +1,134 @@
1
+ # Data Dictionary: Finnhub Bonds (ISIN-LEI + Bond Prices)
2
+
3
+ Last updated: 2026-05-28
4
+
5
+ ## Source Overview
6
+
7
+ This source combines two upstream datasets:
8
+
9
+ 1. **GLEIF-ANNA ISIN-to-LEI mapping** — daily open-source file linking financial instruments (ISIN) to issuers (LEI). The published ZIP is a **full snapshot** of mappings from participating national numbering agencies (~8.7M pairs as of May 2026), refreshed daily. It is not a delta of only newly issued ISINs from the prior day.
10
+ 2. **Finnhub bond prices** — end-of-day close prices from `GET /bond/price` for each ISIN in the mapping file, fetched for **yesterday UTC** each poll cycle.
11
+
12
+ The streamer uses the **diffing** pipeline (`DiffingStreamer`): each mapping pair and each ISIN price observation is stored as JSON under the raw download store, SHA-256 compared against the previous run, and only changed rows are atomized and published.
13
+
14
+ | Item | Value |
15
+ |------|--------|
16
+ | Stream source constant | `finnhubbond-source` |
17
+ | `Record.Source` | `finnhubbond` |
18
+ | GLEIF mapping API | `https://mapping.gleif.org/api/v2/isin-lei` |
19
+ | Finnhub price API | `https://finnhub.io/api/v1/bond/price` |
20
+ | Default poll cadence | 1440 min (`pollTimeMin`) |
21
+
22
+ **Data quality notes**
23
+
24
+ - GLEIF mapping coverage depends on participating NNAs; legacy ISINs outside the program may be absent.
25
+ - Finnhub `/bond/price` returns BondCandles (`c[]` close, `t[]` unix timestamps, `s` status). Status `no_data` produces no price record.
26
+ - Yield on `/bond/price` is only emitted when Finnhub returns a `y[]` array; TRACE trade-level yield is on `/bond/tick` (not ingested in v1).
27
+ - Many mapped ISINs may have no Finnhub price (non-US, non-TRACE, delisted). Failures are logged and skipped.
28
+
29
+ ---
30
+
31
+ ## Entity Types
32
+
33
+ ### `organization`
34
+
35
+ A legal entity that **issued** a mapped security, identified by LEI from the GLEIF-ANNA CSV.
36
+
37
+ - **Subject name:** LEI string (no legal name in mapping file).
38
+ - **Strong id:** `lei` on the organization subject.
39
+ - **Resolver:** Organization flavor `NOT_MERGEABLE`; named entity `MERGEABLE` on LEI for cross-source merge with `gleif-source` entities.
40
+ - **Emitted when:** A `(LEI, ISIN)` mapping row is new or changed in the diffing pass.
41
+
42
+ ### `financial_instrument`
43
+
44
+ A bond or fixed-income instrument identified by ISIN.
45
+
46
+ - **Subject name:** ISIN.
47
+ - **Strong id:** `isin`.
48
+ - **Resolver:** `MERGEABLE` on ISIN — aligns with `gleif`, `sanctions`, and EDGAR `holding_isin` resolution.
49
+ - **Emitted when:** (1) mapping rows add `issued_security` target entities, or (2) price rows publish close/yield observations.
50
+
51
+ ---
52
+
53
+ ## Properties
54
+
55
+ ### Organization
56
+
57
+ * `lei`
58
+ * Definition: Legal Entity Identifier (ISO 17442) of the issuer.
59
+ * Examples: `"5493001KJTIIGC8Y1R12"`
60
+ * Derivation: First CSV column in GLEIF ISIN-LEI mapping.
61
+
62
+ ### Financial instrument
63
+
64
+ * `isin`
65
+ * Definition: International Securities Identification Number (ISO 6166).
66
+ * Examples: `"US0378331005"`, `"US46625HQW33"`
67
+ * Derivation: Second CSV column in mapping; or Finnhub price query key.
68
+
69
+ * `close_price`
70
+ * Definition: Bond close price in USD from Finnhub `/bond/price` field `c[]`.
71
+ * Derivation: One atom per candle point in the response; timestamp from matching `t[]` entry.
72
+ * Attribute: `price_date` (YYYY-MM-DD UTC) on each observation atom.
73
+
74
+ * `yield`
75
+ * Definition: Bond yield when Finnhub returns field `y[]` alongside price candles.
76
+ * Derivation: Optional; same indexing as `c[]` / `t[]`. Often absent on `/bond/price`.
77
+ * Attribute: `price_date` on each observation atom.
78
+
79
+ ---
80
+
81
+ ## Relationships
82
+
83
+ * `issued_security`
84
+ * Definition: The organization (issuer LEI) has issued the target financial instrument (ISIN).
85
+ * Direction: `organization` → `financial_instrument`.
86
+ * Derivation: Each GLEIF-ANNA mapping row where both LEI and ISIN are non-empty.
87
+ * Note: Same relationship name and semantics as `gleif-source` ISIN enrichment (`buildISINAtoms`).
88
+
89
+ ---
90
+
91
+ ## Attributes
92
+
93
+ * `price_date`
94
+ * Definition: UTC calendar date of the bond price observation.
95
+ * Examples: `"2026-05-27"`
96
+ * Derivation: From Finnhub candle timestamp `t[]`, or the configured yesterday date when timestamp missing.
97
+
98
+ ---
99
+
100
+ ## Pipeline Behavior
101
+
102
+ ### FetchRows (single cycle)
103
+
104
+ 1. Download latest GLEIF ISIN-LEI ZIP.
105
+ 2. Parse CSV; emit one diffing row per `(LEI, ISIN)` pair (subject to `maxRows`).
106
+ 3. Deduplicate ISINs; optionally cap with `maxIsins`.
107
+ 4. Parallel Finnhub `/bond/price` for yesterday UTC (`priceWorkers`, `finnhubQPS`).
108
+ 5. Emit one diffing price row per ISIN (`price-{ISIN}-{date}.json`).
109
+
110
+ ### Atomization
111
+
112
+ - **Changed mapping rows:** One record per pair — organization subject + `lei` property + `issued_security` target.
113
+ - **Changed price rows:** One record per ISIN — financial_instrument subject + `isin` + `close_price` / optional `yield` atoms.
114
+
115
+ ### Configuration args
116
+
117
+ | Arg | Default | Purpose |
118
+ |-----|---------|---------|
119
+ | `finnhubToken` | `$FINNHUB_TOKEN` | Required API token |
120
+ | `priceWorkers` | 16 | Parallel Finnhub workers |
121
+ | `finnhubQPS` | 10 | Client-side rate limit |
122
+ | `maxIsins` | 0 (all) | Cap price fetches for dev |
123
+ | `maxRows` | 0 (all) | Cap mapping rows emitted |
124
+ | `writeWorkers` | 8 | Diffing raw-store parallelism |
125
+ | `batchSize` | 100 | Publish batch size |
126
+ | `pollTimeMin` | 1440 | Poll interval (minutes) |
127
+
128
+ ---
129
+
130
+ ## Cross-Source Resolution
131
+
132
+ - **`lei`** property matches `gleif.organization.lei` — issuer orgs from this source should merge with GLEIF LEI records when both exist.
133
+ - **`isin`** property matches `financial_instrument.isin` across gleif, sanctions, EDGAR holdings.
134
+ - **`issued_security`** inverse query: find issuer org whose `issued_security` points at an ISIN instrument node.
@@ -0,0 +1,241 @@
1
+ # Dataset schema for GLEIF ISIN-LEI mapping + Finnhub bond end-of-day prices.
2
+ #
3
+ # The streamer diffs LEI→ISIN mapping rows from the daily GLEIF-ANNA file and
4
+ # fetches Finnhub /bond/price candles for every ISIN in the mapping each cycle.
5
+ name: "finnhubbond"
6
+ description: "GLEIF-ANNA ISIN-to-LEI issuer mappings and Finnhub bond end-of-day close prices for mapped ISINs"
7
+
8
+ extraction:
9
+ flavors: closed
10
+ properties: closed
11
+ relationships: closed
12
+ attributes: closed
13
+ events: closed
14
+
15
+ flavors:
16
+ - name: "organization"
17
+ description: "A particular business, institution, or organization such as a corporation, university, government agency, or non-profit"
18
+ display_name: "Organization"
19
+ mergeability: not_mergeable
20
+ strong_id_properties: ["lei"]
21
+ passive: true
22
+
23
+ - name: "financial_instrument"
24
+ description: "A specific asset that can be traded, such as a stock, ETF, bond, CD, or fund. Companies are organizations, NOT financial instruments. Specific currency amounts are NOT financial instruments."
25
+ display_name: "Financial Instrument"
26
+ mergeability: not_mergeable
27
+ strong_id_properties: ["isin", "figi"]
28
+ passive: true
29
+
30
+ properties:
31
+ - name: "lei"
32
+ type: string
33
+ description: "Legal Entity Identifier — a 20-character alphanumeric code uniquely identifying a legal entity in the global financial system (ISO 17442)"
34
+ display_name: "LEI"
35
+ mergeability: not_mergeable
36
+ domain_flavors: ["organization"]
37
+ passive: true
38
+
39
+ - name: "isin"
40
+ type: string
41
+ description: "International Securities Identification Number (ISO 6166) uniquely identifying this financial instrument"
42
+ display_name: "ISIN"
43
+ mergeability: not_mergeable
44
+ domain_flavors: ["financial_instrument"]
45
+ passive: true
46
+
47
+ - name: "close_price"
48
+ type: float
49
+ description: "Closing price of the trading interval in USD"
50
+ display_name: "Close Price"
51
+ mergeability: not_mergeable
52
+ domain_flavors: ["financial_instrument"]
53
+ passive: true
54
+
55
+ - name: "yield"
56
+ type: float
57
+ description: "Yield on the security."
58
+ display_name: "Yield"
59
+ mergeability: not_mergeable
60
+ domain_flavors: ["financial_instrument"]
61
+ passive: true
62
+
63
+ - name: "figi"
64
+ type: string
65
+ description: "Financial Instrument Global Identifier (Bloomberg OpenFIGI)"
66
+ display_name: "FIGI"
67
+ mergeability: not_mergeable
68
+ domain_flavors: ["financial_instrument"]
69
+ passive: true
70
+
71
+ - name: "bond_type"
72
+ type: string
73
+ description: "Bond type from Finnhub /bond/profile (e.g. Corporate, Government)"
74
+ display_name: "Bond Type"
75
+ mergeability: not_mergeable
76
+ domain_flavors: ["financial_instrument"]
77
+ passive: true
78
+
79
+ - name: "debt_type"
80
+ type: string
81
+ description: "Debt type from Finnhub /bond/profile"
82
+ display_name: "Debt Type"
83
+ mergeability: not_mergeable
84
+ domain_flavors: ["financial_instrument"]
85
+ passive: true
86
+
87
+ - name: "coupon"
88
+ type: float
89
+ description: "Coupon rate of the security (e.g. 7.000% or Variable)."
90
+ display_name: "Coupon"
91
+ mergeability: not_mergeable
92
+ domain_flavors: ["financial_instrument"]
93
+ passive: true
94
+
95
+ - name: "coupon_type"
96
+ type: string
97
+ description: "Coupon type from Finnhub /bond/profile (e.g. Fixed)"
98
+ display_name: "Coupon Type"
99
+ mergeability: not_mergeable
100
+ domain_flavors: ["financial_instrument"]
101
+ passive: true
102
+
103
+ - name: "maturity_date"
104
+ type: string
105
+ description: "Maturity date of the security."
106
+ display_name: "Maturity Date"
107
+ mergeability: not_mergeable
108
+ domain_flavors: ["financial_instrument"]
109
+ passive: true
110
+
111
+ - name: "issue_date"
112
+ type: string
113
+ description: "Issue date of the bonds."
114
+ display_name: "Issue Date"
115
+ mergeability: not_mergeable
116
+ domain_flavors: ["financial_instrument"]
117
+ passive: true
118
+
119
+ - name: "first_coupon_date"
120
+ type: string
121
+ description: "First coupon date from Finnhub /bond/profile"
122
+ display_name: "First Coupon Date"
123
+ mergeability: not_mergeable
124
+ domain_flavors: ["financial_instrument"]
125
+ passive: true
126
+
127
+ - name: "dated_date"
128
+ type: string
129
+ description: "Dated date of the bonds."
130
+ display_name: "Dated Date"
131
+ mergeability: not_mergeable
132
+ domain_flavors: ["financial_instrument"]
133
+ passive: true
134
+
135
+ - name: "payment_frequency"
136
+ type: string
137
+ description: "Payment frequency from Finnhub /bond/profile"
138
+ display_name: "Payment Frequency"
139
+ mergeability: not_mergeable
140
+ domain_flavors: ["financial_instrument"]
141
+ passive: true
142
+
143
+ - name: "security_level"
144
+ type: string
145
+ description: "Security level from Finnhub /bond/profile (e.g. Senior)"
146
+ display_name: "Security Level"
147
+ mergeability: not_mergeable
148
+ domain_flavors: ["financial_instrument"]
149
+ passive: true
150
+
151
+ - name: "amount_outstanding"
152
+ type: float
153
+ description: "Amount outstanding from Finnhub /bond/profile"
154
+ display_name: "Amount Outstanding"
155
+ mergeability: not_mergeable
156
+ domain_flavors: ["financial_instrument"]
157
+ passive: true
158
+
159
+ - name: "original_offering"
160
+ type: float
161
+ description: "Original offering amount from Finnhub /bond/profile"
162
+ display_name: "Original Offering"
163
+ mergeability: not_mergeable
164
+ domain_flavors: ["financial_instrument"]
165
+ passive: true
166
+
167
+ - name: "offering_price"
168
+ type: float
169
+ description: "Offering price from Finnhub /bond/profile"
170
+ display_name: "Offering Price"
171
+ mergeability: not_mergeable
172
+ domain_flavors: ["financial_instrument"]
173
+ passive: true
174
+
175
+ - name: "industry_group"
176
+ type: string
177
+ description: "Industry group from Finnhub /bond/profile"
178
+ display_name: "Industry Group"
179
+ mergeability: not_mergeable
180
+ domain_flavors: ["financial_instrument"]
181
+ passive: true
182
+
183
+ - name: "industry_subgroup"
184
+ type: string
185
+ description: "Industry subgroup from Finnhub /bond/profile"
186
+ display_name: "Industry Subgroup"
187
+ mergeability: not_mergeable
188
+ domain_flavors: ["financial_instrument"]
189
+ passive: true
190
+
191
+ - name: "asset"
192
+ type: string
193
+ description: "Asset from Finnhub /bond/profile"
194
+ display_name: "Asset"
195
+ mergeability: not_mergeable
196
+ domain_flavors: ["financial_instrument"]
197
+ passive: true
198
+
199
+ - name: "asset_type"
200
+ type: string
201
+ description: "Asset type from Finnhub /bond/profile"
202
+ display_name: "Asset Type"
203
+ mergeability: not_mergeable
204
+ domain_flavors: ["financial_instrument"]
205
+ passive: true
206
+
207
+ - name: "day_count"
208
+ type: string
209
+ description: "Day count convention from Finnhub /bond/profile"
210
+ display_name: "Day Count"
211
+ mergeability: not_mergeable
212
+ domain_flavors: ["financial_instrument"]
213
+ passive: true
214
+
215
+ - name: "security_term"
216
+ type: string
217
+ description: "Security term from Finnhub /bond/profile"
218
+ display_name: "Security Term"
219
+ mergeability: not_mergeable
220
+ domain_flavors: ["financial_instrument"]
221
+ passive: true
222
+
223
+ relationships:
224
+ - name: "issued_security"
225
+ description: "The organization has issued this financial instrument, linked via GLEIF-ANNA ISIN-LEI daily mapping. To find the issuer of a security, query inversely: find the entity whose issued_security points to the instrument."
226
+ display_name: "Issued Security"
227
+ mergeability: not_mergeable
228
+ domain_flavors: ["organization"]
229
+ target_flavors: ["financial_instrument"]
230
+ passive: true
231
+
232
+ attributes:
233
+ - properties:
234
+ - "close_price"
235
+ - "yield"
236
+ name: "price_date"
237
+ type: string
238
+ description: "UTC calendar date (YYYY-MM-DD) of the bond price observation from Finnhub timestamp t[]"
239
+ display_name: "Price Date"
240
+ mergeability: not_mergeable
241
+ passive: true
@@ -106,7 +106,7 @@ properties:
106
106
 
107
107
  - name: "close_price"
108
108
  type: float
109
- description: "Closing price of the trading interval in USD, from Alpha Vantage field '4. close'"
109
+ description: "Closing price of the trading interval in USD"
110
110
  display_name: "Close Price"
111
111
  mergeability: not_mergeable
112
112
  domain_flavors: ["financial_instrument"]