| | |
| | | """ |
| | | 华鑫交易 |
| | | """ |
| | | import copy |
| | | import json |
| | | import time |
| | | |
| | | import constant |
| | | from db.redis_manager import RedisManager |
| | | from log_module.log import logger_juejin_trade |
| | | from l2.huaxin import huaxin_delegate_postion_manager |
| | | from log_module import async_log_util |
| | | from log_module.log import logger_juejin_trade, hx_logger_trade_debug, logger_trade |
| | | from trade.buy_money_count_setting import BuyMoneyUtil |
| | | from trade.huaxin import huaxin_trade_api |
| | | from trade.huaxin.huaxin_trade_record_manager import TradeOrderIdManager |
| | | from utils import tool, huaxin_util |
| | | from l2 import huaxin |
| | | from l2 import huaxin, l2_data_util |
| | | |
| | | __context_dict = {} |
| | | |
| | | |
| | | # 交易订单号管理 |
| | | 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): |
| | | cls.__get_redis().sadd(f"huaxin_order_id-{code}", json.dumps((account_id, order_id))) |
| | | cls.__get_redis().expire(f"huaxin_order_id-{code}", tool.get_expire()) |
| | | |
| | | # 删除订单ID |
| | | @classmethod |
| | | def remove_order_id(cls, code, account_id, order_id): |
| | | cls.__get_redis().srem(f"huaxin_order_id-{code}", json.dumps((account_id, order_id))) |
| | | |
| | | # 查询所有的订单号 |
| | | @classmethod |
| | | def list_order_ids(cls, code): |
| | | return cls.__get_redis().smembers(f"huaxin_order_id-{code}") |
| | | __TradeOrderIdManager = TradeOrderIdManager() |
| | | |
| | | |
| | | def init(context): |
| | | __context_dict["init"] = context |
| | | print("掘金交易初始化成功") |
| | | |
| | | |
| | | # 可用金额 |
| | |
| | | |
| | | |
| | | # 通过量下单,返回(代码,账号ID,订单号) |
| | | def order_volume(code, price, count, last_data_index): |
| | | |
| | | if code.find("00") != 0 and code.find("60") != 0: |
| | | raise Exception("只支持00开头与60开头的代码下单") |
| | | start_time = time.time() |
| | | # 保存下单信息 |
| | | huaxin.huaxin_delegate_postion_manager.place_order(code, price, count, last_data_index) |
| | | if not constant.TRADE_ENABLE: |
| | | return |
| | | result = huaxin_trade_api.order(1, code, count, price) |
| | | print("华鑫下单耗时", time.time() - start_time) |
| | | logger_juejin_trade.info(f"{code}:下单耗时{round(time.time() - start_time, 3)}s") |
| | | |
| | | if result: |
| | | print("下单结果", result) |
| | | if result['code'] == 0: |
| | | result = result["data"] |
| | | if result["orderStatus"] == huaxin_util.TORA_TSTP_OST_Rejected: |
| | | logger_juejin_trade.info(f"{code}:下单失败:{result.get('statusMsg')}") |
| | | raise Exception(result.get('statusMsg')) |
| | | def order_volume(code, price, count, last_data, order_ref=None, exec_index=None, shadow_volume=None): |
| | | if not shadow_volume: |
| | | shadow_volume = 100 |
| | | async_log_util.info(logger_trade, f"{code} trade_huaxin.order_volume 开始") |
| | | try: |
| | | price = round(float(price), 2) |
| | | if not tool.is_can_buy_code(code): |
| | | raise Exception("只支持00开头与60开头的代码下单") |
| | | # 保存下单信息 |
| | | shadow_price = tool.get_shadow_price(price) |
| | | huaxin.huaxin_delegate_postion_manager.place_order(code, price, count, exec_index, last_data, order_ref, |
| | | shadow_price=shadow_price, shadow_volume=shadow_volume) |
| | | if not constant.TRADE_ENABLE: |
| | | return |
| | | result = None |
| | | blocking = False |
| | | try: |
| | | async_log_util.info(logger_trade, f"{code}下单开始") |
| | | result = huaxin_trade_api.order(1, code, count, price, blocking=blocking, order_ref=order_ref, |
| | | shadow_price=shadow_price, shadow_volume=shadow_volume) |
| | | async_log_util.info(logger_trade, f"{code}下单结束") |
| | | except Exception as e: |
| | | if str(e).find("超时") >= 0: |
| | | # 此处出现超时,需要通过读取委托列表来设置订单信息 |
| | | async_log_util.error(hx_logger_trade_debug, f"{code}:下单结果反馈出错-{str(e)}") |
| | | else: |
| | | TradeOrderIdManager.add_order_id(code, result["accountID"], result["orderSysID"]) |
| | | logger_juejin_trade.info(f"{code}:下单成功 orderSysID:{result['orderSysID']}") |
| | | return result["securityId"], result["accountID"], result["orderSysID"] |
| | | raise e |
| | | |
| | | if result: |
| | | if blocking: |
| | | if result['code'] == 0: |
| | | result = result["data"] |
| | | if result["orderStatus"] == huaxin_util.TORA_TSTP_OST_Rejected: |
| | | async_log_util.info(hx_logger_trade_debug, f"{code}:下单失败:{result.get('statusMsg')}") |
| | | raise Exception(result.get('statusMsg')) |
| | | else: |
| | | __TradeOrderIdManager.add_order_id(code, result["accountID"], result["orderSysID"]) |
| | | async_log_util.info(hx_logger_trade_debug, f"{code}:下单成功 orderSysID:{result['orderSysID']}") |
| | | return result["securityId"], result["accountID"], result["orderSysID"] |
| | | else: |
| | | raise Exception(result['msg']) |
| | | else: |
| | | order_ref = result["order_ref"] |
| | | __TradeOrderIdManager.add_order_ref(code, order_ref) |
| | | async_log_util.info(hx_logger_trade_debug, f"{code}:下单成功 orderRef:{order_ref}") |
| | | return code, "local", order_ref |
| | | else: |
| | | raise Exception(result['msg']) |
| | | else: |
| | | raise Exception("下单失败,无返回") |
| | | raise Exception("下单失败,无返回") |
| | | finally: |
| | | async_log_util.info(logger_trade, f"{code} trade_huaxin.order_volume 结束") |
| | | |
| | | |
| | | def order_success(code, accountId, orderSysID): |
| | | TradeOrderIdManager.add_order_id(code, accountId, orderSysID) |
| | | # 通过量下单,返回(代码,账号ID,订单号) |
| | | def order_volume_new(code, price, volume, last_data, exec_index=None): |
| | | """ |
| | | 新版下单:拆分为2个订单 |
| | | @param code: |
| | | @param price: |
| | | @param volume: 总股数 |
| | | @param last_data: 最后一条L2数据 |
| | | @param exec_index: 执行位 |
| | | @return: |
| | | """ |
| | | |
| | | async_log_util.info(logger_trade, f"{code} trade_huaxin.order_volume_new 开始") |
| | | try: |
| | | price = round(float(price), 2) |
| | | if not tool.is_can_buy_code(code): |
| | | raise Exception("只支持00开头与60开头的代码下单") |
| | | # 拆单 |
| | | v1, v2 = BuyMoneyUtil.get_possible_buy_volumes_by_total_volume(volume) |
| | | oredr_info_list = [(v1, price, huaxin_util.create_order_ref()), (v2, price, huaxin_util.create_order_ref())] |
| | | huaxin.huaxin_delegate_postion_manager.RealDelegateOrderPositionManager.place_order(code, oredr_info_list, |
| | | exec_index, last_data) |
| | | if not constant.TRADE_ENABLE: |
| | | return |
| | | result = None |
| | | blocking = False |
| | | try: |
| | | async_log_util.info(logger_trade, f"{code}下单开始") |
| | | result = huaxin_trade_api.order_new(1, code, oredr_info_list, blocking=blocking) |
| | | async_log_util.info(logger_trade, f"{code}下单结束") |
| | | except Exception as e: |
| | | if str(e).find("超时") >= 0: |
| | | # 此处出现超时,需要通过读取委托列表来设置订单信息 |
| | | async_log_util.error(hx_logger_trade_debug, f"{code}:下单结果反馈出错-{str(e)}") |
| | | else: |
| | | raise e |
| | | |
| | | if result: |
| | | if blocking: |
| | | if result['code'] == 0: |
| | | result = result["data"] |
| | | if result["orderStatus"] == huaxin_util.TORA_TSTP_OST_Rejected: |
| | | async_log_util.info(hx_logger_trade_debug, f"{code}:下单失败:{result.get('statusMsg')}") |
| | | raise Exception(result.get('statusMsg')) |
| | | else: |
| | | __TradeOrderIdManager.add_order_id(code, result["accountID"], result["orderSysID"]) |
| | | async_log_util.info(hx_logger_trade_debug, f"{code}:下单成功 orderSysID:{result['orderSysID']}") |
| | | return result["securityId"], result["accountID"], result["orderSysID"] |
| | | else: |
| | | raise Exception(result['msg']) |
| | | else: |
| | | order_ref_list = result["order_ref_list"] |
| | | __TradeOrderIdManager.add_order_refs(code, order_ref_list) |
| | | async_log_util.info(hx_logger_trade_debug, f"{code}:下单成功 orderRefs:{order_ref_list}") |
| | | return code, "local", order_ref_list |
| | | else: |
| | | raise Exception("下单失败,无返回") |
| | | finally: |
| | | async_log_util.info(logger_trade, f"{code} trade_huaxin.order_volume_new 结束") |
| | | |
| | | |
| | | def cancel_order_success(code, accountId, orderSysID): |
| | | TradeOrderIdManager.remove_order_id(code, accountId, orderSysID) |
| | | def order_success(code, accountId, orderSysID, orderRef, insertTime): |
| | | # 加入系统订单号 |
| | | __TradeOrderIdManager.add_order_id(code, accountId, orderSysID) |
| | | # 删除临时订单号 |
| | | __TradeOrderIdManager.remove_order_ref(code, orderRef) |
| | | # 根据插入时间判断下单位置是否正确 |
| | | try: |
| | | place_index = huaxin_delegate_postion_manager.get_place_order_position(code) |
| | | if place_index and insertTime: |
| | | # 大致判断是否为真实下单位置 |
| | | total_datas = l2_data_util.local_today_datas.get(code) |
| | | if total_datas: |
| | | if 0 < tool.trade_time_sub(insertTime, total_datas[place_index]["val"]["time"]) < 4: |
| | | # 4s内才会校验 |
| | | volume = total_datas[place_index]["val"]["num"] |
| | | for i in range(place_index + 1, len(total_datas)): |
| | | if total_datas[i]["val"]["num"] == volume and insertTime == total_datas[i]["val"]["time"]: |
| | | huaxin_delegate_postion_manager.set_place_order_position(code, i) |
| | | hx_logger_trade_debug.info("{}校验真实下单成功,{}->{}", code, place_index, i) |
| | | return i |
| | | else: |
| | | raise Exception(f"不满足校验条件,真实下单时间:{insertTime} 预估下单时间:{total_datas[place_index]['val']['time']}") |
| | | else: |
| | | raise Exception("未获取到L2数据") |
| | | else: |
| | | raise Exception(f"尚未获取到数据(place_index-{place_index} insertTime-{insertTime})") |
| | | except Exception as e: |
| | | hx_logger_trade_debug.warning("{}校验真实下单位置出错:{}", code, str(e)) |
| | | return None |
| | | |
| | | |
| | | # 撤单 |
| | | def cancel_order(code): |
| | | orders_info = TradeOrderIdManager.list_order_ids(code) |
| | | def cancel_order(code, msg=''): |
| | | if not constant.TRADE_ENABLE: |
| | | return |
| | | orders_info = __TradeOrderIdManager.list_order_ids_cache(code) |
| | | orders_info = copy.deepcopy(orders_info) |
| | | orders = [] |
| | | if orders_info: |
| | | for order in orders_info: |
| | | order_info = json.loads(order) |
| | | orders.append({'orderSysID': order_info[1], 'accountId': order_info[0]}) |
| | | if orders: |
| | | logger_juejin_trade.info(f"{code}:开始执行撤单") |
| | | logger_juejin_trade.info(f"{code}:撤单成功,撤单数量:{len(orders)}") |
| | | for order in orders: |
| | | huaxin_trade_api.cancel_order(1, code, order["orderSysID"]) |
| | | TradeOrderIdManager.remove_order_id(code, order["accountId"], order["orderSysID"]) |
| | | if orders: |
| | | async_log_util.info(logger_trade, f"{code}:华鑫开始执行撤单 {msg}") |
| | | huaxin_trade_api.batch_cancel_order(huaxin_trade_api.TRADE_DIRECTION_BUY, code, |
| | | [('', order["orderSysID"]) for order in orders]) |
| | | for order in orders: |
| | | __TradeOrderIdManager.remove_order_id(code, order["accountId"], order["orderSysID"]) |
| | | async_log_util.info(logger_trade, f"{code}:华鑫撤单结束,撤单数量:{len(orders)}") |
| | | |
| | | # 查询是否有本地订单号 |
| | | order_refs_info = __TradeOrderIdManager.list_order_refs_cache(code) |
| | | |
| | | if order_refs_info: |
| | | order_refs_info = copy.deepcopy(order_refs_info) |
| | | async_log_util.info(logger_trade, f"{code}:华鑫开始执行撤单 {msg}") |
| | | huaxin_trade_api.batch_cancel_order(huaxin_trade_api.TRADE_DIRECTION_BUY, code, |
| | | [(order_ref, '') for order_ref in order_refs_info]) |
| | | for order_ref in order_refs_info: |
| | | __TradeOrderIdManager.remove_order_ref(code, order_ref) |
| | | async_log_util.info(logger_trade, f"{code}:华鑫执行撤单结束") |
| | | |
| | | |
| | | if __name__ == "__main__": |