sec_id 5.2.0 → 6.1.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.
- checksums.yaml +4 -4
- data/.yardopts +6 -0
- data/CHANGELOG.md +31 -0
- data/MIGRATION.md +101 -0
- data/README.md +245 -17
- data/lib/sec_id/active_model.rb +144 -0
- data/lib/sec_id/base.rb +64 -2
- data/lib/sec_id/bic/country_codes.rb +46 -0
- data/lib/sec_id/bic.rb +123 -0
- data/lib/sec_id/cei.rb +19 -7
- data/lib/sec_id/cfi/attribute_set.rb +49 -0
- data/lib/sec_id/cfi/classification.rb +107 -0
- data/lib/sec_id/cfi/field.rb +56 -0
- data/lib/sec_id/cfi/tables.rb +1033 -0
- data/lib/sec_id/cfi.rb +138 -208
- data/lib/sec_id/cik.rb +13 -0
- data/lib/sec_id/concerns/checkable.rb +2 -2
- data/lib/sec_id/concerns/generatable.rb +71 -0
- data/lib/sec_id/concerns/normalizable.rb +1 -0
- data/lib/sec_id/concerns/validatable.rb +14 -3
- data/lib/sec_id/cusip.rb +18 -7
- data/lib/sec_id/deep_freeze.rb +18 -0
- data/lib/sec_id/detector.rb +29 -31
- data/lib/sec_id/dti.rb +104 -0
- data/lib/sec_id/figi.rb +18 -0
- data/lib/sec_id/fisn.rb +31 -0
- data/lib/sec_id/iban/country_rules.rb +7 -6
- data/lib/sec_id/iban.rb +19 -1
- data/lib/sec_id/isin.rb +20 -15
- data/lib/sec_id/lei.rb +13 -0
- data/lib/sec_id/occ.rb +21 -0
- data/lib/sec_id/railtie.rb +14 -0
- data/lib/sec_id/scanner.rb +18 -27
- data/lib/sec_id/sedol.rb +16 -0
- data/lib/sec_id/valoren.rb +13 -0
- data/lib/sec_id/version.rb +2 -1
- data/lib/sec_id/wkn.rb +16 -0
- data/lib/sec_id.rb +31 -7
- data/sec_id.gemspec +11 -5
- data/sig/manifest.yaml +8 -0
- data/sig/sec_id/base.rbs +78 -0
- data/sig/sec_id/bic/country_codes.rbs +5 -0
- data/sig/sec_id/bic.rbs +30 -0
- data/sig/sec_id/cei.rbs +26 -0
- data/sig/sec_id/cfi/attribute_set.rbs +68 -0
- data/sig/sec_id/cfi/classification.rbs +23 -0
- data/sig/sec_id/cfi/field.rbs +337 -0
- data/sig/sec_id/cfi/tables.rbs +68 -0
- data/sig/sec_id/cfi.rbs +56 -0
- data/sig/sec_id/cik.rbs +19 -0
- data/sig/sec_id/concerns/checkable.rbs +41 -0
- data/sig/sec_id/concerns/generatable.rbs +26 -0
- data/sig/sec_id/concerns/normalizable.rbs +34 -0
- data/sig/sec_id/concerns/validatable.rbs +42 -0
- data/sig/sec_id/cusip.rbs +29 -0
- data/sig/sec_id/deep_freeze.rbs +6 -0
- data/sig/sec_id/detector.rbs +29 -0
- data/sig/sec_id/dti.rbs +27 -0
- data/sig/sec_id/errors.rbs +28 -0
- data/sig/sec_id/figi.rbs +31 -0
- data/sig/sec_id/fisn.rbs +24 -0
- data/sig/sec_id/iban/country_rules.rbs +10 -0
- data/sig/sec_id/iban.rbs +54 -0
- data/sig/sec_id/isin.rbs +40 -0
- data/sig/sec_id/lei.rbs +33 -0
- data/sig/sec_id/occ.rbs +45 -0
- data/sig/sec_id/scanner.rbs +44 -0
- data/sig/sec_id/sedol.rbs +34 -0
- data/sig/sec_id/valoren.rbs +29 -0
- data/sig/sec_id/version.rbs +3 -0
- data/sig/sec_id/wkn.rbs +15 -0
- data/sig/sec_id.rbs +58 -0
- metadata +55 -7
- data/lib/sec_id/concerns/identifier_metadata.rb +0 -56
data/lib/sec_id/valoren.rb
CHANGED
|
@@ -17,9 +17,13 @@ module SecID
|
|
|
17
17
|
# @example Normalize a Valoren to 9 digits
|
|
18
18
|
# SecID::Valoren.normalize('3886335') #=> '003886335'
|
|
19
19
|
class Valoren < Base
|
|
20
|
+
# Human-readable name of the standard.
|
|
20
21
|
FULL_NAME = 'Valoren Number'
|
|
22
|
+
# Valid length(s) of a normalized identifier.
|
|
21
23
|
ID_LENGTH = (5..9)
|
|
24
|
+
# A representative valid identifier.
|
|
22
25
|
EXAMPLE = '3886335'
|
|
26
|
+
# Pattern matching the identifier's permitted character set.
|
|
23
27
|
VALID_CHARS_REGEX = /\A[0-9]+\z/
|
|
24
28
|
|
|
25
29
|
# Regular expression for parsing Valoren components.
|
|
@@ -77,5 +81,14 @@ module SecID
|
|
|
77
81
|
def to_s
|
|
78
82
|
full_id
|
|
79
83
|
end
|
|
84
|
+
|
|
85
|
+
# Generates a random Valoren: an integer rendered without leading zeros.
|
|
86
|
+
#
|
|
87
|
+
# @param random [Random] source of randomness
|
|
88
|
+
# @return [String] a 5-9 digit Valoren
|
|
89
|
+
def self.generate_body(random)
|
|
90
|
+
random.rand(10_000..999_999_999).to_s
|
|
91
|
+
end
|
|
92
|
+
private_class_method :generate_body
|
|
80
93
|
end
|
|
81
94
|
end
|
data/lib/sec_id/version.rb
CHANGED
data/lib/sec_id/wkn.rb
CHANGED
|
@@ -13,9 +13,13 @@ module SecID
|
|
|
13
13
|
# SecID::WKN.valid?('514000') #=> true
|
|
14
14
|
# SecID::WKN.valid?('CBK100') #=> true
|
|
15
15
|
class WKN < Base
|
|
16
|
+
# Human-readable name of the standard.
|
|
16
17
|
FULL_NAME = 'Wertpapierkennnummer'
|
|
18
|
+
# Valid length(s) of a normalized identifier.
|
|
17
19
|
ID_LENGTH = 6
|
|
20
|
+
# A representative valid identifier.
|
|
18
21
|
EXAMPLE = '514000'
|
|
22
|
+
# Pattern matching the identifier's permitted character set.
|
|
19
23
|
VALID_CHARS_REGEX = /\A[0-9A-HJ-NP-Z]+\z/
|
|
20
24
|
|
|
21
25
|
# Regular expression for parsing WKN components.
|
|
@@ -24,6 +28,9 @@ module SecID
|
|
|
24
28
|
(?<identifier>[0-9A-HJ-NP-Z]{6})
|
|
25
29
|
\z/x
|
|
26
30
|
|
|
31
|
+
# Characters valid in a WKN (alphanumeric excluding I and O).
|
|
32
|
+
GENERATE_CHARSET = ALPHANUMERIC.grep(VALID_CHARS_REGEX).freeze
|
|
33
|
+
|
|
27
34
|
# @param wkn [String] the WKN string to parse
|
|
28
35
|
def initialize(wkn)
|
|
29
36
|
wkn_parts = parse(wkn)
|
|
@@ -40,5 +47,14 @@ module SecID
|
|
|
40
47
|
|
|
41
48
|
ISIN.new("#{country_code}000#{identifier}").restore!
|
|
42
49
|
end
|
|
50
|
+
|
|
51
|
+
# Generates a random WKN: 6 characters excluding I and O.
|
|
52
|
+
#
|
|
53
|
+
# @param random [Random] source of randomness
|
|
54
|
+
# @return [String] a 6-character WKN
|
|
55
|
+
def self.generate_body(random)
|
|
56
|
+
random_string(GENERATE_CHARSET, 6, random: random)
|
|
57
|
+
end
|
|
58
|
+
private_class_method :generate_body
|
|
43
59
|
end
|
|
44
60
|
end
|
data/lib/sec_id.rb
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
require 'sec_id/version'
|
|
4
4
|
|
|
5
|
+
# Toolkit for securities identifiers — validate, normalize, parse, detect, convert,
|
|
6
|
+
# generate, and classify ISIN, CUSIP, CEI, SEDOL, FIGI, LEI, IBAN, CIK, OCC, WKN,
|
|
7
|
+
# Valoren, CFI, FISN, BIC, and DTI.
|
|
8
|
+
#
|
|
9
|
+
# @see https://github.com/svyatov/sec_id
|
|
5
10
|
module SecID
|
|
6
11
|
# Base error class for all SecID errors.
|
|
7
12
|
class Error < StandardError; end
|
|
@@ -52,7 +57,7 @@ module SecID
|
|
|
52
57
|
# @return [Boolean]
|
|
53
58
|
# @raise [ArgumentError] if any key in types is unknown
|
|
54
59
|
def valid?(str, types: nil)
|
|
55
|
-
return
|
|
60
|
+
return detector.matches?(str) if types.nil?
|
|
56
61
|
|
|
57
62
|
types.any? { |key| self[key].valid?(str) }
|
|
58
63
|
end
|
|
@@ -80,7 +85,7 @@ module SecID
|
|
|
80
85
|
# @return [Hash] hash with :input and :candidates keys
|
|
81
86
|
def explain(str, types: nil)
|
|
82
87
|
input = str.to_s.strip
|
|
83
|
-
target_keys = types || identifier_list.map
|
|
88
|
+
target_keys = types || identifier_list.map(&:type_key)
|
|
84
89
|
candidates = target_keys.map do |key|
|
|
85
90
|
instance = self[key].new(input)
|
|
86
91
|
{ type: key, valid: instance.valid?, errors: instance.errors.details }
|
|
@@ -120,20 +125,32 @@ module SecID
|
|
|
120
125
|
result || raise(InvalidFormatError, parse_error_message(str, types))
|
|
121
126
|
end
|
|
122
127
|
|
|
128
|
+
# Generates a new, format-valid identifier instance of the given type.
|
|
129
|
+
#
|
|
130
|
+
# @note Generated identifiers are valid in format only — they are not real,
|
|
131
|
+
# registered securities.
|
|
132
|
+
#
|
|
133
|
+
# @param key [Symbol] identifier type (e.g. :isin, :cusip)
|
|
134
|
+
# @param random [Random] seedable source for reproducible output
|
|
135
|
+
# @return [SecID::Base] a generated, format-valid instance of the type mapped to `key`
|
|
136
|
+
# (e.g. {SecID::ISIN} for `:isin`)
|
|
137
|
+
# @raise [ArgumentError] if key is unknown
|
|
138
|
+
def generate(key, random: Random.new)
|
|
139
|
+
self[key].generate(random: random)
|
|
140
|
+
end
|
|
141
|
+
|
|
123
142
|
private
|
|
124
143
|
|
|
125
144
|
# @return [void]
|
|
126
145
|
def register_identifier(klass)
|
|
127
|
-
|
|
128
|
-
identifier_map[key] = klass
|
|
146
|
+
identifier_map[klass.type_key] = klass
|
|
129
147
|
identifier_list << klass
|
|
130
148
|
@detector = nil
|
|
131
149
|
@scanner = nil
|
|
132
150
|
end
|
|
133
151
|
|
|
134
152
|
def parse_any(str)
|
|
135
|
-
|
|
136
|
-
key && self[key].new(str)
|
|
153
|
+
detector.first_match(str)
|
|
137
154
|
end
|
|
138
155
|
|
|
139
156
|
def parse_from(str, types)
|
|
@@ -178,11 +195,12 @@ module SecID
|
|
|
178
195
|
end
|
|
179
196
|
end
|
|
180
197
|
|
|
198
|
+
require 'sec_id/deep_freeze'
|
|
181
199
|
require 'sec_id/errors'
|
|
182
|
-
require 'sec_id/concerns/identifier_metadata'
|
|
183
200
|
require 'sec_id/concerns/normalizable'
|
|
184
201
|
require 'sec_id/concerns/validatable'
|
|
185
202
|
require 'sec_id/concerns/checkable'
|
|
203
|
+
require 'sec_id/concerns/generatable'
|
|
186
204
|
require 'sec_id/base'
|
|
187
205
|
require 'sec_id/detector'
|
|
188
206
|
require 'sec_id/scanner'
|
|
@@ -199,3 +217,9 @@ require 'sec_id/valoren'
|
|
|
199
217
|
require 'sec_id/cei'
|
|
200
218
|
require 'sec_id/cfi'
|
|
201
219
|
require 'sec_id/fisn'
|
|
220
|
+
require 'sec_id/bic'
|
|
221
|
+
require 'sec_id/dti'
|
|
222
|
+
|
|
223
|
+
# Auto-activate the ActiveModel validator inside Rails; a no-op everywhere else (keeps the
|
|
224
|
+
# default require zero-dependency). See SecID::Railtie and lib/sec_id/active_model.rb.
|
|
225
|
+
require 'sec_id/railtie' if defined?(Rails::Railtie)
|
data/sec_id.gemspec
CHANGED
|
@@ -10,19 +10,25 @@ Gem::Specification.new do |spec|
|
|
|
10
10
|
spec.authors = ['Leonid Svyatov']
|
|
11
11
|
spec.email = ['leonid@svyatov.ru']
|
|
12
12
|
|
|
13
|
-
spec.summary = 'A Ruby toolkit for securities identifiers — validate, parse, normalize, detect,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
'
|
|
13
|
+
spec.summary = 'A Ruby toolkit for securities identifiers — validate, parse, normalize, detect, convert, ' \
|
|
14
|
+
'generate, and classify.'
|
|
15
|
+
spec.description = 'Validate, normalize, parse, convert, generate, and classify securities identifiers. ' \
|
|
16
|
+
'Auto-detect identifier type from any string. Calculate and restore check digits. Generate ' \
|
|
17
|
+
'format-valid identifiers as test fixtures. Decode CFI codes to full ISO 10962:2021 ' \
|
|
18
|
+
'classifications. Includes an opt-in ActiveModel/Rails validator that adds no runtime ' \
|
|
19
|
+
'dependency. Supports ISIN, CUSIP, CEI, SEDOL, FIGI, LEI, IBAN, CIK, OCC, WKN, Valoren, ' \
|
|
20
|
+
'CFI, FISN, BIC, and DTI.'
|
|
17
21
|
spec.homepage = 'https://github.com/svyatov/sec_id'
|
|
18
22
|
spec.license = 'MIT'
|
|
19
23
|
|
|
20
24
|
spec.required_ruby_version = '>= 3.2.0'
|
|
21
25
|
|
|
22
26
|
spec.require_paths = ['lib']
|
|
23
|
-
spec.files = Dir['lib/**/*.rb'] +
|
|
27
|
+
spec.files = Dir['lib/**/*.rb'] + Dir['sig/**/*'] +
|
|
28
|
+
%w[.yardopts CHANGELOG.md LICENSE.txt MIGRATION.md README.md sec_id.gemspec]
|
|
24
29
|
|
|
25
30
|
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
31
|
+
spec.metadata['documentation_uri'] = 'https://rubydoc.info/gems/sec_id'
|
|
26
32
|
spec.metadata['source_code_uri'] = 'https://github.com/svyatov/sec_id'
|
|
27
33
|
spec.metadata['changelog_uri'] = 'https://github.com/svyatov/sec_id/blob/main/CHANGELOG.md'
|
|
28
34
|
spec.metadata['bug_tracker_uri'] = 'https://github.com/svyatov/sec_id/issues'
|
data/sig/manifest.yaml
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Standard-library signatures these RBS files reference. Consumers' RBS/Steep
|
|
2
|
+
# load these automatically when they depend on sec_id. (The gem has no runtime
|
|
3
|
+
# gem dependencies, so none are auto-derived from the gemspec.)
|
|
4
|
+
#
|
|
5
|
+
# Set (ISIN, SEDOL, FIGI, Valoren, BIC) is a core class in rbs 4.0 — always
|
|
6
|
+
# loaded, so it needs no manifest entry.
|
|
7
|
+
dependencies:
|
|
8
|
+
- name: date # Date in OCC
|
data/sig/sec_id/base.rbs
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
module SecID
|
|
2
|
+
# Accepted raw input for parsing/validating an identifier: a String, an Integer
|
|
3
|
+
# (Valoren/CIK/CUSIP accept numeric input), or nil.
|
|
4
|
+
type input = String | Integer | nil
|
|
5
|
+
|
|
6
|
+
# The class-object surface the concern ClassMethods modules call through `self`
|
|
7
|
+
# once extended onto an identifier class (they construct instances via `new`).
|
|
8
|
+
interface _IdentifierClass
|
|
9
|
+
def new: (SecID::input) -> Base
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Base class for securities identifiers, providing a common interface for
|
|
13
|
+
# validation, normalization, parsing, and generation.
|
|
14
|
+
class Base
|
|
15
|
+
include Normalizable
|
|
16
|
+
include Validatable
|
|
17
|
+
include Generatable
|
|
18
|
+
extend Normalizable::ClassMethods
|
|
19
|
+
extend Validatable::ClassMethods
|
|
20
|
+
extend Generatable::ClassMethods
|
|
21
|
+
|
|
22
|
+
# Metadata constants each subclass overrides with its concrete shape. Declared
|
|
23
|
+
# here (as the widest shape) so the shared concern method bodies type-check.
|
|
24
|
+
FULL_NAME: String
|
|
25
|
+
ID_LENGTH: Integer | ::Range[Integer] | ::Array[Integer]
|
|
26
|
+
EXAMPLE: String
|
|
27
|
+
VALID_CHARS_REGEX: ::Regexp
|
|
28
|
+
ID_REGEX: ::Regexp
|
|
29
|
+
|
|
30
|
+
attr_reader full_id: String
|
|
31
|
+
# Reader is nilable (nil for invalid input, checked by `valid_format?`); the ivar is
|
|
32
|
+
# typed `untyped` because subclasses use `@identifier` as non-nil after validation and
|
|
33
|
+
# RBS forbids narrowing an inherited ivar's type.
|
|
34
|
+
def identifier: () -> String?
|
|
35
|
+
|
|
36
|
+
def self.type_key: () -> Symbol
|
|
37
|
+
# `@api private` in YARD, but public here: Detector and Scanner call it from outside.
|
|
38
|
+
def self.detection_priority: () -> Array[Integer | Float | nil]
|
|
39
|
+
def self.short_name: () -> String
|
|
40
|
+
def self.full_name: () -> String
|
|
41
|
+
def self.id_length: () -> (Integer | ::Range[Integer] | ::Array[Integer])
|
|
42
|
+
def self.length_values: () -> (::Array[Integer] | ::Range[Integer])
|
|
43
|
+
def self.length_specificity: () -> (Integer | Float | nil)
|
|
44
|
+
def self.example: () -> String
|
|
45
|
+
def self.has_check_digit?: () -> bool
|
|
46
|
+
def self.inherited: (singleton(Base) subclass) -> void
|
|
47
|
+
|
|
48
|
+
def initialize: (SecID::input _sec_id_number) -> void
|
|
49
|
+
|
|
50
|
+
def ==: (Base other) -> bool
|
|
51
|
+
alias eql? ==
|
|
52
|
+
def hash: () -> Integer
|
|
53
|
+
def to_h: () -> Hash[Symbol, untyped]
|
|
54
|
+
def as_json: (*untyped) -> Hash[Symbol, untyped]
|
|
55
|
+
def deconstruct_keys: (::Array[Symbol]? _keys) -> Hash[Symbol, untyped]
|
|
56
|
+
|
|
57
|
+
# Check-digit surface. Only the types that `include Checkable` implement these
|
|
58
|
+
# (they raise/NoMethodError otherwise); declared on Base so `Generatable#generate`
|
|
59
|
+
# and `Checkable::ClassMethods` type-check without narrowing on `has_check_digit?`.
|
|
60
|
+
def restore: () -> String
|
|
61
|
+
def restore!: () -> self
|
|
62
|
+
def calculate_check_digit: () -> (Integer | String)
|
|
63
|
+
|
|
64
|
+
def comparison_id: () -> String
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
|
|
68
|
+
def components: () -> Hash[Symbol, untyped]
|
|
69
|
+
def parse: (SecID::input sec_id_number) -> (::MatchData | ::Hash[Symbol, untyped])
|
|
70
|
+
|
|
71
|
+
@full_id: String
|
|
72
|
+
@identifier: untyped
|
|
73
|
+
self.@short_name: String
|
|
74
|
+
self.@has_check_digit: bool
|
|
75
|
+
self.@type_key: Symbol
|
|
76
|
+
self.@detection_priority: Array[Integer | Float | nil]
|
|
77
|
+
end
|
|
78
|
+
end
|
data/sig/sec_id/bic.rbs
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module SecID
|
|
2
|
+
# Business Identifier Code (BIC / SWIFT code).
|
|
3
|
+
class BIC < Base
|
|
4
|
+
FULL_NAME: String
|
|
5
|
+
ID_LENGTH: Array[Integer]
|
|
6
|
+
EXAMPLE: String
|
|
7
|
+
VALID_CHARS_REGEX: ::Regexp
|
|
8
|
+
ID_REGEX: ::Regexp
|
|
9
|
+
|
|
10
|
+
def self.countries: () -> Array[String]
|
|
11
|
+
|
|
12
|
+
attr_reader bank_code: String?
|
|
13
|
+
attr_reader country_code: String?
|
|
14
|
+
attr_reader location_code: String?
|
|
15
|
+
attr_reader branch_code: String?
|
|
16
|
+
|
|
17
|
+
def initialize: (SecID::input bic) -> void
|
|
18
|
+
private def self.generate_body: (Random random) -> String
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def components: () -> Hash[Symbol, untyped]
|
|
23
|
+
def valid_format?: () -> bool
|
|
24
|
+
def detect_errors: () -> Array[Symbol]
|
|
25
|
+
def validation_message: (Symbol code) -> String?
|
|
26
|
+
def recognized_country?: () -> bool
|
|
27
|
+
|
|
28
|
+
self.@countries: Array[String]
|
|
29
|
+
end
|
|
30
|
+
end
|
data/sig/sec_id/cei.rbs
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module SecID
|
|
2
|
+
# CUSIP Entity Identifier (CEI).
|
|
3
|
+
class CEI < 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 prefix: String?
|
|
14
|
+
attr_reader numeric: String?
|
|
15
|
+
attr_reader entity_id: String?
|
|
16
|
+
|
|
17
|
+
def initialize: (SecID::input cei) -> void
|
|
18
|
+
def calculate_check_digit: () -> Integer
|
|
19
|
+
def self.check_digit: (SecID::input id) -> Integer
|
|
20
|
+
private def self.generate_body: (Random random) -> String
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def components: () -> Hash[Symbol, untyped]
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Generated by `rake sig:cfi` from SecID::CFI::Tables. Do not edit by hand.
|
|
2
|
+
module SecID
|
|
3
|
+
class CFI < Base
|
|
4
|
+
# The ordered collection of decoded attribute Fields.
|
|
5
|
+
class AttributeSet
|
|
6
|
+
include Enumerable[Field]
|
|
7
|
+
|
|
8
|
+
# `fields` is typed `untyped` because `#initialize` calls
|
|
9
|
+
# `define_singleton_method(field.meaning)` and `field.meaning` is nilable.
|
|
10
|
+
def initialize: (untyped fields) -> void
|
|
11
|
+
def each: () { (Field) -> void } -> self
|
|
12
|
+
| () -> Enumerator[Field, self]
|
|
13
|
+
def []: (Symbol meaning) -> Field?
|
|
14
|
+
def empty?: () -> bool
|
|
15
|
+
def to_h: () -> Hash[untyped, untyped]
|
|
16
|
+
def as_json: (*untyped) -> Hash[Symbol, untyped]
|
|
17
|
+
|
|
18
|
+
# Per-meaning readers — the union of every attribute meaning. Each instance
|
|
19
|
+
# only answers the meanings actually present; an absent one raises
|
|
20
|
+
# NoMethodError at runtime. Use #[] for the presence-uncertain path.
|
|
21
|
+
def asset_class: () -> Field
|
|
22
|
+
def assets: () -> Field
|
|
23
|
+
def barrier_dependency: () -> Field
|
|
24
|
+
def calculation_frequency: () -> Field
|
|
25
|
+
def call_put: () -> Field
|
|
26
|
+
def closed_open: () -> Field
|
|
27
|
+
def components: () -> Field
|
|
28
|
+
def composition: () -> Field
|
|
29
|
+
def currency: () -> Field
|
|
30
|
+
def delivery: () -> Field
|
|
31
|
+
def distribution: () -> Field
|
|
32
|
+
def distribution_policy: () -> Field
|
|
33
|
+
def equity_type: () -> Field
|
|
34
|
+
def exercise_style: () -> Field
|
|
35
|
+
def form: () -> Field
|
|
36
|
+
def further_grouping: () -> Field
|
|
37
|
+
def guarantee: () -> Field
|
|
38
|
+
def income: () -> Field
|
|
39
|
+
def interest_rate_type: () -> Field
|
|
40
|
+
def interest_type: () -> Field
|
|
41
|
+
def investment_strategy: () -> Field
|
|
42
|
+
def issuer_type: () -> Field
|
|
43
|
+
def long_short: () -> Field
|
|
44
|
+
def notional: () -> Field
|
|
45
|
+
def option_style: () -> Field
|
|
46
|
+
def ownership_restrictions: () -> Field
|
|
47
|
+
def payment_status: () -> Field
|
|
48
|
+
def redemption: () -> Field
|
|
49
|
+
def repayment: () -> Field
|
|
50
|
+
def return_trigger: () -> Field
|
|
51
|
+
def return_type: () -> Field
|
|
52
|
+
def security_type: () -> Field
|
|
53
|
+
def standardized: () -> Field
|
|
54
|
+
def strategy_style: () -> Field
|
|
55
|
+
def termination: () -> Field
|
|
56
|
+
def type: () -> Field
|
|
57
|
+
def underlying: () -> Field
|
|
58
|
+
def underlying_assets: () -> Field
|
|
59
|
+
def underlying_fund_type: () -> Field
|
|
60
|
+
def valuation: () -> Field
|
|
61
|
+
def voting_right: () -> Field
|
|
62
|
+
def warrant_type: () -> Field
|
|
63
|
+
def weighting: () -> Field
|
|
64
|
+
|
|
65
|
+
@fields: Array[Field]
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module SecID
|
|
2
|
+
class CFI < Base
|
|
3
|
+
# The decoded ISO 10962:2021 classification of a valid CFI, built by {CFI#decode}.
|
|
4
|
+
class Classification
|
|
5
|
+
attr_reader category: Field
|
|
6
|
+
attr_reader group: Field
|
|
7
|
+
attr_reader attributes: AttributeSet
|
|
8
|
+
|
|
9
|
+
def initialize: (String category_code, String group_code, Array[String] letters) -> void
|
|
10
|
+
def to_s: () -> String
|
|
11
|
+
def to_h: () -> Hash[Symbol, untyped]
|
|
12
|
+
def as_json: (*untyped) -> Hash[Symbol, untyped]
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def build_category: (String code) -> Field
|
|
17
|
+
def build_group: (String category_code, String code) -> Field
|
|
18
|
+
def build_attributes: (String category_code, String group_code, Array[String] letters) -> AttributeSet
|
|
19
|
+
def build_attribute: (untyped position, String letter) -> Field
|
|
20
|
+
def decode_value: (untyped value_map, String letter) -> [Symbol, String]
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|