Class: SecID::ISIN

Inherits:
Base
  • Object
show all
Includes:
Checkable, Suggestable
Defined in:
lib/sec_id/isin.rb

Overview

International Securities Identification Number (ISIN) - a 12-character alphanumeric code that uniquely identifies a security globally.

Format: 2-letter country code + 9-character NSIN + 1-digit checksum

Examples:

Validate an ISIN

SecID::ISIN.valid?('US5949181045')  #=> true

Restore checksum

SecID::ISIN.restore!('US594918104')  #=> #<SecID::ISIN>

See Also:

Constant Summary collapse

FULL_NAME =

Human-readable name of the standard.

'International Securities Identification Number'
ID_LENGTH =

Valid length(s) of a normalized identifier.

12
EXAMPLE =

A representative valid identifier.

'US5949181045'
VALID_CHARS_REGEX =

Pattern matching the identifier's permitted character set.

/\A[A-Z0-9]+\z/
ID_REGEX =

Regular expression for parsing ISIN components.

/\A
  (?<identifier>
    (?<country_code>[A-Z]{2})
    (?<nsin>[A-Z0-9]{9}))
  (?<checksum>\d)?
\z/x
CGS_COUNTRY_CODES =

Country codes that use CUSIP Global Services (CGS) for NSIN assignment.

Set.new(
  %w[
    US CA AG AI AN AR AS AW BB BL BM BO BQ BS BZ CL CO CR CW DM DO EC FM GD
    GS GU GY HN HT JM KN KY LC MF MH MP MX NI PA PE PH PR PW PY SR SV SX TT
    UM UY VC VE VG VI YT
  ]
).freeze
NSIN_COUNTRY_TYPES =

Maps country codes to their NSIN identifier types. Countries not in this map return :generic (CGS countries handled via #cgs?).

{
  # SEDOL countries (UK, Ireland, Crown Dependencies, and Overseas Territories)
  'GB' => :sedol,
  'IE' => :sedol,
  'GG' => :sedol,
  'IM' => :sedol,
  'JE' => :sedol,
  'FK' => :sedol,
  # WKN country (Germany)
  'DE' => :wkn,
  # Valoren countries (Switzerland and Liechtenstein)
  'CH' => :valoren,
  'LI' => :valoren
}.freeze

Constants included from Suggestable

Suggestable::HOMOGLYPHS, Suggestable::RANK

Constants included from Checkable

Checkable::CHAR_TO_DIGIT, Checkable::CHAR_TO_DIGITS

Constants included from Generatable

Generatable::ALPHA, Generatable::ALPHANUMERIC, Generatable::DIGITS

Constants included from Validatable

Validatable::ERROR_MAP

Constants included from Normalizable

Normalizable::SEPARATORS

Instance Attribute Summary collapse

Attributes inherited from Base

#full_id, #identifier

Instance Method Summary collapse

Methods included from Suggestable

#suggest

Methods included from Checkable

#calculate_check_digit, #check_digit, #restore, #restore!, #to_s, #valid?

Methods inherited from Base

#==, #as_json, #deconstruct_keys, detection_priority, example, full_name, has_check_digit?, has_checksum?, #hash, id_length, length_specificity, length_values, short_name, #to_h, type_key

Methods included from Validatable

#errors, #valid?, #validate, #validate!

Methods included from Normalizable

#normalize!, #normalized, #to_s, #to_str

Constructor Details

#initialize(isin) ⇒ ISIN

Returns a new instance of ISIN.

Parameters:

  • isin (String)

    the ISIN string to parse



70
71
72
73
74
75
76
# File 'lib/sec_id/isin.rb', line 70

def initialize(isin)
  isin_parts = parse isin
  @identifier = isin_parts[:identifier]
  @country_code = isin_parts[:country_code]
  @nsin = isin_parts[:nsin]
  @checksum = isin_parts[:checksum]&.to_i
end

Instance Attribute Details

#country_codeString? (readonly)

Returns the ISO 3166-1 alpha-2 country code.

Returns:

  • (String, nil)

    the ISO 3166-1 alpha-2 country code



64
65
66
# File 'lib/sec_id/isin.rb', line 64

def country_code
  @country_code
end

#nsinString? (readonly)

Returns the National Securities Identifying Number (9 characters).

Returns:

  • (String, nil)

    the National Securities Identifying Number (9 characters)



67
68
69
# File 'lib/sec_id/isin.rb', line 67

def nsin
  @nsin
end

Instance Method Details

#calculate_checksumInteger

Returns the calculated checksum (0-9).

Returns:

  • (Integer)

    the calculated checksum (0-9)

Raises:



87
88
89
90
# File 'lib/sec_id/isin.rb', line 87

def calculate_checksum
  validate_format_for_calculation!
  mod10(luhn_sum_standard(reversed_digits_multi(identifier)))
end

#cgs?Boolean

Returns true if the country code is a CGS country.

Returns:

  • (Boolean)

    true if the country code is a CGS country



110
111
112
# File 'lib/sec_id/isin.rb', line 110

def cgs?
  CGS_COUNTRY_CODES.include?(country_code)
end

#nsin_typeSymbol

Returns the type of NSIN embedded in this ISIN.

Returns:

  • (Symbol)

    :cusip, :sedol, :wkn, :valoren, or :generic



156
157
158
159
160
# File 'lib/sec_id/isin.rb', line 156

def nsin_type
  return :cusip if cgs?

  NSIN_COUNTRY_TYPES.fetch(country_code, :generic)
end

#sedol?Boolean

Returns true if the country code uses SEDOL.

Returns:

  • (Boolean)

    true if the country code uses SEDOL



115
116
117
# File 'lib/sec_id/isin.rb', line 115

def sedol?
  NSIN_COUNTRY_TYPES[country_code] == :sedol
end

#to_cusipCUSIP

Returns a new CUSIP instance.

Returns:

  • (CUSIP)

    a new CUSIP instance

Raises:



103
104
105
106
107
# File 'lib/sec_id/isin.rb', line 103

def to_cusip
  raise InvalidFormatError, "'#{country_code}' is not a CGS country code!" unless cgs?

  CUSIP.new(nsin)
end

#to_nsinCUSIP, ...

Extracts the national identifier from this ISIN.

Returns:

Raises:



166
167
168
169
170
171
172
173
174
175
176
# File 'lib/sec_id/isin.rb', line 166

def to_nsin
  raise InvalidFormatError, 'Invalid ISIN format' unless valid_format?

  case nsin_type
  when :cusip   then to_cusip
  when :sedol   then to_sedol
  when :wkn     then to_wkn
  when :valoren then to_valoren
  else nsin # :generic - return raw string
  end
end

#to_pretty_sString?

Returns:

  • (String, nil)


79
80
81
82
83
# File 'lib/sec_id/isin.rb', line 79

def to_pretty_s
  return nil unless valid?

  "#{country_code} #{nsin} #{checksum}"
end

#to_sedolSEDOL

Returns a new SEDOL instance.

Returns:

  • (SEDOL)

    a new SEDOL instance

Raises:



131
132
133
134
135
# File 'lib/sec_id/isin.rb', line 131

def to_sedol
  raise InvalidFormatError, "'#{country_code}' is not a SEDOL country code!" unless sedol?

  SEDOL.new(nsin[2..])
end

#to_valorenValoren

Returns a new Valoren instance.

Returns:

  • (Valoren)

    a new Valoren instance

Raises:



147
148
149
150
151
# File 'lib/sec_id/isin.rb', line 147

def to_valoren
  raise InvalidFormatError, "'#{country_code}' is not a Valoren country code!" unless valoren?

  Valoren.new(nsin)
end

#to_wknWKN

Returns a new WKN instance.

Returns:

  • (WKN)

    a new WKN instance

Raises:



139
140
141
142
143
# File 'lib/sec_id/isin.rb', line 139

def to_wkn
  raise InvalidFormatError, "'#{country_code}' is not a WKN country code!" unless wkn?

  WKN.new(nsin[3..])
end

#valoren?Boolean

Returns true if the country code uses Valoren.

Returns:

  • (Boolean)

    true if the country code uses Valoren



125
126
127
# File 'lib/sec_id/isin.rb', line 125

def valoren?
  NSIN_COUNTRY_TYPES[country_code] == :valoren
end

#wkn?Boolean

Returns true if the country code uses WKN.

Returns:

  • (Boolean)

    true if the country code uses WKN



120
121
122
# File 'lib/sec_id/isin.rb', line 120

def wkn?
  country_code == 'DE'
end