sec_id 5.2.0 → 6.0.0

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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +6 -0
  3. data/CHANGELOG.md +24 -0
  4. data/MIGRATION.md +101 -0
  5. data/README.md +200 -17
  6. data/lib/sec_id/active_model.rb +144 -0
  7. data/lib/sec_id/base.rb +33 -1
  8. data/lib/sec_id/bic/country_codes.rb +46 -0
  9. data/lib/sec_id/bic.rb +123 -0
  10. data/lib/sec_id/cei.rb +19 -7
  11. data/lib/sec_id/cfi/attribute_set.rb +49 -0
  12. data/lib/sec_id/cfi/classification.rb +107 -0
  13. data/lib/sec_id/cfi/field.rb +56 -0
  14. data/lib/sec_id/cfi/tables.rb +1033 -0
  15. data/lib/sec_id/cfi.rb +138 -208
  16. data/lib/sec_id/cik.rb +13 -0
  17. data/lib/sec_id/concerns/checkable.rb +2 -2
  18. data/lib/sec_id/concerns/generatable.rb +71 -0
  19. data/lib/sec_id/concerns/normalizable.rb +1 -0
  20. data/lib/sec_id/concerns/validatable.rb +14 -3
  21. data/lib/sec_id/cusip.rb +18 -7
  22. data/lib/sec_id/deep_freeze.rb +18 -0
  23. data/lib/sec_id/detector.rb +28 -7
  24. data/lib/sec_id/dti.rb +104 -0
  25. data/lib/sec_id/figi.rb +18 -0
  26. data/lib/sec_id/fisn.rb +31 -0
  27. data/lib/sec_id/iban/country_rules.rb +7 -6
  28. data/lib/sec_id/iban.rb +19 -1
  29. data/lib/sec_id/isin.rb +20 -15
  30. data/lib/sec_id/lei.rb +13 -0
  31. data/lib/sec_id/occ.rb +21 -0
  32. data/lib/sec_id/railtie.rb +14 -0
  33. data/lib/sec_id/scanner.rb +2 -6
  34. data/lib/sec_id/sedol.rb +16 -0
  35. data/lib/sec_id/valoren.rb +13 -0
  36. data/lib/sec_id/version.rb +2 -1
  37. data/lib/sec_id/wkn.rb +16 -0
  38. data/lib/sec_id.rb +29 -4
  39. data/sec_id.gemspec +11 -5
  40. data/sig/manifest.yaml +8 -0
  41. data/sig/sec_id/base.rbs +72 -0
  42. data/sig/sec_id/bic/country_codes.rbs +5 -0
  43. data/sig/sec_id/bic.rbs +30 -0
  44. data/sig/sec_id/cei.rbs +26 -0
  45. data/sig/sec_id/cfi/attribute_set.rbs +68 -0
  46. data/sig/sec_id/cfi/classification.rbs +23 -0
  47. data/sig/sec_id/cfi/field.rbs +337 -0
  48. data/sig/sec_id/cfi/tables.rbs +68 -0
  49. data/sig/sec_id/cfi.rbs +56 -0
  50. data/sig/sec_id/cik.rbs +19 -0
  51. data/sig/sec_id/concerns/checkable.rbs +41 -0
  52. data/sig/sec_id/concerns/generatable.rbs +26 -0
  53. data/sig/sec_id/concerns/normalizable.rbs +34 -0
  54. data/sig/sec_id/concerns/validatable.rbs +42 -0
  55. data/sig/sec_id/cusip.rbs +29 -0
  56. data/sig/sec_id/deep_freeze.rbs +6 -0
  57. data/sig/sec_id/detector.rbs +35 -0
  58. data/sig/sec_id/dti.rbs +27 -0
  59. data/sig/sec_id/errors.rbs +28 -0
  60. data/sig/sec_id/figi.rbs +31 -0
  61. data/sig/sec_id/fisn.rbs +24 -0
  62. data/sig/sec_id/iban/country_rules.rbs +10 -0
  63. data/sig/sec_id/iban.rbs +54 -0
  64. data/sig/sec_id/isin.rbs +40 -0
  65. data/sig/sec_id/lei.rbs +33 -0
  66. data/sig/sec_id/occ.rbs +45 -0
  67. data/sig/sec_id/scanner.rbs +46 -0
  68. data/sig/sec_id/sedol.rbs +34 -0
  69. data/sig/sec_id/valoren.rbs +29 -0
  70. data/sig/sec_id/version.rbs +3 -0
  71. data/sig/sec_id/wkn.rbs +15 -0
  72. data/sig/sec_id.rbs +58 -0
  73. metadata +55 -7
  74. data/lib/sec_id/concerns/identifier_metadata.rb +0 -56
@@ -0,0 +1,68 @@
1
+ module SecID
2
+ class CFI < Base
3
+ # ISO 10962:2021 CFI code tables.
4
+ #
5
+ # @api private
6
+ module Tables
7
+ # `{ letter => [value_symbol, value_label] }` for one attribute position.
8
+ # Values are typed loosely: the `[symbol, label]` tuple literals widen to
9
+ # `Array[Symbol | String]` under `Hash#freeze`, and `map(&:first)` on them feeds
10
+ # Field domains (Array[Symbol]) — untyped keeps both sides consistent.
11
+ type value_map = Hash[String, untyped]
12
+
13
+ # A group definition and the (loosely-typed, deeply-nested) group table.
14
+ type group_def = Hash[Symbol, untyped]
15
+
16
+ NA: nil
17
+
18
+ FORM: value_map
19
+ VOTING: value_map
20
+ OWNERSHIP: value_map
21
+ PAYMENT: value_map
22
+ PREF_REDEMPTION: value_map
23
+ PREF_INCOME: value_map
24
+ DEBT_GUARANTEE: value_map
25
+ DEBT_REDEMPTION: value_map
26
+ DEBT_INTEREST_FZVK: value_map
27
+ DEBT_INTEREST_FZV: value_map
28
+ STRUCTURED_DISTRIBUTION: value_map
29
+ STRUCTURED_UNDERLYING: value_map
30
+ WARRANT_UNDERLYING: value_map
31
+ EXERCISE_STYLE: value_map
32
+ CIV_CLOSED_OPEN: value_map
33
+ CIV_DISTRIBUTION: value_map
34
+ CIV_ASSETS: value_map
35
+ CIV_SECURITY_FULL: value_map
36
+ CIV_SECURITY_SHORT: value_map
37
+ OPTION_STYLE: value_map
38
+ OPTION_UNDERLYING: value_map
39
+ STANDARDIZED: value_map
40
+ COMMODITY_ASSETS: value_map
41
+ RETURN_TRIGGER: value_map
42
+ H_OPTION_STYLE: value_map
43
+ H_VALUATION: value_map
44
+ DELIVERY_CP: value_map
45
+ DELIVERY_PN: value_map
46
+ DELIVERY_PCN: value_map
47
+ DELIVERY_CPE: value_map
48
+ H_DELIVERY: value_map
49
+ H_DELIVERY_N: value_map
50
+ H_DELIVERY_NA: value_map
51
+ FWD_TRIGGER_CSF: value_map
52
+ FWD_TRIGGER_SF: value_map
53
+ FWD_TRIGGER_CF: value_map
54
+
55
+ # `{ letter => [category_symbol, category_label] }`. Typed loosely (widening tuple
56
+ # values; generation also indexes with nilable `.keys.sample` results).
57
+ CATEGORIES: Hash[untyped, untyped]
58
+
59
+ # `{ cat_letter => { grp_letter => group_def } }` (typed loosely, as above).
60
+ GROUPS: Hash[untyped, untyped]
61
+
62
+ ED_REDEMPTION_RULE: Hash[Symbol, untyped]
63
+
64
+ def self.ed_rule_applies?: (untyped category_code, untyped group_code, untyped letters) -> bool
65
+ def self.group: (untyped category_code, untyped group_code) -> untyped
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,56 @@
1
+ module SecID
2
+ # Classification of Financial Instruments (CFI) — ISO 10962:2021.
3
+ class CFI < Base
4
+ FULL_NAME: String
5
+ ID_LENGTH: Integer
6
+ EXAMPLE: String
7
+ VALID_CHARS_REGEX: ::Regexp
8
+ ID_REGEX: ::Regexp
9
+
10
+ # Derived semantic maps (letter => symbol).
11
+ CATEGORIES: Hash[String, Symbol]
12
+ GROUPS: Hash[String, Hash[String, Symbol]]
13
+
14
+ def self.categories: () -> Hash[String, Symbol]
15
+ def self.groups_for: (String category_code) -> Hash[String, Symbol]?
16
+
17
+ # Used unguarded as non-nil after validation (indexed into the tables); typed loosely
18
+ # so static Steep and runtime RBS::Test (which sees nil for invalid) agree.
19
+ attr_reader category_code: untyped
20
+ attr_reader group_code: untyped
21
+ attr_reader attr1: untyped
22
+ attr_reader attr2: untyped
23
+ attr_reader attr3: untyped
24
+ attr_reader attr4: untyped
25
+
26
+ def initialize: (SecID::input cfi) -> void
27
+ def category: () -> Symbol?
28
+ def group: () -> Symbol?
29
+ def decode: () -> Classification?
30
+ def to_s: () -> String
31
+
32
+ private def self.generate_body: (Random random) -> String
33
+ private def self.sample_attribute: (untyped position, Random random) -> String
34
+ private def self.enforce_ed_rule: (untyped category_code, untyped group_code, untyped letters, Random random) -> void
35
+
36
+ private
37
+
38
+ def components: () -> Hash[Symbol, untyped]
39
+ def valid_format?: () -> bool
40
+ def detect_errors: () -> Array[Symbol]
41
+ def validation_message: (Symbol code) -> String?
42
+ def valid_category?: () -> bool
43
+ def valid_group?: () -> bool
44
+ def valid_attributes?: () -> bool
45
+ # `[position, letter]` pairs; typed loosely since the tuple literals widen.
46
+ def attribute_violations: () -> Array[untyped]
47
+ def compute_attribute_violations: () -> Array[untyped]
48
+ def permitted_attribute?: (untyped position, String letter) -> bool
49
+ def ed_rule_violations: () -> Array[untyped]
50
+ def ed_rule_applies?: () -> bool
51
+ def attribute_letters: () -> Array[String]
52
+ def attribute_error_message: () -> String
53
+
54
+ @attribute_violations: Array[untyped]
55
+ end
56
+ end
@@ -0,0 +1,19 @@
1
+ module SecID
2
+ # Central Index Key (CIK).
3
+ class CIK < Base
4
+ FULL_NAME: String
5
+ # Typed loosely: `#normalized` does `ID_LENGTH.max` and Range#max is nilable in RBS.
6
+ ID_LENGTH: untyped
7
+ EXAMPLE: String
8
+ VALID_CHARS_REGEX: ::Regexp
9
+ ID_REGEX: ::Regexp
10
+
11
+ attr_reader padding: String?
12
+
13
+ def initialize: (SecID::input cik) -> void
14
+ def normalized: () -> String
15
+ def normalize!: () -> self
16
+ def to_s: () -> String
17
+ private def self.generate_body: (Random random) -> String
18
+ end
19
+ end
@@ -0,0 +1,41 @@
1
+ module SecID
2
+ # Provides check-digit validation and calculation for identifiers with a check digit.
3
+ module Checkable : SecID::Base
4
+ CHAR_TO_DIGITS: Hash[String, Integer | Array[Integer]]
5
+ CHAR_TO_DIGIT: Hash[String, Integer]
6
+
7
+ def self.included: (Module base) -> void
8
+
9
+ attr_reader check_digit: (Integer | String)?
10
+
11
+ # Class methods added when Checkable is included.
12
+ module ClassMethods : SecID::_IdentifierClass
13
+ def restore: (SecID::input id_without_check_digit) -> String
14
+ def restore!: (SecID::input id_without_check_digit) -> Base
15
+ def check_digit: (SecID::input id) -> (Integer | String)
16
+ end
17
+
18
+ def valid?: () -> bool
19
+ def restore: () -> String
20
+ def restore!: () -> self
21
+ def calculate_check_digit: () -> (Integer | String)
22
+ def to_s: () -> String
23
+
24
+ private
25
+
26
+ def luhn_sum_double_add_double: (Array[Integer] digits) -> Integer
27
+ def luhn_sum_indexed: (Array[Integer] digits) -> Integer
28
+ def luhn_sum_standard: (Array[Integer] digits) -> Integer
29
+ def reversed_digits_single: (untyped id) -> Array[Integer]
30
+ def reversed_digits_multi: (untyped id) -> Array[Integer]
31
+ def error_codes: () -> Array[Symbol]
32
+ def check_digit_width: () -> Integer
33
+ def validation_message: (Symbol code) -> String?
34
+ def validate_format_for_calculation!: () -> void
35
+ def mod10: (Integer sum) -> Integer
36
+ def div10mod10: (Integer number) -> Integer
37
+ def mod97: (String numeric_string) -> Integer
38
+
39
+ @check_digit: (Integer | String)?
40
+ end
41
+ end
@@ -0,0 +1,26 @@
1
+ module SecID
2
+ # Provides generation of new, format-valid identifiers for use as test fixtures.
3
+ module Generatable
4
+ ALPHA: Array[String]
5
+ DIGITS: Array[String]
6
+ ALPHANUMERIC: Array[String]
7
+
8
+ def self.included: (Module base) -> void
9
+
10
+ # The class-object surface Generatable's methods call once extended.
11
+ interface _GeneratableClass
12
+ def new: (SecID::input) -> Base
13
+ def has_check_digit?: () -> bool
14
+ end
15
+
16
+ # Class methods added when Generatable is included.
17
+ module ClassMethods : SecID::Generatable::_GeneratableClass
18
+ def generate: (?random: Random) -> Base
19
+
20
+ private
21
+
22
+ def generate_body: (Random _random) -> String
23
+ def random_string: (Array[String] charset, Integer length, random: Random) -> String
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,34 @@
1
+ module SecID
2
+ # Host surface Normalizable's instance methods call through `self`.
3
+ interface _NormalizableHost
4
+ def identifier: () -> String?
5
+ def valid?: () -> bool
6
+ def validate!: () -> void
7
+ end
8
+
9
+ # Provides normalization and display-formatting methods for identifier types.
10
+ #
11
+ # `ClassMethods#normalize`/`#to_pretty_s` read `self::SEPARATORS` (polymorphic
12
+ # constant dispatch); the extend-module `self` can't be typed as `singleton(Base)`,
13
+ # so that access resolves via the relaxed UnknownConstant diagnostic (see Steepfile).
14
+ module Normalizable : SecID::_NormalizableHost
15
+ SEPARATORS: ::Regexp
16
+
17
+ def self.included: (Module base) -> void
18
+
19
+ # Class methods added when Normalizable is included.
20
+ module ClassMethods : SecID::_IdentifierClass
21
+ def normalize: (_ToS id) -> String
22
+ def to_pretty_s: (_ToS id) -> String?
23
+ end
24
+
25
+ def normalized: () -> String
26
+ alias normalize normalized
27
+ def normalize!: () -> self
28
+ def to_pretty_s: () -> String?
29
+ def to_s: () -> String
30
+ def to_str: () -> String
31
+
32
+ @full_id: String
33
+ end
34
+ end
@@ -0,0 +1,42 @@
1
+ module SecID
2
+ # Host surface Validatable's instance methods call through `self`. The refined
3
+ # `class` return lets `self.class::ID_LENGTH` and the class metadata resolve.
4
+ interface _ValidatableHost
5
+ def identifier: () -> String?
6
+ def full_id: () -> String
7
+ def class: () -> singleton(SecID::Base)
8
+ end
9
+
10
+ # Provides validation methods for identifier types.
11
+ module Validatable : SecID::_ValidatableHost
12
+ ERROR_MAP: Hash[Symbol, singleton(SecID::Error)]
13
+
14
+ def self.included: (Module base) -> void
15
+
16
+ # Class methods added when Validatable is included.
17
+ module ClassMethods : SecID::_IdentifierClass
18
+ def valid?: (SecID::input id) -> bool
19
+ def validate: (SecID::input id) -> Base
20
+ def validate!: (SecID::input id) -> Base
21
+ def error_class_for: (Symbol code) -> singleton(SecID::Error)
22
+ end
23
+
24
+ def valid?: () -> bool
25
+ def validate: () -> self
26
+ def errors: () -> Errors
27
+ def validate!: () -> self
28
+
29
+ private
30
+
31
+ def valid_format?: () -> bool
32
+ def error_codes: () -> Array[Symbol]
33
+ def detect_errors: () -> Array[Symbol]
34
+ def valid_length?: () -> bool
35
+ def valid_characters?: () -> bool
36
+ def check_digit_width: () -> Integer
37
+ def validation_message: (Symbol code) -> String?
38
+ def build_error: (Symbol code, String? message) -> Errors::detail
39
+
40
+ @errors: Errors
41
+ end
42
+ end
@@ -0,0 +1,29 @@
1
+ module SecID
2
+ # Committee on Uniform Securities Identification Procedures (CUSIP).
3
+ class CUSIP < Base
4
+ include Checkable
5
+ extend Checkable::ClassMethods
6
+
7
+ FULL_NAME: String
8
+ ID_LENGTH: Integer
9
+ EXAMPLE: String
10
+ VALID_CHARS_REGEX: ::Regexp
11
+ ID_REGEX: ::Regexp
12
+
13
+ # `#cins?` indexes `cusip6[0]` (nilable even for a non-nil String); typed loosely.
14
+ attr_reader cusip6: untyped
15
+ attr_reader issue: String?
16
+
17
+ def initialize: (SecID::input cusip) -> void
18
+ def to_pretty_s: () -> String?
19
+ def calculate_check_digit: () -> Integer
20
+ def self.check_digit: (SecID::input id) -> Integer
21
+ private def self.generate_body: (Random random) -> String
22
+ def to_isin: (String country_code) -> ISIN
23
+ def cins?: () -> bool
24
+
25
+ private
26
+
27
+ def components: () -> Hash[Symbol, untyped]
28
+ end
29
+ end
@@ -0,0 +1,6 @@
1
+ module SecID
2
+ # Recursively freezes a nested structure of Hashes and Arrays and returns it.
3
+ module DeepFreeze
4
+ def self.call: (untyped object) -> untyped
5
+ end
6
+ end
@@ -0,0 +1,35 @@
1
+ module SecID
2
+ # Detects which identifier types match a given string.
3
+ #
4
+ # @api private
5
+ class Detector
6
+ type priority = Array[Integer | Float | nil]
7
+
8
+ def initialize: (Array[singleton(Base)] identifier_list) -> void
9
+ def call: (SecID::input str) -> Array[Symbol]
10
+ def matches?: (SecID::input str) -> bool
11
+ def first_match: (SecID::input str) -> Base?
12
+
13
+ private
14
+
15
+ def filter_candidates: (String upcased) -> Array[singleton(Base)]
16
+ def validate_and_sort: (String input, Array[untyped] candidates) -> Array[Symbol]
17
+ def precompute: () -> void
18
+ def build_discriminator_sets: () -> void
19
+ def build_length_table: () -> void
20
+ def build_priority_table: () -> void
21
+ def build_key_table: () -> void
22
+ def stage1_special_chars: (String upcased) -> Array[singleton(Base)]?
23
+ def stage2_length: (Integer length) -> Array[singleton(Base)]
24
+ def stage3_charset: (String upcased, Array[singleton(Base)] candidates) -> Array[singleton(Base)]
25
+ def accepts_char?: (singleton(Base) klass, String char) -> bool
26
+
27
+ @classes: Array[singleton(Base)]
28
+ @slash_types: Array[singleton(Base)]
29
+ @space_only_types: Array[singleton(Base)]
30
+ @special_types: Array[singleton(Base)]
31
+ @candidates_by_length: Hash[Integer, Array[singleton(Base)]]
32
+ @priority_for: Hash[singleton(Base), priority]
33
+ @key_for: Hash[singleton(Base), Symbol]
34
+ end
35
+ end
@@ -0,0 +1,27 @@
1
+ module SecID
2
+ # Digital Token Identifier (DTI, ISO 24165).
3
+ class DTI < Base
4
+ include Checkable
5
+ extend Checkable::ClassMethods
6
+
7
+ FULL_NAME: String
8
+ ID_LENGTH: Integer
9
+ EXAMPLE: String
10
+ VALID_CHARS_REGEX: ::Regexp
11
+ ID_REGEX: ::Regexp
12
+ ALPHABET: Array[String]
13
+ ALPHABET_VALUE: Hash[String, Integer]
14
+ GENERATE_CHARSET: Array[String]
15
+ GRANDFATHERED_CODES: Hash[String, String]
16
+
17
+ def initialize: (SecID::input dti) -> void
18
+ def calculate_check_digit: () -> String
19
+ private def self.generate_body: (Random random) -> String
20
+
21
+ private
22
+
23
+ def components: () -> Hash[Symbol, untyped]
24
+ def grandfathered_check_digit: (untyped base) -> String?
25
+ def iso7064_mod31_30_check_char: (untyped base) -> String
26
+ end
27
+ end
@@ -0,0 +1,28 @@
1
+ module SecID
2
+ # Immutable value object representing validation errors for an identifier.
3
+ class Errors
4
+ # A single error entry. `{ error:, message: }` in the source, but `Hash#freeze`
5
+ # in `build_error` widens the record literal, so it is modelled as a Hash.
6
+ type detail = Hash[Symbol, untyped]
7
+
8
+ attr_reader details: Array[detail]
9
+
10
+ def initialize: (Array[detail] errors) -> void
11
+
12
+ def messages: () -> Array[String?]
13
+
14
+ def any?: () -> bool
15
+
16
+ def empty?: () -> bool
17
+
18
+ alias none? empty?
19
+
20
+ def size: () -> Integer
21
+
22
+ def each: () { (detail) -> void } -> Array[detail]
23
+
24
+ def to_a: () -> Array[String?]
25
+
26
+ def as_json: (*untyped) -> Array[detail]
27
+ end
28
+ end
@@ -0,0 +1,31 @@
1
+ module SecID
2
+ # Financial Instrument Global Identifier (FIGI).
3
+ class FIGI < Base
4
+ include Checkable
5
+ extend Checkable::ClassMethods
6
+
7
+ FULL_NAME: String
8
+ ID_LENGTH: Integer
9
+ EXAMPLE: String
10
+ VALID_CHARS_REGEX: ::Regexp
11
+ ID_REGEX: ::Regexp
12
+ RESTRICTED_PREFIXES: Set[String]
13
+ GENERATE_CHARSET: Array[String]
14
+
15
+ attr_reader prefix: String?
16
+ attr_reader random_part: String?
17
+
18
+ def initialize: (SecID::input figi) -> void
19
+ def to_pretty_s: () -> String?
20
+ def calculate_check_digit: () -> Integer
21
+ def self.check_digit: (SecID::input id) -> Integer
22
+ private def self.generate_body: (Random random) -> String
23
+
24
+ private
25
+
26
+ def components: () -> Hash[Symbol, untyped]
27
+ def valid_format?: () -> bool
28
+ def detect_errors: () -> Array[Symbol]
29
+ def validation_message: (Symbol code) -> String?
30
+ end
31
+ end
@@ -0,0 +1,24 @@
1
+ module SecID
2
+ # Financial Instrument Short Name (FISN).
3
+ class FISN < Base
4
+ FULL_NAME: String
5
+ ID_LENGTH: ::Range[Integer]
6
+ EXAMPLE: String
7
+ VALID_CHARS_REGEX: ::Regexp
8
+ SEPARATORS: ::Regexp
9
+ ID_REGEX: ::Regexp
10
+ FISN_CHARSET: Array[String]
11
+
12
+ attr_reader issuer: String?
13
+ attr_reader description: String?
14
+
15
+ def initialize: (SecID::input fisn) -> void
16
+ def to_s: () -> String
17
+ private def self.generate_body: (Random random) -> String
18
+ private def self.generate_part: (Integer length, Random random) -> String
19
+
20
+ private
21
+
22
+ def components: () -> Hash[Symbol, untyped]
23
+ end
24
+ end
@@ -0,0 +1,10 @@
1
+ module SecID
2
+ class IBAN < Base
3
+ # `{ length: Integer, format: Regexp, components?: {name => [start, length]} }`, but
4
+ # the nested literal infers as a broad Hash, so it is modelled loosely.
5
+ type rule = Hash[Symbol, untyped]
6
+
7
+ COUNTRY_RULES: Hash[String, rule]
8
+ LENGTH_ONLY_COUNTRIES: Hash[String, Integer]
9
+ end
10
+ end
@@ -0,0 +1,54 @@
1
+ module SecID
2
+ # International Bank Account Number (IBAN).
3
+ class IBAN < Base
4
+ include Checkable
5
+ extend Checkable::ClassMethods
6
+
7
+ FULL_NAME: String
8
+ ID_LENGTH: ::Range[Integer]
9
+ EXAMPLE: String
10
+ VALID_CHARS_REGEX: ::Regexp
11
+ ID_REGEX: ::Regexp
12
+ NUMERIC_COUNTRY_RULES: Array[[String, rule]]
13
+
14
+ def self.supported_countries: () -> Array[String]
15
+
16
+ # country_code/bban are used unguarded after validation; typed loosely so static
17
+ # Steep and runtime RBS::Test (which sees nil for invalid) agree.
18
+ attr_reader country_code: untyped
19
+ attr_reader bban: untyped
20
+ # Optional BBAN components; typed loosely so `#components` (which conditionally
21
+ # assigns them into an inferred hash) type-checks.
22
+ attr_reader bank_code: untyped
23
+ attr_reader branch_code: untyped
24
+ attr_reader account_number: untyped
25
+ attr_reader national_check: untyped
26
+
27
+ def initialize: (SecID::input iban) -> void
28
+ def restore: () -> String
29
+ def calculate_check_digit: () -> Integer
30
+ def self.check_digit: (SecID::input id) -> Integer
31
+ private def self.generate_body: (Random random) -> String
32
+ def valid_bban_format?: () -> bool
33
+ def country_rule: () -> rule?
34
+ def known_country?: () -> bool
35
+ def to_s: () -> String
36
+ def to_pretty_s: () -> String?
37
+
38
+ private
39
+
40
+ def components: () -> Hash[Symbol, untyped]
41
+ def check_digit_width: () -> Integer
42
+ def valid_format?: () -> bool
43
+ def detect_errors: () -> Array[Symbol]
44
+ def validation_message: (Symbol code) -> String?
45
+ def extract_check_digit_and_bban: (String rest) -> void
46
+ def expected_bban_length_for_country: () -> Integer?
47
+ def check_digits?: (untyped rest, Integer? expected_bban_length) -> bool
48
+ def extract_bban_components: () -> void
49
+ def valid_bban_length_only?: () -> bool
50
+ def numeric_string_for_check: () -> String
51
+
52
+ self.@supported_countries: Array[String]
53
+ end
54
+ end
@@ -0,0 +1,40 @@
1
+ module SecID
2
+ # International Securities Identification Number (ISIN).
3
+ class ISIN < Base
4
+ include Checkable
5
+ extend Checkable::ClassMethods
6
+
7
+ FULL_NAME: String
8
+ ID_LENGTH: Integer
9
+ EXAMPLE: String
10
+ VALID_CHARS_REGEX: ::Regexp
11
+ ID_REGEX: ::Regexp
12
+ CGS_COUNTRY_CODES: Set[String]
13
+ NSIN_COUNTRY_TYPES: Hash[String, Symbol]
14
+
15
+ # Used unguarded as non-nil after validation (indexed/looked-up); typed loosely
16
+ # so both static Steep and runtime RBS::Test (which sees nil for invalid) agree.
17
+ attr_reader country_code: untyped
18
+ attr_reader nsin: untyped
19
+
20
+ def initialize: (SecID::input isin) -> void
21
+ def to_pretty_s: () -> String?
22
+ def calculate_check_digit: () -> Integer
23
+ def self.check_digit: (SecID::input id) -> Integer
24
+ private def self.generate_body: (Random random) -> String
25
+ def to_cusip: () -> CUSIP
26
+ def cgs?: () -> bool
27
+ def sedol?: () -> bool
28
+ def wkn?: () -> bool
29
+ def valoren?: () -> bool
30
+ def to_sedol: () -> SEDOL
31
+ def to_wkn: () -> WKN
32
+ def to_valoren: () -> Valoren
33
+ def nsin_type: () -> Symbol
34
+ def to_nsin: () -> (CUSIP | SEDOL | WKN | Valoren | String | nil)
35
+
36
+ private
37
+
38
+ def components: () -> Hash[Symbol, untyped]
39
+ end
40
+ end
@@ -0,0 +1,33 @@
1
+ module SecID
2
+ # Legal Entity Identifier (LEI).
3
+ class LEI < Base
4
+ include Checkable
5
+ extend Checkable::ClassMethods
6
+
7
+ FULL_NAME: String
8
+ ID_LENGTH: Integer
9
+ EXAMPLE: String
10
+ VALID_CHARS_REGEX: ::Regexp
11
+ ID_REGEX: ::Regexp
12
+
13
+ attr_reader lou_id: String?
14
+ attr_reader reserved: String?
15
+ attr_reader entity_id: String?
16
+
17
+ # Used unguarded after validation (`#numeric_identifier`); typed loosely so static
18
+ # Steep and runtime RBS::Test (which sees nil for invalid) agree.
19
+ def identifier: () -> untyped
20
+
21
+ def initialize: (SecID::input lei) -> void
22
+ def to_pretty_s: () -> String?
23
+ def calculate_check_digit: () -> Integer
24
+ def self.check_digit: (SecID::input id) -> Integer
25
+ private def self.generate_body: (Random random) -> String
26
+
27
+ private
28
+
29
+ def components: () -> Hash[Symbol, untyped]
30
+ def check_digit_width: () -> Integer
31
+ def numeric_identifier: () -> String
32
+ end
33
+ end
@@ -0,0 +1,45 @@
1
+ module SecID
2
+ # OCC Option Symbol.
3
+ class OCC < Base
4
+ FULL_NAME: String
5
+ ID_LENGTH: ::Range[Integer]
6
+ EXAMPLE: String
7
+ VALID_CHARS_REGEX: ::Regexp
8
+ SEPARATORS: ::Regexp
9
+ ID_REGEX: ::Regexp
10
+
11
+ # Used unguarded as non-nil after validation; typed loosely so static Steep and
12
+ # runtime RBS::Test (which sees nil for invalid) agree.
13
+ attr_reader underlying: untyped
14
+ attr_reader date_str: untyped
15
+ attr_reader type: untyped
16
+ attr_reader strike_mills: untyped
17
+
18
+ def self.generate: (?random: Random) -> OCC
19
+ # build/compose accept any Numeric strike (e.g. Rational) and a String or Symbol type.
20
+ def self.build: (underlying: untyped, date: String | Date, type: untyped, strike: Integer | Float | Rational | String) -> OCC
21
+ def self.compose_symbol: (untyped underlying, untyped date_str, untyped type, untyped strike_mills) -> String
22
+
23
+ def initialize: (SecID::input symbol) -> void
24
+ def normalized: () -> String
25
+ def valid?: () -> bool
26
+ def date: () -> Date?
27
+ alias date_obj date
28
+ def strike: () -> Float?
29
+ def to_s: () -> String
30
+ def to_pretty_s: () -> String?
31
+
32
+ private
33
+
34
+ # `Integer | Float | Rational` (not `Numeric`, which lacks `#*` in RBS) so the
35
+ # `when Numeric then strike * 1000` branch type-checks; String is the 8-digit form.
36
+ def self.normalize_strike_mills: (Integer | Float | Rational | String strike) -> String
37
+
38
+ def components: () -> Hash[Symbol, untyped]
39
+ def error_codes: () -> Array[Symbol]
40
+ def validation_message: (Symbol code) -> String?
41
+
42
+ @date: Date?
43
+ @strike: Float?
44
+ end
45
+ end