tea-bond 0.2.8__cp310-abi3-macosx_11_0_arm64.whl → 0.3.0__cp310-abi3-macosx_11_0_arm64.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/__init__.py +0 -2
- pybond/bond.py +2 -0
- pybond/ffi/__init__.py +1 -0
- pybond/ffi/bond.py +1 -1
- pybond/ffi/evaluators.py +186 -0
- pybond/nb/__init__.py +4 -0
- pybond/nb/nb_bond.py +2 -8
- pybond/nb/nb_date.py +3 -3
- pybond/nb/nb_datetime.py +0 -5
- pybond/nb/nb_duration.py +0 -11
- pybond/nb/nb_evaluators.py +557 -0
- pybond/pl.py +271 -0
- pybond/pybond.abi3.so +0 -0
- pybond/pybond.pyi +22 -2
- {tea_bond-0.2.8.dist-info → tea_bond-0.3.0.dist-info}/METADATA +1 -1
- tea_bond-0.3.0.dist-info/RECORD +25 -0
- {tea_bond-0.2.8.dist-info → tea_bond-0.3.0.dist-info}/WHEEL +1 -1
- tea_bond-0.2.8.dist-info/RECORD +0 -22
pybond/__init__.py
CHANGED
|
@@ -2,7 +2,6 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from .bond import Bond
|
|
4
4
|
|
|
5
|
-
# from .pnl import calc_bond_trade_pnl
|
|
6
5
|
from .pybond import Future, Ib, Sse
|
|
7
6
|
from .pybond import TfEvaluator as _TfEvaluatorRS
|
|
8
7
|
|
|
@@ -13,5 +12,4 @@ class TfEvaluator(_TfEvaluatorRS):
|
|
|
13
12
|
bond = Bond(bond)
|
|
14
13
|
return super().__new__(cls, future, bond, *args, **kwargs)
|
|
15
14
|
|
|
16
|
-
|
|
17
15
|
__all__ = ["Bond", "Future", "Ib", "Sse", "TfEvaluator"]
|
pybond/bond.py
CHANGED
|
@@ -5,6 +5,7 @@ from pathlib import Path
|
|
|
5
5
|
|
|
6
6
|
from .pybond import Bond as _BondRS
|
|
7
7
|
from .pybond import Future, download_bond
|
|
8
|
+
# from .ffi.utils import set_bond_data_path
|
|
8
9
|
|
|
9
10
|
WIND_AVAILABLE = find_spec("WindPy") is not None
|
|
10
11
|
|
|
@@ -14,6 +15,7 @@ if os.environ.get("BONDS_INFO_PATH") is not None:
|
|
|
14
15
|
else:
|
|
15
16
|
bonds_info_environ_flag = False
|
|
16
17
|
bonds_info_path = Path(__file__).parent / "data" / "bonds_info"
|
|
18
|
+
os.environ["BONDS_INFO_PATH"] = str(bonds_info_path)
|
|
17
19
|
|
|
18
20
|
if not bonds_info_path.exists():
|
|
19
21
|
bonds_info_path.mkdir(parents=True)
|
pybond/ffi/__init__.py
CHANGED
pybond/ffi/bond.py
CHANGED
pybond/ffi/evaluators.py
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import ctypes
|
|
2
|
+
|
|
3
|
+
from .lib import lib
|
|
4
|
+
|
|
5
|
+
# TfEvaluator creation and destruction
|
|
6
|
+
create_tf_evaluator = lib.create_tf_evaluator
|
|
7
|
+
create_tf_evaluator.argtypes = [
|
|
8
|
+
ctypes.c_void_p, # future_code_ptr
|
|
9
|
+
ctypes.c_size_t, # future_code_len
|
|
10
|
+
ctypes.c_double, # future_price
|
|
11
|
+
ctypes.c_void_p, # bond_code_ptr
|
|
12
|
+
ctypes.c_size_t, # bond_code_len
|
|
13
|
+
ctypes.c_double, # bond_ytm
|
|
14
|
+
ctypes.c_double, # capital_rate
|
|
15
|
+
ctypes.c_uint32, # year
|
|
16
|
+
ctypes.c_uint32, # month
|
|
17
|
+
ctypes.c_uint32, # day
|
|
18
|
+
]
|
|
19
|
+
create_tf_evaluator.restype = ctypes.c_void_p
|
|
20
|
+
|
|
21
|
+
create_tf_evaluator_with_reinvest = lib.create_tf_evaluator_with_reinvest
|
|
22
|
+
create_tf_evaluator_with_reinvest.argtypes = [
|
|
23
|
+
ctypes.c_void_p, # future_code_ptr
|
|
24
|
+
ctypes.c_size_t, # future_code_len
|
|
25
|
+
ctypes.c_double, # future_price
|
|
26
|
+
ctypes.c_void_p, # bond_code_ptr
|
|
27
|
+
ctypes.c_size_t, # bond_code_len
|
|
28
|
+
ctypes.c_double, # bond_ytm
|
|
29
|
+
ctypes.c_double, # capital_rate
|
|
30
|
+
ctypes.c_double, # reinvest_rate
|
|
31
|
+
ctypes.c_uint32, # year
|
|
32
|
+
ctypes.c_uint32, # month
|
|
33
|
+
ctypes.c_uint32, # day
|
|
34
|
+
]
|
|
35
|
+
create_tf_evaluator_with_reinvest.restype = ctypes.c_void_p
|
|
36
|
+
|
|
37
|
+
free_tf_evaluator = lib.free_tf_evaluator
|
|
38
|
+
free_tf_evaluator.argtypes = [ctypes.c_void_p]
|
|
39
|
+
free_tf_evaluator.restype = None
|
|
40
|
+
|
|
41
|
+
# Basic properties
|
|
42
|
+
tf_evaluator_is_deliverable = lib.tf_evaluator_is_deliverable
|
|
43
|
+
tf_evaluator_is_deliverable.argtypes = [ctypes.c_void_p]
|
|
44
|
+
tf_evaluator_is_deliverable.restype = ctypes.c_int
|
|
45
|
+
|
|
46
|
+
tf_evaluator_bond_code = lib.tf_evaluator_bond_code
|
|
47
|
+
tf_evaluator_bond_code.argtypes = [ctypes.c_void_p]
|
|
48
|
+
tf_evaluator_bond_code.restype = ctypes.c_char_p
|
|
49
|
+
|
|
50
|
+
tf_evaluator_future_code = lib.tf_evaluator_future_code
|
|
51
|
+
tf_evaluator_future_code.argtypes = [ctypes.c_void_p]
|
|
52
|
+
tf_evaluator_future_code.restype = ctypes.c_char_p
|
|
53
|
+
|
|
54
|
+
tf_evaluator_bond_ytm = lib.tf_evaluator_bond_ytm
|
|
55
|
+
tf_evaluator_bond_ytm.argtypes = [ctypes.c_void_p]
|
|
56
|
+
tf_evaluator_bond_ytm.restype = ctypes.c_double
|
|
57
|
+
|
|
58
|
+
tf_evaluator_future_price = lib.tf_evaluator_future_price
|
|
59
|
+
tf_evaluator_future_price.argtypes = [ctypes.c_void_p]
|
|
60
|
+
tf_evaluator_future_price.restype = ctypes.c_double
|
|
61
|
+
|
|
62
|
+
tf_evaluator_capital_rate = lib.tf_evaluator_capital_rate
|
|
63
|
+
tf_evaluator_capital_rate.argtypes = [ctypes.c_void_p]
|
|
64
|
+
tf_evaluator_capital_rate.restype = ctypes.c_double
|
|
65
|
+
|
|
66
|
+
tf_evaluator_reinvest_rate = lib.tf_evaluator_reinvest_rate
|
|
67
|
+
tf_evaluator_reinvest_rate.argtypes = [ctypes.c_void_p]
|
|
68
|
+
tf_evaluator_reinvest_rate.restype = ctypes.c_double
|
|
69
|
+
|
|
70
|
+
# Date functions
|
|
71
|
+
tf_evaluator_get_date = lib.tf_evaluator_get_date
|
|
72
|
+
tf_evaluator_get_date.argtypes = [
|
|
73
|
+
ctypes.c_void_p,
|
|
74
|
+
ctypes.POINTER(ctypes.c_uint32),
|
|
75
|
+
ctypes.POINTER(ctypes.c_uint32),
|
|
76
|
+
ctypes.POINTER(ctypes.c_uint32),
|
|
77
|
+
]
|
|
78
|
+
tf_evaluator_get_date.restype = None
|
|
79
|
+
|
|
80
|
+
tf_evaluator_get_deliver_date = lib.tf_evaluator_get_deliver_date
|
|
81
|
+
tf_evaluator_get_deliver_date.argtypes = [
|
|
82
|
+
ctypes.c_void_p,
|
|
83
|
+
ctypes.POINTER(ctypes.c_uint32),
|
|
84
|
+
ctypes.POINTER(ctypes.c_uint32),
|
|
85
|
+
ctypes.POINTER(ctypes.c_uint32),
|
|
86
|
+
]
|
|
87
|
+
tf_evaluator_get_deliver_date.restype = ctypes.c_int
|
|
88
|
+
|
|
89
|
+
# Calculation functions
|
|
90
|
+
tf_evaluator_accrued_interest = lib.tf_evaluator_accrued_interest
|
|
91
|
+
tf_evaluator_accrued_interest.argtypes = [ctypes.c_void_p]
|
|
92
|
+
tf_evaluator_accrued_interest.restype = ctypes.c_double
|
|
93
|
+
|
|
94
|
+
tf_evaluator_deliver_accrued_interest = lib.tf_evaluator_deliver_accrued_interest
|
|
95
|
+
tf_evaluator_deliver_accrued_interest.argtypes = [ctypes.c_void_p]
|
|
96
|
+
tf_evaluator_deliver_accrued_interest.restype = ctypes.c_double
|
|
97
|
+
|
|
98
|
+
tf_evaluator_cf = lib.tf_evaluator_cf
|
|
99
|
+
tf_evaluator_cf.argtypes = [ctypes.c_void_p]
|
|
100
|
+
tf_evaluator_cf.restype = ctypes.c_double
|
|
101
|
+
|
|
102
|
+
tf_evaluator_dirty_price = lib.tf_evaluator_dirty_price
|
|
103
|
+
tf_evaluator_dirty_price.argtypes = [ctypes.c_void_p]
|
|
104
|
+
tf_evaluator_dirty_price.restype = ctypes.c_double
|
|
105
|
+
|
|
106
|
+
tf_evaluator_clean_price = lib.tf_evaluator_clean_price
|
|
107
|
+
tf_evaluator_clean_price.argtypes = [ctypes.c_void_p]
|
|
108
|
+
tf_evaluator_clean_price.restype = ctypes.c_double
|
|
109
|
+
|
|
110
|
+
tf_evaluator_future_dirty_price = lib.tf_evaluator_future_dirty_price
|
|
111
|
+
tf_evaluator_future_dirty_price.argtypes = [ctypes.c_void_p]
|
|
112
|
+
tf_evaluator_future_dirty_price.restype = ctypes.c_double
|
|
113
|
+
|
|
114
|
+
tf_evaluator_deliver_cost = lib.tf_evaluator_deliver_cost
|
|
115
|
+
tf_evaluator_deliver_cost.argtypes = [ctypes.c_void_p]
|
|
116
|
+
tf_evaluator_deliver_cost.restype = ctypes.c_double
|
|
117
|
+
|
|
118
|
+
tf_evaluator_basis_spread = lib.tf_evaluator_basis_spread
|
|
119
|
+
tf_evaluator_basis_spread.argtypes = [ctypes.c_void_p]
|
|
120
|
+
tf_evaluator_basis_spread.restype = ctypes.c_double
|
|
121
|
+
|
|
122
|
+
tf_evaluator_f_b_spread = lib.tf_evaluator_f_b_spread
|
|
123
|
+
tf_evaluator_f_b_spread.argtypes = [ctypes.c_void_p]
|
|
124
|
+
tf_evaluator_f_b_spread.restype = ctypes.c_double
|
|
125
|
+
|
|
126
|
+
tf_evaluator_carry = lib.tf_evaluator_carry
|
|
127
|
+
tf_evaluator_carry.argtypes = [ctypes.c_void_p]
|
|
128
|
+
tf_evaluator_carry.restype = ctypes.c_double
|
|
129
|
+
|
|
130
|
+
tf_evaluator_net_basis_spread = lib.tf_evaluator_net_basis_spread
|
|
131
|
+
tf_evaluator_net_basis_spread.argtypes = [ctypes.c_void_p]
|
|
132
|
+
tf_evaluator_net_basis_spread.restype = ctypes.c_double
|
|
133
|
+
|
|
134
|
+
tf_evaluator_duration = lib.tf_evaluator_duration
|
|
135
|
+
tf_evaluator_duration.argtypes = [ctypes.c_void_p]
|
|
136
|
+
tf_evaluator_duration.restype = ctypes.c_double
|
|
137
|
+
|
|
138
|
+
tf_evaluator_irr = lib.tf_evaluator_irr
|
|
139
|
+
tf_evaluator_irr.argtypes = [ctypes.c_void_p]
|
|
140
|
+
tf_evaluator_irr.restype = ctypes.c_double
|
|
141
|
+
|
|
142
|
+
tf_evaluator_future_ytm = lib.tf_evaluator_future_ytm
|
|
143
|
+
tf_evaluator_future_ytm.argtypes = [ctypes.c_void_p]
|
|
144
|
+
tf_evaluator_future_ytm.restype = ctypes.c_double
|
|
145
|
+
|
|
146
|
+
tf_evaluator_remain_days_to_deliver = lib.tf_evaluator_remain_days_to_deliver
|
|
147
|
+
tf_evaluator_remain_days_to_deliver.argtypes = [ctypes.c_void_p]
|
|
148
|
+
tf_evaluator_remain_days_to_deliver.restype = ctypes.c_int
|
|
149
|
+
|
|
150
|
+
tf_evaluator_remain_cp_num = lib.tf_evaluator_remain_cp_num
|
|
151
|
+
tf_evaluator_remain_cp_num.argtypes = [ctypes.c_void_p]
|
|
152
|
+
tf_evaluator_remain_cp_num.restype = ctypes.c_int
|
|
153
|
+
|
|
154
|
+
tf_evaluator_remain_cp_to_deliver = lib.tf_evaluator_remain_cp_to_deliver
|
|
155
|
+
tf_evaluator_remain_cp_to_deliver.argtypes = [ctypes.c_void_p]
|
|
156
|
+
tf_evaluator_remain_cp_to_deliver.restype = ctypes.c_double
|
|
157
|
+
|
|
158
|
+
tf_evaluator_remain_cp_to_deliver_wm = lib.tf_evaluator_remain_cp_to_deliver_wm
|
|
159
|
+
tf_evaluator_remain_cp_to_deliver_wm.argtypes = [ctypes.c_void_p]
|
|
160
|
+
tf_evaluator_remain_cp_to_deliver_wm.restype = ctypes.c_double
|
|
161
|
+
|
|
162
|
+
tf_evaluator_calc_all = lib.tf_evaluator_calc_all
|
|
163
|
+
tf_evaluator_calc_all.argtypes = [ctypes.c_void_p]
|
|
164
|
+
tf_evaluator_calc_all.restype = ctypes.c_int
|
|
165
|
+
|
|
166
|
+
# Update function
|
|
167
|
+
tf_evaluator_update_info = lib.tf_evaluator_update_info
|
|
168
|
+
tf_evaluator_update_info.argtypes = [
|
|
169
|
+
ctypes.c_void_p, # evaluator
|
|
170
|
+
ctypes.c_void_p, # future_code_ptr
|
|
171
|
+
ctypes.c_size_t, # future_code_len
|
|
172
|
+
ctypes.c_double, # future_price
|
|
173
|
+
ctypes.c_void_p, # bond_code_ptr
|
|
174
|
+
ctypes.c_size_t, # bond_code_len
|
|
175
|
+
ctypes.c_double, # bond_ytm
|
|
176
|
+
ctypes.c_double, # capital_rate
|
|
177
|
+
ctypes.c_uint32, # year
|
|
178
|
+
ctypes.c_uint32, # month
|
|
179
|
+
ctypes.c_uint32, # day
|
|
180
|
+
]
|
|
181
|
+
tf_evaluator_update_info.restype = ctypes.c_int
|
|
182
|
+
|
|
183
|
+
# Utility function
|
|
184
|
+
free_string = lib.free_string
|
|
185
|
+
free_string.argtypes = [ctypes.c_char_p]
|
|
186
|
+
free_string.restype = None
|
pybond/nb/__init__.py
CHANGED
|
@@ -4,6 +4,7 @@ from .nb_bond import Bond, BondType, bond_type
|
|
|
4
4
|
from .nb_date import DateType, date_type
|
|
5
5
|
from .nb_datetime import DateTime, DateTimeType, datetime_type
|
|
6
6
|
from .nb_duration import Duration, DurationType, duration_type
|
|
7
|
+
from .nb_evaluators import TfEvaluator, TfEvaluatorType, tf_evaluator_type
|
|
7
8
|
from .nb_time import Time, TimeType, time_type
|
|
8
9
|
|
|
9
10
|
__all__ = [
|
|
@@ -16,6 +17,9 @@ __all__ = [
|
|
|
16
17
|
"Duration",
|
|
17
18
|
"DurationType",
|
|
18
19
|
"duration_type",
|
|
20
|
+
"TfEvaluator",
|
|
21
|
+
"TfEvaluatorType",
|
|
22
|
+
"tf_evaluator_type",
|
|
19
23
|
"Time",
|
|
20
24
|
"TimeType",
|
|
21
25
|
# "date",
|
pybond/nb/nb_bond.py
CHANGED
|
@@ -1,25 +1,19 @@
|
|
|
1
|
-
import numba as nb
|
|
2
1
|
from llvmlite import ir
|
|
3
2
|
from numba import types
|
|
4
3
|
from numba.core import cgutils, utils
|
|
5
4
|
from numba.cpython.hashing import _Py_hash_t
|
|
6
|
-
from numba.experimental import jitclass
|
|
7
5
|
from numba.extending import (
|
|
8
|
-
NativeValue,
|
|
9
6
|
as_numba_type,
|
|
10
7
|
box,
|
|
11
8
|
intrinsic,
|
|
12
9
|
lower_builtin,
|
|
13
|
-
lower_getattr,
|
|
14
10
|
make_attribute_wrapper,
|
|
15
11
|
models,
|
|
16
|
-
overload,
|
|
17
12
|
overload_attribute,
|
|
18
13
|
overload_method,
|
|
19
14
|
register_model,
|
|
20
15
|
type_callable,
|
|
21
16
|
typeof_impl,
|
|
22
|
-
unbox,
|
|
23
17
|
)
|
|
24
18
|
|
|
25
19
|
from pybond import Bond
|
|
@@ -46,12 +40,12 @@ as_numba_type.register(Bond, bond_type)
|
|
|
46
40
|
|
|
47
41
|
|
|
48
42
|
@typeof_impl.register(Bond)
|
|
49
|
-
def
|
|
43
|
+
def typeof_bond(val, c):
|
|
50
44
|
return bond_type
|
|
51
45
|
|
|
52
46
|
|
|
53
47
|
@type_callable(Bond)
|
|
54
|
-
def
|
|
48
|
+
def type_bond(context):
|
|
55
49
|
def typer(val):
|
|
56
50
|
return bond_type
|
|
57
51
|
|
pybond/nb/nb_date.py
CHANGED
|
@@ -93,9 +93,9 @@ def unbox_date(typ, obj, c):
|
|
|
93
93
|
c.pyapi.decref(day_obj)
|
|
94
94
|
|
|
95
95
|
date = cgutils.create_struct_proxy(typ)(c.context, c.builder)
|
|
96
|
-
date.year = year
|
|
97
|
-
date.month = month
|
|
98
|
-
date.day = second
|
|
96
|
+
date.year = c.builder.trunc(year, ir.IntType(32))
|
|
97
|
+
date.month = c.builder.trunc(month, ir.IntType(32))
|
|
98
|
+
date.day = c.builder.trunc(second, ir.IntType(32))
|
|
99
99
|
# Check for errors
|
|
100
100
|
is_error = cgutils.is_not_null(c.builder, c.pyapi.err_occurred())
|
|
101
101
|
return NativeValue(date._getvalue(), is_error=is_error)
|
pybond/nb/nb_datetime.py
CHANGED
|
@@ -20,12 +20,9 @@ from numba.extending import (
|
|
|
20
20
|
unbox,
|
|
21
21
|
)
|
|
22
22
|
|
|
23
|
-
# from pybond import ffi
|
|
24
23
|
from pybond.ffi import (
|
|
25
24
|
datetime_add_duration,
|
|
26
25
|
datetime_sub_duration,
|
|
27
|
-
# build_datetime_from_utc_ns,
|
|
28
|
-
# build_datetime_ns,
|
|
29
26
|
get_datetime_day,
|
|
30
27
|
get_datetime_hour,
|
|
31
28
|
get_datetime_minute,
|
|
@@ -33,9 +30,7 @@ from pybond.ffi import (
|
|
|
33
30
|
get_datetime_nanosecond,
|
|
34
31
|
get_datetime_second,
|
|
35
32
|
get_datetime_year,
|
|
36
|
-
# local_timestamp_nanos,
|
|
37
33
|
timestamp_nanos,
|
|
38
|
-
# utc_timestamp_to_local,
|
|
39
34
|
)
|
|
40
35
|
|
|
41
36
|
from .ir_utils import (
|
pybond/nb/nb_duration.py
CHANGED
|
@@ -1,27 +1,16 @@
|
|
|
1
|
-
import datetime
|
|
2
|
-
import operator
|
|
3
|
-
|
|
4
1
|
from llvmlite import ir
|
|
5
2
|
from numba import types
|
|
6
3
|
from numba.core import cgutils, utils
|
|
7
4
|
from numba.extending import (
|
|
8
|
-
NativeValue,
|
|
9
5
|
as_numba_type,
|
|
10
|
-
box,
|
|
11
6
|
lower_builtin,
|
|
12
7
|
make_attribute_wrapper,
|
|
13
8
|
models,
|
|
14
|
-
overload,
|
|
15
|
-
overload_attribute,
|
|
16
|
-
overload_method,
|
|
17
9
|
register_model,
|
|
18
10
|
type_callable,
|
|
19
11
|
typeof_impl,
|
|
20
|
-
unbox,
|
|
21
12
|
)
|
|
22
13
|
|
|
23
|
-
# from .nb_time import Time
|
|
24
|
-
|
|
25
14
|
|
|
26
15
|
class Duration:
|
|
27
16
|
def __init__(self, fmt: str):
|
|
@@ -0,0 +1,557 @@
|
|
|
1
|
+
from llvmlite import ir
|
|
2
|
+
from numba import types
|
|
3
|
+
from numba.core import cgutils, utils
|
|
4
|
+
from numba.extending import (
|
|
5
|
+
as_numba_type,
|
|
6
|
+
box,
|
|
7
|
+
intrinsic,
|
|
8
|
+
lower_builtin,
|
|
9
|
+
make_attribute_wrapper,
|
|
10
|
+
models,
|
|
11
|
+
overload_attribute,
|
|
12
|
+
overload_method,
|
|
13
|
+
register_model,
|
|
14
|
+
type_callable,
|
|
15
|
+
typeof_impl,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
from pybond import TfEvaluator
|
|
19
|
+
from pybond.ffi import (
|
|
20
|
+
tf_evaluator_accrued_interest,
|
|
21
|
+
tf_evaluator_basis_spread,
|
|
22
|
+
tf_evaluator_bond_ytm,
|
|
23
|
+
tf_evaluator_calc_all,
|
|
24
|
+
tf_evaluator_capital_rate,
|
|
25
|
+
tf_evaluator_carry,
|
|
26
|
+
tf_evaluator_cf,
|
|
27
|
+
tf_evaluator_clean_price,
|
|
28
|
+
tf_evaluator_deliver_accrued_interest,
|
|
29
|
+
tf_evaluator_deliver_cost,
|
|
30
|
+
tf_evaluator_dirty_price,
|
|
31
|
+
tf_evaluator_duration,
|
|
32
|
+
tf_evaluator_f_b_spread,
|
|
33
|
+
tf_evaluator_future_dirty_price,
|
|
34
|
+
tf_evaluator_future_price,
|
|
35
|
+
tf_evaluator_future_ytm,
|
|
36
|
+
tf_evaluator_irr,
|
|
37
|
+
tf_evaluator_is_deliverable,
|
|
38
|
+
tf_evaluator_net_basis_spread,
|
|
39
|
+
tf_evaluator_reinvest_rate,
|
|
40
|
+
tf_evaluator_remain_cp_num,
|
|
41
|
+
tf_evaluator_remain_cp_to_deliver,
|
|
42
|
+
tf_evaluator_remain_cp_to_deliver_wm,
|
|
43
|
+
tf_evaluator_remain_days_to_deliver,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
from .nb_date import date_type
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class TfEvaluatorType(types.Type):
|
|
50
|
+
def __init__(self):
|
|
51
|
+
super().__init__(name="TfEvaluator")
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
tf_evaluator_type = TfEvaluatorType()
|
|
55
|
+
as_numba_type.register(TfEvaluator, tf_evaluator_type)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@typeof_impl.register(TfEvaluator)
|
|
59
|
+
def typeof_tf_evaluator(val, c):
|
|
60
|
+
return tf_evaluator_type
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@type_callable(TfEvaluator)
|
|
64
|
+
def type_tf_evaluator(context):
|
|
65
|
+
def typer(
|
|
66
|
+
future,
|
|
67
|
+
bond,
|
|
68
|
+
date=None,
|
|
69
|
+
future_price=float("nan"),
|
|
70
|
+
bond_ytm=float("nan"),
|
|
71
|
+
capital_rate=float("nan"),
|
|
72
|
+
reinvest_rate=None,
|
|
73
|
+
):
|
|
74
|
+
return tf_evaluator_type
|
|
75
|
+
|
|
76
|
+
return typer
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@register_model(TfEvaluatorType)
|
|
80
|
+
class TfEvaluatorModel(models.StructModel):
|
|
81
|
+
def __init__(self, dmm, fe_type):
|
|
82
|
+
members = [
|
|
83
|
+
("ptr", types.voidptr),
|
|
84
|
+
]
|
|
85
|
+
models.StructModel.__init__(self, dmm, fe_type, members)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
make_attribute_wrapper(TfEvaluatorType, "ptr", "ptr")
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@lower_builtin(
|
|
92
|
+
TfEvaluator,
|
|
93
|
+
types.string,
|
|
94
|
+
types.string,
|
|
95
|
+
date_type,
|
|
96
|
+
types.float64,
|
|
97
|
+
types.float64,
|
|
98
|
+
types.float64,
|
|
99
|
+
)
|
|
100
|
+
def impl_tf_evaluator_builder(context, builder, sig, args):
|
|
101
|
+
typ = sig.return_type
|
|
102
|
+
(
|
|
103
|
+
future,
|
|
104
|
+
bond,
|
|
105
|
+
date_val,
|
|
106
|
+
future_price,
|
|
107
|
+
bond_ytm,
|
|
108
|
+
capital_rate,
|
|
109
|
+
) = args
|
|
110
|
+
|
|
111
|
+
# Get string data from Numba strings
|
|
112
|
+
future_code = context.make_helper(builder, types.string, future)
|
|
113
|
+
bond_code = context.make_helper(builder, types.string, bond)
|
|
114
|
+
date = context.make_helper(builder, date_type, date_val)
|
|
115
|
+
|
|
116
|
+
# Call create_tf_evaluator
|
|
117
|
+
fn = cgutils.get_or_insert_function(
|
|
118
|
+
builder.module,
|
|
119
|
+
ir.FunctionType(
|
|
120
|
+
ir.PointerType(ir.IntType(8)),
|
|
121
|
+
[
|
|
122
|
+
ir.PointerType(ir.IntType(8)), # future_code_ptr
|
|
123
|
+
ir.IntType(utils.MACHINE_BITS), # future_code_len
|
|
124
|
+
ir.DoubleType(), # future_price
|
|
125
|
+
ir.PointerType(ir.IntType(8)), # bond_code_ptr
|
|
126
|
+
ir.IntType(utils.MACHINE_BITS), # bond_code_len
|
|
127
|
+
ir.DoubleType(), # bond_ytm
|
|
128
|
+
ir.DoubleType(), # capital_rate
|
|
129
|
+
ir.IntType(32), # year
|
|
130
|
+
ir.IntType(32), # month
|
|
131
|
+
ir.IntType(32), # day
|
|
132
|
+
],
|
|
133
|
+
),
|
|
134
|
+
name="create_tf_evaluator",
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
ptr = builder.call(
|
|
138
|
+
fn,
|
|
139
|
+
[
|
|
140
|
+
future_code.data,
|
|
141
|
+
future_code.length,
|
|
142
|
+
future_price,
|
|
143
|
+
bond_code.data,
|
|
144
|
+
bond_code.length,
|
|
145
|
+
bond_ytm,
|
|
146
|
+
capital_rate,
|
|
147
|
+
date.year,
|
|
148
|
+
date.month,
|
|
149
|
+
date.day,
|
|
150
|
+
],
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
# Create TfEvaluator object
|
|
154
|
+
evaluator = cgutils.create_struct_proxy(typ)(context, builder)
|
|
155
|
+
evaluator.ptr = ptr
|
|
156
|
+
return evaluator._getvalue()
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
@lower_builtin(
|
|
160
|
+
TfEvaluator,
|
|
161
|
+
types.string,
|
|
162
|
+
types.string,
|
|
163
|
+
date_type,
|
|
164
|
+
types.float64,
|
|
165
|
+
types.float64,
|
|
166
|
+
types.float64,
|
|
167
|
+
types.float64,
|
|
168
|
+
)
|
|
169
|
+
def impl_tf_evaluator_builder_with_reinvest(context, builder, sig, args):
|
|
170
|
+
typ = sig.return_type
|
|
171
|
+
(
|
|
172
|
+
future_code_val,
|
|
173
|
+
bond_code_val,
|
|
174
|
+
date_val,
|
|
175
|
+
future_price_val,
|
|
176
|
+
bond_ytm_val,
|
|
177
|
+
capital_rate_val,
|
|
178
|
+
reinvest_rate_val,
|
|
179
|
+
) = args
|
|
180
|
+
|
|
181
|
+
# Get string data from Numba strings
|
|
182
|
+
future_code = context.make_helper(builder, types.string, future_code_val)
|
|
183
|
+
bond_code = context.make_helper(builder, types.string, bond_code_val)
|
|
184
|
+
|
|
185
|
+
# Get date components
|
|
186
|
+
date = context.make_helper(builder, date_type, date_val)
|
|
187
|
+
|
|
188
|
+
# Call create_tf_evaluator_with_reinvest
|
|
189
|
+
fn = cgutils.get_or_insert_function(
|
|
190
|
+
builder.module,
|
|
191
|
+
ir.FunctionType(
|
|
192
|
+
ir.PointerType(ir.IntType(8)),
|
|
193
|
+
[
|
|
194
|
+
ir.PointerType(ir.IntType(8)), # future_code_ptr
|
|
195
|
+
ir.IntType(utils.MACHINE_BITS), # future_code_len
|
|
196
|
+
ir.DoubleType(), # future_price
|
|
197
|
+
ir.PointerType(ir.IntType(8)), # bond_code_ptr
|
|
198
|
+
ir.IntType(utils.MACHINE_BITS), # bond_code_len
|
|
199
|
+
ir.DoubleType(), # bond_ytm
|
|
200
|
+
ir.DoubleType(), # capital_rate
|
|
201
|
+
ir.DoubleType(), # reinvest_rate
|
|
202
|
+
ir.IntType(32), # year
|
|
203
|
+
ir.IntType(32), # month
|
|
204
|
+
ir.IntType(32), # day
|
|
205
|
+
],
|
|
206
|
+
),
|
|
207
|
+
name="create_tf_evaluator_with_reinvest",
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
ptr = builder.call(
|
|
211
|
+
fn,
|
|
212
|
+
[
|
|
213
|
+
future_code.data,
|
|
214
|
+
future_code.length,
|
|
215
|
+
future_price_val,
|
|
216
|
+
bond_code.data,
|
|
217
|
+
bond_code.length,
|
|
218
|
+
bond_ytm_val,
|
|
219
|
+
capital_rate_val,
|
|
220
|
+
reinvest_rate_val,
|
|
221
|
+
date.year,
|
|
222
|
+
date.month,
|
|
223
|
+
date.day,
|
|
224
|
+
],
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
# Create TfEvaluator object
|
|
228
|
+
evaluator = cgutils.create_struct_proxy(typ)(context, builder)
|
|
229
|
+
evaluator.ptr = ptr
|
|
230
|
+
return evaluator._getvalue()
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
# Property getters
|
|
234
|
+
@overload_attribute(TfEvaluatorType, "is_deliverable")
|
|
235
|
+
def tf_evaluator_attr_is_deliverable(evaluator):
|
|
236
|
+
def impl(evaluator):
|
|
237
|
+
return tf_evaluator_is_deliverable(evaluator.ptr) == 1
|
|
238
|
+
|
|
239
|
+
return impl
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
@overload_attribute(TfEvaluatorType, "bond_ytm")
|
|
243
|
+
def tf_evaluator_attr_bond_ytm(evaluator):
|
|
244
|
+
def impl(evaluator):
|
|
245
|
+
return tf_evaluator_bond_ytm(evaluator.ptr)
|
|
246
|
+
|
|
247
|
+
return impl
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
@overload_attribute(TfEvaluatorType, "future_price")
|
|
251
|
+
def tf_evaluator_attr_future_price(evaluator):
|
|
252
|
+
def impl(evaluator):
|
|
253
|
+
return tf_evaluator_future_price(evaluator.ptr)
|
|
254
|
+
|
|
255
|
+
return impl
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
@overload_attribute(TfEvaluatorType, "capital_rate")
|
|
259
|
+
def tf_evaluator_attr_capital_rate(evaluator):
|
|
260
|
+
def impl(evaluator):
|
|
261
|
+
return tf_evaluator_capital_rate(evaluator.ptr)
|
|
262
|
+
|
|
263
|
+
return impl
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
@overload_attribute(TfEvaluatorType, "reinvest_rate")
|
|
267
|
+
def tf_evaluator_attr_reinvest_rate(evaluator):
|
|
268
|
+
def impl(evaluator):
|
|
269
|
+
return tf_evaluator_reinvest_rate(evaluator.ptr)
|
|
270
|
+
|
|
271
|
+
return impl
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
# Calculation methods
|
|
275
|
+
@overload_attribute(TfEvaluatorType, "accrued_interest")
|
|
276
|
+
def tf_evaluator_method_accrued_interest(evaluator):
|
|
277
|
+
def impl(evaluator):
|
|
278
|
+
return tf_evaluator_accrued_interest(evaluator.ptr)
|
|
279
|
+
|
|
280
|
+
return impl
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
@overload_attribute(TfEvaluatorType, "deliver_accrued_interest")
|
|
284
|
+
def tf_evaluator_method_deliver_accrued_interest(evaluator):
|
|
285
|
+
def impl(evaluator):
|
|
286
|
+
return tf_evaluator_deliver_accrued_interest(evaluator.ptr)
|
|
287
|
+
|
|
288
|
+
return impl
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
@overload_attribute(TfEvaluatorType, "cf")
|
|
292
|
+
def tf_evaluator_method_cf(evaluator):
|
|
293
|
+
def impl(evaluator):
|
|
294
|
+
return tf_evaluator_cf(evaluator.ptr)
|
|
295
|
+
|
|
296
|
+
return impl
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
@overload_attribute(TfEvaluatorType, "dirty_price")
|
|
300
|
+
def tf_evaluator_method_dirty_price(evaluator):
|
|
301
|
+
def impl(evaluator):
|
|
302
|
+
return tf_evaluator_dirty_price(evaluator.ptr)
|
|
303
|
+
|
|
304
|
+
return impl
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
@overload_attribute(TfEvaluatorType, "clean_price")
|
|
308
|
+
def tf_evaluator_method_clean_price(evaluator):
|
|
309
|
+
def impl(evaluator):
|
|
310
|
+
return tf_evaluator_clean_price(evaluator.ptr)
|
|
311
|
+
|
|
312
|
+
return impl
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
@overload_attribute(TfEvaluatorType, "future_dirty_price")
|
|
316
|
+
def tf_evaluator_method_future_dirty_price(evaluator):
|
|
317
|
+
def impl(evaluator):
|
|
318
|
+
return tf_evaluator_future_dirty_price(evaluator.ptr)
|
|
319
|
+
|
|
320
|
+
return impl
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
@overload_attribute(TfEvaluatorType, "deliver_cost")
|
|
324
|
+
def tf_evaluator_method_deliver_cost(evaluator):
|
|
325
|
+
def impl(evaluator):
|
|
326
|
+
return tf_evaluator_deliver_cost(evaluator.ptr)
|
|
327
|
+
|
|
328
|
+
return impl
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
@overload_attribute(TfEvaluatorType, "basis_spread")
|
|
332
|
+
def tf_evaluator_method_basis_spread(evaluator):
|
|
333
|
+
def impl(evaluator):
|
|
334
|
+
return tf_evaluator_basis_spread(evaluator.ptr)
|
|
335
|
+
|
|
336
|
+
return impl
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
@overload_attribute(TfEvaluatorType, "f_b_spread")
|
|
340
|
+
def tf_evaluator_method_f_b_spread(evaluator):
|
|
341
|
+
def impl(evaluator):
|
|
342
|
+
return tf_evaluator_f_b_spread(evaluator.ptr)
|
|
343
|
+
|
|
344
|
+
return impl
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
@overload_attribute(TfEvaluatorType, "carry")
|
|
348
|
+
def tf_evaluator_method_carry(evaluator):
|
|
349
|
+
def impl(evaluator):
|
|
350
|
+
return tf_evaluator_carry(evaluator.ptr)
|
|
351
|
+
|
|
352
|
+
return impl
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
@overload_attribute(TfEvaluatorType, "net_basis_spread")
|
|
356
|
+
def tf_evaluator_method_net_basis_spread(evaluator):
|
|
357
|
+
def impl(evaluator):
|
|
358
|
+
return tf_evaluator_net_basis_spread(evaluator.ptr)
|
|
359
|
+
|
|
360
|
+
return impl
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
@overload_attribute(TfEvaluatorType, "duration")
|
|
364
|
+
def tf_evaluator_method_duration(evaluator):
|
|
365
|
+
def impl(evaluator):
|
|
366
|
+
return tf_evaluator_duration(evaluator.ptr)
|
|
367
|
+
|
|
368
|
+
return impl
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
@overload_attribute(TfEvaluatorType, "irr")
|
|
372
|
+
def tf_evaluator_method_irr(evaluator):
|
|
373
|
+
def impl(evaluator):
|
|
374
|
+
return tf_evaluator_irr(evaluator.ptr)
|
|
375
|
+
|
|
376
|
+
return impl
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
@overload_attribute(TfEvaluatorType, "future_ytm")
|
|
380
|
+
def tf_evaluator_method_future_ytm(evaluator):
|
|
381
|
+
def impl(evaluator):
|
|
382
|
+
return tf_evaluator_future_ytm(evaluator.ptr)
|
|
383
|
+
|
|
384
|
+
return impl
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
@overload_attribute(TfEvaluatorType, "remain_days_to_deliver")
|
|
388
|
+
def tf_evaluator_method_remain_days_to_deliver(evaluator):
|
|
389
|
+
def impl(evaluator):
|
|
390
|
+
return tf_evaluator_remain_days_to_deliver(evaluator.ptr)
|
|
391
|
+
|
|
392
|
+
return impl
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
@overload_attribute(TfEvaluatorType, "remain_cp_num")
|
|
396
|
+
def tf_evaluator_method_remain_cp_num(evaluator):
|
|
397
|
+
def impl(evaluator):
|
|
398
|
+
return tf_evaluator_remain_cp_num(evaluator.ptr)
|
|
399
|
+
|
|
400
|
+
return impl
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
@overload_attribute(TfEvaluatorType, "remain_cp_to_deliver")
|
|
404
|
+
def tf_evaluator_method_remain_cp_to_deliver(evaluator):
|
|
405
|
+
def impl(evaluator):
|
|
406
|
+
return tf_evaluator_remain_cp_to_deliver(evaluator.ptr)
|
|
407
|
+
|
|
408
|
+
return impl
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
@overload_attribute(TfEvaluatorType, "remain_cp_to_deliver_wm")
|
|
412
|
+
def tf_evaluator_method_remain_cp_to_deliver_wm(evaluator):
|
|
413
|
+
def impl(evaluator):
|
|
414
|
+
return tf_evaluator_remain_cp_to_deliver_wm(evaluator.ptr)
|
|
415
|
+
|
|
416
|
+
return impl
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
@overload_method(TfEvaluatorType, "calc_all")
|
|
420
|
+
def tf_evaluator_method_calc_all(evaluator):
|
|
421
|
+
def impl(evaluator):
|
|
422
|
+
_ = tf_evaluator_calc_all(evaluator.ptr)
|
|
423
|
+
return evaluator
|
|
424
|
+
|
|
425
|
+
return impl
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
@box(TfEvaluatorType)
|
|
429
|
+
def box_tf_evaluator(typ, val, c):
|
|
430
|
+
"""
|
|
431
|
+
Convert a native TfEvaluator structure to python TfEvaluator.
|
|
432
|
+
"""
|
|
433
|
+
evaluator = cgutils.create_struct_proxy(typ)(c.context, c.builder, value=val)
|
|
434
|
+
|
|
435
|
+
# Convert the pointer to usize for from_ptr method
|
|
436
|
+
ptr_as_usize = c.builder.ptrtoint(evaluator.ptr, ir.IntType(64))
|
|
437
|
+
ptr_obj = c.pyapi.from_native_value(types.uint64, ptr_as_usize)
|
|
438
|
+
|
|
439
|
+
# Get TfEvaluator class and call from_ptr
|
|
440
|
+
class_obj = c.pyapi.unserialize(c.pyapi.serialize_object(TfEvaluator))
|
|
441
|
+
from_ptr_method = c.pyapi.object_getattr_string(class_obj, "from_ptr")
|
|
442
|
+
|
|
443
|
+
# Call TfEvaluator.from_ptr(ptr)
|
|
444
|
+
res = c.pyapi.call_function_objargs(from_ptr_method, (ptr_obj,))
|
|
445
|
+
|
|
446
|
+
# Clean up Python objects
|
|
447
|
+
c.pyapi.decref(ptr_obj)
|
|
448
|
+
c.pyapi.decref(class_obj)
|
|
449
|
+
c.pyapi.decref(from_ptr_method)
|
|
450
|
+
|
|
451
|
+
return res
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
@intrinsic
|
|
455
|
+
def _tf_evaluator_update_call(
|
|
456
|
+
typingctx,
|
|
457
|
+
evaluator_t,
|
|
458
|
+
future_price_t,
|
|
459
|
+
bond_ytm_t,
|
|
460
|
+
date_t,
|
|
461
|
+
future_code_t,
|
|
462
|
+
bond_code_t,
|
|
463
|
+
capital_rate_t,
|
|
464
|
+
):
|
|
465
|
+
"""Intrinsic for calling tf_evaluator_update_info FFI function."""
|
|
466
|
+
|
|
467
|
+
def codegen(context, builder, sig, args):
|
|
468
|
+
(
|
|
469
|
+
evaluator_val,
|
|
470
|
+
future_price_val,
|
|
471
|
+
bond_ytm_val,
|
|
472
|
+
date_val,
|
|
473
|
+
future_code_val,
|
|
474
|
+
bond_code_val,
|
|
475
|
+
capital_rate_val,
|
|
476
|
+
) = args
|
|
477
|
+
|
|
478
|
+
# Get existing evaluator
|
|
479
|
+
evaluator = cgutils.create_struct_proxy(tf_evaluator_type)(
|
|
480
|
+
context, builder, value=evaluator_val
|
|
481
|
+
)
|
|
482
|
+
|
|
483
|
+
# Get string data from Numba strings
|
|
484
|
+
future_code = context.make_helper(builder, types.string, future_code_val)
|
|
485
|
+
bond_code = context.make_helper(builder, types.string, bond_code_val)
|
|
486
|
+
|
|
487
|
+
# Get date components
|
|
488
|
+
date = context.make_helper(builder, date_type, date_val)
|
|
489
|
+
|
|
490
|
+
# Call tf_evaluator_update_info
|
|
491
|
+
fn = cgutils.get_or_insert_function(
|
|
492
|
+
builder.module,
|
|
493
|
+
ir.FunctionType(
|
|
494
|
+
ir.IntType(32), # return type: i32
|
|
495
|
+
[
|
|
496
|
+
ir.PointerType(ir.IntType(8)), # evaluator ptr
|
|
497
|
+
ir.PointerType(ir.IntType(8)), # future_code_ptr
|
|
498
|
+
ir.IntType(utils.MACHINE_BITS), # future_code_len
|
|
499
|
+
ir.DoubleType(), # future_price
|
|
500
|
+
ir.PointerType(ir.IntType(8)), # bond_code_ptr
|
|
501
|
+
ir.IntType(utils.MACHINE_BITS), # bond_code_len
|
|
502
|
+
ir.DoubleType(), # bond_ytm
|
|
503
|
+
ir.DoubleType(), # capital_rate
|
|
504
|
+
ir.IntType(32), # year
|
|
505
|
+
ir.IntType(32), # month
|
|
506
|
+
ir.IntType(32), # day
|
|
507
|
+
],
|
|
508
|
+
),
|
|
509
|
+
name="tf_evaluator_update_info",
|
|
510
|
+
)
|
|
511
|
+
|
|
512
|
+
result = builder.call(
|
|
513
|
+
fn,
|
|
514
|
+
[
|
|
515
|
+
evaluator.ptr,
|
|
516
|
+
future_code.data,
|
|
517
|
+
future_code.length,
|
|
518
|
+
future_price_val,
|
|
519
|
+
bond_code.data,
|
|
520
|
+
bond_code.length,
|
|
521
|
+
bond_ytm_val,
|
|
522
|
+
capital_rate_val,
|
|
523
|
+
date.year,
|
|
524
|
+
date.month,
|
|
525
|
+
date.day,
|
|
526
|
+
],
|
|
527
|
+
)
|
|
528
|
+
|
|
529
|
+
return result
|
|
530
|
+
|
|
531
|
+
sig = types.int32(
|
|
532
|
+
evaluator_t,
|
|
533
|
+
future_price_t,
|
|
534
|
+
bond_ytm_t,
|
|
535
|
+
date_t,
|
|
536
|
+
future_code_t,
|
|
537
|
+
bond_code_t,
|
|
538
|
+
capital_rate_t,
|
|
539
|
+
)
|
|
540
|
+
return sig, codegen
|
|
541
|
+
|
|
542
|
+
|
|
543
|
+
@overload_method(TfEvaluatorType, "update")
|
|
544
|
+
# 采用和update pyi同样的参数顺序
|
|
545
|
+
def tf_evaluator_method_update(
|
|
546
|
+
evaluator, future_price, bond_ytm, date, future, bond, capital_rate
|
|
547
|
+
):
|
|
548
|
+
def update_impl(
|
|
549
|
+
evaluator, future_price, bond_ytm, date, future, bond, capital_rate
|
|
550
|
+
):
|
|
551
|
+
_result = _tf_evaluator_update_call(
|
|
552
|
+
evaluator, future_price, bond_ytm, date, future, bond, capital_rate
|
|
553
|
+
)
|
|
554
|
+
# Return the evaluator itself (it's been updated in-place)
|
|
555
|
+
return evaluator
|
|
556
|
+
|
|
557
|
+
return update_impl
|
pybond/pl.py
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from polars.type_aliases import IntoExpr
|
|
7
|
+
import polars as pl
|
|
8
|
+
|
|
9
|
+
from .polars_utils import parse_into_expr, register_plugin
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class TfEvaluators:
|
|
13
|
+
"""A class for treasury futures evaluation using Polars expressions."""
|
|
14
|
+
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
future: IntoExpr = "future",
|
|
18
|
+
bond: IntoExpr = "bond",
|
|
19
|
+
date: IntoExpr = "date",
|
|
20
|
+
future_price: IntoExpr = "future_price",
|
|
21
|
+
bond_ytm: IntoExpr = "bond_ytm",
|
|
22
|
+
capital_rate: IntoExpr = "capital_rate",
|
|
23
|
+
reinvest_rate=None,
|
|
24
|
+
):
|
|
25
|
+
"""
|
|
26
|
+
Initialize TfEvaluators with default column expressions.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
future: Future contract code column expression
|
|
30
|
+
bond: Bond code column expression
|
|
31
|
+
date: Evaluation date column expression
|
|
32
|
+
future_price: Future price column expression
|
|
33
|
+
bond_ytm: Bond yield to maturity column expression
|
|
34
|
+
capital_rate: Capital cost rate column expression
|
|
35
|
+
reinvest_rate: Reinvestment rate (optional)
|
|
36
|
+
"""
|
|
37
|
+
if future is None:
|
|
38
|
+
future = pl.lit(None).cast(str)
|
|
39
|
+
self.future = parse_into_expr(future)
|
|
40
|
+
self.bond = parse_into_expr(bond)
|
|
41
|
+
self.date = parse_into_expr(date)
|
|
42
|
+
self.future_price = parse_into_expr(future_price)
|
|
43
|
+
self.bond_ytm = parse_into_expr(bond_ytm)
|
|
44
|
+
self.capital_rate = parse_into_expr(capital_rate)
|
|
45
|
+
self.reinvest_rate = reinvest_rate
|
|
46
|
+
|
|
47
|
+
def _call_plugin(self, symbol: str):
|
|
48
|
+
"""Helper method to call plugin with consistent arguments."""
|
|
49
|
+
return register_plugin(
|
|
50
|
+
args=[
|
|
51
|
+
self.future,
|
|
52
|
+
self.bond,
|
|
53
|
+
self.date,
|
|
54
|
+
self.future_price,
|
|
55
|
+
self.bond_ytm,
|
|
56
|
+
self.capital_rate,
|
|
57
|
+
],
|
|
58
|
+
kwargs={"reinvest_rate": self.reinvest_rate},
|
|
59
|
+
symbol=symbol,
|
|
60
|
+
is_elementwise=False,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def net_basis_spread(self):
|
|
65
|
+
"""
|
|
66
|
+
Calculate net basis spread (净基差).
|
|
67
|
+
|
|
68
|
+
Net basis spread = basis spread - carry return
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
Polars expression for net basis spread
|
|
72
|
+
"""
|
|
73
|
+
return self._call_plugin("evaluators_net_basis_spread")
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def accrued_interest(self):
|
|
77
|
+
"""
|
|
78
|
+
Calculate accrued interest (应计利息).
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
Polars expression for accrued interest
|
|
82
|
+
"""
|
|
83
|
+
return self._call_plugin("evaluators_accrued_interest")
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def deliver_accrued_interest(self):
|
|
87
|
+
"""
|
|
88
|
+
Calculate delivery accrued interest (国债期货交割应计利息).
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
Polars expression for delivery accrued interest
|
|
92
|
+
"""
|
|
93
|
+
return self._call_plugin("evaluators_deliver_accrued_interest")
|
|
94
|
+
|
|
95
|
+
@property
|
|
96
|
+
def cf(self):
|
|
97
|
+
"""
|
|
98
|
+
Calculate conversion factor (转换因子).
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
Polars expression for conversion factor
|
|
102
|
+
"""
|
|
103
|
+
return self._call_plugin("evaluators_cf")
|
|
104
|
+
|
|
105
|
+
@property
|
|
106
|
+
def dirty_price(self):
|
|
107
|
+
"""
|
|
108
|
+
Calculate bond dirty price (债券全价).
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
Polars expression for bond dirty price
|
|
112
|
+
"""
|
|
113
|
+
return self._call_plugin("evaluators_dirty_price")
|
|
114
|
+
|
|
115
|
+
@property
|
|
116
|
+
def clean_price(self):
|
|
117
|
+
"""
|
|
118
|
+
Calculate bond clean price (债券净价).
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
Polars expression for bond clean price
|
|
122
|
+
"""
|
|
123
|
+
return self._call_plugin("evaluators_clean_price")
|
|
124
|
+
|
|
125
|
+
@property
|
|
126
|
+
def future_dirty_price(self):
|
|
127
|
+
"""
|
|
128
|
+
Calculate future dirty price (期货全价/发票价格).
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
Polars expression for future dirty price
|
|
132
|
+
"""
|
|
133
|
+
return self._call_plugin("evaluators_future_dirty_price")
|
|
134
|
+
|
|
135
|
+
@property
|
|
136
|
+
def deliver_cost(self):
|
|
137
|
+
"""
|
|
138
|
+
Calculate delivery cost (交割成本).
|
|
139
|
+
|
|
140
|
+
Delivery cost = bond dirty price - interim coupon payments
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
Polars expression for delivery cost
|
|
144
|
+
"""
|
|
145
|
+
return self._call_plugin("evaluators_deliver_cost")
|
|
146
|
+
|
|
147
|
+
@property
|
|
148
|
+
def basis_spread(self):
|
|
149
|
+
"""
|
|
150
|
+
Calculate basis spread (基差).
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
Polars expression for basis spread
|
|
154
|
+
"""
|
|
155
|
+
return self._call_plugin("evaluators_basis_spread")
|
|
156
|
+
|
|
157
|
+
@property
|
|
158
|
+
def f_b_spread(self):
|
|
159
|
+
"""
|
|
160
|
+
Calculate futures-bond spread (期现价差).
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
Polars expression for futures-bond spread
|
|
164
|
+
"""
|
|
165
|
+
return self._call_plugin("evaluators_f_b_spread")
|
|
166
|
+
|
|
167
|
+
@property
|
|
168
|
+
def carry(self):
|
|
169
|
+
"""
|
|
170
|
+
Calculate carry return (持有收益).
|
|
171
|
+
|
|
172
|
+
Carry return = (delivery accrued - trading accrued + interim coupons) +
|
|
173
|
+
capital cost rate * (weighted average interim coupons - bond dirty price * remaining days / 365)
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
Polars expression for carry return
|
|
177
|
+
"""
|
|
178
|
+
return self._call_plugin("evaluators_carry")
|
|
179
|
+
|
|
180
|
+
@property
|
|
181
|
+
def duration(self):
|
|
182
|
+
"""
|
|
183
|
+
Calculate modified duration (修正久期).
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
Polars expression for modified duration
|
|
187
|
+
"""
|
|
188
|
+
return self._call_plugin("evaluators_duration")
|
|
189
|
+
|
|
190
|
+
@property
|
|
191
|
+
def irr(self):
|
|
192
|
+
"""
|
|
193
|
+
Calculate internal rate of return (内部收益率).
|
|
194
|
+
|
|
195
|
+
Returns:
|
|
196
|
+
Polars expression for internal rate of return
|
|
197
|
+
"""
|
|
198
|
+
return self._call_plugin("evaluators_irr")
|
|
199
|
+
|
|
200
|
+
@property
|
|
201
|
+
def future_ytm(self):
|
|
202
|
+
"""
|
|
203
|
+
Calculate futures implied yield to maturity (期货隐含收益率).
|
|
204
|
+
|
|
205
|
+
Returns:
|
|
206
|
+
Polars expression for futures implied yield to maturity
|
|
207
|
+
"""
|
|
208
|
+
return self._call_plugin("evaluators_future_ytm")
|
|
209
|
+
|
|
210
|
+
@property
|
|
211
|
+
def remain_cp_to_deliver(self):
|
|
212
|
+
"""
|
|
213
|
+
Calculate remaining coupon payments to delivery (到交割的期间付息).
|
|
214
|
+
|
|
215
|
+
Returns:
|
|
216
|
+
Polars expression for remaining coupon payments to delivery
|
|
217
|
+
"""
|
|
218
|
+
return self._call_plugin("evaluators_remain_cp_to_deliver")
|
|
219
|
+
|
|
220
|
+
@property
|
|
221
|
+
def remain_cp_to_deliver_wm(self):
|
|
222
|
+
"""
|
|
223
|
+
Calculate weighted average remaining coupon payments to delivery (加权平均到交割的期间付息).
|
|
224
|
+
|
|
225
|
+
Returns:
|
|
226
|
+
Polars expression for weighted average remaining coupon payments to delivery
|
|
227
|
+
"""
|
|
228
|
+
return self._call_plugin("evaluators_remain_cp_to_deliver_wm")
|
|
229
|
+
|
|
230
|
+
@property
|
|
231
|
+
def remain_cp_num(self):
|
|
232
|
+
"""
|
|
233
|
+
Calculate remaining number of coupon payments (债券剩余付息次数).
|
|
234
|
+
|
|
235
|
+
Returns:
|
|
236
|
+
Polars expression for remaining number of coupon payments
|
|
237
|
+
"""
|
|
238
|
+
return self._call_plugin("evaluators_remain_cp_num")
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
class Bonds:
|
|
242
|
+
def __init__(self, bond: IntoExpr = "symbol"):
|
|
243
|
+
self.bond = bond
|
|
244
|
+
|
|
245
|
+
def _evaluator(self, date=None, ytm=None) -> TfEvaluators:
|
|
246
|
+
return TfEvaluators(
|
|
247
|
+
future=None,
|
|
248
|
+
bond=self.bond,
|
|
249
|
+
date=date,
|
|
250
|
+
bond_ytm=ytm,
|
|
251
|
+
future_price=None,
|
|
252
|
+
capital_rate=None,
|
|
253
|
+
reinvest_rate=None,
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
def accrued_interest(self, date="date"):
|
|
257
|
+
return self._evaluator(date=date).accrued_interest
|
|
258
|
+
|
|
259
|
+
def clean_price(self, ytm="ytm", date="date"):
|
|
260
|
+
return self._evaluator(date=date, ytm=ytm).clean_price
|
|
261
|
+
|
|
262
|
+
def dirty_price(self, ytm="ytm", date="date"):
|
|
263
|
+
return self._evaluator(date=date, ytm=ytm).dirty_price
|
|
264
|
+
|
|
265
|
+
def duration(self, ytm="ytm", date="date"):
|
|
266
|
+
return self._evaluator(date=date, ytm=ytm).duration
|
|
267
|
+
|
|
268
|
+
def remain_cp_num(self, date="date"):
|
|
269
|
+
return self._evaluator(date=date).remain_cp_num
|
|
270
|
+
|
|
271
|
+
# TODO(Teamon): 实现向量化根据净价反推ytm的函数
|
pybond/pybond.abi3.so
CHANGED
|
Binary file
|
pybond/pybond.pyi
CHANGED
|
@@ -187,6 +187,26 @@ class TfEvaluator:
|
|
|
187
187
|
reinvest_rate: float | None = None,
|
|
188
188
|
) -> None: ...
|
|
189
189
|
def copy(self) -> TfEvaluator: ...
|
|
190
|
+
|
|
191
|
+
def date(self) -> date:
|
|
192
|
+
"""获取计算日期"""
|
|
193
|
+
|
|
194
|
+
@property
|
|
195
|
+
def bond_code(self) -> str:
|
|
196
|
+
"""获取债券代码"""
|
|
197
|
+
|
|
198
|
+
@property
|
|
199
|
+
def bond_ytm(self) -> float:
|
|
200
|
+
"""获取债券收益率"""
|
|
201
|
+
|
|
202
|
+
@property
|
|
203
|
+
def future(self) -> str:
|
|
204
|
+
"""获取期货代码"""
|
|
205
|
+
|
|
206
|
+
@property
|
|
207
|
+
def future_price(self) -> float:
|
|
208
|
+
"""获取期货价格"""
|
|
209
|
+
|
|
190
210
|
@property
|
|
191
211
|
def deliverable(self) -> bool:
|
|
192
212
|
"""判断债券是否是期货的可交割券"""
|
|
@@ -277,8 +297,8 @@ class TfEvaluator:
|
|
|
277
297
|
future_price: float | None = None,
|
|
278
298
|
bond_ytm: float | None = None,
|
|
279
299
|
date: date | None = None,
|
|
280
|
-
future: Future | None = None,
|
|
281
|
-
bond: Bond | None = None,
|
|
300
|
+
future: Future | str | None = None,
|
|
301
|
+
bond: Bond | str | int | None = None,
|
|
282
302
|
capital_rate: float | None = None,
|
|
283
303
|
reinvest_rate: float | None = None,
|
|
284
304
|
) -> TfEvaluator:
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
pybond/__init__.py,sha256=7x1hBQtlQRhvgxfe6Z0wtQ5tWpTfUPMnaKyjddRyk9Y,430
|
|
2
|
+
pybond/bond.py,sha256=8Tgy5rnDVk8OM6a1pXQlvfiv358BK_qS410XhgfC7mU,6533
|
|
3
|
+
pybond/download.py,sha256=ehl_LfcfjCB5dtVvqD0P9PJzK1UYlqhzpDcBq5BycDI,4222
|
|
4
|
+
pybond/ffi/__init__.py,sha256=x4FSqdM-SZPir9DL_XSMjoO9c4CWsyE5XfQr4GraGsg,94
|
|
5
|
+
pybond/ffi/bond.py,sha256=8SFjwBtf-t0uEEgdgdP2TCHkTr-pJCvVsJ7qIKsdh6c,1586
|
|
6
|
+
pybond/ffi/datetime.py,sha256=84vkmBhIf0HH4NEFeMLFbf83D_VewB5-PKeaDUobNmE,1989
|
|
7
|
+
pybond/ffi/duration.py,sha256=ryVI3MmkLFaCKUlQa6L6MWFm5rFXmkhq1XlolyZsZGE,670
|
|
8
|
+
pybond/ffi/evaluators.py,sha256=wz-52tVrK-0uUmCwIMl0yuTA13wTIVoYAHbEHdosBEI,6875
|
|
9
|
+
pybond/ffi/lib.py,sha256=PtAjBwzpNG8CYKJ-NbLAXJCcezMmFR4VZ3vpvmuhsUI,173
|
|
10
|
+
pybond/nb/__init__.py,sha256=-JvP7GpzQTKz-1Hcow_46EnakBWzJsr-3OoZjW8RQLY,746
|
|
11
|
+
pybond/nb/ir_utils.py,sha256=a4CoNvRdXR5ENUOmBn-h4ZEWRc3BnSZ1LlY2wX_RDbU,1557
|
|
12
|
+
pybond/nb/nb_bond.py,sha256=dLKVCgUgAwQu4MZm-zhRbzKPgM2wiWW_RIlA0VUvY7Y,5863
|
|
13
|
+
pybond/nb/nb_date.py,sha256=f4-3C8j4tz_j8cG4iuDBRsWiNnPalg9epJt-fd6VPQs,5621
|
|
14
|
+
pybond/nb/nb_datetime.py,sha256=9fLD9rnfpHQ-cvX4H6PoFh_O3jgk475ZKrG8q_UxT34,10264
|
|
15
|
+
pybond/nb/nb_duration.py,sha256=FSX1y2JbHB_SJn-hcVe-7Zf2v0xpQKKZ1MfWBY7d7IQ,1639
|
|
16
|
+
pybond/nb/nb_evaluators.py,sha256=fCYxcvW717_1E4qY9AV8R5Pv8eTvWqKk3Zj-zMU1kiw,14987
|
|
17
|
+
pybond/nb/nb_time.py,sha256=LaqXfcNvmYD_lZ2u108MwrxCXoVCBX3cr3oOnPp3c1g,8649
|
|
18
|
+
pybond/pl.py,sha256=CakQvQPjvWu8XykDfkBznFmFkIB8m-lVllF-8_BrUsw,7860
|
|
19
|
+
pybond/pnl.py,sha256=P3KXc-gz6_TA2QxDQR9NHJIJPCvLOGT_v4qN4gzdcRY,1568
|
|
20
|
+
pybond/polars_utils.py,sha256=A8D5T0x08oMCndWiQ5DPhLsuWp8s4OPgqvAnK36d8yY,2567
|
|
21
|
+
pybond/pybond.abi3.so,sha256=mjMUO5EJvRSLTrMqRUIyvPQYLuE9YVT3KOjO5QpaeDs,23194624
|
|
22
|
+
pybond/pybond.pyi,sha256=xME119HJzVNqNCJ9FapVaQg1amxbNHlbd-qfFyiuhL4,11230
|
|
23
|
+
tea_bond-0.3.0.dist-info/METADATA,sha256=c2dzL9VFNbo_TPTU0qanImpw1gZ1oMgQ0xdChChprD0,258
|
|
24
|
+
tea_bond-0.3.0.dist-info/WHEEL,sha256=6SJFcjb7LrrHSS0REgEixoO-eTgWD5-kklKS9aVl8Lw,103
|
|
25
|
+
tea_bond-0.3.0.dist-info/RECORD,,
|
tea_bond-0.2.8.dist-info/RECORD
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
pybond/__init__.py,sha256=3jDh14aBcaYtIqcCdHgEmO3Um3_4iJu8oOmQ-TrP3no,470
|
|
2
|
-
pybond/bond.py,sha256=vqp404MB6wtkCs7MVwXLLkqE9M3fF81XNXpgKdSp5T4,6432
|
|
3
|
-
pybond/download.py,sha256=ehl_LfcfjCB5dtVvqD0P9PJzK1UYlqhzpDcBq5BycDI,4222
|
|
4
|
-
pybond/ffi/__init__.py,sha256=AfoWeiKIR8kRNOtHRiVKSkKYdh76usXG9ca5CmTQig0,68
|
|
5
|
-
pybond/ffi/bond.py,sha256=zxmDRaMX51rdDW5DLjqKbVGWFmalbw_oGuiXA_9vNp4,1587
|
|
6
|
-
pybond/ffi/datetime.py,sha256=84vkmBhIf0HH4NEFeMLFbf83D_VewB5-PKeaDUobNmE,1989
|
|
7
|
-
pybond/ffi/duration.py,sha256=ryVI3MmkLFaCKUlQa6L6MWFm5rFXmkhq1XlolyZsZGE,670
|
|
8
|
-
pybond/ffi/lib.py,sha256=PtAjBwzpNG8CYKJ-NbLAXJCcezMmFR4VZ3vpvmuhsUI,173
|
|
9
|
-
pybond/nb/__init__.py,sha256=cqo0ohfxkVwDY-TQr8A68X_DCBG04FuP12RnO4FF5b0,604
|
|
10
|
-
pybond/nb/ir_utils.py,sha256=a4CoNvRdXR5ENUOmBn-h4ZEWRc3BnSZ1LlY2wX_RDbU,1557
|
|
11
|
-
pybond/nb/nb_bond.py,sha256=lFLrM7pKHcSLc1OfhUzUHz9e8bRxcav0jkwUMaOk5Ag,5988
|
|
12
|
-
pybond/nb/nb_date.py,sha256=YUOxn3ZMrPEh6r6WVSug8N6cXLq4qlKKXxObXg2WW_A,5522
|
|
13
|
-
pybond/nb/nb_datetime.py,sha256=-pXT5t0f7JL9TFcoq9UplFJ_Dafk0aCd-FMXJcuI8PY,10407
|
|
14
|
-
pybond/nb/nb_duration.py,sha256=2e-KpUW74-g4cfaHH3HG-TPFeFBgwjp0gmV2bw-jGb0,1797
|
|
15
|
-
pybond/nb/nb_time.py,sha256=LaqXfcNvmYD_lZ2u108MwrxCXoVCBX3cr3oOnPp3c1g,8649
|
|
16
|
-
pybond/pnl.py,sha256=P3KXc-gz6_TA2QxDQR9NHJIJPCvLOGT_v4qN4gzdcRY,1568
|
|
17
|
-
pybond/polars_utils.py,sha256=A8D5T0x08oMCndWiQ5DPhLsuWp8s4OPgqvAnK36d8yY,2567
|
|
18
|
-
pybond/pybond.abi3.so,sha256=fGWCyYB-B4OzRNIH6Xqh5xxB9ajPRrcynPGxoN4I_DY,22859280
|
|
19
|
-
pybond/pybond.pyi,sha256=tfBUxdT-oArCqgBvkxBq0OBbuaIG9M0K24t4vYZQ9zg,10823
|
|
20
|
-
tea_bond-0.2.8.dist-info/METADATA,sha256=XiFpennfidloYPdBFu_KydrPbyFzb2ZWjARwZiTdxyk,258
|
|
21
|
-
tea_bond-0.2.8.dist-info/WHEEL,sha256=wD2Ctt3-v4IFHfNiZHWpu5VDIR34tiGUub2S7_0Exgc,103
|
|
22
|
-
tea_bond-0.2.8.dist-info/RECORD,,
|