gj-unitrad 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.
@@ -0,0 +1,10 @@
1
+ Metadata-Version: 2.1
2
+ Name: gj_unitrad
3
+ Version: 0.0.1
4
+ Summary: unitrad打包
5
+ Author: yin
6
+ Author-email: 2018209921@qq.com
7
+ Requires-Python: >3.6
8
+ Description-Content-Type: text/markdown
9
+
10
+ 第一次上传unitrad
@@ -0,0 +1,4 @@
1
+ from .unitrad import WebSocketClient
2
+
3
+ __all__ = ['WebSocketClient']
4
+
@@ -0,0 +1,398 @@
1
+ import asyncio
2
+ import aiohttp
3
+ import json
4
+ import yaml
5
+ import threading
6
+ import time
7
+ import datetime
8
+
9
+ FUNCTION_ID_RTN_STRATEGY_LOG = 11004
10
+
11
+ gstop_event = asyncio.Event()
12
+ class WebSocketClient:
13
+ def __init__(self, uri, user, passwd, strategy_name, strategy_param):
14
+ self.uri = uri
15
+ self.user = user
16
+ self.passwd = passwd
17
+ self.strategy_name = strategy_name
18
+ self.strategy_param = strategy_param
19
+ self.session = None
20
+ self.websocket = None
21
+ self.connected = False
22
+ self.strategy_id = -1
23
+ self.select_strategy = ""
24
+ self.results = {"position": [], "trades" : []}
25
+ self.condition = threading.Condition()
26
+ self.lock = asyncio.Lock() # 创建一个锁
27
+ self.ready = False
28
+ self._isFinish = False
29
+ self.func_map = {
30
+ 10001: self.handle_login_response,
31
+ 10005: self.handle_create_strategy_response,
32
+ 10020: self.handle_rtn_strategy_status,
33
+ 12029: self.handle_query_trade_list,
34
+ 11004: self.handle_rtn_strategy_log,
35
+ 12030: self.handle_query_position_list
36
+ }
37
+ # 日志级别映射
38
+ self.log_levels = {
39
+ 0: 'Verbose',
40
+ 1: 'Debug',
41
+ 2: 'Info',
42
+ 3: 'Warn',
43
+ 4: 'Error',
44
+ 5: 'Fatal'
45
+ }
46
+
47
+ async def update_positions(self, new_data):
48
+ # 处理接收到的新数据并更新结果
49
+ for item in new_data:
50
+ self.results["position"].extend(item['positionList'])
51
+
52
+ async def isFinish(self):
53
+ async with self.lock: # 加锁以确保线程安全
54
+ return self._isFinish
55
+
56
+ async def setFinish(self, value):
57
+ async with self.lock: # 加锁以确保线程安全
58
+ self._isFinish = value
59
+ print(f"setFinish called with value: {self._isFinish}")
60
+
61
+ def wait_for_condition(self):
62
+ with self.condition:
63
+ print("Waiting for condition to be met...")
64
+ while not self.ready:
65
+ self.condition.wait()
66
+ def set_condition(self):
67
+ time.sleep(2) # 模拟一些工作
68
+ with self.condition:
69
+ self.ready = True
70
+ self.condition.notify_all() # 通知所有等待的线程
71
+
72
+ async def connect(self):
73
+ """建立 WebSocket 连接并保持活动状态"""
74
+ self.session = aiohttp.ClientSession()
75
+ try:
76
+ self.websocket = await self.session.ws_connect(self.uri)
77
+ self.connected = True
78
+ print("连接成功!")
79
+
80
+ # 登录请求
81
+ await self.login_request()
82
+
83
+ # 监听消息
84
+ await self.listen()
85
+
86
+ except Exception as e:
87
+ print(f"连接失败: {e}")
88
+ await self.close_session() # 确保关闭会话
89
+ await self.reconnect()
90
+
91
+ async def listen(self):
92
+ """监听服务器消息"""
93
+ try:
94
+ async for msg in self.websocket:
95
+ if msg.type == aiohttp.WSMsgType.TEXT:
96
+ await self.process_response(msg.data)
97
+ elif msg.type == aiohttp.WSMsgType.ERROR:
98
+ print(f"WebSocket 错误: {self.websocket.exception()}")
99
+ break
100
+ except Exception as e:
101
+ print(f"监听时发生异常: {e}")
102
+ finally:
103
+ self.connected = False
104
+
105
+ async def process_response(self, response):
106
+ """处理接收到的消息"""
107
+ try:
108
+ data = json.loads(response)
109
+ funcion_id = data.get("funcionId")
110
+ err_id = data.get("errId")
111
+ err_msg = data.get("errMsg")
112
+ response_data = data.get("data")
113
+
114
+ if err_id != 0:
115
+ print(f"错误代码 {err_id}: {err_msg}")
116
+ return
117
+
118
+ # 处理对应的 funcionId
119
+ if funcion_id in self.func_map:
120
+ await self.func_map[funcion_id](response_data)
121
+ else:
122
+ print(f"未找到处理函数 для funcionId: {funcion_id}")
123
+
124
+ except json.JSONDecodeError:
125
+ print("接收到的消息不是有效的 JSON 格式")
126
+
127
+ async def send_request(self, request_data):
128
+ """发送请求"""
129
+ if self.connected:
130
+ print("发送请求:", request_data)
131
+ await self.websocket.send_str(json.dumps(request_data))
132
+ else:
133
+ print("WebSocket 尚未连接,无法发送请求")
134
+ async def sub_strategy_log(self):
135
+ request_data = {
136
+ "funcionId": 12014,
137
+ "finished": True,
138
+ "dataType": 1,
139
+ "requestId": 1,
140
+ "errId": 0,
141
+ "errMsg": "",
142
+ "data": [
143
+ {
144
+ "userId": f"{self.user}"
145
+ }
146
+ ]
147
+ }
148
+ await self.send_request(request_data)
149
+
150
+ async def login_request(self):
151
+ """发送登录请求"""
152
+ request_data = {
153
+ "funcionId": 10001,
154
+ "finished": True,
155
+ "dataType": 1,
156
+ "requestId": 1,
157
+ "errId": 0,
158
+ "errMsg": "",
159
+ "data": [
160
+ {
161
+ "userName": self.user,
162
+ "passWord": self.passwd
163
+ }
164
+ ]
165
+ }
166
+ await self.send_request(request_data)
167
+
168
+ async def handle_login_response(self, data):
169
+ """处理登录响应"""
170
+ print(f"处理登录响应: {data}")
171
+ if isinstance(data, list) and data:
172
+ response_data = data[0]
173
+ print(response_data)
174
+ if response_data.get("msg") == "welcome":
175
+ await self.sub_strategy_log()
176
+ print("登录成功!")
177
+ await self.create_strategy()
178
+ else:
179
+ print("登录失败!")
180
+ else:
181
+ print("无效的响应数据格式")
182
+ async def convert_to_json(self, data):
183
+ """将 Python 对象转换为 JSON 字符串"""
184
+ return json.dumps(data, ensure_ascii=False, indent=4)
185
+ async def create_strategy(self):
186
+ """创建策略请求"""
187
+ print("开始创建策略")
188
+ param = await self.convert_to_json(self.strategy_param)
189
+ request = {
190
+ "funcionId": 10005,
191
+ "finished": True,
192
+ "dataType": 1,
193
+ "requestId": 2,
194
+ "errId": 0,
195
+ "errMsg": "",
196
+ "data": [
197
+ {
198
+ "soName": self.strategy_name,
199
+ "param": param,
200
+ "operationType": 1,
201
+ "strategyId": 0,
202
+ "strategyType": 2,
203
+ "frequencyType": 1,
204
+ "status": 0
205
+ }
206
+ ]
207
+ }
208
+ await self.send_request(request)
209
+
210
+ async def query_trade_list(self):
211
+
212
+ request_data = {
213
+ "funcionId": 12029,
214
+ "finished": True,
215
+ "dataType": 1,
216
+ "requestId": 1,
217
+ "errId": 0,
218
+ "errMsg": "",
219
+ "data": [{
220
+ "strategyId": self.select_strategy["strategyId"]
221
+ }]
222
+ }
223
+ await self.send_request(request_data)
224
+ async def query_position_list(self):
225
+
226
+ request_data = {
227
+ "funcionId": 12030,
228
+ "finished": True,
229
+ "dataType": 1,
230
+ "requestId": 1,
231
+ "errId": 0,
232
+ "errMsg": "",
233
+ "data": [{
234
+ "strategyId": self.select_strategy["strategyId"]
235
+ }]
236
+ }
237
+ await self.send_request(request_data)
238
+
239
+ async def start_strategy(self):
240
+ """创建策略请求"""
241
+ print("开始创建策略")
242
+ param = await self.convert_to_json(self.strategy_param)
243
+ request = {
244
+ "funcionId": 10005,
245
+ "finished": True,
246
+ "dataType": 1,
247
+ "requestId": 2,
248
+ "errId": 0,
249
+ "errMsg": "",
250
+ "data": [
251
+ {
252
+ "soName": self.strategy_name,
253
+ "param": self.select_strategy["param"],
254
+ "operationType": 5,
255
+ "strategyId": self.select_strategy["strategyId"],
256
+ "strategyType": 2,
257
+ "frequencyType": 1,
258
+ "status": self.select_strategy["status"]
259
+ }
260
+ ]
261
+ }
262
+ await self.send_request(request)
263
+ async def handle_create_strategy_response(self, data):
264
+ """处理创建策略响应"""
265
+ #print(f"处理创建策略响应: {data}")
266
+ # 过滤出 soName 为 self.strategy_name 的对象
267
+ filtered_data = [item for item in data if item['soName'] == self.strategy_name]
268
+
269
+ # 如果有匹配的对象,则找到 strategyid 最大的对象
270
+ if filtered_data:
271
+ self.select_strategy = max(filtered_data, key=lambda x: x['strategyId'])
272
+ print(self.select_strategy)
273
+
274
+ if self.select_strategy["status"] == 2:
275
+ await self.start_strategy()
276
+ self.strategy_id = int(self.select_strategy["strategyId"])
277
+ else:
278
+ print("没有找到匹配的对象")
279
+
280
+
281
+
282
+ async def close_session(self):
283
+ """关闭客户端会话"""
284
+ if self.session:
285
+ await self.session.close()
286
+ print("客户端会话已关闭")
287
+
288
+
289
+ async def handle_rtn_strategy_status(self, data):
290
+ print(f"处理策略状态推送: ", data)
291
+ filtered_data = [item for item in data if item['strategyId'] == self.strategy_id]
292
+
293
+
294
+ if filtered_data:
295
+ self.select_strategy = filtered_data[0]
296
+
297
+ if self.select_strategy["status"] == 6:
298
+ print("策略更新状态: 回测完成", filtered_data)
299
+ await self.query_trade_list()
300
+
301
+ async def handle_query_trade_list(self, data):
302
+ #print(f"处理策略成交推送: ", data)
303
+ self.results["trades"] = data
304
+ await self.query_position_list()
305
+
306
+ async def handle_rtn_strategy_log(self, data):
307
+ for entry in data:
308
+ log_level = entry['logLevel']
309
+ log_message = entry['logMessage']
310
+ log_time = entry['logTime']
311
+
312
+ # 转换 logTime 为可视化时间
313
+ # 假设 logTime 是以微秒为单位的时间戳
314
+ readable_time = datetime.datetime.fromtimestamp(log_time / 1_000_000).strftime('%Y-%m-%d %H:%M:%S')
315
+
316
+
317
+ # 打印格式化的日志信息
318
+ print(f"时间: {readable_time}")
319
+ print(f"日志级别: {self.log_levels.get(log_level, 'Unknown')}")
320
+ print("日志信息:")
321
+ print(log_message.strip()) # 去除首尾空白
322
+
323
+ async def handle_query_position_list(self, data):
324
+ #print(f"处理策略持仓推送: ", data)
325
+ await self.update_positions(data)
326
+ #self.results["position"] = data
327
+ gstop_event.set()
328
+ self.set_condition()
329
+ await self.setFinish(True)
330
+
331
+
332
+ uri = ""
333
+ user = ""
334
+ passwd = ""
335
+ strategy_name = ""
336
+ strategy_param = ""
337
+
338
+ gclient = WebSocketClient("", "", "", "", "")
339
+
340
+ def read_yaml_file(filepath):
341
+ """读取 YAML 文件"""
342
+ with open(filepath, 'r', encoding='utf-8') as file:
343
+ return yaml.safe_load(file)
344
+
345
+ async def run_func(config):
346
+ """运行函数,读取配置并执行相关逻辑"""
347
+ try:
348
+ config_data = read_yaml_file(config)
349
+ except FileNotFoundError:
350
+ print(f"文件 {config} 不存在!")
351
+ except yaml.YAMLError as e:
352
+ print("解析 YAML 文件时出错:", e)
353
+
354
+ env_config = config_data.get("env", {})
355
+ uri = env_config.get("uri")
356
+ user = env_config.get("user")
357
+ passwd = env_config.get("passwd")
358
+ strategy_name = env_config.get("pystrategy")
359
+ strategy_param = config_data
360
+
361
+ global gclient
362
+ gclient = WebSocketClient(uri, user, passwd, strategy_name, strategy_param)
363
+ await gclient.connect()
364
+
365
+ async def monitor_condition():
366
+ global gclient
367
+ while True:
368
+ # 检查 gclient.isFinish() 的返回值
369
+ if await gclient.isFinish():
370
+ print("Condition met, stopping the execution.")
371
+ gstop_event.set() # 设置事件,通知 run_func 停止
372
+ break # 退出循环
373
+ await asyncio.sleep(0.5) # 每 0.5 秒检查一次
374
+
375
+ async def run_strategy(config):
376
+ global gclient
377
+ # 创建任务
378
+ task = asyncio.create_task(run_func(config))
379
+ monitor_task = asyncio.create_task(monitor_condition())
380
+ # 等待任务完成或条件满足
381
+ await asyncio.wait([task, monitor_task], return_when=asyncio.FIRST_COMPLETED)
382
+
383
+ # 如果条件满足,取消任务
384
+ if gstop_event.is_set():
385
+ task.cancel()
386
+ try:
387
+ await task # 等待任务取消完成
388
+ except asyncio.CancelledError:
389
+ print("run_func was cancelled.")
390
+ #await gclient.close_session()
391
+
392
+ def run_unitrade(config):
393
+ global gclient
394
+ asyncio.run(run_strategy(config))
395
+ gclient.wait_for_condition()
396
+
397
+ return gclient.results
398
+
@@ -0,0 +1,10 @@
1
+ Metadata-Version: 2.1
2
+ Name: gj-unitrad
3
+ Version: 0.0.1
4
+ Summary: unitrad打包
5
+ Author: yin
6
+ Author-email: 2018209921@qq.com
7
+ Requires-Python: >3.6
8
+ Description-Content-Type: text/markdown
9
+
10
+ 第一次上传unitrad
@@ -0,0 +1,8 @@
1
+ setup.py
2
+ gj_unitrad/__init__.py
3
+ gj_unitrad/unitrad.py
4
+ gj_unitrad.egg-info/PKG-INFO
5
+ gj_unitrad.egg-info/SOURCES.txt
6
+ gj_unitrad.egg-info/dependency_links.txt
7
+ gj_unitrad.egg-info/requires.txt
8
+ gj_unitrad.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ yaml==6.0.2
2
+ aiohttp==3.11.10
@@ -0,0 +1 @@
1
+ gj_unitrad
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,22 @@
1
+ from setuptools import setup, find_packages
2
+
3
+ with open('description_info.md', 'r', encoding='utf-8') as f:
4
+ long_description = f.read()
5
+
6
+ setup(
7
+ name='gj_unitrad', # 你的包名
8
+ version='0.0.1', # 版本号
9
+ description='unitrad打包', # 包的简要描述
10
+ long_description=long_description, # 包的详细描述
11
+ long_description_content_type='text/markdown', # 描述文件的类型
12
+ include_package_data=True, # 包含包数据
13
+ package_data={'gj_unitrad': ['*.py']}, # 指定数据文件
14
+ author='yin', # 作者姓名
15
+ author_email='2018209921@qq.com', # 作者邮箱
16
+ packages=find_packages(), # 自动查找包目录
17
+ python_requires='>3.6', # python版本要求
18
+ install_requires=[
19
+ 'yaml==6.0.2',
20
+ 'aiohttp==3.11.10'
21
+ ], # 依赖库列表 (除开python自带的包外的其他依赖库(代码中如果缺少了对应的库会导致无法运行的包))
22
+ )