tea-bond 0.2.8__cp310-abi3-win_amd64.whl

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.

Potentially problematic release.


This version of tea-bond might be problematic. Click here for more details.

pybond/nb/nb_bond.py ADDED
@@ -0,0 +1,219 @@
1
+ import numba as nb
2
+ from llvmlite import ir
3
+ from numba import types
4
+ from numba.core import cgutils, utils
5
+ from numba.cpython.hashing import _Py_hash_t
6
+ from numba.experimental import jitclass
7
+ from numba.extending import (
8
+ NativeValue,
9
+ as_numba_type,
10
+ box,
11
+ intrinsic,
12
+ lower_builtin,
13
+ lower_getattr,
14
+ make_attribute_wrapper,
15
+ models,
16
+ overload,
17
+ overload_attribute,
18
+ overload_method,
19
+ register_model,
20
+ type_callable,
21
+ typeof_impl,
22
+ unbox,
23
+ )
24
+
25
+ from pybond import Bond
26
+ from pybond.ffi import (
27
+ bond_accrued_interest,
28
+ bond_calc_ytm,
29
+ bond_clean_price,
30
+ bond_coupon_rate,
31
+ bond_dirty_price,
32
+ bond_duration,
33
+ )
34
+ from pybond.nb.nb_datetime import DateTimeType # , create_bond
35
+
36
+ from .nb_date import DateType
37
+
38
+
39
+ class BondType(types.Type):
40
+ def __init__(self):
41
+ super().__init__(name="Bond")
42
+
43
+
44
+ bond_type = BondType()
45
+ as_numba_type.register(Bond, bond_type)
46
+
47
+
48
+ @typeof_impl.register(Bond)
49
+ def typeof_index(val, c):
50
+ return bond_type
51
+
52
+
53
+ @type_callable(Bond)
54
+ def type_datetime(context):
55
+ def typer(val):
56
+ return bond_type
57
+
58
+ return typer
59
+
60
+
61
+ @register_model(BondType)
62
+ class BondModel(models.StructModel):
63
+ def __init__(self, dmm, fe_type):
64
+ members = [
65
+ ("ptr", types.voidptr),
66
+ ]
67
+ models.StructModel.__init__(self, dmm, fe_type, members)
68
+
69
+
70
+ make_attribute_wrapper(BondType, "ptr", "ptr")
71
+
72
+
73
+ @lower_builtin(Bond, types.string)
74
+ def impl_bond_builder(context, builder, sig, args):
75
+ typ = sig.return_type
76
+ (val,) = args
77
+ # Get string data from Numba string
78
+ code = context.make_helper(builder, types.string, val)
79
+ fn = cgutils.get_or_insert_function(
80
+ builder.module,
81
+ ir.FunctionType(
82
+ ir.PointerType(ir.IntType(8)),
83
+ [ir.PointerType(ir.IntType(8)), ir.IntType(utils.MACHINE_BITS)],
84
+ ),
85
+ name="create_bond",
86
+ )
87
+ ptr = builder.call(fn, [code.data, code.length])
88
+ # Create Bond object
89
+ bond = cgutils.create_struct_proxy(typ)(context, builder)
90
+ bond.ptr = ptr
91
+ return bond._getvalue()
92
+
93
+
94
+ @overload_attribute(BondType, "coupon_rate")
95
+ def bond_attr_coupon_rate(bond):
96
+ def impl(bond):
97
+ return bond_coupon_rate(bond.ptr)
98
+
99
+ return impl
100
+
101
+
102
+ def ir_get_bond_full_code(ptr, context, builder):
103
+ """根据Bond的指针获取bond的代码(包括交易所信息)"""
104
+ fn = cgutils.get_or_insert_function(
105
+ builder.module,
106
+ ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.PointerType(ir.IntType(8))]),
107
+ name="bond_full_code",
108
+ )
109
+ cstr = builder.call(fn, [ptr])
110
+ # 使用 LLVM strlen
111
+ strlen_fn = cgutils.get_or_insert_function(
112
+ builder.module,
113
+ ir.FunctionType(ir.IntType(64), [ir.PointerType(ir.IntType(8))]),
114
+ name="strlen",
115
+ )
116
+ length = builder.call(strlen_fn, [cstr])
117
+ uni_str = cgutils.create_struct_proxy(types.unicode_type)(context, builder)
118
+ uni_str.data = cstr
119
+ uni_str.length = length
120
+ uni_str.kind = ir.Constant(ir.IntType(32), 1) # kind=1 is PY_UNICODE_1BYTE_KIND
121
+ uni_str.is_ascii = ir.Constant(ir.IntType(32), 1)
122
+ uni_str.meminfo = context.get_constant_null(types.voidptr)
123
+ # Set hash to -1 to indicate that it should be computed.
124
+ # We cannot bake in the hash value because of hashseed randomization.
125
+ uni_str.hash = context.get_constant(_Py_hash_t, -1)
126
+ uni_str.parent = cgutils.get_null_value(uni_str.parent.type)
127
+ return uni_str._getvalue()
128
+
129
+
130
+ @intrinsic
131
+ def get_bond_full_code(typingctx, bond_ptr):
132
+ """根据Bond的指针获取bond的代码(包括交易所信息)"""
133
+
134
+ def codegen(context, builder, sig, args):
135
+ return ir_get_bond_full_code(args[0], context, builder)
136
+
137
+ sig = types.unicode_type(bond_ptr)
138
+ return sig, codegen
139
+
140
+
141
+ @overload_attribute(BondType, "full_code")
142
+ def get_full_code_attr(bond):
143
+ if isinstance(bond, BondType):
144
+
145
+ def impl(bond):
146
+ return get_bond_full_code(bond.ptr)
147
+
148
+ return impl
149
+
150
+
151
+ @overload_method(BondType, "duration")
152
+ def bond_calc_duration(bond, ytm, date):
153
+ if not isinstance(date, (DateType, DateTimeType)):
154
+ return
155
+
156
+ def impl(bond, ytm, date):
157
+ return bond_duration(bond.ptr, ytm, date.year, date.month, date.day)
158
+
159
+ return impl
160
+
161
+
162
+ @overload_method(BondType, "accrued_interest")
163
+ def bond_calc_accrued_interest(bond, date):
164
+ if not isinstance(date, (DateType, DateTimeType)):
165
+ return
166
+
167
+ def impl(bond, date):
168
+ return bond_accrued_interest(bond.ptr, date.year, date.month, date.day)
169
+
170
+ return impl
171
+
172
+
173
+ @overload_method(BondType, "dirty_price")
174
+ def bond_calc_dirty_price(bond, ytm, date):
175
+ if not isinstance(date, (DateType, DateTimeType)):
176
+ return
177
+
178
+ def impl(bond, ytm, date):
179
+ return bond_dirty_price(bond.ptr, ytm, date.year, date.month, date.day)
180
+
181
+ return impl
182
+
183
+
184
+ @overload_method(BondType, "clean_price")
185
+ def bond_calc_clean_price(bond, ytm, date):
186
+ if not isinstance(date, (DateType, DateTimeType)):
187
+ return
188
+
189
+ def impl(bond, ytm, date):
190
+ return bond_clean_price(bond.ptr, ytm, date.year, date.month, date.day)
191
+
192
+ return impl
193
+
194
+
195
+ @overload_method(BondType, "calc_ytm_with_price")
196
+ def bond_ytm_with_price(bond, dirty_price, date):
197
+ if not isinstance(date, (DateType, DateTimeType)):
198
+ return
199
+
200
+ def impl(bond, dirty_price, date):
201
+ return bond_calc_ytm(bond.ptr, dirty_price, date.year, date.month, date.day)
202
+
203
+ return impl
204
+
205
+
206
+ @box(BondType)
207
+ def box_bond(typ, val, c):
208
+ """
209
+ Convert a native Bond structure to python Bond.
210
+ """
211
+ bond = cgutils.create_struct_proxy(typ)(c.context, c.builder, value=val)
212
+ bond_code = ir_get_bond_full_code(bond.ptr, c.context, c.builder)
213
+ # Call Bond new to create a new Bond object
214
+ val_obj = c.pyapi.from_native_value(types.unicode_type, bond_code)
215
+ class_obj = c.pyapi.unserialize(c.pyapi.serialize_object(Bond))
216
+ res = c.pyapi.call_function_objargs(class_obj, (val_obj,))
217
+ c.pyapi.decref(val_obj)
218
+ c.pyapi.decref(class_obj)
219
+ return res
pybond/nb/nb_date.py ADDED
@@ -0,0 +1,209 @@
1
+ import datetime
2
+ import operator
3
+
4
+ from llvmlite import ir
5
+ from numba import types
6
+ from numba.core import cgutils
7
+ from numba.extending import (
8
+ NativeValue,
9
+ as_numba_type,
10
+ box,
11
+ lower_builtin,
12
+ make_attribute_wrapper,
13
+ models,
14
+ overload,
15
+ register_model,
16
+ type_callable,
17
+ typeof_impl,
18
+ unbox,
19
+ )
20
+
21
+ from .ir_utils import long_as_ulong
22
+
23
+
24
+ class DateType(types.Type):
25
+ def __init__(self):
26
+ super().__init__(name="Date")
27
+
28
+
29
+ date_type = DateType()
30
+ as_numba_type.register(datetime.date, date_type)
31
+
32
+
33
+ @typeof_impl.register(datetime.date)
34
+ def typeof_datetime_date(val, c):
35
+ return date_type
36
+
37
+
38
+ @type_callable(datetime.date)
39
+ def type_date(context):
40
+ def typer(year, month, day):
41
+ return date_type
42
+
43
+ return typer
44
+
45
+
46
+ @register_model(DateType)
47
+ class DateModel(models.StructModel):
48
+ def __init__(self, dmm, fe_type):
49
+ members = [
50
+ ("year", types.uint32),
51
+ ("month", types.uint32),
52
+ ("day", types.uint32),
53
+ ]
54
+ models.StructModel.__init__(self, dmm, fe_type, members)
55
+
56
+
57
+ make_attribute_wrapper(DateType, "year", "year")
58
+ make_attribute_wrapper(DateType, "month", "month")
59
+ make_attribute_wrapper(DateType, "day", "day")
60
+
61
+
62
+ @lower_builtin(datetime.date, types.uint32, types.uint32, types.uint32)
63
+ @lower_builtin(datetime.date, types.int32, types.int32, types.int32)
64
+ def datetime_date_constructor_u32(context, builder, sig, args):
65
+ date_type = sig.return_type
66
+ date = cgutils.create_struct_proxy(date_type)(context, builder)
67
+ date.year = args[0]
68
+ date.month = args[1]
69
+ date.day = args[2]
70
+ return date._getvalue()
71
+
72
+
73
+ @lower_builtin(datetime.date, types.int64, types.int64, types.int64)
74
+ def datetime_date_constructor_i64(context, builder, sig, args):
75
+ date_type = sig.return_type
76
+ date = cgutils.create_struct_proxy(date_type)(context, builder)
77
+ date.year = builder.trunc(args[0], ir.IntType(32))
78
+ date.month = builder.trunc(args[1], ir.IntType(32))
79
+ date.day = builder.trunc(args[2], ir.IntType(32))
80
+ return date._getvalue()
81
+
82
+
83
+ @unbox(DateType)
84
+ def unbox_date(typ, obj, c):
85
+ year_obj = c.pyapi.object_getattr_string(obj, "year")
86
+ year = long_as_ulong(c.pyapi, year_obj)
87
+ month_obj = c.pyapi.object_getattr_string(obj, "month")
88
+ month = long_as_ulong(c.pyapi, month_obj)
89
+ day_obj = c.pyapi.object_getattr_string(obj, "day")
90
+ second = long_as_ulong(c.pyapi, day_obj)
91
+ c.pyapi.decref(year_obj)
92
+ c.pyapi.decref(month_obj)
93
+ c.pyapi.decref(day_obj)
94
+
95
+ date = cgutils.create_struct_proxy(typ)(c.context, c.builder)
96
+ date.year = year
97
+ date.month = month
98
+ date.day = second
99
+ # Check for errors
100
+ is_error = cgutils.is_not_null(c.builder, c.pyapi.err_occurred())
101
+ return NativeValue(date._getvalue(), is_error=is_error)
102
+
103
+
104
+ @box(DateType)
105
+ def box_date(typ, val, c):
106
+ """
107
+ Box a native date object into a Python datetime.date object.
108
+ """
109
+ date = cgutils.create_struct_proxy(typ)(c.context, c.builder, value=val)
110
+ year_obj = c.pyapi.long_from_unsigned_int(date.year)
111
+ month_obj = c.pyapi.long_from_unsigned_int(date.month)
112
+ day_obj = c.pyapi.long_from_unsigned_int(date.day)
113
+
114
+ class_obj = c.pyapi.unserialize(c.pyapi.serialize_object(datetime.date))
115
+ date_obj = c.pyapi.call_function_objargs(class_obj, (year_obj, month_obj, day_obj))
116
+ c.pyapi.decref(year_obj)
117
+ c.pyapi.decref(month_obj)
118
+ c.pyapi.decref(day_obj)
119
+ return date_obj
120
+
121
+
122
+ @overload(operator.ge)
123
+ def impl_ge(dt, dt2):
124
+ if not isinstance(dt, DateType) or not isinstance(dt, DateType):
125
+ return
126
+
127
+ def impl(dt, dt2):
128
+ if dt.year == dt2.year:
129
+ if dt.month == dt2.month:
130
+ return dt.day >= dt2.day
131
+ else:
132
+ return dt.month >= dt2.month
133
+ else:
134
+ return dt.year >= dt2.year
135
+
136
+ return impl
137
+
138
+
139
+ @overload(operator.gt)
140
+ def impl_gt(dt, dt2):
141
+ if not isinstance(dt, DateType) or not isinstance(dt, DateType):
142
+ return
143
+
144
+ def impl(dt, dt2):
145
+ if dt.year == dt2.year:
146
+ if dt.month == dt2.month:
147
+ return dt.day > dt2.day
148
+ else:
149
+ return dt.month > dt2.month
150
+ else:
151
+ return dt.year > dt2.year
152
+
153
+ return impl
154
+
155
+
156
+ @overload(operator.le)
157
+ def impl_le(dt, dt2):
158
+ if not isinstance(dt, DateType) or not isinstance(dt, DateType):
159
+ return
160
+
161
+ def impl(dt, dt2):
162
+ if dt.year == dt2.year:
163
+ if dt.month == dt2.month:
164
+ return dt.day <= dt2.day
165
+ else:
166
+ return dt.month <= dt2.month
167
+ else:
168
+ return dt.year <= dt2.year
169
+
170
+ return impl
171
+
172
+
173
+ @overload(operator.lt)
174
+ def impl_lt(dt, dt2):
175
+ if not isinstance(dt, DateType) or not isinstance(dt, DateType):
176
+ return
177
+
178
+ def impl(dt, dt2):
179
+ if dt.year == dt2.year:
180
+ if dt.month == dt2.month:
181
+ return dt.day < dt2.day
182
+ else:
183
+ return dt.month < dt2.month
184
+ else:
185
+ return dt.year < dt2.year
186
+
187
+ return impl
188
+
189
+
190
+ @overload(operator.eq)
191
+ def impl_eq(dt, dt2):
192
+ if not isinstance(dt, DateType) or not isinstance(dt, DateType):
193
+ return
194
+
195
+ def impl(dt, dt2):
196
+ return dt.year == dt2.year and dt.month == dt2.month and dt.day == dt2.day
197
+
198
+ return impl
199
+
200
+
201
+ @overload(operator.ne)
202
+ def impl_ne(dt, dt2):
203
+ if not isinstance(dt, DateType) or not isinstance(dt, DateType):
204
+ return
205
+
206
+ def impl(dt, dt2):
207
+ return dt.year != dt2.year or dt.month != dt2.month or dt.day != dt2.day
208
+
209
+ return impl