ISIN consists of CUSIP with a prepended 2-letter country code and an appended checksum digit. In my opinion, the description of the checksum algorithm from wikipedia in the time of this writing is slightly vague. Being not really clever, I was obliged to spend some time in order to understand how that should work.
For those who are impatient or just need to get their job done ASAP, bon appétit:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
/* Use at your own risk! Double test before deploying to prod! */ const reduce = require('lodash/reduce'); const reduceRight = require('lodash/reduceRight'); const getIsinFromCusip = rawValue => { const cusipAlphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; const numericString = reduce(rawValue, (acc, cur) => acc.concat(cusipAlphabet.indexOf(cur)), ''); const total = reduceRight(numericString, (acc, cur, idx, arr) => { let addend = Number.parseInt(cur, 10); addend = (arr.length - idx) % 2 ? addend * 2 : addend; addend = addend < 10 ? addend : addend - 9; return acc + addend; }, 0); return (10 - total % 10) % 10; }; let res; res = getIsinFromCusip('US931142103') console.log(`WALMART : US931142103 ${res} === 9`); res = getIsinFromCusip('US037833100') console.log(`APPLE : US037833100 ${res} === 5`); res = getIsinFromCusip('US17275R102') console.log(`CISCO : US17275R102 ${res} === 3`); res = getIsinFromCusip('US38259P508') console.log(`GOOGLE : US38259P508 ${res} === 9`); |
The key phrase in the algorithm description on wikipedia is:
Since the NSIN element can be any alpha numeric sequence (9 characters), an odd number of letters will result in an even number of digits and an even number of letters will result in an odd number of digits. For an odd number of digits, the approach in the first example is used. For an even number of digits, the approach in the second example is used
That just means that if we have CUSIP(or NSIN) which looks like that: 1234567AB (you see we have an even number of letters and therefore an odd number of digits), the first algorithm must be used! In case if we have CUSIP which looks like that 123456ABC (an odd number of letters and therefore an even number of digits), the second algorithms has to be applied.
But lucky we’re – we can get rid of this complicated ” if ” statement at all, if we just reverse the numeric string(see reduceRight in my implementation), which we got when we converted all letters to numbers, and start multiplying every other element by 2. That’s all. I hope it’ll save someone’s time!