tea-bond 0.3.10__cp38-abi3-manylinux_2_34_x86_64.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 ADDED
@@ -0,0 +1,16 @@
1
+ from __future__ import annotations
2
+
3
+ from .bond import Bond
4
+ from .pybond import Future, Ib, Sse
5
+ from .pybond import TfEvaluator as _TfEvaluatorRS
6
+
7
+
8
+ class TfEvaluator(_TfEvaluatorRS):
9
+ def __new__(cls, future, bond, *args, **kwargs):
10
+ if not isinstance(bond, Bond):
11
+ # 便于直接从Wind下载债券基础数据
12
+ bond = Bond(bond)
13
+ return super().__new__(cls, future, bond, *args, **kwargs)
14
+
15
+
16
+ __all__ = ["Bond", "Future", "Ib", "Sse", "TfEvaluator"]
pybond/bond.py ADDED
@@ -0,0 +1,190 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ from datetime import date
5
+ from importlib.util import find_spec
6
+ from pathlib import Path
7
+
8
+ from .pybond import Bond as _BondRS
9
+ from .pybond import Future, download_bond
10
+
11
+ # from .ffi.utils import set_bond_data_path
12
+
13
+ WIND_AVAILABLE = find_spec("WindPy") is not None
14
+
15
+ if os.environ.get("BONDS_INFO_PATH") is not None:
16
+ bonds_info_environ_flag = True
17
+ bonds_info_path = Path(os.environ.get("BONDS_INFO_PATH"))
18
+ else:
19
+ bonds_info_environ_flag = False
20
+ bonds_info_path = Path(__file__).parent / "data" / "bonds_info"
21
+ os.environ["BONDS_INFO_PATH"] = str(bonds_info_path)
22
+
23
+ if not bonds_info_path.exists():
24
+ bonds_info_path.mkdir(parents=True)
25
+
26
+
27
+ class Bond(_BondRS):
28
+ def __new__(cls, code: str | int = "", path: str | Path | None = None):
29
+ """
30
+ Create a new Bond instance.
31
+
32
+ Args:
33
+ code (str | int): The bond code. If no extension is provided, '.IB' will be appended.
34
+ path (str | Path | None): Path to the bond info file. If None, uses default bonds_info_path.
35
+
36
+ Returns:
37
+ Bond: A new Bond instance, either loaded from existing JSON file or downloaded.
38
+
39
+ Note:
40
+ If a JSON file for the bond code doesn't exist at the specified path,
41
+ the bond info will be downloaded automatically.
42
+ """
43
+ code = str(code)
44
+ if code == "":
45
+ return super().__new__(cls, "", path)
46
+ if "." not in code:
47
+ code = code + ".IB"
48
+ path = bonds_info_path if path is None else Path(path)
49
+ if (path / (code + ".json")).exists():
50
+ return super().__new__(cls, code, path)
51
+ else:
52
+ cls.download(code, path)
53
+ return super().__new__(cls, code, path)
54
+
55
+ @classmethod
56
+ def from_json(cls, data: str | dict) -> Bond:
57
+ if isinstance(data, str):
58
+ import json
59
+
60
+ data = json.loads(data)
61
+ bond = Bond()
62
+ for k, v in data.items():
63
+ setattr(bond, k, v)
64
+ return bond
65
+
66
+ @staticmethod
67
+ def download(
68
+ code: str, path: str | None = None, source: str | None = None, save=True
69
+ ):
70
+ """
71
+ Download bond information from a specified source.
72
+
73
+ This method downloads bond information for a given bond code from either Wind or Rust.
74
+ If no source is specified, it defaults to Wind if the WindPy module is available; otherwise,
75
+ it falls back to Rust.
76
+
77
+ If the source is 'rust', the method will download IB bond information from China Money and
78
+ SH bond information from SSE (Shanghai Stock Exchange).
79
+
80
+ Args:
81
+ code (str): The bond code in the format 'XXXXXX.YY'. The code must include a dot.
82
+ path (str | None): The directory path where the downloaded bond information should be saved.
83
+ If None, the default path is used.
84
+ source (str | None): The source from which to download the bond information. Valid options are
85
+ 'wind' or 'rust'. If None, the source is automatically determined.
86
+ save (bool): Whether to save the downloaded bond information to the specified path.
87
+ Defaults to True.
88
+
89
+ Returns:
90
+ Bond: The downloaded bond object if the source is 'rust' and save is False.
91
+ Otherwise, returns None.
92
+
93
+ Raises:
94
+ AssertionError: If the code is not in the correct format or if the source is invalid.
95
+ """
96
+ if source is None:
97
+ # 优先从wind下载
98
+ source = "wind" if WIND_AVAILABLE else "rust"
99
+ assert "." in code, "code should be in the format of XXXXXX.YY"
100
+ assert source in ("wind", "rust")
101
+ if source == "wind":
102
+ from .download import fetch_symbols, login
103
+
104
+ print(f"Start downloading bond info for {code} from Wind")
105
+ login()
106
+ fetch_symbols([code], save=save, save_folder=path)
107
+ else:
108
+ # let rust side handle the download
109
+ print(f"download {code}")
110
+ bond = download_bond(code)
111
+ if save:
112
+ bond.save(path)
113
+ return bond
114
+
115
+ def accrued_interest(
116
+ self, date: date, cp_dates: tuple[date, date] | None = None
117
+ ) -> float:
118
+ """
119
+ 计算应计利息
120
+
121
+ 银行间和交易所的计算规则不同,银行间是算头不算尾,而交易所是算头又算尾
122
+ """
123
+ return self.calc_accrued_interest(date, cp_dates=cp_dates)
124
+
125
+ def dirty_price(
126
+ self,
127
+ ytm: float,
128
+ date: date,
129
+ cp_dates: tuple[date, date] | None = None,
130
+ remain_cp_num: int | None = None,
131
+ ) -> float:
132
+ """通过ytm计算债券全价"""
133
+ return self.calc_dirty_price_with_ytm(
134
+ ytm, date, cp_dates=cp_dates, remain_cp_num=remain_cp_num
135
+ )
136
+
137
+ def clean_price(
138
+ self,
139
+ ytm: float,
140
+ date: date,
141
+ cp_dates: tuple[date, date] | None = None,
142
+ remain_cp_num: int | None = None,
143
+ ) -> float:
144
+ """通过ytm计算债券净价"""
145
+ return self.calc_clean_price_with_ytm(
146
+ ytm, date, cp_dates=cp_dates, remain_cp_num=remain_cp_num
147
+ )
148
+
149
+ def macaulay_duration(
150
+ self,
151
+ ytm: float,
152
+ date: date,
153
+ cp_dates: tuple[date, date] | None = None,
154
+ remain_cp_num: int | None = None,
155
+ ) -> float:
156
+ """计算麦考利久期"""
157
+ return self.calc_macaulay_duration(
158
+ ytm, date, cp_dates=cp_dates, remain_cp_num=remain_cp_num
159
+ )
160
+
161
+ def duration(
162
+ self,
163
+ ytm: float,
164
+ date: date,
165
+ cp_dates: tuple[date, date] | None = None,
166
+ remain_cp_num: int | None = None,
167
+ ) -> float:
168
+ """计算修正久期"""
169
+ return self.calc_duration(
170
+ ytm, date, cp_dates=cp_dates, remain_cp_num=remain_cp_num
171
+ )
172
+
173
+ def cf(self, future: str | Future) -> float:
174
+ """计算转换因子"""
175
+ from .pybond import TfEvaluator
176
+
177
+ return TfEvaluator(future, self).cf
178
+
179
+ def calc_ytm_with_clean_price(
180
+ self,
181
+ clean_price: float,
182
+ date: date,
183
+ cp_dates: tuple[date, date] | None = None,
184
+ remain_cp_num: int | None = None,
185
+ ) -> float:
186
+ """通过净价计算债券ytm"""
187
+ dirty_price = clean_price + self.accrued_interest(date, cp_dates=cp_dates)
188
+ return self.calc_ytm_with_price(
189
+ dirty_price, date, cp_dates=cp_dates, remain_cp_num=remain_cp_num
190
+ )
pybond/download.py ADDED
@@ -0,0 +1,147 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ from datetime import date
5
+ from decimal import Decimal
6
+ from pathlib import Path
7
+
8
+ from WindPy import w
9
+
10
+ default_save_folder = Path("bonds_info")
11
+ # if not default_save_folder.exists():
12
+ # default_save_folder.mkdir()
13
+
14
+
15
+ def save_json(path: Path | str, data: dict) -> None:
16
+ """
17
+ Save data into json file in temp path.
18
+ """
19
+ path = Path(path)
20
+ with path.open(mode="w+", encoding="UTF-8") as f:
21
+ json.dump(data, f, indent=4, ensure_ascii=False)
22
+
23
+
24
+ def get_interest_type(typ: str):
25
+ if typ == "固定利率":
26
+ return "Fixed"
27
+ elif typ == "浮动利率":
28
+ return "Floating"
29
+ elif typ == "累进利率":
30
+ return "Progressive"
31
+ elif typ == "零息":
32
+ return "Zero"
33
+ else:
34
+ msg = f"Unknown interest type: {typ}"
35
+ raise ValueError(msg)
36
+
37
+
38
+ def get_payment_type(typ: str):
39
+ if typ == "附息":
40
+ return "Coupon_Bear"
41
+ elif typ == "到期一次还本付息":
42
+ return "One_Time"
43
+ elif typ == "贴现":
44
+ return "Zero_Coupon"
45
+ else:
46
+ msg = f"Unknown payment type: {typ}"
47
+ raise ValueError(msg)
48
+
49
+
50
+ def fetch_symbols(
51
+ symbols: list[str],
52
+ *,
53
+ save: bool = True,
54
+ skip: bool = True,
55
+ save_folder: Path | str | None = None,
56
+ ):
57
+ if save_folder is None:
58
+ save_folder = default_save_folder
59
+ if isinstance(save_folder, str):
60
+ save_folder = Path(save_folder)
61
+ if skip:
62
+ symbols = [s for s in symbols if not (save_folder / f"{s}.json").exists()]
63
+ data = w.wss(
64
+ symbols,
65
+ "sec_name,carrydate,maturitydate,interesttype,couponrate,paymenttype,actualbenchmark,coupon,interestfrequency,latestpar",
66
+ f"tradeDate={date.today()}",
67
+ ).Data
68
+ returns = []
69
+ for i, symbol in enumerate(symbols):
70
+ m = {"bond_code": symbol}
71
+ m["mkt"] = symbol.split(".")[1].upper()
72
+ m["abbr"] = data[0][i] # 债券简称
73
+ m["par_value"] = float(data[9][i]) # 面值
74
+ m["cp_type"] = get_payment_type(data[7][i]) # 付息频率
75
+ m["interest_type"] = get_interest_type(data[3][i]) # 付息方式
76
+ m["cp_rate_1st"] = float(Decimal(str(data[4][i])) / 100) # 票面利率
77
+ m["base_rate"] = None
78
+ m["rate_spread"] = None
79
+ if m["cp_type"] == "Coupon_Bear":
80
+ m["inst_freq"] = int(data[8][i]) # 年付息次数
81
+ elif m["cp_type"] == "One_Time":
82
+ m["inst_freq"] = 1
83
+ elif m["cp_type"] == "Zero_Coupon":
84
+ m["inst_freq"] = 0
85
+ m["carry_date"] = data[1][i].strftime("%Y-%m-%d") # 起息日
86
+ m["maturity_date"] = data[2][i].strftime("%Y-%m-%d") # 到期日
87
+ m["day_count"] = data[6][i] # 实际基准
88
+ returns.append(m)
89
+ print(m)
90
+ if save:
91
+ if not save_folder.exists():
92
+ save_folder.mkdir(parents=True)
93
+ path = save_folder / f"{symbol}.json"
94
+ save_json(path, m)
95
+ return returns
96
+
97
+
98
+ WAIT_LOGIN = False
99
+
100
+
101
+ def login():
102
+ global WAIT_LOGIN
103
+ if w.isconnected():
104
+ return
105
+ if WAIT_LOGIN:
106
+ import time
107
+
108
+ time.sleep(0.2)
109
+ login()
110
+ WAIT_LOGIN = True
111
+ login_res = w.start(waitTime=8)
112
+ WAIT_LOGIN = False
113
+ if login_res.ErrorCode != 0:
114
+ msg = f"Failed to login to Wind: {login_res.ErrorCode}"
115
+ raise RuntimeError(msg)
116
+
117
+
118
+ def get_all_symbols():
119
+ sector_ids = (
120
+ # "a101010101000000", # 国债银行间
121
+ # "a101010104000000", # 政策性银行债
122
+ "a101010201000000", # 上交所国债
123
+ )
124
+ res = []
125
+ names = []
126
+ for sector_id in sector_ids:
127
+ all_symbols = w.wset(
128
+ "sectorconstituent", f"sectorid={sector_id};field=wind_code,sec_name"
129
+ ).Data
130
+ res.extend(all_symbols[0])
131
+ names.extend(all_symbols[1])
132
+ print("共有", len(res), "只债券")
133
+ return res
134
+
135
+
136
+ if __name__ == "__main__":
137
+ login()
138
+ # symbols = ["220003.IB", "220021.IB", "220006.IB", "220010.IB"]
139
+ # symbols = ["240006.IB"]
140
+
141
+ # symbols = ["019733.SH"]
142
+ # symbols = ["020647.SH"]
143
+ # symbols = ["019727.SH"]
144
+ symbols = ["2400006.IB"]
145
+ # symbols = get_all_symbols()
146
+
147
+ fetch_symbols(symbols, save=0, skip=True)
pybond/ffi/__init__.py ADDED
@@ -0,0 +1,4 @@
1
+ from .bond import *
2
+ from .datetime import *
3
+ from .duration import *
4
+ from .evaluators import *
pybond/ffi/bond.py ADDED
@@ -0,0 +1,68 @@
1
+ import ctypes
2
+
3
+ from .lib import lib
4
+
5
+ create_bond = lib.create_bond
6
+ create_bond.argtypes = (ctypes.c_void_p, ctypes.c_size_t)
7
+ create_bond.restype = ctypes.c_void_p
8
+
9
+ free_bond = lib.free_bond
10
+ free_bond.argtypes = [ctypes.c_void_p]
11
+ free_bond.restype = None
12
+
13
+ bond_coupon_rate = lib.bond_coupon_rate
14
+ bond_coupon_rate.argtypes = [ctypes.c_void_p]
15
+ bond_coupon_rate.restype = ctypes.c_double
16
+
17
+ bond_full_code = lib.bond_full_code
18
+ bond_full_code.argtypes = [ctypes.c_void_p]
19
+ bond_full_code.restype = ctypes.c_char_p
20
+
21
+ bond_calc_ytm = lib.bond_calc_ytm
22
+ bond_calc_ytm.argtypes = [
23
+ ctypes.c_void_p,
24
+ ctypes.c_double,
25
+ ctypes.c_uint32,
26
+ ctypes.c_uint32,
27
+ ctypes.c_uint32,
28
+ ]
29
+ bond_calc_ytm.restype = ctypes.c_double
30
+
31
+ bond_duration = lib.bond_duration
32
+ bond_duration.argtypes = [
33
+ ctypes.c_void_p,
34
+ ctypes.c_double,
35
+ ctypes.c_uint32,
36
+ ctypes.c_uint32,
37
+ ctypes.c_uint32,
38
+ ]
39
+ bond_duration.restype = ctypes.c_double
40
+
41
+ bond_accrued_interest = lib.bond_accrued_interest
42
+ bond_accrued_interest.argtypes = [
43
+ ctypes.c_void_p,
44
+ ctypes.c_uint32,
45
+ ctypes.c_uint32,
46
+ ctypes.c_uint32,
47
+ ]
48
+ bond_accrued_interest.restype = ctypes.c_double
49
+
50
+ bond_dirty_price = lib.bond_dirty_price
51
+ bond_dirty_price.argtypes = [
52
+ ctypes.c_void_p,
53
+ ctypes.c_double,
54
+ ctypes.c_uint32,
55
+ ctypes.c_uint32,
56
+ ctypes.c_uint32,
57
+ ]
58
+ bond_dirty_price.restype = ctypes.c_double
59
+
60
+ bond_clean_price = lib.bond_clean_price
61
+ bond_clean_price.argtypes = [
62
+ ctypes.c_void_p,
63
+ ctypes.c_double,
64
+ ctypes.c_uint32,
65
+ ctypes.c_uint32,
66
+ ctypes.c_uint32,
67
+ ]
68
+ bond_clean_price.restype = ctypes.c_double
pybond/ffi/datetime.py ADDED
@@ -0,0 +1,58 @@
1
+ import ctypes
2
+
3
+ from .lib import lib
4
+
5
+ build_datetime_ns = lib.build_datetime_ns
6
+ build_datetime_ns.argtypes = (ctypes.c_int64,)
7
+ build_datetime_ns.restype = ctypes.c_void_p
8
+
9
+ build_datetime_from_utc_ns = lib.build_datetime_from_utc_ns
10
+ build_datetime_from_utc_ns.argtypes = (ctypes.c_int64,)
11
+ build_datetime_from_utc_ns.restype = ctypes.c_void_p
12
+
13
+ local_timestamp_nanos = lib.local_timestamp_nanos
14
+ local_timestamp_nanos.argtypes = (ctypes.c_void_p,)
15
+ local_timestamp_nanos.restype = ctypes.c_int64
16
+
17
+ timestamp_nanos = lib.timestamp_nanos
18
+ timestamp_nanos.argtypes = (ctypes.c_void_p,)
19
+ timestamp_nanos.restype = ctypes.c_int64
20
+
21
+ utc_timestamp_to_local = lib.utc_timestamp_to_local
22
+ utc_timestamp_to_local.argtypes = (ctypes.c_int64,)
23
+ utc_timestamp_to_local.restype = ctypes.c_int64
24
+
25
+ _free_datetime = lib.free_datetime
26
+ _free_datetime.argtypes = (ctypes.c_void_p,)
27
+
28
+ get_datetime_year = lib.get_datetime_year
29
+ get_datetime_year.argtypes = (ctypes.c_void_p,)
30
+ get_datetime_year.restype = ctypes.c_int32
31
+
32
+ get_datetime_month = lib.get_datetime_month
33
+ get_datetime_month.argtypes = (ctypes.c_void_p,)
34
+ get_datetime_month.restype = ctypes.c_int32
35
+
36
+ get_datetime_day = lib.get_datetime_day
37
+ get_datetime_day.argtypes = (ctypes.c_void_p,)
38
+ get_datetime_day.restype = ctypes.c_int32
39
+
40
+ get_datetime_hour = lib.get_datetime_hour
41
+ get_datetime_hour.argtypes = (ctypes.c_void_p,)
42
+ get_datetime_hour.restype = ctypes.c_int32
43
+
44
+ get_datetime_minute = lib.get_datetime_minute
45
+ get_datetime_minute.argtypes = (ctypes.c_void_p,)
46
+ get_datetime_minute.restype = ctypes.c_int32
47
+
48
+ get_datetime_second = lib.get_datetime_second
49
+ get_datetime_second.argtypes = (ctypes.c_void_p,)
50
+ get_datetime_second.restype = ctypes.c_int32
51
+
52
+ get_datetime_nanosecond = lib.get_datetime_nanosecond
53
+ get_datetime_nanosecond.argtypes = (ctypes.c_void_p,)
54
+ get_datetime_nanosecond.restype = ctypes.c_int32
55
+
56
+ datetime_with_time = lib.datetime_with_time
57
+ datetime_with_time.argtypes = (ctypes.c_void_p, (ctypes.c_uint32 * 6))
58
+ datetime_with_time.restype = ctypes.c_void_p
pybond/ffi/duration.py ADDED
@@ -0,0 +1,19 @@
1
+ import ctypes
2
+
3
+ from .lib import lib
4
+
5
+ parse_duration = lib.parse_duration
6
+ parse_duration.argtypes = [ctypes.c_void_p, ctypes.c_size_t]
7
+ parse_duration.restype = ctypes.c_void_p
8
+
9
+ datetime_sub_datetime = lib.datetime_sub_datetime
10
+ datetime_sub_datetime.argtypes = [ctypes.c_int64, ctypes.c_int64]
11
+ datetime_sub_datetime.restype = ctypes.c_void_p
12
+
13
+ datetime_add_duration = lib.datetime_add_duration
14
+ datetime_add_duration.argtypes = [ctypes.c_int64, ctypes.c_void_p]
15
+ datetime_add_duration.restype = ctypes.c_int64
16
+
17
+ datetime_sub_duration = lib.datetime_sub_duration
18
+ datetime_sub_duration.argtypes = [ctypes.c_int64, ctypes.c_void_p]
19
+ datetime_sub_duration.restype = ctypes.c_int64
@@ -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/ffi/lib.py ADDED
@@ -0,0 +1,8 @@
1
+ import ctypes
2
+
3
+ import llvmlite.binding
4
+
5
+ from pybond import pybond
6
+
7
+ lib = ctypes.cdll.LoadLibrary(pybond.__file__)
8
+ llvmlite.binding.load_library_permanently(pybond.__file__)