libfinance 0.0.1__tar.gz

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 libfinance might be problematic. Click here for more details.

@@ -0,0 +1,16 @@
1
+ Metadata-Version: 2.1
2
+ Name: libfinance
3
+ Version: 0.0.1
4
+ Summary: libfinance
5
+ Home-page:
6
+ Author:
7
+ Author-email:
8
+ License: Apache License v2
9
+ Classifier: Programming Language :: Python
10
+ Classifier: Operating System :: Microsoft :: Windows
11
+ Classifier: Operating System :: Unix
12
+ Classifier: Programming Language :: Python :: 3.7
13
+ Classifier: Programming Language :: Python :: 3.8
14
+ Requires-Dist: dill>=0.3.8
15
+ Requires-Dist: thriftpy2>=0.3.9
16
+ Requires-Dist: pandas>=0.16.2
@@ -0,0 +1,59 @@
1
+ # libfinance
2
+
3
+ `libfinance` is python library for accessing financial data easily. The goal of `libfinance` is to provide HIGH quality financial data for scholars, researchers and developers in research and production environment.
4
+
5
+
6
+ # install
7
+
8
+ Install `libfinance` by `pip`
9
+
10
+ ``` {.sourceCode .bash}
11
+ $ pip install libfinance
12
+ ```
13
+
14
+ Install with a develop mode
15
+ ~~~
16
+ git clone https://github.com/StateOfTheArt-quant/libfinance.git
17
+ cd libfinance
18
+ python setup.py develop
19
+ ~~~
20
+
21
+ # quick-start
22
+
23
+ ~~~
24
+ from libfinance import get_trading_dates, history_bars
25
+
26
+ trading_dates = get_trading_dates(start_date="2023-12-25", end_date="2024-01-11")
27
+ print(trading_dates)
28
+
29
+
30
+ DatetimeIndex(['2023-12-25', '2023-12-26', '2023-12-27', '2023-12-28',
31
+ '2023-12-29', '2024-01-02', '2024-01-03', '2024-01-04',
32
+ '2024-01-05', '2024-01-08', '2024-01-09', '2024-01-10',
33
+ '2024-01-11'],
34
+ dtype='datetime64[ns]', freq=None)
35
+
36
+
37
+
38
+
39
+ trading_data = history_bars(order_book_ids=["000001.XSHE","600000.XSHG"], bar_count=6, frequency="1d", datetime="2024-01-11")
40
+ print(trading_data)
41
+
42
+
43
+ open close ... volume total_turnover
44
+ order_book_id datetime ...
45
+ 000001.XSHE 2024-01-04 9.19 9.11 ... 86419399.0 7.874701e+08
46
+ 2024-01-05 9.10 9.27 ... 199162216.0 1.852660e+09
47
+ 2024-01-08 9.23 9.15 ... 112115619.0 1.029007e+09
48
+ 2024-01-09 9.16 9.18 ... 76619388.0 7.003757e+08
49
+ 2024-01-10 9.16 9.09 ... 85862091.0 7.837712e+08
50
+ 2024-01-11 9.08 9.17 ... 93468637.0 8.538902e+08
51
+ 600000.XSHG 2024-01-04 6.64 6.62 ... 28885978.0 1.905806e+08
52
+ 2024-01-05 6.60 6.68 ... 44421387.0 2.969769e+08
53
+ 2024-01-08 6.68 6.59 ... 37520337.0 2.479778e+08
54
+ 2024-01-09 6.60 6.61 ... 30741897.0 2.026476e+08
55
+ 2024-01-10 6.61 6.57 ... 22240946.0 1.466959e+08
56
+ 2024-01-11 6.56 6.53 ... 35914708.0 2.353121e+08
57
+ ~~~
58
+
59
+ # Documentation
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+
4
+ __all__ = []
5
+
6
+ from .version import __version__
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
@@ -0,0 +1,129 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ import bisect
4
+ import datetime
5
+ import pandas as pd
6
+
7
+ from libfinance.client import get_client
8
+ from libfinance.utils.decorators import export_as_api, ttl_cache, compatible_with_parm
9
+
10
+ def _to_timestamp(d):
11
+ return pd.Timestamp(d).replace(hour=0, minute=0, second=0, microsecond=0)
12
+
13
+ @ttl_cache(24 * 3600)
14
+ def _get_all_trading_dates():
15
+ return get_client().get_trading_calendar()
16
+
17
+ @export_as_api
18
+ def get_trading_dates(start_date, end_date):
19
+ r"""get the trading datata
20
+
21
+ 获取A股某个区间的交易日期
22
+
23
+ :param start_date: 开始日期
24
+ :param end_date: 结束如期
25
+
26
+ Example::
27
+
28
+ 获取2020-05-10至2020-05-20之间的交易日期
29
+
30
+ .. code-block:: python3
31
+
32
+ from libfinance.api import get_trading_dates
33
+
34
+
35
+ >>> trading_dates = get_trading_dates(start_date = "2020-05-11", end_date="2020-05-20")
36
+ >>> print(trading_dates)
37
+ DatetimeIndex(['2020-05-11', '2020-05-12', '2020-05-13', '2020-05-14',
38
+ '2020-05-15', '2020-05-18', '2020-05-19', '2020-05-20'],
39
+ dtype='datetime64[ns]', freq=None)
40
+ """
41
+ trading_dates = _get_all_trading_dates()
42
+
43
+ start_date = _to_timestamp(start_date)
44
+ end_date = _to_timestamp(end_date)
45
+ left = trading_dates.searchsorted(start_date)
46
+ right = trading_dates.searchsorted(end_date, side='right')
47
+ return trading_dates[left:right]
48
+
49
+ @export_as_api
50
+ def get_previous_trading_date(date, n=1):
51
+ """获取指定日期的之前的第 n 个交易日
52
+
53
+ :param date: 指定日期
54
+ :param n: 第 n 个交易日
55
+
56
+ Example::
57
+
58
+ 2020-05-18之前3天的交易日
59
+
60
+ .. code-block:: python3
61
+
62
+ from libfinance.api import get_previous_trading_date
63
+
64
+ >>> get_previous_trading_date(date='2020-05-18', n=3)
65
+ Timestamp('2020-05-13 00:00:00')
66
+ """
67
+ trading_dates = _get_all_trading_dates()
68
+ pos = trading_dates.searchsorted(_to_timestamp(date))
69
+ if pos >= n:
70
+ return trading_dates[pos - n]
71
+ else:
72
+ return trading_dates[0]
73
+
74
+ @export_as_api
75
+ def get_next_trading_date(date, n=1):
76
+ """
77
+ 获取指定日期之后的第 n 个交易日
78
+
79
+ :param date: 指定日期
80
+ :param n: 第 n 个交易日
81
+
82
+ :example:
83
+
84
+ .. code-block:: python3
85
+
86
+ from simonsc.api import get_next_trading_date
87
+
88
+ >>> get_next_trading_date(date='2020-05-13', n=3)
89
+ Timestamp('2020-05-18 00:00:00')
90
+ """
91
+ trading_dates = _get_all_trading_dates()
92
+ pos = trading_dates.searchsorted(_to_timestamp(date), side='right')
93
+ if pos + n > len(trading_dates):
94
+ return trading_dates[-1]
95
+ else:
96
+ return trading_dates[pos + n - 1]
97
+
98
+ @export_as_api
99
+ def is_trading_date(date):
100
+ date = _to_timestamp(date)
101
+ trading_dates = _get_all_trading_dates()
102
+ pos = trading_dates.searchsorted(date)
103
+ return pos < len(trading_dates) and trading_dates[pos] == date
104
+
105
+ @export_as_api
106
+ def get_n_trading_dates_until(date, n):
107
+ trading_dates = _get_all_trading_dates()
108
+ pos = trading_dates.searchsorted(_to_timestamp(date), side='right')
109
+ if pos >= n:
110
+ return trading_dates[pos - n:pos]
111
+ return trading_dates[:pos]
112
+
113
+ @export_as_api
114
+ def count_trading_dates(start_date, end_date):
115
+ start_date = _to_timestamp(start_date)
116
+ end_date = _to_timestamp(end_date)
117
+ trading_dates = _get_all_trading_dates()
118
+ return trading_dates.searchsorted(end_date, side='right') - trading_dates.searchsorted(start_date)
119
+
120
+
121
+ if __name__ == "__main__":
122
+ start_date = "2024-01-01"
123
+ end_date = "2024-02-27"
124
+
125
+ trading_dates = get_trading_dates(start_date, end_date)
126
+
127
+
128
+
129
+
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+
4
+ from typing import List, Union
5
+ import datetime
6
+
7
+ import pandas as pd
8
+ from libfinance.client import get_client
9
+ from libfinance.utils.decorators import export_as_api, ttl_cache, compatible_with_parm
10
+ from libfinance.utils.datetime_func import convert_dateteime_to_timestamp
11
+
12
+ @export_as_api
13
+ def history_bars(
14
+ order_book_ids: list,
15
+ bar_count: int,
16
+ frequency: str,
17
+ datetime: str,
18
+ fields: List[str]=None,
19
+ skip_suspended: bool=True,
20
+ include_now: bool=True,
21
+ adjust_type: str="none",
22
+ adjust_orig:datetime.datetime = None) -> pd.DataFrame:
23
+ """获取指定合约的历史 k 线行情,支持任意日频率xd(1d,5d)和任意分钟频率xm(1m,3m,5m,15m)的历史数据。
24
+
25
+ :param order_book_ids: 多个标的合约代码
26
+ :param bar_count: 获取的历史数据数量,必填项
27
+ :param frequency: 获取数据什么样的频率进行。'1d'或'1m'分别表示每日和每分钟,必填项
28
+ :param fields: 返回数据字段。必填项。见下方列表。
29
+ :param skip_suspended: 是否跳过停牌数据
30
+ :param include_now: 是否包含当前数据
31
+ :param adjust_type: 复权类型,默认为前复权 pre;可选 pre, none, post
32
+
33
+ ========================= ===================================================
34
+ fields 字段名
35
+ ========================= ===================================================
36
+ datetime 时间戳
37
+ open 开盘价
38
+ high 最高价
39
+ low 最低价
40
+ close 收盘价
41
+ volume 成交量
42
+ total_turnover 成交额
43
+ open_interest 持仓量(期货专用)
44
+ basis_spread 期现差(股指期货专用)
45
+ settlement 结算价(期货日线专用)
46
+ prev_settlement 结算价(期货日线专用)
47
+ ========================= ===================================================
48
+
49
+ Example1::
50
+
51
+ 获取中国平安和万科 2020-04-20之前10天的交易数据
52
+
53
+ .. code-block:: python3
54
+
55
+ import pandas as pd
56
+ from simons.api import history_bars
57
+
58
+ #
59
+ >>> dt = pd.Timestamp("2020-04-20")
60
+ >>> fields=["datetime","open","high","low","close","volume"]
61
+ >>> data = history_bars(order_book_ids=["000001.XSHE", "000002.XSHE"], datatime=dt, bar_count=10, frequency="1d", fields=fields)
62
+ >>> print(data)
63
+
64
+ open high low close volume
65
+ order_book_id datetime
66
+ 000001.XSHE 2020-04-07 12.89 12.94 12.81 12.88 87031371.0
67
+ 2020-04-08 12.88 12.92 12.72 12.78 52871614.0
68
+ 2020-04-09 12.88 12.89 12.72 12.74 40855377.0
69
+ 2020-04-10 12.76 12.98 12.65 12.79 66667495.0
70
+ 2020-04-13 12.67 12.71 12.47 12.59 44621440.0
71
+ 2020-04-14 12.65 12.86 12.57 12.86 68608687.0
72
+ 2020-04-15 12.86 12.93 12.78 12.87 65639640.0
73
+ 2020-04-16 12.79 12.79 12.54 12.68 78915498.0
74
+ 2020-04-17 12.77 13.04 12.65 12.89 133116477.0
75
+ 2020-04-20 12.86 13.05 12.77 12.99 81845583.0
76
+ 000002.XSHE 2020-04-07 27.34 27.42 26.80 27.07 67154006.0
77
+ 2020-04-08 26.90 27.25 26.75 26.96 41251395.0
78
+ 2020-04-09 27.10 27.16 26.60 26.69 38726254.0
79
+ 2020-04-10 26.84 27.34 26.59 26.88 62460322.0
80
+ 2020-04-13 26.74 27.13 26.61 27.04 43264902.0
81
+ 2020-04-14 27.10 27.75 27.02 27.35 64241868.0
82
+ 2020-04-15 27.20 27.23 26.55 26.70 70359257.0
83
+ 2020-04-16 26.52 26.76 26.40 26.58 50238931.0
84
+ 2020-04-17 26.78 27.03 26.55 26.72 83813322.0
85
+ 2020-04-20 26.78 26.81 26.05 26.58 85012343.0
86
+
87
+ """
88
+ dt = convert_dateteime_to_timestamp(datetime)
89
+ return get_client().multi_history_bars(order_book_ids=order_book_ids,
90
+ bar_count=bar_count,
91
+ frequency=frequency,
92
+ fields=fields,
93
+ dt=dt,
94
+ skip_suspended=skip_suspended,
95
+ include_now=include_now,
96
+ adjust_type=adjust_type,
97
+ adjust_orig=adjust_orig)
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+
4
+ import datetime
5
+ from typing import Any, Union, Optional, Iterable, Dict, List, Sequence, Iterable
6
+
7
+ import pandas as pd
8
+ from libfinance.client import get_client
9
+ from libfinance.utils.decorators import export_as_api, ttl_cache, compatible_with_parm
10
+
11
+ @export_as_api
12
+ def get_instrument_industry(order_book_ids: list, date: Union[str, datetime.datetime], source: str = "010303") -> pd.DataFrame():
13
+
14
+ return get_client().get_instrument_industry(order_book_ids=order_book_ids, date=date, source=source)
15
+
16
+ @export_as_api
17
+ def get_index_weights(index_id: str = "000300.XSHG", date: Union[str, datetime.datetime] = None) -> pd.DataFrame:
18
+ return get_client().get_index_weights(index_id=index_id, date = date)
19
+
20
+
@@ -0,0 +1,147 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ import time
4
+ import socket
5
+ import threading
6
+ import warnings
7
+
8
+ import pdb
9
+
10
+ import thriftpy2 as thriftpy
11
+ from thriftpy2.rpc import make_client
12
+ from thriftpy2.transport import TTransportException
13
+ try:
14
+ from thriftpy2.protocol.cybin import ProtocolError
15
+ except ImportError:
16
+ ProtocolError = type('FakeProtocolError', (Exception,), {})
17
+
18
+ #from libfinance.thriftclient import libfinance_thrift
19
+ from libfinance.utils.serialize import serialize_object, deserialize_object
20
+ from libfinance.utils.loader import load_thrift_module
21
+
22
+ socket_error = (TTransportException, socket.error, ProtocolError)
23
+
24
+ libfinance_thrift = load_thrift_module(__file__, "libfinance.thrift")
25
+
26
+
27
+ class ResponseError(Exception):
28
+ """响应错误"""
29
+
30
+
31
+
32
+ class LibFinanceClient(object):
33
+
34
+ _threading_local = threading.local()
35
+ _auth_params = {}
36
+
37
+ _default_host = "127.0.0.1"
38
+ _default_port = 9090
39
+
40
+ request_timeout = 300
41
+ request_attempt_count = 3
42
+
43
+ def __init__(self, host=None, port=None, username="", password="", token=""):
44
+ self.host = host or self._default_host
45
+ self.port = int(port or self._default_port)
46
+ self.username = username
47
+ self.password = password
48
+ self.token = token
49
+
50
+ assert self.host, "host is required"
51
+ assert self.port, "port is required"
52
+ #assert self.username or self.token, "username is required"
53
+ #assert self.password or self.token, "password is required"
54
+
55
+ self.client = None
56
+ self.inited = False
57
+ self.not_auth = True
58
+ self.compress = True
59
+ self.data_api_url = ""
60
+ self._http_token = ""
61
+
62
+ self._create_client()
63
+
64
+ def _create_client(self):
65
+ self.client = make_client(
66
+ libfinance_thrift.LibfinanceService,
67
+ self.host,
68
+ self.port,
69
+ timeout=(self.request_timeout * 1000)
70
+ )
71
+ return self.client
72
+
73
+ def __getattr__(self, api_name):
74
+ return lambda **kwargs: self(api_name, **kwargs)
75
+
76
+ def __call__(self, api_name, **kwargs):
77
+ err, result = None, None
78
+ for attempt_index in range(self.request_attempt_count):
79
+ try:
80
+ result = self.query(api_name, kwargs)
81
+ break
82
+ except socket_error as ex:
83
+ if (
84
+ isinstance(ex, socket.timeout) or
85
+ "TSocket read 0 bytes" in str(ex) or
86
+ not self._ping_server()
87
+ ):
88
+ self._reset()
89
+ err = ex
90
+ if attempt_index < self.request_attempt_count - 1:
91
+ time.sleep(0.6)
92
+ except ResponseError as ex:
93
+ err = ex
94
+
95
+ if result is None and isinstance(err, Exception):
96
+ if "TSocket read 0 bytes" in str(err):
97
+ raise Exception("连接被关闭,请减少数据查询量或检查网络后重试")
98
+ raise err
99
+
100
+ return result
101
+
102
+ def query(self, api_name, params):
103
+
104
+ request = libfinance_thrift.St_Query_Req()
105
+ request.api_name = api_name
106
+ request.params = serialize_object(params)
107
+
108
+
109
+ result = None
110
+ try:
111
+ #pdb.set_trace()
112
+ #self.ensure_auth()
113
+ response = self.client.query(request)
114
+ #pdb.set_trace()
115
+ if response.status is False:
116
+ # error occur
117
+ # raise RuntimeError(response.msg)
118
+ warnings.warn(response.msg)
119
+
120
+ # get process result
121
+ result = deserialize_object(response.result)
122
+ except Exception as e:
123
+ print(e)
124
+ raise RuntimeError("error:{}".format(e))
125
+
126
+ return result
127
+
128
+
129
+ _CLIENT = LibFinanceClient()
130
+
131
+
132
+ def get_client():
133
+ return _CLIENT
134
+
135
+
136
+
137
+
138
+ if __name__ == "__main__":
139
+ client = LibFinanceClient()
140
+
141
+
142
+ #output = client.get_trading_dates(start_date="2024-01-01",end_date="2024-02-22")
143
+ #print(output)
144
+
145
+ output = client.get_trading_dates("2024-01-01","2024-02-22")
146
+ print(output)
147
+
@@ -0,0 +1,16 @@
1
+ struct St_Query_Req {
2
+ 1:required string api_name,
3
+ 2:required binary params,
4
+ }
5
+
6
+ struct St_Query_Rsp {
7
+ 1:required bool status,
8
+ 2:optional string msg,
9
+ 3:optional binary result
10
+ }
11
+
12
+ service LibfinanceService {
13
+ St_Query_Rsp query(1:St_Query_Req request),
14
+ St_Query_Rsp auth(1:string username, 2:string password)//, 5:bool compress, 8:string mac, 10:string version),
15
+ St_Query_Rsp auth_by_token(1: string token)
16
+ }
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Created on Sun Feb 25 18:59:59 2024
5
+
6
+ @author: yujiang
7
+ """
8
+
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ import six
4
+ import datetime
5
+ import pandas as pd
6
+
7
+ def convert_datetime_to_str(dt):
8
+ if dt is None:
9
+ return None
10
+ if isinstance(dt, pd.Timestamp):
11
+ dt = dt.to_pydatetime()
12
+ if isinstance(dt, six.string_types):
13
+ return dt
14
+ if isinstance(dt, datetime.datetime):
15
+ return dt.strftime("%Y-%m-%d %H:%M:%S")
16
+ if isinstance(dt, datetime.date):
17
+ return dt.strftime("%Y-%m-%d")
18
+
19
+
20
+ def convert_dateteime_to_timestamp(dt):
21
+ if isinstance(dt, pd.Timestamp):
22
+ return dt
23
+
24
+ if isinstance(dt, ((str, datetime.date, datetime.datetime))):
25
+ return pd.Timestamp(dt)
26
+ return dt
@@ -0,0 +1,150 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+
4
+ import time
5
+ import types
6
+ import warnings
7
+ from functools import wraps, partial, update_wrapper
8
+
9
+ import libfinance
10
+
11
+
12
+ def deprecated(func=None, msg=None):
13
+ if func is None:
14
+ return partial(deprecated, msg=msg)
15
+
16
+ if msg is None:
17
+ msg = func.__name__ + " is deprecated, and will be removed in future."
18
+
19
+ @wraps(func)
20
+ def wrap(*args, **kwargs):
21
+ warnings.warn(msg, category=DeprecationWarning, stacklevel=0)
22
+ return func(*args, **kwargs)
23
+
24
+ return wrap
25
+
26
+
27
+ def export_as_api(f=None, name=None, namespace=None, priority=0):
28
+ if f is None:
29
+ return partial(export_as_api, name=name, namespace=namespace)
30
+ name = name if name else f.__name__
31
+ if namespace:
32
+ if hasattr(libfinance, namespace):
33
+ namespace = getattr(libfinance, namespace)
34
+ else:
35
+ namespace_name = namespace
36
+ namespace = types.ModuleType(namespace_name)
37
+ namespace.__file__ = 'libfinance plugin'
38
+ namespace.__module__ = "libfinance"
39
+ setattr(libfinance, namespace_name, namespace)
40
+ libfinance.__all__.append(namespace_name)
41
+ else:
42
+ namespace = libfinance
43
+ libfinance.__all__.append(name)
44
+
45
+ old_f = getattr(namespace, name, None)
46
+ if old_f is not None:
47
+ if old_f.__priority > priority:
48
+ warnings.warn("!!!! CAN'T OVERWRITE API {} WITH {} BECAUSE OLD PRIPORITY {} > {} !!!!".format(name, f, old_f.__priority, priority))
49
+ return f
50
+ warnings.warn("!!!! OVERWRITE API {} WITH {} !!!!".format(name, f))
51
+
52
+ f.__priority = priority
53
+ setattr(namespace, name, f)
54
+
55
+ return f
56
+
57
+
58
+ def retry(count, suppress_exceptions, delay=1.0):
59
+ def decorate(func):
60
+ @wraps(func)
61
+ def wrap(*args, **kwargs):
62
+ c = count
63
+ while c > 0:
64
+ try:
65
+ return func(*args, **kwargs)
66
+ except suppress_exceptions as e:
67
+ c -= 1
68
+ if c == 0:
69
+ raise e
70
+ if delay:
71
+ time.sleep(delay)
72
+
73
+ return wrap
74
+
75
+ return decorate
76
+
77
+
78
+ def coroutine(func):
79
+ @wraps(func)
80
+ def primer(*args, **kwargs):
81
+ gen = func(*args, **kwargs)
82
+ next(gen)
83
+ return gen
84
+
85
+ return primer
86
+
87
+
88
+ _ttl_cached_functions = set()
89
+
90
+
91
+ def ttl_cache(ttl):
92
+ if not isinstance(ttl, int) or not ttl > 0:
93
+ raise TypeError("Expected ttl to be a positive integer")
94
+
95
+ def decorating_function(user_function):
96
+ wrapper = _ttl_cache_wrapper(user_function, ttl)
97
+ _ttl_cached_functions.add(wrapper)
98
+ return update_wrapper(wrapper, user_function)
99
+
100
+ return decorating_function
101
+
102
+
103
+ def ttl_cache_clear():
104
+ for f in _ttl_cached_functions:
105
+ f.clear()
106
+
107
+
108
+ def _ttl_cache_wrapper(user_function, ttl):
109
+ sentinel = object()
110
+ cache = {}
111
+ cache_get = cache.get # bound method to lookup a key or return None
112
+ cache_clear = cache.clear
113
+
114
+ def wrapper(*args, **kwargs):
115
+ if kwargs:
116
+ key = args + (repr(sorted(kwargs.items())),)
117
+ else:
118
+ key = args
119
+
120
+ # in cpython, dict.get is thread-safe
121
+ result = cache_get(key, sentinel)
122
+ if result is not sentinel:
123
+ expire_at, value = result
124
+ if expire_at > time.time():
125
+ return value
126
+ value = user_function(*args, **kwargs)
127
+ cache[key] = (time.time() + ttl, value)
128
+ return value
129
+
130
+ setattr(wrapper, 'clear', cache_clear)
131
+ return wrapper
132
+
133
+
134
+ def compatible_with_parm(func=None, name=None, value=None, replace=None):
135
+ if func is None:
136
+ return partial(compatible_with_parm, name=name, value=value, replace=replace)
137
+
138
+ @wraps(func)
139
+ def wrap(*args, **kwargs):
140
+ if name:
141
+ if name in kwargs:
142
+ msg = "'{}' is no longer used, please use '{}' instead ".format(name, replace)
143
+ warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
144
+ item = kwargs.pop(name)
145
+ if item != value:
146
+ raise ValueError("'{}': except '{}', got '{}'".format(name, value, item))
147
+ return func(*args, **kwargs)
148
+
149
+ return wrap
150
+
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+
4
+ import thriftpy2
5
+
6
+ from typing import Any
7
+ from pathlib import Path
8
+
9
+
10
+ def load_thrift_module(dir_or_file: str, thrift_file: str = "") -> Any:
11
+ """加载thrift模块
12
+
13
+ Args:
14
+ dir_or_file (str): .thrift所在的文件或文件夹路径,若是文件则取当前文件所在目录为默认根目录
15
+ thrift_file (str, optional): thrift文件名全称,如果未提供,则默认按传入的文件名进行解析
16
+
17
+ Returns:
18
+ Any: thrifty配置文件加载后的实例
19
+
20
+ Examples:
21
+ >>> load_thrift_module(__file__, "pingpong.thrift")
22
+ <module 'pingpong_thrift'>
23
+ >>> load_thrift_module("/home/user/pingpong.thrift")
24
+ <module 'pingpong_thrift'>
25
+ """
26
+ # current file absolute working directory
27
+ working_dir = Path(dir_or_file).absolute()
28
+ # if file get file directory
29
+ if working_dir.is_file():
30
+ working_dir = working_dir.parent
31
+ thrift_file = thrift_file or working_dir.name
32
+ # is file name valid
33
+ if len(thrift_file) == 0:
34
+ raise ValueError(
35
+ "thrift file name is empty, please check path '{}' contains ".format(dir_or_file) +
36
+ "file name or given 'thrift_file' parameter when called 'load_thrift_module' function."
37
+ )
38
+ # convert file name from 'demo.thrifty' to module name 'demo_thrifty'
39
+ thrift_module_name = thrift_file.replace(".", "_")
40
+ # thriftpy2 do not support pathlib
41
+ thrift_module = thriftpy2.load(path=str(working_dir.joinpath(thrift_file)),
42
+ module_name=thrift_module_name)
43
+
44
+ return thrift_module
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ import dill
4
+ import pickle
5
+
6
+ from typing import Any
7
+
8
+
9
+ def serialize_object(obj: Any, protocol: int = pickle.DEFAULT_PROTOCOL) -> bytes:
10
+ """serialize obj to bytes
11
+
12
+ protocol v5 only available in python3.8,it`s a new feature that can accelerate memory process efficiency.
13
+ We highly recommend use v5,but to adapt more other python version choose protocol v4 as default,consider
14
+ adding a new api in 'Handle' class to sync client and server protocol.
15
+
16
+ Args:
17
+ obj (object): almost support all python standard types,exclude frame, generator, traceback
18
+ protocol (int, optional): protocol can be 0-5,refer to https://docs.python.org/zh-cn/3/library/pickle.html#pickle-protocols
19
+
20
+ Returns:
21
+ bytes: serialize value
22
+ """
23
+ return dill.dumps(obj, protocol=protocol)
24
+
25
+
26
+ def deserialize_object(stream: bytes) -> Any:
27
+ """deserialize bytes to object
28
+
29
+ Args:
30
+ stream (bytes): serialize bytes
31
+
32
+ Returns:
33
+ Any: deserialize object
34
+ """
35
+ if stream is None:
36
+ return
37
+
38
+ return dill.loads(stream)
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ __version__ = "0.0.1"
@@ -0,0 +1,16 @@
1
+ Metadata-Version: 2.1
2
+ Name: libfinance
3
+ Version: 0.0.1
4
+ Summary: libfinance
5
+ Home-page:
6
+ Author:
7
+ Author-email:
8
+ License: Apache License v2
9
+ Classifier: Programming Language :: Python
10
+ Classifier: Operating System :: Microsoft :: Windows
11
+ Classifier: Operating System :: Unix
12
+ Classifier: Programming Language :: Python :: 3.7
13
+ Classifier: Programming Language :: Python :: 3.8
14
+ Requires-Dist: dill>=0.3.8
15
+ Requires-Dist: thriftpy2>=0.3.9
16
+ Requires-Dist: pandas>=0.16.2
@@ -0,0 +1,21 @@
1
+ README.md
2
+ setup.py
3
+ libfinance/__init__.py
4
+ libfinance/client.py
5
+ libfinance/libfinance.thrift
6
+ libfinance/version.py
7
+ libfinance.egg-info/PKG-INFO
8
+ libfinance.egg-info/SOURCES.txt
9
+ libfinance.egg-info/dependency_links.txt
10
+ libfinance.egg-info/not-zip-safe
11
+ libfinance.egg-info/requires.txt
12
+ libfinance.egg-info/top_level.txt
13
+ libfinance/api/__init__.py
14
+ libfinance/api/calendar.py
15
+ libfinance/api/get_price.py
16
+ libfinance/api/index_components.py
17
+ libfinance/utils/__init__.py
18
+ libfinance/utils/datetime_func.py
19
+ libfinance/utils/decorators.py
20
+ libfinance/utils/loader.py
21
+ libfinance/utils/serialize.py
@@ -0,0 +1,3 @@
1
+ dill>=0.3.8
2
+ thriftpy2>=0.3.9
3
+ pandas>=0.16.2
@@ -0,0 +1 @@
1
+ libfinance
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ from os.path import dirname, join
4
+
5
+ from setuptools import find_packages, setup
6
+
7
+ from libfinance.version import __version__
8
+
9
+ def read_file(file):
10
+ with open(file, "rt") as f:
11
+ return f.read()
12
+
13
+
14
+ setup(
15
+ name='libfinance',
16
+ version=__version__,
17
+ description='libfinance',
18
+ packages=find_packages(exclude=[]),
19
+ author='',
20
+ author_email='',
21
+ license='Apache License v2',
22
+ package_data={'': ['*.*']},
23
+ url='',
24
+ install_requires=["dill>=0.3.8", "thriftpy2>=0.3.9","pandas>=0.16.2"],
25
+ zip_safe=False,
26
+ classifiers=[
27
+ 'Programming Language :: Python',
28
+ 'Operating System :: Microsoft :: Windows',
29
+ 'Operating System :: Unix',
30
+ 'Programming Language :: Python :: 3.7',
31
+ 'Programming Language :: Python :: 3.8',
32
+ ],
33
+ )