-
Notifications
You must be signed in to change notification settings - Fork 189
Expand file tree
/
Copy pathfinance.py
More file actions
150 lines (117 loc) · 3.86 KB
/
Copy pathfinance.py
File metadata and controls
150 lines (117 loc) · 3.86 KB
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
"""Finance."""
from .utils import validator
def _cusip_checksum(cusip: str):
check, val = 0, None
for idx in range(9):
c = cusip[idx]
if c >= "0" and c <= "9":
val = ord(c) - ord("0")
elif c >= "A" and c <= "Z":
val = 10 + ord(c) - ord("A")
elif c >= "a" and c <= "z":
val = 10 + ord(c) - ord("a")
elif c == "*":
val = 36
elif c == "@":
val = 37
elif c == "#":
val = 38
else:
return False
if idx & 1:
val += val
check = check + (val // 10) + (val % 10)
return (check % 10) == 0
def _isin_checksum(value: str):
# The check digit (last character) is always numeric.
if not value[-1].isdecimal():
return False
# Expand the code into a string of digits, mapping each letter to its
# two-digit value (A=10, ..., Z=35) and leaving digits unchanged.
digits = ""
for idx in range(12):
c = value[idx]
if c >= "0" and c <= "9" and idx > 1:
digits += c
elif c >= "A" and c <= "Z":
digits += str(10 + ord(c) - ord("A"))
elif c >= "a" and c <= "z":
digits += str(10 + ord(c) - ord("a"))
else:
return False
# Luhn checksum over the expanded digit string: starting from the
# rightmost digit, double every second digit and sum the resulting digits.
check = 0
for idx, c in enumerate(reversed(digits)):
val = ord(c) - ord("0")
if idx & 1:
val += val
check += (val // 10) + (val % 10)
return (check % 10) == 0
@validator
def cusip(value: str):
"""Return whether or not given value is a valid CUSIP.
Checks if the value is a valid [CUSIP][1].
[1]: https://en.wikipedia.org/wiki/CUSIP
Examples:
>>> cusip('037833DP2')
True
>>> cusip('037833DP3')
ValidationError(func=cusip, args={'value': '037833DP3'})
Args:
value: CUSIP string to validate.
Returns:
(Literal[True]): If `value` is a valid CUSIP string.
(ValidationError): If `value` is an invalid CUSIP string.
"""
return len(value) == 9 and _cusip_checksum(value)
@validator
def isin(value: str):
"""Return whether or not given value is a valid ISIN.
Checks if the value is a valid [ISIN][1].
[1]: https://en.wikipedia.org/wiki/International_Securities_Identification_Number
Examples:
>>> isin('037833DP2')
ValidationError(func=isin, args={'value': '037833DP2'})
>>> isin('037833DP3')
ValidationError(func=isin, args={'value': '037833DP3'})
Args:
value: ISIN string to validate.
Returns:
(Literal[True]): If `value` is a valid ISIN string.
(ValidationError): If `value` is an invalid ISIN string.
"""
return len(value) == 12 and _isin_checksum(value)
@validator
def sedol(value: str):
"""Return whether or not given value is a valid SEDOL.
Checks if the value is a valid [SEDOL][1].
[1]: https://en.wikipedia.org/wiki/SEDOL
Examples:
>>> sedol('2936921')
True
>>> sedol('29A6922')
ValidationError(func=sedol, args={'value': '29A6922'})
Args:
value: SEDOL string to validate.
Returns:
(Literal[True]): If `value` is a valid SEDOL string.
(ValidationError): If `value` is an invalid SEDOL string.
"""
if len(value) != 7:
return False
weights = [1, 3, 1, 7, 3, 9, 1]
check = 0
for idx in range(7):
c = value[idx]
if c in "AEIOU":
return False
val = None
if c >= "0" and c <= "9":
val = ord(c) - ord("0")
elif c >= "A" and c <= "Z":
val = 10 + ord(c) - ord("A")
else:
return False
check += val * weights[idx]
return (check % 10) == 0