Administrator
2023-08-04 b79f40afbe849f56f7c2db94e9bcebf3f5e92ec6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
"""
华鑫交易
"""
import hashlib
import json
import random
 
# 交易API
import socket
import time
 
# 交易订单号管理
import constant
from utils import tool
from db.redis_manager import RedisManager, RedisUtils
from log_module.log import logger_huaxin_trade
 
 
class TradeOrderIdManager:
    __redisManager = RedisManager(2)
 
    @classmethod
    def __get_redis(cls):
        return cls.__redisManager.getRedis()
 
    # 添加订单ID
    @classmethod
    def add_order_id(cls, code, account_id, order_id):
        RedisUtils.sadd(cls.__get_redis(), f"huaxin_order_id-{code}", json.dumps((account_id, order_id)))
        RedisUtils.expire(cls.__get_redis(), f"huaxin_order_id-{code}", tool.get_expire())
 
    # 删除订单ID
    @classmethod
    def remove_order_id(cls, code, account_id, order_id):
        RedisUtils.srem(cls.__get_redis(), f"huaxin_order_id-{code}", json.dumps((account_id, order_id)))
 
    # 查询所有的订单号
    @classmethod
    def list_order_ids(cls, code):
        return RedisUtils.smembers(cls.__get_redis(), f"huaxin_order_id-{code}")
 
 
class TradeApi:
    @classmethod
    def __send_msg(cls, data):
        if "req_id" not in data:
            data["req_id"] = f"{round(time.time() * 1000)}_{random.randint(0, 10000)}"
        # 签名
        list_str = []
        for k in data:
            list_str.append(f"{k}={data[k]}")
        list_str.sort()
        __str = "&".join(list_str) + "JiaBei@!*."
        md5 = hashlib.md5(__str.encode(encoding='utf-8')).hexdigest()
        data["sign"] = md5
        # 生成socket,连接server
        ip_port = ("127.0.0.1", 9002)  # server地址和端口号(最好是10000以后)
        client = socket.socket()  # 生成socket,连接server
        client.connect(ip_port)
        client.send(json.dumps(data).encode("utf-8"))
        rec = client.recv(1024000)
        result = rec.decode("gbk")
        client.close()
        return result
 
    @classmethod
    def buy(cls, code, count, price):
        data = {"type": 0,
                "data": json.dumps({"code": code, "count": count, "price": price})}
        result = cls.__send_msg(data)
        result = json.loads(result)
        print("华鑫下单结果", result)
        if result["code"] != 0:
            raise Exception(result.get("msg"))
        code_data = result["data"]
        securityId = code_data["securityId"]
        orderStatus = int(code_data["orderStatus"])
        accountId = code_data["accountId"]
        orderSysID = code_data["orderStatus"]
        if orderStatus == 7:
            raise Exception("交易所已拒绝")
        return securityId, accountId, orderSysID
 
    @classmethod
    def cancel_buy(cls, code, order_sys_id):
        data = {"type": 1,
                "data": json.dumps({"code": code, "order_sys_id": order_sys_id})}
        result = cls.__send_msg(data)
        result = json.loads(result)
        print("华鑫撤单结果", result)
        if result["code"] != 0:
            raise Exception(result.get("msg"))
        result = result["data"]
        if not result["cancel"]:
            raise Exception(result.get("errorMsg"))
 
    # 内容格式
    # {"securityID": pOrderField.SecurityID, "orderLocalID": pOrderField.OrderLocalID,
    #  "direction": pOrderField.Direction, "orderSysID": pOrderField.OrderSysID,
    #  "insertTime": pOrderField.InsertTime, "insertDate": pOrderField.InsertDate,
    #  "acceptTime": pOrderField.AcceptTime, "cancelTime": pOrderField.CancelTime,
    #  "turnover": pOrderField.Turnover,
    #  "volume": pOrderField.VolumeTotalOriginal,
    #  "volumeTraded": pOrderField.VolumeTraded, "orderStatus": pOrderField.OrderStatus,
    #  "orderSubmitStatus": pOrderField.OrderSubmitStatus, "statusMsg": pOrderField.StatusMsg})
    @classmethod
    def list_delegate(cls):
        data = {"type": 2}
        result_str = cls.__send_msg(data)
        result_json = json.loads(result_str)
        if result_json["code"] != 0:
            raise Exception(result_json.get("msg"))
        return result_json["data"]
 
    # 内容格式
    # {"tradeID": pTradeField.TradeID, "securityID": pTradeField.SecurityID,
    #  "orderLocalID": pTradeField.OrderLocalID,
    #  "direction": pTradeField.Direction, "orderSysID": pTradeField.OrderSysID, "price": pTradeField.Price,
    #  "tradeTime": pTradeField.TradeTime,
    #  "volume": pTradeField.Volume, "tradeDate": pTradeField.TradeDate, "tradingDay": pTradeField.TradingDay,
    #  "PbuID": pTradeField.PbuID, "accountID": pTradeField.AccountID}
    @classmethod
    def list_traded(cls):
        data = {"type": 3}
        result = cls.__send_msg(data)
        result_json = json.loads(result)
        if result_json["code"] != 0:
            raise Exception(result_json.get("msg"))
        return result_json["data"]
 
 
# 通过量下单,返回(代码,账号ID,订单号)
def order_volume(code, price, count):
    if not constant.TRADE_ENABLE:
        return
    if code.find("00") != 0 and code.find("60") != 0:
        raise Exception("只支持00开头与60开头的代码下单")
    start_time = time.time()
    try:
        securityId, accountId, orderSysID = TradeApi.buy(code, count, price)
        print("华鑫下单耗时", time.time() - start_time)
        logger_huaxin_trade.info(f"{code}:下单耗时{round(time.time() - start_time, 3)}s")
        TradeOrderIdManager.add_order_id(code, accountId, orderSysID)
        logger_huaxin_trade.info(f"{code}:下单成功 security_id:{securityId} ord_sys_id:{orderSysID}, accountId:{accountId}")
        return securityId, accountId, orderSysID
    except Exception as e:
        logger_huaxin_trade.info(f"{code}:下单失败:{str(e)}")
        raise e
 
 
# 撤单
def cancel_order(code):
    orders_info = TradeOrderIdManager.list_order_ids(code)
    if orders_info:
        logger_huaxin_trade.info(f"{code}:开始执行撤单")
        for order in orders_info:
            order_info = json.loads(order)
            # for i in range(3):
            try:
                TradeApi.cancel_buy(code, order_info[1])
            except Exception as e:
                # 状态异常表示已经撤单过了,不算无效撤单
                if str(e).find("状态异常") < 0:
                    raise e
 
            logger_huaxin_trade.info(f"{code}:撤单成功:{order_info}")
            TradeOrderIdManager.remove_order_id(code, order_info[0], order_info[1])