@tasenor/common-plugins 1.9.124 → 1.9.126

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.
Files changed (56) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/.turbo/turbo-ci.log +2 -2
  3. package/data/TickerData.mjs +8 -0
  4. package/dist/AssetReport/backend/index.d.ts +2 -2
  5. package/dist/AssetReport/backend/index.js +17 -7
  6. package/dist/AssetReport/backend/index.js.map +1 -1
  7. package/dist/FinnishBalanceSheetReport/backend/index.d.ts +2 -2
  8. package/dist/FinnishBalanceSheetReport/backend/index.js +2 -2
  9. package/dist/FinnishBalanceSheetReport/backend/index.js.map +1 -1
  10. package/dist/FinnishBalanceSheetReportLite/backend/index.d.ts +2 -2
  11. package/dist/FinnishBalanceSheetReportLite/backend/index.js +2 -2
  12. package/dist/FinnishBalanceSheetReportLite/backend/index.js.map +1 -1
  13. package/dist/FinnishIncomeStatementReport/backend/index.d.ts +2 -2
  14. package/dist/FinnishIncomeStatementReport/backend/index.js +2 -2
  15. package/dist/FinnishIncomeStatementReport/backend/index.js.map +1 -1
  16. package/dist/FinnishIncomeStatementReportLite/backend/index.d.ts +2 -2
  17. package/dist/FinnishIncomeStatementReportLite/backend/index.js +2 -2
  18. package/dist/FinnishIncomeStatementReportLite/backend/index.js.map +1 -1
  19. package/dist/IncomeAndExpenses/backend/index.js +1 -1
  20. package/dist/IncomeAndExpenses/backend/index.js.map +1 -1
  21. package/dist/JournalReport/backend/index.d.ts +1 -1
  22. package/dist/JournalReport/backend/index.js +1 -1
  23. package/dist/JournalReport/backend/index.js.map +1 -1
  24. package/dist/LedgerReport/backend/index.d.ts +1 -1
  25. package/dist/LedgerReport/backend/index.js +1 -1
  26. package/dist/LedgerReport/backend/index.js.map +1 -1
  27. package/dist/TickerData/backend/index.d.ts +45 -0
  28. package/dist/TickerData/backend/index.js +187 -0
  29. package/dist/TickerData/backend/index.js.map +1 -0
  30. package/dist/VATFinland/backend/index.js +1 -1
  31. package/dist/VATFinland/backend/index.js.map +1 -1
  32. package/dist/index.d.ts +1 -0
  33. package/dist/index.js +1 -0
  34. package/dist/index.js.map +1 -1
  35. package/package.json +6 -5
  36. package/src/AssetReport/backend/index.ts +19 -7
  37. package/src/FinnishBalanceSheetReport/backend/index.ts +2 -2
  38. package/src/FinnishBalanceSheetReportLite/backend/index.ts +2 -2
  39. package/src/FinnishIncomeStatementReport/backend/index.ts +2 -2
  40. package/src/FinnishIncomeStatementReportLite/backend/index.ts +2 -2
  41. package/src/IncomeAndExpenses/backend/index.ts +1 -1
  42. package/src/JournalReport/backend/index.ts +1 -1
  43. package/src/LedgerReport/backend/index.ts +1 -1
  44. package/src/TickerData/backend/cryptocurrencies.json +3762 -0
  45. package/src/TickerData/backend/currencies.json +181 -0
  46. package/src/TickerData/backend/etf.json +3339 -0
  47. package/src/TickerData/backend/hel.json +144 -0
  48. package/src/TickerData/backend/index.ts +215 -0
  49. package/src/TickerData/backend/nasdaq.json +505 -0
  50. package/src/TickerData/backend/nyse.json +514 -0
  51. package/src/TickerData/backend/otc.json +3 -0
  52. package/src/TickerData/backend/tal.json +36 -0
  53. package/src/TickerData/backend/tsx.json +421 -0
  54. package/src/TickerData/backend/xetra.json +15 -0
  55. package/src/VATFinland/backend/index.ts +1 -1
  56. package/src/index.ts +1 -0
@@ -0,0 +1,144 @@
1
+ {
2
+ "ACG1V": "Aspocomp Group Oyj",
3
+ "AFAGR": "Afarak Group",
4
+ "AKTIA": "Aktia Bank Abp",
5
+ "ALBAV": "Ålandsbanken Abp A",
6
+ "ALBBV": "Ålandsbanken Abp B",
7
+ "ALISA": "Alisa Pankki Oyj",
8
+ "ALMA": "Alma Media Oyj",
9
+ "ANORA": "Anora Group Oyj",
10
+ "APETIT": "Apetit Oyj",
11
+ "ASPO": "Aspo Oyj",
12
+ "ATRAV": "Atria Oyj A",
13
+ "BIOBV": "Biohit Oyj B",
14
+ "BITTI": "Bittium Oyj",
15
+ "BOREO": "Boreo Oyj",
16
+ "CAPMAN": "CapMan Oyj",
17
+ "CAV1V": "Caverion Oyj",
18
+ "CGCBV": "Cargotec Oyj",
19
+ "CONSTI": "Consti Oyj",
20
+ "CTH1V": "Componenta Oyj",
21
+ "CTY1S": "Citycon Oyj",
22
+ "DIGIA": "Digia Oyj",
23
+ "DIGIGR": "Digitalist Group Oyj",
24
+ "DOV1V": "Dovre Group Oyj",
25
+ "EEZY": "Eezy Oyj",
26
+ "ELEAV": "Elecster Oyj A",
27
+ "ELISA": "Elisa Oyj",
28
+ "ENENTO": "Enento Group Oyj",
29
+ "EQV1V": "eQ Oyj",
30
+ "ESENSE": "Enersense International Oyj",
31
+ "ETTE": "Etteplan Oyj",
32
+ "EVLI": "Evli Oyj",
33
+ "EXL1V": "Exel Composites Oyj",
34
+ "FIA1S": "Finnair Oyj",
35
+ "FORTUM": "Fortum Oyj",
36
+ "FSECURE": "F-Secure Oyj",
37
+ "FSKRS": "Fiskars Oyj Abp",
38
+ "GLA1V": "Glaston Oyj Abp",
39
+ "GOFORE": "Gofore Oyj",
40
+ "HARVIA": "Harvia Oyj",
41
+ "HKSAV": "HKScan Oyj A",
42
+ "HONBS": "Honkarakenne Oyj B",
43
+ "HUH1V": "Huhtamäki Oyj",
44
+ "ICP1V": "Incap Oyj",
45
+ "IFA1V": "Innofactor Plc",
46
+ "ILKKA2": "Ilkka Oyj 2",
47
+ "INVEST": "Investors House Oyj",
48
+ "KAMUX": "Kamux Oyj",
49
+ "KCR": "Konecranes Oyj",
50
+ "KELAS": "Kesla Oyj A",
51
+ "KEMIRA": "Kemira Oyj",
52
+ "KESKOA": "Kesko Oyj A",
53
+ "KESKOB": "Kesko Oyj B",
54
+ "KHG": "KH Group Oyj",
55
+ "KNEBV": "KONE Oyj",
56
+ "KOJAMO": "Kojamo Oyj",
57
+ "KOSKI": "Koskisen Oyj",
58
+ "KREATE": "Kreate Group Oyj",
59
+ "KSLAV": "Keskisuomalainen Oyj A",
60
+ "LAMOR": "Lamor Corporation Oyj",
61
+ "LAT1V": "Lassila & Tikanoja Oyj",
62
+ "LEHTO": "Lehto Group Oyj",
63
+ "MANTA": "Mandatum",
64
+ "MARAS": "Martela Oyj A",
65
+ "MEKKO": "Marimekko Oyj",
66
+ "METSA": "Metsä Board Oyj A",
67
+ "METSB": "Metsä Board Oyj B",
68
+ "METSO": "Metso Oyj",
69
+ "MUSTI": "Musti Group Oyj",
70
+ "NDA_FI": "Nordea Bank Abp",
71
+ "NESTE": "Neste Oyj",
72
+ "NLG1V": "Nurminen Logistics Oyj",
73
+ "NOHO": "NoHo Partners Oyj",
74
+ "NOKIA": "Nokia Oyj",
75
+ "OKDAV": "Oriola Oyj A",
76
+ "OKDBV": "Oriola Oyj B",
77
+ "OLVAS": "Olvi Oyj A",
78
+ "OMASP": "Oma Säästöpankki Oyj",
79
+ "OPTOMED": "Optomed Oyj",
80
+ "ORNAV": "Orion Oyj A",
81
+ "ORNBV": "Orion Oyj B",
82
+ "ORTHEX": "Orthex Oyj",
83
+ "OUT1V": "Outokumpu Oyj",
84
+ "OVARO": "Ovaro Kiinteistösijoitus Oyj",
85
+ "PAMPALO": "Endomines Finland Oyj",
86
+ "PIHLIS": "Pihlajalinna Oyj",
87
+ "PNA1V": "Panostaja Oyj",
88
+ "PON1V": "Ponsse Oyj 1",
89
+ "PUMU": "PunaMusta Media Oyj",
90
+ "PURMO": "Purmo Group Oyj C",
91
+ "PUUILO": "Puuilo Oyj",
92
+ "QPR1V": "QPR Software Oyj",
93
+ "QTCOM": "Qt Group Oyj",
94
+ "RAIVV": "Raisio Oyj Vaihto-osake",
95
+ "RAP1V": "Rapala VMC Oyj",
96
+ "RAUTE": "Raute Oyj",
97
+ "REG1V": "Revenio Group Oyj",
98
+ "REKA": "Reka Industrial Oyj",
99
+ "RELAIS": "Relais Group Oyj",
100
+ "REMEDY": "Remedy Entertainment Oyj",
101
+ "ROBIT": "Robit Oyj",
102
+ "ROVIO": "Rovio Entertainment Oyj",
103
+ "SAGCV": "Saga Furs Oyj C",
104
+ "SAMPO": "Sampo Oyj A",
105
+ "SANOMA": "Sanoma Oyj",
106
+ "SCANFL": "Scanfil Oyj",
107
+ "SIILI": "Siili Solutions Oyj",
108
+ "SITOWS": "Sitowise Group Oyj",
109
+ "SOLTEQ": "Solteq Oyj",
110
+ "SOSI1": "Sotkamo Silver AB",
111
+ "SRV1V": "SRV Yhtiöt Oyj",
112
+ "SSABAH": "SSAB A",
113
+ "SSABBH": "SSAB B",
114
+ "SSH1V": "SSH Communications Security",
115
+ "STEAV": "Stora Enso Oyj A",
116
+ "STERV": "Stora Enso Oyj R",
117
+ "STOCKA": "Stockmann Oyj Abp",
118
+ "SUY1V": "Suominen Oyj",
119
+ "TAALA": "Taaleri Oyj",
120
+ "TALLINK": "AS Tallink Grupp FDR",
121
+ "TELIA1": "Telia Company",
122
+ "TEM1V": "Tecnotree Oyj",
123
+ "TIETO": "TietoEVRY Oyj",
124
+ "TLT1V": "Teleste Oyj",
125
+ "TNOM": "Talenom Oyj",
126
+ "TOKMAN": "Tokmanni Group Oyj",
127
+ "TRH1V": "Trainers´ House Oyj",
128
+ "TTALO": "Terveystalo Oyj",
129
+ "TULAV": "Tulikivi Oyj A",
130
+ "TYRES": "Nokian Renkaat Oyj",
131
+ "UNITED": "United Bankers Oyj",
132
+ "UPM": "UPM-Kymmene Oyj",
133
+ "UPONOR": "Uponor Oyj",
134
+ "VAIAS": "Vaisala Oyj A",
135
+ "VALMT": "Valmet Oyj",
136
+ "VALOE": "Valoe Oyj",
137
+ "VERK": "Verkkokauppa.com Oyj",
138
+ "VIK1V": "Viking Line Abp",
139
+ "WETTERI": "Wetteri Oyj",
140
+ "WITH": "WithSecure Oyj",
141
+ "WRT1V": "Wärtsilä Oyj Abp",
142
+ "WUF1V": "Wulff-Yhtiöt Oyj",
143
+ "YIT": "YIT Oyj"
144
+ }
@@ -0,0 +1,215 @@
1
+ import { DataPlugin } from '@tasenor/common-node'
2
+ import { ALL, PluginCode, Version, error } from '@tasenor/common'
3
+
4
+ interface ExchangeInfo {
5
+ code: string
6
+ name: string
7
+ aliases: string[]
8
+ file: string
9
+ type: 'stock' | 'crypto' | 'currency'
10
+ }
11
+
12
+ interface TickerInfo {
13
+ exchange: Omit<Omit<ExchangeInfo, 'file'>, 'type'>
14
+ ticker: string
15
+ name: string
16
+ aliases: string[]
17
+ }
18
+
19
+ /**
20
+ * Data sets for stock tickers and crypto currencies.
21
+ *
22
+ * Backend Queries:
23
+ *
24
+ * * (*exchange*, ALL) - List of all known exhanges.
25
+ * * (*exchange*, *code*) - Exchange data if code, name or alias match, null otherwise.
26
+ * * (*ticker*, *type*:*code*) - Lookup from all exchanges the specific ticker of the given type.
27
+ * * (*ticker*, *type*:*exchange*:*code*) - Lookup from the given exchange the specific ticker.
28
+ *
29
+ * Data sources and/or ideas:
30
+ *
31
+ * * HEL - Manually constructed from public Nasdaq Helsinki data.
32
+ * * TAL - Manually constructed from public Nasdaq Helsinki data.
33
+ * * crypto - https://github.com/crypti/cryptocurrencies/blob/master/cryptocurrencies.json
34
+ *
35
+ * ...others done manually so far (need some source and conversion tool)...
36
+ *
37
+ * Note: there is useful tool to generate from CSV in `tasenor-bookkeeper/apps/cli/bin/convert-csv-to-map.mjs`.
38
+ */
39
+ class TickerData extends DataPlugin {
40
+
41
+ // TODO: Currency name data.
42
+
43
+ constructor() {
44
+ super({ common: [], backend: ['exchange', 'ticker'] })
45
+
46
+ this.code = 'TickerData'as PluginCode
47
+ this.title = 'Asset ticker names'
48
+ this.version = '1.0.0' as Version
49
+ this.icon = '<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M16 7H5v10h11l3.55-5z" opacity=".3"/><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16zM16 17H5V7h11l3.55 5L16 17z"/></svg>'
50
+ this.releaseDate = '2024-01-15'
51
+ this.use = 'backend'
52
+ this.type = 'data'
53
+ this.description = 'List of stock tickers and exchanges and their names. Lookup services for those.'
54
+
55
+ this.languages = {
56
+ }
57
+ }
58
+
59
+ async queryBackend<T>(dataSet: string, query: typeof ALL | string): Promise<undefined | T> {
60
+ if (dataSet === 'exchange') {
61
+ return this.queryExchange(query) as T
62
+ }
63
+ if (dataSet === 'ticker' && query !== ALL) {
64
+ return this.queryTicker(query) as T
65
+ }
66
+ return undefined
67
+ }
68
+
69
+ async queryExchange(query: typeof ALL | string): Promise<undefined | ExchangeInfo | ExchangeInfo[]> {
70
+ if (query === ALL) {
71
+ // This also priority order if there is no better knowledge for ticker exchange, when queried.
72
+ return [
73
+ {
74
+ code: 'ETF',
75
+ name: 'List of ETFs',
76
+ aliases: [],
77
+ file: 'etf.json',
78
+ type: 'stock'
79
+ },
80
+ {
81
+ code: 'NYSE',
82
+ name: 'New York Stock Exchange',
83
+ aliases: [],
84
+ file: 'nyse.json',
85
+ type: 'stock'
86
+ },
87
+ {
88
+ code: 'NASDAQ',
89
+ name: 'The Nasdaq Stock Market',
90
+ aliases: ['Nasdaq', 'National Association of Securities Dealers Automated Quotations'],
91
+ file: 'nasdaq.json',
92
+ type: 'stock'
93
+ },
94
+ {
95
+ code: 'XETRA',
96
+ name: 'Deutsche Börse',
97
+ aliases: [],
98
+ file: 'xetra.json',
99
+ type: 'stock'
100
+ },
101
+ {
102
+ code: 'HEL',
103
+ name: 'Nasdaq Helsinki',
104
+ aliases: ['HE'],
105
+ file: 'hel.json',
106
+ type: 'stock'
107
+ },
108
+ {
109
+ code: 'TAL',
110
+ name: 'Nasdaq Tallinn',
111
+ aliases: ['TL'],
112
+ file: 'tal.json',
113
+ type: 'stock'
114
+ },
115
+ {
116
+ code: 'OTC',
117
+ name: 'Over the Counter',
118
+ aliases: ['PINK', 'Pink Sheets'],
119
+ file: 'otc.json',
120
+ type: 'stock'
121
+ },
122
+ {
123
+ code: 'TSX',
124
+ name: 'Toronto Stock Exchange',
125
+ aliases: ['TO'],
126
+ file: 'tsx.json',
127
+ type: 'stock'
128
+ },
129
+ {
130
+ code: 'CRYPTO',
131
+ name: 'Crypto Currency',
132
+ aliases: [],
133
+ file: 'cryptocurrencies.json',
134
+ type: 'crypto'
135
+ },
136
+ {
137
+ code: 'CURRENCY',
138
+ name: 'Currency',
139
+ aliases: [],
140
+ file: 'currencies.json',
141
+ type: 'currency'
142
+ },
143
+ ]
144
+ }
145
+ const all = await this.queryExchange(ALL) as ExchangeInfo[]
146
+ for (const ex of all) {
147
+ if (ex.code === query || ex.name === query || ex.aliases.includes(query)) {
148
+ return ex
149
+ }
150
+ }
151
+ return undefined
152
+ }
153
+
154
+ /**
155
+ * If the result is ambiquous, all results are returned.
156
+ */
157
+ async queryTicker(query: string): Promise<undefined | TickerInfo[]> {
158
+ if (query.indexOf(':') < 0) {
159
+ error(`${this.code}: Invalid query '${query}' for plugin '${this.code}'.`)
160
+ return undefined
161
+ }
162
+
163
+ const parts = query.split(':')
164
+ const type = parts[0]
165
+ const exchange = parts.length >= 3 ? parts[1] : null
166
+ const ticker = parts.length >= 3 ? parts[2] : parts[1]
167
+
168
+ // Single exchange.
169
+ if (exchange !== null) {
170
+ const ex = await this.queryExchange(exchange) as ExchangeInfo | undefined
171
+ if (ex === undefined) {
172
+ return undefined
173
+ }
174
+ if (ex.type !== type) {
175
+ error(`${this.code}: Invalid type '${type}' when queried from exchange '${exchange}'.`)
176
+ return undefined
177
+ }
178
+ // TODO: Alias support. Perhaps post-load hook and if instead of the company name we have
179
+ // ["Name of the company", "ALIAS1", "ALIAS2"] the aliases are taken from there.
180
+ const tickers: Record<string, string> = this.loadCached(ex.file)
181
+ if (tickers[ticker] === undefined) {
182
+ return undefined
183
+ }
184
+ return [{
185
+ exchange: { code: ex.code, name: ex.name, aliases: ex.aliases },
186
+ ticker,
187
+ name: tickers[ticker],
188
+ aliases: []
189
+ }]
190
+ }
191
+
192
+ // Scan all exchanges.
193
+ let result: TickerInfo[] = []
194
+ let typeFound = false
195
+ for (const ex of await this.queryExchange(ALL) as ExchangeInfo[]) {
196
+ if (ex.type === type) {
197
+ typeFound = true
198
+ const match = await this.queryTicker(`${type}:${ex.code}:${ticker}`)
199
+ if (match !== undefined) {
200
+ result = result.concat(match)
201
+ }
202
+ }
203
+ }
204
+ if (result.length) {
205
+ return result
206
+ }
207
+ if (!typeFound) {
208
+ error(`${this.code}: Cannot find any exchange to provide data for type '${type}'.`)
209
+ }
210
+
211
+ return undefined
212
+ }
213
+ }
214
+
215
+ export default TickerData