| | |
| | | from log_module import async_log_util |
| | | from third_data import code_plate_key_manager |
| | | from trade.buy_radical import radical_buy_data_manager |
| | | from utils import tool |
| | | from utils import tool, trade_util |
| | | from l2.transaction_progress import TradeBuyQueue |
| | | from trade import l2_trade_factor, trade_record_log_util, trade_constant |
| | | from trade import l2_trade_factor, trade_record_log_util, trade_constant, trade_manager |
| | | from l2 import l2_log, l2_data_source_util |
| | | from l2.l2_data_util import L2DataUtil, local_today_datas, local_today_canceled_buyno_map, local_today_buyno_map |
| | | from log_module.log import logger_l2_s_cancel, logger_debug, logger_l2_l_cancel, logger_l2_h_cancel |
| | |
| | | self.__compute_watch_index(code, buy_single_index) |
| | | |
| | | |
| | | |
| | | # ---------------------------------D撤------------------------------- |
| | | # 计算 成交位->真实下单位置 总共还剩下多少手没有撤单 |
| | | # 成交位变化之后重新计算 |
| | | class DCancelBigNumComputer: |
| | | __db = 0 |
| | | __redis_manager = redis_manager.RedisManager(0) |
| | | __instance = None |
| | | |
| | | def __new__(cls, *args, **kwargs): |
| | | if not cls.__instance: |
| | | cls.__instance = super(DCancelBigNumComputer, cls).__new__(cls, *args, **kwargs) |
| | | return cls.__instance |
| | | |
| | | def need_cancel(self, code, buy1_info, limit_up_price, time_str): |
| | | """ |
| | | 是否需要撤单 |
| | | @param limit_up_price: |
| | | @param code: |
| | | @param buy1_info:(买1价, 买1量) |
| | | @param time_str: 时间字符串 |
| | | @return: |
| | | """ |
| | | # 获取是否处于下单状态 |
| | | trade_state = trade_manager.CodesTradeStateManager().get_trade_state_cache(code) |
| | | if not trade_util.is_delegated(trade_state): |
| | | return False, "尚未下单" |
| | | |
| | | if abs(limit_up_price - buy1_info[0]) >= 0.001: |
| | | return False, "非涨停价" |
| | | |
| | | # 是否小于3000w |
| | | if buy1_info[0] * buy1_info[1] > 3000e4: |
| | | return False, "封单额大于3000w" |
| | | |
| | | # 获取下单时间 |
| | | place_order_index = SCancelBigNumComputer().get_real_place_order_index_cache(code) |
| | | if not place_order_index: |
| | | return False, "没获取到真实下单位置" |
| | | total_datas = local_today_datas.get(code) |
| | | # 买1时间要大于下单时间 |
| | | if total_datas[place_order_index]['val']['time'] >= time_str: |
| | | return False, "L1时间<=下单时间" |
| | | human_rate = CancelRateHumanSettingManager().get_l_down(code) |
| | | if human_rate and human_rate > 0.7: |
| | | return False, "人为设置撤单比例大于0.7" |
| | | |
| | | volume_rate = code_volumn_manager.CodeVolumeManager().get_volume_rate(code) |
| | | if volume_rate <= 0.4 and tool.trade_time_sub(time_str, total_datas[place_order_index]['val']['time']) <= 6: |
| | | return True, f"量比({volume_rate})<=40%且在挂单6s内,封单额≤3000万" |
| | | |
| | | if 6 < tool.trade_time_sub(time_str, total_datas[place_order_index]['val']['time']) <= 10*60: |
| | | return True, f"下单后10分钟内,封单额≤3000万" |
| | | |
| | | return False, '无撤单条件' |
| | | |
| | | |
| | | if __name__ == "__main__": |
| | | CancelRateHumanSettingManager() |
| | |
| | | L2_CODES_INFO_PATH = "/home/userzjj/logs/l2_codes.txt" |
| | | # 影子订单的量 |
| | | SHADOW_ORDER_VOLUME = 100 |
| | | # 启用虚拟账户 |
| | | ENABLE_VIRTUAL_ACCOUNT = True |
| | |
| | | |
| | | import zmq |
| | | |
| | | from huaxin_client import command_manager |
| | | from huaxin_client import command_manager, huaxin_sinfo_util |
| | | from huaxin_client import constant |
| | | from huaxin_client import socket_util |
| | | import traderapi |
| | |
| | | from huaxin_client.log import logger |
| | | |
| | | # 正式账号 |
| | | from huaxin_client.trade_transform_protocol import TradeRequest, TradeResponse |
| | | from log_module import async_log_util |
| | | from log_module.log import logger_local_huaxin_trade_debug, logger_system, logger_trade |
| | | from utils import tool |
| | | from log_module.log import logger_local_huaxin_trade_debug, logger_system, logger_trade, logger_debug |
| | | |
| | | ########B类######## |
| | | from utils import tool |
| | | |
| | | UserID = '388000013349' |
| | | # 登陆密码 |
| | | Password = '110808' |
| | |
| | | self.__temp_money_account_list_dict = {} |
| | | self.__temp_order_found_list_dict = {} |
| | | self.call_back_thread_pool = concurrent.futures.ThreadPoolExecutor(max_workers=10) |
| | | self.own_order_local_ids = set() |
| | | |
| | | def OnFrontConnected(self) -> "void": |
| | | logger.info('OnFrontConnected') |
| | |
| | | |
| | | def OnRtnOrder(self, pOrderField: "CTORATstpOrderField") -> "void": |
| | | try: |
| | | # TODO |
| | | # if constant.ENABLE_VIRTUAL_ACCOUNT and not huaxin_sinfo_util.is_own_channel(pOrderField.SInfo): |
| | | # # 非自有渠道的单 |
| | | # return |
| | | order_data = {"sinfo": pOrderField.SInfo, "securityID": pOrderField.SecurityID, |
| | | "orderLocalID": pOrderField.OrderLocalID, |
| | | "direction": pOrderField.Direction, "orderSysID": pOrderField.OrderSysID, |
| | | "insertTime": pOrderField.InsertTime, "insertDate": pOrderField.InsertDate, |
| | | "acceptTime": pOrderField.AcceptTime, "cancelTime": pOrderField.CancelTime, |
| | | "limitPrice": pOrderField.LimitPrice, "accountID": pOrderField.AccountID, |
| | | "orderRef": pOrderField.OrderRef, "turnover": pOrderField.Turnover, |
| | | "volume": pOrderField.VolumeTotalOriginal, "volumeTraded": pOrderField.VolumeTraded, |
| | | "orderStatus": pOrderField.OrderStatus, |
| | | "orderSubmitStatus": pOrderField.OrderSubmitStatus, |
| | | "statusMsg": pOrderField.StatusMsg, "volumeCanceled": pOrderField.VolumeCanceled, |
| | | "localUpdateTime": int(time.time() * 1000000)} |
| | | try: |
| | | if huaxin_sinfo_util.is_own_channel(pOrderField.SInfo): |
| | | self.own_order_local_ids.add(pOrderField.OrderLocalID) |
| | | async_log_util.info(logger_local_huaxin_trade_debug, f"添加自有订单号:{pOrderField.OrderLocalID}") |
| | | except Exception as e: |
| | | logger_debug.exception(e) |
| | | |
| | | async_log_util.info(logger_local_huaxin_trade_debug, |
| | | '[%d] OnRtnOrder: SInfo[%s] InvestorID[%s] SecurityID[%s] OrderRef[%d] OrderLocalID[%s] LimitPrice[%.2f] VolumeTotalOriginal[%d] OrderSysID[%s] OrderStatus[%s] InsertTime[%s]' |
| | | % (round(time.time() * 1000), pOrderField.SInfo, pOrderField.InvestorID, |
| | |
| | | pOrderField.OrderStatus, pOrderField.InsertTime)) |
| | | if pOrderField.OrderStatus == traderapi.TORA_TSTP_OST_Unknown: |
| | | pass |
| | | # if queue_trade_w_l2_r is not None: |
| | | # queue_trade_w_l2_r.put_nowait( |
| | | # json.dumps({"type": "listen_volume", "data": {"code": pOrderField.SecurityID, |
| | | # "volume": pOrderField.VolumeTotalOriginal}}).encode( |
| | | # 'utf-8')) |
| | | else: |
| | | order_data = {"sinfo": pOrderField.SInfo, "securityID": pOrderField.SecurityID, |
| | | "orderLocalID": pOrderField.OrderLocalID, |
| | | "direction": pOrderField.Direction, "orderSysID": pOrderField.OrderSysID, |
| | | "insertTime": pOrderField.InsertTime, "insertDate": pOrderField.InsertDate, |
| | | "acceptTime": pOrderField.AcceptTime, "cancelTime": pOrderField.CancelTime, |
| | | "limitPrice": pOrderField.LimitPrice, "accountID": pOrderField.AccountID, |
| | | "orderRef": pOrderField.OrderRef, "turnover": pOrderField.Turnover, |
| | | "volume": pOrderField.VolumeTotalOriginal, "volumeTraded": pOrderField.VolumeTraded, |
| | | "orderStatus": pOrderField.OrderStatus, |
| | | "orderSubmitStatus": pOrderField.OrderSubmitStatus, |
| | | "statusMsg": pOrderField.StatusMsg, "volumeCanceled": pOrderField.VolumeCanceled, |
| | | "localUpdateTime": int(time.time()*1000)} |
| | | self.call_back_thread_pool.submit(self.__data_callback, TYPE_ORDER, 0, order_data) |
| | | except Exception as e: |
| | | async_log_util.error(logger_local_huaxin_trade_debug, "OnRtnOrder 出错") |
| | |
| | | |
| | | def OnRtnTrade(self, pTradeField: "CTORATstpTradeField") -> "void": |
| | | try: |
| | | # if constant.ENABLE_VIRTUAL_ACCOUNT and pTradeField.OrderLocalID not in self.own_order_local_ids: |
| | | # # 非自有渠道的单 |
| | | # return |
| | | async_log_util.info(logger_local_huaxin_trade_debug, |
| | | 'OnRtnTrade: TradeID[%s] InvestorID[%s] SecurityID[%s] OrderRef[%d] OrderLocalID[%s] Price[%.2f] Volume[%d]' |
| | | % (pTradeField.TradeID, pTradeField.InvestorID, pTradeField.SecurityID, |
| | | pTradeField.OrderRef, pTradeField.OrderLocalID, pTradeField.Price, |
| | | pTradeField.Volume)) |
| | | trade_data = { |
| | | "direction": pTradeField.Direction, "orderSysID": pTradeField.OrderSysID, |
| | | "securityID": pTradeField.SecurityID, |
| | | "tradeID": pTradeField.TradeID, "orderLocalID": pTradeField.OrderLocalID, "price": pTradeField.Price, |
| | | "volume": pTradeField.Volume, "tradeDate": pTradeField.TradeDate, "tradeTime": pTradeField.TradeTime |
| | | } |
| | | except: |
| | | pass |
| | | |
| | |
| | | if nRequestID not in self.__temp_order_list_dict: |
| | | self.__temp_order_list_dict[nRequestID] = [] |
| | | if not bIsLast: |
| | | if huaxin_sinfo_util.is_own_channel(pOrderField.SInfo): |
| | | self.own_order_local_ids.add(pOrderField.OrderLocalID) |
| | | # logger.info( |
| | | # 'OnRspQryOrder[%d]: SecurityID[%s] OrderLocalID[%s] Direction[%s] OrderRef[%d] OrderSysID[%s] VolumeTraded[%d] OrderStatus[%s] OrderSubmitStatus[%s], StatusMsg[%s]' |
| | | # % (nRequestID, pOrderField.SecurityID, pOrderField.OrderLocalID, pOrderField.Direction, |
| | |
| | | from l2.l2_transaction_data_manager import HuaXinBuyOrderManager, HuaXinSellOrderStatisticManager |
| | | from trade.sell.sell_rule_manager import TradeRuleManager |
| | | |
| | | from utils import tool |
| | | from utils import tool, trade_util |
| | | from l2.transaction_progress import TradeBuyQueue |
| | | from trade import trade_queue_manager, l2_trade_factor, trade_manager, trade_data_manager |
| | | from l2 import l2_log, l2_data_source_util, code_price_manager |
| | |
| | | if total_datas[index]["val"]["orderNo"] not in deal_order_nos: |
| | | return True |
| | | return False |
| | | |
| | | |
| | | # ---------------------------------D撤------------------------------- |
| | | # 计算 成交位->真实下单位置 总共还剩下多少手没有撤单 |
| | | # 成交位变化之后重新计算 |
| | | class DCancelBigNumComputer: |
| | | __db = 0 |
| | | __redis_manager = redis_manager.RedisManager(0) |
| | | |
| | | __instance = None |
| | | |
| | | # 下单位之后的封单中的大单 |
| | | __follow_big_order_cache = {} |
| | | |
| | | def __new__(cls, *args, **kwargs): |
| | | if not cls.__instance: |
| | | cls.__instance = super(DCancelBigNumComputer, cls).__new__(cls, *args, **kwargs) |
| | | cls.__load_datas() |
| | | return cls.__instance |
| | | |
| | | @classmethod |
| | | def __load_datas(cls): |
| | | __redis = cls.__get_redis() |
| | | try: |
| | | pass |
| | | finally: |
| | | RedisUtils.realse(__redis) |
| | | |
| | | @classmethod |
| | | def __get_redis(cls): |
| | | return cls.__redis_manager.getRedis() |
| | | |
| | | # 是否有撤买的规则 |
| | | def has_auto_cancel_rules(self, code): |
| | | rules = self.get_auto_cancel_rules(code) |
| | | return True if rules else False |
| | | |
| | | def get_auto_cancel_rules(self, code): |
| | | try: |
| | | rules = TradeRuleManager().list_can_excut_rules_cache([TradeRuleManager.TYPE_BUY_CANCEL], code) |
| | | return rules |
| | | except: |
| | | return None |
| | | |
| | | def need_cancel(self, code, buy1_volume): |
| | | rules = self.get_auto_cancel_rules(code) |
| | | if rules: |
| | | for r in rules: |
| | | if r.buy1_volume >= buy1_volume: |
| | | # 量低于 |
| | | return True, r.id_ |
| | | return False, None |
| | | |
| | | def compute_d_cancel_watch_index(self, code): |
| | | # 计算D撤囊括范围 |
| | | # real_place_order_index = self.__SCancelBigNumComputer.get_real_place_order_index_cache(code) |
| | | pass |
| | | |
| | | def __clear_data(self, code): |
| | | if code in self.__follow_big_order_cache: |
| | | self.__follow_big_order_cache.pop(code) |
| | | |
| | | def place_order_success(self, code, buy_single_index, buy_exec_index): |
| | | self.__clear_data(code) |
| | | |
| | | |
| | | # ---------------------------------RD撤------------------------------- |
| | | # 扫入下单大单撤 |
| | |
| | | cancel_data, cancel_msg, cancel_type = l_cancel(order_begin_pos.buy_single_index, |
| | | order_begin_pos.buy_exec_index) |
| | | |
| | | if cancel_data and not DCancelBigNumComputer().has_auto_cancel_rules(code): |
| | | if cancel_data: |
| | | try: |
| | | # 撤单 |
| | | cls.cancel_buy(code, cancel_msg, cancel_index=cancel_data["index"], cancel_type=cancel_type) |
| | |
| | | if cancel_type != trade_constant.CANCEL_TYPE_HUMAN: |
| | | # 是否是交易队列触发 |
| | | # 扫入下单只有L撤能撤单 |
| | | if order_begin_pos and order_begin_pos.mode == OrderBeginPosInfo.MODE_RADICAL and cancel_type not in { |
| | | if order_begin_pos and cancel_type not in { |
| | | trade_constant.CANCEL_TYPE_L_DOWN, trade_constant.CANCEL_TYPE_L, trade_constant.CANCEL_TYPE_RD, |
| | | trade_constant.CANCEL_TYPE_P, trade_constant.CANCEL_TYPE_F}: |
| | | trade_constant.CANCEL_TYPE_P, trade_constant.CANCEL_TYPE_F, trade_constant.CANCEL_TYPE_D}: |
| | | l2_log.cancel_debug(code, "撤单中断,原因:{}", "扫入下单不是L撤") |
| | | return False |
| | | # 加绿只有L撤/人撤生效 |
| | |
| | | filter=lambda record: record["extra"].get("name") == "limit_up_record", |
| | | rotation="00:00", compression="zip", enqueue=True) |
| | | |
| | | |
| | | logger.add(self.get_path("virtual_account", "virtual_account_money_records"), |
| | | filter=lambda record: record["extra"].get("name") == "virtual_account_money_records", |
| | | rotation="00:00", compression="zip", enqueue=True) |
| | | |
| | | ################################华鑫日志################################ |
| | | logger.add(self.get_hx_path("l2", "transaction"), |
| | | filter=lambda record: record["extra"].get("name") == "hx_l2_transaction", |
| | |
| | | logger.add(self.get_local_huaxin_path("trade", "trade_debug"), |
| | | filter=lambda record: record["extra"].get("name") == "local_huaxin_trade_debug", |
| | | rotation="00:00", compression="zip", enqueue=True) |
| | | |
| | | logger.add(self.get_local_huaxin_path("trade", "deal"), |
| | | filter=lambda record: record["extra"].get("name") == "local_huaxin_trade_deal", |
| | | rotation="00:00", compression="zip", enqueue=True) |
| | | |
| | | logger.add(sys.stdout, |
| | | filter=lambda record: record["extra"].get("name") == "local_huaxin_l1_show_info") |
| | | logger.add(self.get_local_huaxin_path("l1", "show_info"), |
| | |
| | | |
| | | logger_l2_radical_buy_data = __mylogger.get_logger("l2_radical_buy_data") |
| | | |
| | | logger_virtual_account_money_records= __mylogger.get_logger("virtual_account_money_records") |
| | | |
| | | # -------------------------------华鑫日志--------------------------------- |
| | | hx_logger_l2_orderdetail = __mylogger.get_logger("hx_l2_orderdetail") |
| | | hx_logger_l2_transaction = __mylogger.get_logger("hx_l2_transaction") |
| | |
| | | logger_local_huaxin_l2_subscript = __mylogger.get_logger("local_huaxin_subscript") |
| | | logger_local_huaxin_contact_debug = __mylogger.get_logger("local_huaxin_debug") |
| | | logger_local_huaxin_trade_debug = __mylogger.get_logger("local_huaxin_trade_debug") |
| | | logger_local_huaxin_trade_deal = __mylogger.get_logger("local_huaxin_trade_deal") |
| | | |
| | | |
| | | logger_local_huaxin_l1 = __mylogger.get_logger("local_huaxin_l1_show_info") |
| | | logger_local_huaxin_g_cancel = __mylogger.get_logger("local_huaxin_g_cancel") |
| | | logger_local_huaxin_l2_buy_no = __mylogger.get_logger("local_huaxin_l2_buy_no") |
| | |
| | | return cancel_reason_dict |
| | | |
| | | |
| | | |
| | | def __parse_content(line): |
| | | line = line.split(" - ")[1] |
| | | time_str = line[line.find("[") + 1:line.find("[") + 9] |
| | | data = line[line.find("]") + 1:].strip() |
| | | if data.find("thread-id=")>-1 and data.find("code=")>-1: |
| | | data = data[data.find("code=")+11:].strip() |
| | | if data.find("thread-id=") > -1 and data.find("code=") > -1: |
| | | data = data[data.find("code=") + 11:].strip() |
| | | return time_str, data |
| | | |
| | | |
| | |
| | | return fdatas |
| | | |
| | | |
| | | |
| | | @cache_log |
| | | def load_huaxin_l2_sell_deal_list(code=None, date=tool.get_now_date_str()): |
| | | path = f"{constant.get_path_prefix()}/logs/huaxin/l2/sell_l2_deal.{date}.log" |
| | |
| | | data = line.split(" - ")[1].strip() |
| | | if data.startswith("["): |
| | | data = data[data.find("]") + 1:].strip() |
| | | if data.find("涨停主动买成交:") <0: |
| | | if data.find("涨停主动买成交:") < 0: |
| | | continue |
| | | data = data.split("涨停主动买成交:")[1] |
| | | data = eval(data) |
| | |
| | | path = f"{constant.get_path_prefix()}/logs/gp/plates/special_codes.{date}.log" |
| | | lines = __load_file_content(path) |
| | | if lines: |
| | | line = lines[0] |
| | | line = line[line.find(" - ") + 3:] |
| | | return eval(line) |
| | | line = lines[0] |
| | | line = line[line.find(" - ") + 3:] |
| | | return eval(line) |
| | | return None |
| | | |
| | | |
| | | def load_virtual_trade_account(date=tool.get_now_date_str()): |
| | | """ |
| | | 加载虚拟交易数据 |
| | | :param date: |
| | | :return: |
| | | """ |
| | | path = f"{constant.get_path_prefix()}/logs/gp/virtual_account/virtual_account_money_records.{date}.log" |
| | | fdatas = [] |
| | | if os.path.exists(path): |
| | | with open(path, 'r', encoding="utf-8") as f: |
| | | lines = f.readlines() |
| | | if lines: |
| | | for line in lines: |
| | | time_str = __get_async_log_time(line) |
| | | data = line[line.find("]") + 1:].strip() |
| | | fdatas.append((time_str, eval(data))) |
| | | return fdatas |
| | | |
| | | |
| | | def load_deal_list(date=tool.get_now_date_str()): |
| | | """ |
| | | 加载虚拟交易数据 |
| | | :param date: |
| | | :return: |
| | | """ |
| | | path = f"{constant.get_path_prefix()}/logs/huaxin_local/trade/deal.{date}.log" |
| | | fdatas = [] |
| | | if os.path.exists(path): |
| | | with open(path, 'r', encoding="utf-8") as f: |
| | | lines = f.readlines() |
| | | if lines: |
| | | for line in lines: |
| | | # time_str = __get_async_log_time(line) |
| | | data = line[line.find("]") + 1:].strip() |
| | | fdatas.append(eval(data)) |
| | | return fdatas |
| | | |
| | | |
| | | if __name__ == '__main__': |
| | | line = """ |
| | | 2025-03-12 14:49:15.028 | DEBUG | log_module.async_log_util:run_sync:66 - [14:49:14.899602] thread-id=3048 code=600841 L前监控范围:{1477, 1478, 1479, 1480, 1481, 1482, 1486, 1487, 1488, 1489, 1492, 1493, 1495, 1498, 1500} 计算范围:1477-1503 |
| | |
| | | |
| | | import constant |
| | | import outside_api_command_manager |
| | | from cancel_strategy.s_l_h_cancel_strategy import SCancelBigNumComputer |
| | | from cancel_strategy.s_l_h_cancel_strategy import SCancelBigNumComputer, DCancelBigNumComputer |
| | | from code_attribute import gpcode_manager, code_volumn_manager, global_data_loader, zyltgb_util |
| | | from code_attribute.code_l1_data_manager import L1DataManager |
| | | from code_attribute.gpcode_manager import CodePrePriceManager, CodesNameManager, \ |
| | |
| | | from huaxin_client.trade_transform_protocol import TradeResponse |
| | | from l2 import l2_data_manager_new, l2_log, code_price_manager, l2_data_util, transaction_progress, \ |
| | | l2_data_source_util, l2_data_log, data_callback |
| | | from l2.cancel_buy_strategy import GCancelBigNumComputer, \ |
| | | DCancelBigNumComputer, RDCancelBigNumComputer |
| | | from l2.cancel_buy_strategy import GCancelBigNumComputer |
| | | from l2.code_price_manager import Buy1PriceManager |
| | | from l2.huaxin import huaxin_target_codes_manager, l2_huaxin_util |
| | | from l2.huaxin.huaxin_target_codes_manager import HuaXinL1TargetCodesManager |
| | |
| | | |
| | | # -----------------------判断是是否有自动撤单规则----------------------- |
| | | try: |
| | | if DCancelBigNumComputer().has_auto_cancel_rules(code): |
| | | need_cancel, rule_id = DCancelBigNumComputer().need_cancel(code, buy_1_volume) |
| | | if True: |
| | | need_cancel, msg = DCancelBigNumComputer().need_cancel(code, (buy_1_price, buy_1_volume), |
| | | limit_up_price, time_str) |
| | | if need_cancel: |
| | | try: |
| | | l2_data_manager_new.L2TradeDataProcessor.cancel_buy(code, f"盯封单撤:{time_str}-{buy_1_volume}", |
| | | l2_data_manager_new.L2TradeDataProcessor.cancel_buy(code, |
| | | f"盯封单撤:{time_str}-{buy_1_volume} , {msg}", |
| | | cancel_type=trade_constant.CANCEL_TYPE_D) |
| | | finally: |
| | | TradeRuleManager().excuted(rule_id) |
| | | pass |
| | | except Exception as e: |
| | | logger_debug.exception(e) |
| | | |