| | |
| | | |
| | | # 是否具有K线形态 |
| | | def is_has_k_format(limit_up_price, record_datas): |
| | | is_too_high, is_new_top, is_lowest, is_near_new_top, is_n, is_v, has_format, volume_info, is_special = get_k_format( |
| | | is_too_high, is_new_top, is_lowest, is_near_new_top, is_n, is_v, has_format, volume_info, is_special, has_max_volume = get_k_format( |
| | | float(limit_up_price), record_datas) |
| | | if not has_format: |
| | | return False, "不满足K线形态" |
| | |
| | | |
| | | |
| | | # 是否涨得太高 |
| | | def is_up_too_high_in_10d(record_datas): |
| | | def is_up_too_high_in_10d_with_limit_up(record_datas): |
| | | datas = copy.deepcopy(record_datas) |
| | | datas.sort(key=lambda x: x["bob"]) |
| | | datas = datas[-10:] |
| | |
| | | return False |
| | | |
| | | |
| | | # 在最近几天内股价是否长得太高 |
| | | def is_price_too_high_in_days(record_datas, limit_up_price, day_count=6): |
| | | datas = copy.deepcopy(record_datas) |
| | | datas.sort(key=lambda x: x["bob"]) |
| | | datas = datas[0 - day_count:] |
| | | min_price = None |
| | | max_price = None |
| | | for d in datas: |
| | | if min_price is None: |
| | | min_price = d["low"] |
| | | if max_price is None: |
| | | max_price = d["high"] |
| | | if min_price > d["low"]: |
| | | min_price = d["low"] |
| | | if max_price < d["high"]: |
| | | max_price = d["high"] |
| | | if max_price > float(limit_up_price): |
| | | return False |
| | | rate = (float(limit_up_price) - min_price) / min_price |
| | | # print(rate) |
| | | if rate >= 0.25: |
| | | return True |
| | | return False |
| | | |
| | | |
| | | # 是否有涨停 |
| | | def get_first_limit_up_count(datas): |
| | | datas = copy.deepcopy(datas) |
| | |
| | | k_format = code_nature_analyse.get_k_format(limit_up_price, volumes_data) |
| | | code_nature_analyse.CodeNatureRecordManager().save_k_format(code, k_format) |
| | | |
| | | if code_nature_analyse.is_up_too_high_in_10d(volumes_data): |
| | | if code_nature_analyse.is_up_too_high_in_10d_with_limit_up(volumes_data): |
| | | # 判断是否太高 |
| | | l2_trade_util.forbidden_trade(code, "股价长得太高") |
| | | HighIncreaseCodeManager().add_code(code) |
| | |
| | | l2_trade_util.forbidden_trade(code, "120天内股价长得太高") |
| | | HighIncreaseCodeManager().add_code(code) |
| | | |
| | | if code_nature_analyse.is_price_too_high_in_days(volumes_data, limit_up_price): |
| | | # 判断是否太高 |
| | | l2_trade_util.forbidden_trade(code, "6天内股价长得太高") |
| | | HighIncreaseCodeManager().add_code(code) |
| | | |
| | | if code_nature_analyse.is_have_latest_max_volume(volumes_data, 2): |
| | | # 最近2天是否是最高量 |
| | | code_nature_analyse.LatestMaxVolumeManager().set_has_latest_max_volume(code) |
| | |
| | | d = {"dataTimeStamp": pDepthMarketData['DataTimeStamp'], "securityID": pDepthMarketData['SecurityID'], |
| | | "lastPrice": pDepthMarketData['LastPrice'], |
| | | "totalVolumeTrade": pDepthMarketData['TotalVolumeTrade'], |
| | | "totalValueTrade":pDepthMarketData['TotalValueTrade'], |
| | | "totalAskVolume": pDepthMarketData['TotalAskVolume'], |
| | | "avgAskPrice": pDepthMarketData["AvgAskPrice"], |
| | | "buy": [(pDepthMarketData['BidPrice1'], pDepthMarketData['BidVolume1']), |
| | |
| | | # 最近3分钟内的买1金额 |
| | | __latest_3m_buy1_money_list_dict = {} |
| | | __open_limit_up_lowest_price_cache = {} |
| | | # 均价 |
| | | __average_rate_dict = {} |
| | | |
| | | __instance = None |
| | | |
| | |
| | | price = self.__get_open_limit_up_lowest_price_cache(code) |
| | | return price |
| | | |
| | | # 处理 |
| | | def get_average_rate(self, code): |
| | | return self.__average_rate_dict.get(code) |
| | | |
| | | def process(self, code, buy_1_price, buy_1_volume, time_str, limit_up_price, sell_1_price, sell_1_volumn): |
| | | # 处理 |
| | | def process(self, code, buy_1_price, buy_1_volume, time_str, limit_up_price, sell_1_price, sell_1_volumn, |
| | | average_rate=None): |
| | | self.__average_rate_dict[code] = average_rate |
| | | data_str = f"{buy_1_price},{buy_1_volume},{time_str},{limit_up_price},{sell_1_price},{sell_1_volumn}" |
| | | if self.__latest_data.get(code) == data_str: |
| | | return |
| | | |
| | | # 记录日志 |
| | | logger_trade_queue_price_info.info( |
| | | f"code={code} data: time_str-{time_str}, buy_1_price-{buy_1_price},limit_up_price-{limit_up_price},sell_1_price-{sell_1_price},sell_1_volumn-{sell_1_volumn}") |
| | | f"code={code} data: time_str-{time_str}, buy_1_price-{buy_1_price},limit_up_price-{limit_up_price},sell_1_price-{sell_1_price},sell_1_volumn-{sell_1_volumn},percent_rate-{percent_rate}") |
| | | # 买1价格不能小于1块 |
| | | if float(buy_1_price) < 1.0: |
| | | return |
| | |
| | | l2_trade_util.forbidden_trade(code, msg="当日下单次数已达10次") |
| | | return False, True, f"当日下单次数已达10次" |
| | | |
| | | # ---------均价约束------------- |
| | | average_rate = cls.__Buy1PriceManager.get_average_rate(code) |
| | | if average_rate and average_rate <= 0.01: |
| | | return False, True, f"均价涨幅({average_rate})小于1%" |
| | | |
| | | # -------量的约束-------- |
| | | if cls.volume_rate_info[code][0] < 0.2: |
| | | return False, True, f"当日量比({cls.volume_rate_info[code][0]})小于0.2" |
| | |
| | | def test_block(self): |
| | | code = "002962" |
| | | KPLCodeJXBlockManager().load_jx_blocks(code, 14.99, 14.99) |
| | | KPLCodeJXBlockManager().load_jx_blocks(code, 14.99, 14.99) |
| | | block_info.init_code(code) |
| | | kpl_data_manager.KPLLimitUpDataRecordManager.load_total_datas() |
| | | yesterday_codes = kpl_data_manager.get_yesterday_limit_up_codes() |
New file |
| | |
| | | from code_attribute import code_nature_analyse |
| | | from utils import init_data_util |
| | | |
| | | |
| | | def is_too_high(datas): |
| | | limit_up_price = round(datas[0]["close"] * 1.1, 2) |
| | | datas.reverse() |
| | | is_new_high = code_nature_analyse.is_price_too_high_in_days(datas, limit_up_price) |
| | | return is_new_high |
| | | |
| | | |
| | | if __name__ == "__main__": |
| | | code_str = "000536,000625,000628,000670,000766,000829,001311,001331,002189,002275,002331,002341,002363,002406,002416,002655,002691,002848,002861,002885,002906,002917,002962,300217,300462,300552,301111,301215,301372,600107,600178,600222,600288,600513,600698,600960,601777,603029,603286,603297,603569,605020,688314,688789" |
| | | codes = code_str.split(",") |
| | | for code in codes: |
| | | if code.find("00") != 0 and code.find("60") != 0: |
| | | continue |
| | | try: |
| | | datas = init_data_util.get_volumns_by_code(code, 120) |
| | | datas = datas[3:] |
| | | result = is_too_high(datas) |
| | | if result: |
| | | print(code, result) |
| | | except: |
| | | print(code, "出错") |
| | |
| | | async_log_util.info(logger_kpl_block_can_buy, f"{code}:获取到精选板块-{blocks}") |
| | | else: |
| | | # 还没涨停的需要更新精选板块 更新精选板块 |
| | | if abs(float(buy_1_price) - float(limit_up_price)) >= 0.001: |
| | | if abs(float(buy_1_price) - float(limit_up_price)) >= 0.001 or constant.TEST: |
| | | # 非涨停状态 |
| | | UPDATE_TIME_SPACE = 5 * 60 |
| | | time_diff = tool.trade_time_sub(tool.get_now_time_str(), "09:30:00") |
| | |
| | | |
| | | |
| | | def __run_recv_queue_trade(queue: multiprocessing.Queue): |
| | | |
| | | def __process_order(data): |
| | | code = data["securityID"] |
| | | accountID = data["accountID"] |
| | | orderStatus = data["orderStatus"] |
| | | orderRef = data["orderRef"] |
| | | orderSysID = data["orderSysID"] |
| | | insertTime = data.get("insertTime") |
| | | acceptTime = data.get("acceptTime") |
| | | insertDate = data.get("insertDate") |
| | | direction = data.get("direction") |
| | | limitPrice = data.get("limitPrice") |
| | | volume = data.get("volume") |
| | | is_shadow_order = False |
| | | # 获取涨停价 |
| | | limit_up_price = gpcode_manager.get_limit_up_price(code) |
| | | if limit_up_price and volume == huaxin_client_constant.SHADOW_ORDER_VOLUME: |
| | | if abs(float(limitPrice) - float(limit_up_price)) >= 0.01: |
| | | is_shadow_order = True |
| | | |
| | | order = HuaxinOrderEntity(code, orderStatus, orderRef, accountID, orderSysID, |
| | | insertTime=insertTime, acceptTime=acceptTime, |
| | | insertDate=insertDate, direction=direction, |
| | | is_shadow_order=is_shadow_order) |
| | | try: |
| | | if order.direction == str(huaxin_util.TORA_TSTP_D_Sell): |
| | | # 刷新持仓列表 |
| | | huaxin_trade_data_update.add_position_list() |
| | | TradeResultProcessor.process_buy_order(order) |
| | | TradeResultProcessor.process_sell_order(order) |
| | | finally: |
| | | try: |
| | | # 加入2次,增大加入成功率 |
| | | __save_data_queue.put_nowait(data) |
| | | except Exception as e: |
| | | hx_logger_trade_debug.exception(e) |
| | | |
| | | if not is_shadow_order: |
| | | # 订单相关回调 |
| | | # 重新请求委托列表与资金 |
| | | # huaxin_trade_data_update.add_delegate_list("来自交易管道") |
| | | huaxin_trade_data_update.add_deal_list() |
| | | huaxin_trade_data_update.add_money_list() |
| | | |
| | | # 设置结果 |
| | | def __set_response(data_json): |
| | | if 'request_id' not in data_json: |
| | |
| | | async_log_util.info(hx_logger_trade_callback, |
| | | f"response:request_id-{request_id}") |
| | | __response_thread_pool.submit(__set_response, data_json) |
| | | if type(data_json.get("data")) == dict: |
| | | data = data_json["data"].get("data") |
| | | if type(data) == dict and "orderRef" in data: |
| | | __response_thread_pool.submit(__process_order, data) |
| | | elif type_ == "trade_callback": |
| | | try: |
| | | # 交易回调 |
| | |
| | | if ctype == 0: |
| | | data = data_json.get("data") |
| | | # 获取订单状态 |
| | | code = data["securityID"] |
| | | accountID = data["accountID"] |
| | | orderStatus = data["orderStatus"] |
| | | orderRef = data["orderRef"] |
| | | orderSysID = data["orderSysID"] |
| | | insertTime = data.get("insertTime") |
| | | acceptTime = data.get("acceptTime") |
| | | insertDate = data.get("insertDate") |
| | | direction = data.get("direction") |
| | | limitPrice = data.get("limitPrice") |
| | | volume = data.get("volume") |
| | | is_shadow_order = False |
| | | # 获取涨停价 |
| | | limit_up_price = gpcode_manager.get_limit_up_price(code) |
| | | if limit_up_price and volume == huaxin_client_constant.SHADOW_ORDER_VOLUME: |
| | | if abs(float(limitPrice) - float(limit_up_price)) >= 0.01: |
| | | is_shadow_order = True |
| | | |
| | | order = HuaxinOrderEntity(code, orderStatus, orderRef, accountID, orderSysID, |
| | | insertTime=insertTime, acceptTime=acceptTime, |
| | | insertDate=insertDate, direction=direction, |
| | | is_shadow_order=is_shadow_order) |
| | | try: |
| | | if order.direction == str(huaxin_util.TORA_TSTP_D_Sell): |
| | | # 刷新持仓列表 |
| | | huaxin_trade_data_update.add_position_list() |
| | | TradeResultProcessor.process_buy_order(order) |
| | | TradeResultProcessor.process_sell_order(order) |
| | | finally: |
| | | try: |
| | | # 加入2次,增大加入成功率 |
| | | __save_data_queue.put_nowait(data) |
| | | except Exception as e: |
| | | hx_logger_trade_debug.exception(e) |
| | | |
| | | if not is_shadow_order: |
| | | # 订单相关回调 |
| | | # 重新请求委托列表与资金 |
| | | # huaxin_trade_data_update.add_delegate_list("来自交易管道") |
| | | huaxin_trade_data_update.add_deal_list() |
| | | huaxin_trade_data_update.add_money_list() |
| | | # print("响应结果:", data_json['data']) |
| | | __process_order(data) |
| | | finally: |
| | | pass |
| | | except: |
| | |
| | | import inited_data |
| | | import outside_api_command_manager |
| | | from code_attribute import gpcode_manager, code_volumn_manager, global_data_loader |
| | | from code_attribute.gpcode_manager import CodePrePriceManager |
| | | from code_attribute.gpcode_manager import CodePrePriceManager, CodesNameManager |
| | | from db import mysql_data_delegate as mysql_data, redis_manager_delegate as redis_manager |
| | | from db.redis_manager_delegate import RedisUtils |
| | | from huaxin_client import l1_subscript_codes_manager, l2_data_transform_protocol |
| | |
| | | limit_up_price = gpcode_manager.get_limit_up_price(code) |
| | | |
| | | if limit_up_price is not None: |
| | | average_rate = None |
| | | try: |
| | | average_price = data["totalValueTrade"] / data["totalVolumeTrade"] |
| | | pre_close_price = CodePrePriceManager.get_price_pre_cache(code) |
| | | average_rate = round((average_price - pre_close_price) / pre_close_price, 4) |
| | | except: |
| | | pass |
| | | # 处理买1,卖1信息 |
| | | code_price_manager.Buy1PriceManager().process(code, buy_1_price, buy_1_volume, time_str, |
| | | limit_up_price, |
| | | sell_1_price, sell_1_volume // 100) |
| | | sell_1_price, sell_1_volume // 100, average_rate) |
| | | latest_3m_buy1_money_list = code_price_manager.Buy1PriceManager().get_latest_3m_buy1_money_list(code) |
| | | # -----------------------------重新计算L撤后--------------------------- |
| | | # 如果时涨停状态 |
| | |
| | | volume_info = l2_data_manager_new.L2TradeDataProcessor.volume_rate_info.get(code) |
| | | if volume_info: |
| | | volume_rate = volume_info[0] |
| | | need_cancel, msg = UCancelBigNumComputer().need_cancel(code, order_begin_pos, kpl_data_manager.KPLLimitUpDataRecordManager.get_current_reason_codes_dict(), volume_rate) |
| | | need_cancel, msg = UCancelBigNumComputer().need_cancel(code, order_begin_pos, |
| | | kpl_data_manager.KPLLimitUpDataRecordManager.get_current_reason_codes_dict(), |
| | | volume_rate) |
| | | if need_cancel: |
| | | l2_data_manager_new.L2TradeDataProcessor.cancel_buy(code, msg) |
| | | except Exception as e: |
| | |
| | | raise Exception("没有获取到L1现价") |
| | | price = round(float(current_price) - 0.05, 2) |
| | | async_log_util.info(logger_trade, f"API卖: 单价-{price}") |
| | | result = huaxin_trade_api.order(direction, code, volume, price, sinfo=sinfo, |
| | | order_ref = huaxin_util.create_order_ref() |
| | | result = huaxin_trade_api.order(direction, code, volume, price, sinfo=sinfo, order_ref=order_ref, |
| | | blocking=True, request_id=request_id) |
| | | logger_debug.info(f"卖接口返回数据:{result}") |
| | | order_ref = result.get("order_ref") |
| | | # 如果是在正常交易时间提交的2s之内还未成交的需要撤单 |
| | | if int("092958") <= int(tool.get_now_time_str().replace(":", "")) <= int("150000"): |
| | | self.__cancel_sell_thread_pool.submit(lambda: self.__cancel_sell_order(code, order_ref)) |
| | | |
| | | self.send_response({"code": 0, "data": result}, client_id, request_id) |
| | | self.send_response(result, client_id, request_id) |
| | | else: |
| | | result = huaxin_trade_api.order(direction, code, volume, price, price_type=price_type, sinfo=sinfo, |
| | | blocking=True, request_id=request_id) |
| | |
| | | fdata = {"code": code, "total": 0, "available": 0, "sell_rules_count": sell_rules_count} |
| | | if positions: |
| | | for d in positions: |
| | | code_name = gpcode_manager.get_code_name(d["securityID"]) |
| | | if not code_name: |
| | | # 判断是否有名称 |
| | | results = HistoryKDatasUtils.get_gp_codes_names([d["securityID"]]) |
| | | threading.Thread( |
| | | target=CodesNameManager.add_first_code_name(d["securityID"], results[0])).start() |
| | | if d["prePosition"] <= 0: |
| | | continue |
| | | if d["securityID"] != code: |
| | |
| | | break |
| | | result = {"code": 0, "data": fdata} |
| | | self.send_response(result, client_id, request_id) |
| | | |
| | | |
| | | except Exception as e: |
| | | logging.exception(e) |
| | | self.send_response(json.dumps({"code": 1, "msg": f"数据处理出错:{e}"}), client_id, request_id) |
| | |
| | | def OnCommonRequest(self, client_id, request_id, data): |
| | | # 通用请求 |
| | | ctype = data["ctype"] |
| | | try: |
| | | if ctype == "get_sell_result": |
| | | order_ref = data["order_ref"] |
| | | order_entity = huaxin_trade_order_processor.TradeResultProcessor.get_huaxin_order_by_order_ref( |
| | | order_ref) |
| | | if not order_entity: |
| | | self.send_response(json.dumps({"code": 1, "msg": f"没有获取到订单状态"}), client_id, request_id) |
| | | else: |
| | | code_name = gpcode_manager.get_code_name(order_entity.code) |
| | | result = {} |
| | | if huaxin_util.is_canceled(order_entity.orderStatus): |
| | | result = {"code": 0, |
| | | "data": {"orderStatus": order_entity.orderStatus, "code": order_entity.code, |
| | | "msg": f"【{order_entity.code}({code_name})】已撤单"}} |
| | | elif huaxin_util.is_deal(order_entity.orderStatus): |
| | | result = {"code": 0, |
| | | "data": {"orderStatus": order_entity.orderStatus, "code": order_entity.code, |
| | | "msg": f"【{order_entity.code}({code_name})】已经成交"}} |
| | | else: |
| | | result = {"code": 0, |
| | | "data": {"orderStatus": order_entity.orderStatus, "code": order_entity.code, |
| | | "msg": f"【{order_entity.code}({code_name})】已挂单"}} |
| | | self.send_response(result, client_id, request_id) |
| | | except Exception as e: |
| | | logging.exception(e) |
| | | self.send_response(json.dumps({"code": 1, "msg": f"数据处理出错:{e}"}), client_id, request_id) |
| | | |
| | | # 获取子类型 |
| | | |
| | | |