rquote 0.3.4__py3-none-any.whl → 0.3.6__py3-none-any.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.
rquote/utils/web.py ADDED
@@ -0,0 +1,109 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Web工具
4
+ """
5
+ import random
6
+ import uuid
7
+ import httpx
8
+ import logging
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+
13
+ class WebUtils:
14
+ """Web工具类"""
15
+
16
+ UA_LIST = [
17
+ 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101',
18
+ 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122',
19
+ 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71',
20
+ 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95',
21
+ 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71',
22
+ 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)',
23
+ 'Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50',
24
+ 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0',
25
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/534.55.3 (KHTML, like Gecko) Version/5.1.5 Safari/534.55.3',
26
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36',
27
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/521.61'
28
+ ]
29
+
30
+ @staticmethod
31
+ def ua():
32
+ """获取随机User-Agent"""
33
+ return random.choice(WebUtils.UA_LIST)
34
+
35
+ @classmethod
36
+ def headers(cls):
37
+ """获取请求头"""
38
+ return {
39
+ 'referer': str(uuid.uuid4()),
40
+ 'user-agent': cls.ua()
41
+ }
42
+
43
+ @classmethod
44
+ def http_get(cls, url, headers, method, proxy=None):
45
+ """
46
+ HTTP GET请求(已废弃,建议使用HTTPClient)
47
+ """
48
+ headers['user-agent'] = cls.ua()
49
+ try:
50
+ r = httpx.get(url, allow_redirects=True, headers=headers)
51
+ except Exception as e:
52
+ logger.error('Fetch url {} err: {}'.format(url, e))
53
+ return None
54
+ if r:
55
+ if method == 'text':
56
+ return r.text
57
+ elif method == 'content':
58
+ return r.content
59
+
60
+ @classmethod
61
+ def test_proxy(cls, proxy: str):
62
+ """
63
+ 测试代理是否可用
64
+
65
+ Args:
66
+ proxy: 代理地址,格式 'ip:port'
67
+
68
+ Returns:
69
+ 1表示可用,0表示不可用
70
+ """
71
+ try:
72
+ proxies = {'http://': proxy, 'https://': proxy} if '://' not in proxy else proxy
73
+ with httpx.Client(proxies=proxies, timeout=2) as client:
74
+ r = client.get('https://baidu.com', timeout=2)
75
+ if r.status_code == 200:
76
+ logger.info(f'test proxy {proxy} positive')
77
+ return 1
78
+ else:
79
+ logger.info(f'test proxy {proxy} negative (status: {r.status_code})')
80
+ return 0
81
+ except Exception as e:
82
+ logger.info(f'test proxy {proxy} negative: {e}')
83
+ return 0
84
+
85
+
86
+ class hget:
87
+ """
88
+ HTTP GET请求类(向后兼容)
89
+
90
+ 注意:建议使用HTTPClient替代
91
+ """
92
+ def __init__(self, url, *args, **kwargs):
93
+ self.url = url
94
+ r = None
95
+ try:
96
+ r = httpx.get(
97
+ self.url, follow_redirects=True, headers=WebUtils.headers(),
98
+ *args, **kwargs)
99
+ self.text = r.text
100
+ self.content = r.content
101
+ except Exception as e:
102
+ logger.error(f'fetch {self.url} err: {e}')
103
+ self.text = ''
104
+ self.content = b''
105
+ finally:
106
+ # 确保响应对象被关闭,释放SSL连接
107
+ if r is not None:
108
+ r.close()
109
+
rquote/utils.py CHANGED
@@ -1,197 +1,11 @@
1
1
  # -*- coding: utf-8 -*-
2
-
3
- import time
4
- import random
5
- import logging
6
- import httpx
7
- import pandas as pd
8
- import uuid
9
-
10
- def setup_logger():
11
- logger = logging.getLogger('rquote')
12
- if not logger.handlers:
13
- logger.setLevel(logging.INFO)
14
- file_handler = logging.FileHandler('/tmp/rquote.log')
15
-
16
- formatter = logging.Formatter('%(asctime)-15s:%(lineno)s %(message)s')
17
- file_handler.setFormatter(formatter)
18
-
19
- logger.addHandler(file_handler)
20
- logger.addHandler(logging.StreamHandler())
21
-
22
- return logger
23
-
24
- logger = setup_logger()
25
-
26
-
27
- class WebUtils:
28
- @staticmethod
29
- def ua():
30
- ua_list = [
31
- 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101',
32
- 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122',
33
- 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71',
34
- 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95',
35
- 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71',
36
- 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)',
37
- 'Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50',
38
- 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0',
39
- 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/534.55.3 (KHTML, like Gecko) Version/5.1.5 Safari/534.55.3',
40
- 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36',
41
- 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/521.61'
42
- ]
43
- return random.choice(ua_list)
44
-
45
- @classmethod
46
- def headers(cls):
47
- header = {
48
- 'referer': str(uuid.uuid4()),
49
- 'user-agent': cls.ua()
50
- }
51
- return header
52
-
53
- @classmethod
54
- def http_get(cls, url, headers, method, proxy=None):
55
- '''
56
- request.get() wrapper
57
- '''
58
- headers['user-agent'] = cls.ua
59
- try:
60
- r = httpx.get(url, allow_redirects=True)
61
- except Exception as e:
62
- logger.error('Fetch url {} err: {}'.format(url, e))
63
- return None
64
- if r:
65
- if method == 'text':
66
- return r.text
67
- elif method == 'content':
68
- return r.content
69
-
70
- @classmethod
71
- def test_proxy(cls, proxy: str):
72
- '''
73
- proxy format 'ip:port'
74
- test baidu.com for cn
75
- # test google.com for non-cn (not effective due to DNS hijacking)
76
- '''
77
- try:
78
- with httpx.Client(proxies=proxy) as client:
79
- r = client.get('https://baidu.com', timeout=2)
80
- if r.ok:
81
- return 1
82
- else:
83
- return 0
84
- except Exception as e:
85
- logger.info(f'test proxy {proxy} negative')
86
- return 0
87
- if r.ok:
88
- logger.info(f'test proxy {proxy} positive')
89
- return 1
90
-
91
-
92
- class BasicFactors:
93
-
94
- @staticmethod
95
- def break_rise(d) -> float:
96
- if d.open[-1] / d.close[-2] > 1.002 and d.close[-1] > d.open[-1]:
97
- return round((d.open[-1] - d.close[-2]) / d.close[-2], 2)
98
- else:
99
- return 0
100
-
101
- @staticmethod
102
- def min_resist(d) -> float:
103
- sup, pre, pcur = 0, 0, d.close[-1]
104
- for i in d.iterrows():
105
- p = (i[1].open + i[1].close) / 2
106
- if p > pcur:
107
- pre += i[1].vol
108
- if p < pcur:
109
- sup += i[1].vol
110
- minres = (sup - pre) / (sup + pre)
111
- if abs(minres - 1) < .01 and d.close[-2] < max(d.close[:-2]):
112
- minres += .2
113
- minres = round(minres, 2)
114
- return minres
115
-
116
- @staticmethod
117
- def vol_extreme(d):
118
- d = d.vol
119
- v60max = d.rolling(60).max()
120
- v60min = d.rolling(60).min()
121
- # any in last 3days
122
- for i in range(1, 3):
123
- if d[-i] > v60max[-i - 1]:
124
- return round(d[-i] / v60max[-i - 1], 2)
125
- if d[-i] < v60min[-i - 1]:
126
- return round(-d[-i] / v60min[-i - 1], 2)
127
- else:
128
- return 0
129
-
130
- @staticmethod
131
- def bias_rate_over_ma60(d):
132
- r60 = d.close - d.close.rolling(60).mean()
133
- if r60[-1] > 0:
134
- return round(r60[-1] / r60.rolling(60).max()[-1], 2)
135
- else:
136
- return round(-r60[-1] / r60.rolling(60).min()[-1], 2)
137
-
138
- @staticmethod
139
- def op_ma(d) -> float:
140
- ''' op: ma score'''
141
- if len(d) < 22:
142
- return
143
- d['mv5'] = d.close.rolling(5).mean()
144
- d['mv10'] = d.close.rolling(10).mean()
145
- d['mv20'] = d.close.rolling(20).mean()
146
- d['mv60'] = d.close.rolling(60).mean()
147
-
148
- def ma20(d):
149
- ret = 0
150
- # .2 for over ma60
151
- if d.close[-1] > d.mv60[-1]:
152
- ret += 0.2
153
- # .2 for all upwards ma's
154
- if (d.mv5[-1] > d.mv5[-2] and d.mv10[-1] >
155
- d.mv10[-2] and d.mv20[-1] > d.mv20[-2]):
156
- ret += 0.2
157
- for j in range(1, 3):
158
- if not (d.close[-j] > d.mv5[-j] and d.close[-j]
159
- > d.mv10[-j] and d.close[-j] > d.mv20[-j]):
160
- return ret
161
- for j in range(3, 5):
162
- if (d.close[-j] > d.mv5[-j] and d.close[-j] >
163
- d.mv10[-j] and d.close[-j] > d.mv20[-j]):
164
- return ret
165
- # .2 for just rush over ma's (fresh score)
166
- ret += 0.2
167
- return ret
168
- return ma20(d)
169
-
170
- @staticmethod
171
- def op_cnt(d, cont_min=3) -> (int):
172
- ''' op: count continous bulling days over index'''
173
- d.index = pd.DatetimeIndex(d.index)
174
- td = (d.p_change_on_sh.rolling(cont_min).min() > 0).astype(int) * \
175
- (d.p_change.rolling(cont_min).min() > 0).astype(int)
176
- ret = 0 if td[-1] <= 0 else td[-1]
177
- # is_first_day = True if td[-2] <= 0 else False
178
- return ret
179
-
180
-
181
- class hget:
182
- '''
183
- class version request.get wrapper
184
- '''
185
- def __init__(self, url, *args, **kwargs):
186
- self.url = url
187
- try:
188
- r = httpx.get(
189
- self.url, follow_redirects=True, headers=WebUtils.headers(),
190
- *args, **kwargs)
191
- self.text = r.text
192
- self.content = r.content
193
- except Exception as e:
194
- logger.error(f'fetch {self.url} err: {e}')
195
- self.text = ''
196
- self.content = b''
2
+ """
3
+ 工具模块(向后兼容)
4
+ """
5
+ # 从新模块导入,保持向后兼容
6
+ from .utils.logging import logger, setup_logger
7
+ from .utils.web import WebUtils, hget
8
+ from .factors.technical import BasicFactors
9
+
10
+ __all__ = ['WebUtils', 'BasicFactors', 'hget', 'logger', 'setup_logger']
197
11