@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
|
@@ -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
|
package/skill/stocks/schema.yaml
CHANGED
|
@@ -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
|
|
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"]
|