129 lines
2.7 KiB
Go
129 lines
2.7 KiB
Go
package gofakeit
|
|
|
|
import (
|
|
"math/rand"
|
|
"strconv"
|
|
"unicode"
|
|
)
|
|
|
|
const cusipStr = upperStr + numericStr
|
|
|
|
// CUSIP
|
|
func Cusip() string {
|
|
return cusip(globalFaker.Rand)
|
|
}
|
|
|
|
func (f *Faker) Cusip() string {
|
|
return cusip(f.Rand)
|
|
}
|
|
|
|
func cusip(r *rand.Rand) string {
|
|
cusipBytes := make([]byte, 8)
|
|
for i := 0; i < len(cusipBytes); i++ {
|
|
cusipBytes[i] = byte(cusipStr[r.Intn(len(cusipStr))])
|
|
}
|
|
|
|
baseCusip := string(cusipBytes)
|
|
|
|
chkDigit := cusipChecksumDigit(baseCusip)
|
|
return baseCusip + chkDigit
|
|
}
|
|
|
|
// ISIN
|
|
func Isin() string {
|
|
return isin(globalFaker.Rand)
|
|
}
|
|
|
|
func (f *Faker) Isin() string {
|
|
return isin(f.Rand)
|
|
}
|
|
|
|
func isin(r *rand.Rand) string {
|
|
countryCode := CountryAbr()
|
|
nsin := cusip(r)
|
|
isinChkDig := isinChecksumDigit(countryCode + nsin)
|
|
return countryCode + nsin + isinChkDig
|
|
}
|
|
|
|
// cusipChecksumDigit returns the checksum digit for a CUSIP
|
|
func cusipChecksumDigit(cusip string) string {
|
|
sum := 0
|
|
for i, c := range cusip {
|
|
v := 0
|
|
if unicode.IsDigit(c) {
|
|
v = int(c - '0')
|
|
}
|
|
if unicode.IsLetter(c) {
|
|
//0-indexed ordinal position of Letter + 10
|
|
v = int(c-'A') + 10
|
|
}
|
|
if i%2 != 0 {
|
|
// Multiply odd digits by two
|
|
v = v * 2
|
|
}
|
|
|
|
sum = sum + int(v/10) + v%10
|
|
}
|
|
|
|
return strconv.Itoa((10 - (sum % 10)) % 10)
|
|
}
|
|
|
|
// isinChecksumDigit returns the checksum digit for an ISIN
|
|
func isinChecksumDigit(isin string) string {
|
|
isinDigits := make([]int, 0)
|
|
for _, c := range isin {
|
|
if unicode.IsLetter(c) {
|
|
letterVal := int(c) - 55
|
|
// Each digit is added as a separate value
|
|
isinDigits = append(isinDigits, letterVal/10)
|
|
isinDigits = append(isinDigits, letterVal%10)
|
|
}
|
|
if unicode.IsDigit(c) {
|
|
isinDigits = append(isinDigits, int(c-'0'))
|
|
}
|
|
}
|
|
|
|
oddSum := 0
|
|
evenSum := 0
|
|
|
|
// Take the per digit sum of the digitized ISIN, doubling even indexed digits
|
|
for i, d := range isinDigits {
|
|
if i%2 == 0 {
|
|
elem := 2 * d
|
|
if elem > 9 {
|
|
// If the element now has two digits, sum those digits
|
|
elem = (elem % 10) + (elem / 10)
|
|
}
|
|
evenSum += elem
|
|
} else {
|
|
oddSum += d
|
|
}
|
|
}
|
|
|
|
return strconv.Itoa((10 - (oddSum+evenSum)%10) % 10)
|
|
}
|
|
|
|
// Lookup Adds
|
|
func addFinanceLookup() {
|
|
AddFuncLookup("cusip", Info{
|
|
Display: "CUSIP",
|
|
Category: "finance",
|
|
Description: "Unique identifier for securities, especially bonds, in the United States and Canada",
|
|
Example: "38259P508",
|
|
Output: "string",
|
|
Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) {
|
|
return cusip(r), nil
|
|
},
|
|
})
|
|
AddFuncLookup("isin", Info{
|
|
Display: "ISIN",
|
|
Category: "finance",
|
|
Description: "International standard code for uniquely identifying securities worldwide",
|
|
Example: "CVLRQCZBXQ97",
|
|
Output: "string",
|
|
Generate: func(r *rand.Rand, m *MapParams, info *Info) (any, error) {
|
|
return isin(r), nil
|
|
},
|
|
})
|
|
}
|