New file |
| | |
| | | """ |
| | | 股性分析 |
| | | """ |
| | | |
| | | # 是否有涨停 |
| | | import copy |
| | | import json |
| | | |
| | | import gpcode_manager |
| | | |
| | | # 代码股性记录管理 |
| | | import tool |
| | | from db.redis_manager import RedisManager |
| | | |
| | | |
| | | class CodeNatureRecordManager: |
| | | __redisManager = RedisManager(0) |
| | | |
| | | @classmethod |
| | | def __get_redis(cls): |
| | | return cls.__redisManager.getRedis() |
| | | |
| | | # 保存K线形态 |
| | | @classmethod |
| | | def save_k_format(cls, code, k_format): |
| | | cls.__get_redis().setex(f"k_format-{code}", tool.get_expire(), json.dumps(k_format)) |
| | | |
| | | @classmethod |
| | | def get_k_format(cls, code): |
| | | val = cls.__get_redis().get(f"k_format-{code}") |
| | | if val: |
| | | return json.loads(val) |
| | | return None |
| | | |
| | | # 保存股性 |
| | | @classmethod |
| | | def save_nature(cls, code, natures): |
| | | cls.__get_redis().setex(f"code_nature-{code}", tool.get_expire(), json.dumps(natures)) |
| | | |
| | | @classmethod |
| | | def get_nature(cls, code): |
| | | val = cls.__get_redis().get(f"code_nature-{code}") |
| | | if val: |
| | | return json.loads(val) |
| | | return None |
| | | |
| | | |
| | | # 设置历史K线 |
| | | def set_record_datas(code, limit_up_price, record_datas): |
| | | k_format = get_k_format(limit_up_price, record_datas) |
| | | CodeNatureRecordManager.save_k_format(code, k_format) |
| | | natures = get_nature(record_datas) |
| | | CodeNatureRecordManager.save_nature(code, natures) |
| | | |
| | | # 获取K线形态 |
| | | # 返回 (15个交易日涨幅是否大于24.9%,是否破前高,是否超跌,是否接近前高,是否N,是否V) |
| | | def get_k_format(limit_up_price, record_datas): |
| | | p1 = get_lowest_price_rate(record_datas) >= 0.249 |
| | | p2 = __is_new_top(limit_up_price, record_datas) |
| | | p3 = __is_lowest(record_datas) |
| | | p4 = __is_near_new_top(limit_up_price, record_datas) |
| | | p5 = __is_n_model(record_datas) |
| | | p6 = __is_v_model(record_datas) |
| | | # N字型包含了N字型 |
| | | if p5: |
| | | p6 = False |
| | | return (p1, p2, p3, p4, p5, p6) |
| | | |
| | | |
| | | # 是否具有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 = get_k_format(limit_up_price, record_datas) |
| | | |
| | | # if is_too_high: |
| | | # return False, "15个交易日涨幅大于24.9%" |
| | | # if is_near_new_top: |
| | | # return False, "逼近前高" |
| | | if is_new_top: |
| | | return True, "破前高" |
| | | if is_lowest: |
| | | return True, "超跌补涨" |
| | | if is_n: |
| | | return True, "N字型" |
| | | if is_v: |
| | | return True, "V字形" |
| | | return False, "不满足K线形态" |
| | | |
| | | |
| | | # 获取股性 |
| | | # 返回(是否涨停,首板溢价率是否大于0.6) |
| | | def get_nature(record_datas): |
| | | limit_up = is_have_limit_up(record_datas) |
| | | premium_rate = get_limit_up_premium_rate(record_datas) |
| | | result = (limit_up, premium_rate >= 0.6) |
| | | |
| | | return result |
| | | |
| | | |
| | | def get_lowest_price_rate(record_datas): |
| | | datas = copy.deepcopy(record_datas) |
| | | datas.sort(key=lambda x: x["bob"]) |
| | | datas = datas[-15:] |
| | | low_price = datas[0]["close"] |
| | | for data in datas: |
| | | if low_price > data["close"]: |
| | | low_price = data["close"] |
| | | return (datas[-1]["close"] - low_price) / low_price |
| | | |
| | | |
| | | # 是否有涨停 |
| | | def is_have_limit_up(datas): |
| | | datas = copy.deepcopy(datas) |
| | | for i in range(len(datas)): |
| | | item = datas[i] |
| | | limit_up_price = float(gpcode_manager.get_limit_up_price_by_preprice(item["pre_close"])) |
| | | if abs(limit_up_price - item["close"]) < 0.01: |
| | | return True |
| | | return False |
| | | |
| | | |
| | | def is_have_limit_up_by_code(code): |
| | | return False |
| | | |
| | | |
| | | # 是否破前高 |
| | | def __is_new_top(limit_up_price, datas): |
| | | datas = copy.deepcopy(datas) |
| | | datas.sort(key=lambda x: x["bob"]) |
| | | datas = datas[-80:] |
| | | max_price = 0 |
| | | for data in datas: |
| | | if max_price < data["high"]: |
| | | max_price = data["high"] |
| | | if limit_up_price > max_price: |
| | | return True |
| | | return False |
| | | |
| | | |
| | | # 接近新高 |
| | | def __is_near_new_top(limit_up_price, datas): |
| | | datas = copy.deepcopy(datas) |
| | | datas.sort(key=lambda x: x["bob"]) |
| | | datas = datas[-80:] |
| | | max_volume = 0 |
| | | price = 0 |
| | | for data in datas: |
| | | if max_volume < data["volume"]: |
| | | max_volume = data["volume"] |
| | | price = data["high"] |
| | | print(max_volume) |
| | | if limit_up_price < price and (price - limit_up_price) / limit_up_price < 0.03: |
| | | return True |
| | | return False |
| | | |
| | | |
| | | # 是否跌破箱体 |
| | | def __is_lowest(datas): |
| | | datas = copy.deepcopy(datas) |
| | | datas.sort(key=lambda x: x["bob"]) |
| | | datas = datas[-80:] |
| | | min_price = 100000 |
| | | for data in datas: |
| | | if min_price > data["low"]: |
| | | min_price = data["low"] |
| | | # 近5天内的最低价 |
| | | min_price_5 = 10000 |
| | | for data in datas[-5:]: |
| | | if min_price_5 > data["low"]: |
| | | min_price_5 = data["low"] |
| | | if abs(min_price_5 - min_price) / min_price < 0.015: |
| | | return True |
| | | return False |
| | | |
| | | |
| | | # N字形 |
| | | def __is_n_model(datas): |
| | | datas = copy.deepcopy(datas) |
| | | datas.sort(key=lambda x: x["bob"]) |
| | | datas = datas[-80:] |
| | | if len(datas) >= 6: |
| | | max_price = 0 |
| | | min_price = 1000000 |
| | | for i in range(len(datas) - 5, len(datas)): |
| | | item = datas[i] |
| | | print(item) |
| | | limit_up_price = float(gpcode_manager.get_limit_up_price_by_preprice(item["pre_close"])) |
| | | if abs(limit_up_price - item["close"]) < 0.001 and abs( |
| | | limit_up_price - datas[i - 1]["close"]) >= 0.001: |
| | | # 涨停,前一天非涨停 |
| | | max_price = item["close"] |
| | | elif max_price > 0: |
| | | if min_price > item["low"]: |
| | | min_price = item["low"] |
| | | if max_price > min_price: |
| | | return True |
| | | return False |
| | | |
| | | |
| | | # V字形 |
| | | def __is_v_model(datas): |
| | | datas = copy.deepcopy(datas) |
| | | datas.sort(key=lambda x: x["bob"]) |
| | | datas = datas[-30:] |
| | | max_price = 0 |
| | | max_price_index = -1 |
| | | for i in range(0, len(datas)): |
| | | if max_price < datas[i]["close"]: |
| | | max_price = datas[i]["close"] |
| | | max_price_index = i |
| | | min_price = max_price |
| | | min_price_index = max_price_index |
| | | for i in range(max_price_index, len(datas)): |
| | | if min_price > datas[i]["close"]: |
| | | min_price = datas[i]["close"] |
| | | min_price_index = i |
| | | |
| | | if (max_price - min_price) / max_price > 0.249: |
| | | return True |
| | | |
| | | return False |
| | | |
| | | |
| | | # 首板涨停溢价率 |
| | | def get_limit_up_premium_rate(datas): |
| | | datas = copy.deepcopy(datas) |
| | | datas.sort(key=lambda x: x["bob"]) |
| | | first_rate_list = [] |
| | | for i in range(0, len(datas)): |
| | | item = datas[i] |
| | | limit_up_price = float(gpcode_manager.get_limit_up_price_by_preprice(item["pre_close"])) |
| | | if abs(limit_up_price - item["close"]) < 0.001 and abs( |
| | | limit_up_price - datas[i - 1]["close"]) >= 0.001 and 0 < i < len(datas) - 1: |
| | | # 首板涨停 |
| | | rate = (datas[i + 1]["high"] - datas[i + 1]["pre_close"]) / datas[i + 1]["pre_close"] |
| | | first_rate_list.append(rate) |
| | | if not first_rate_list: |
| | | return 1 |
| | | count = 0 |
| | | for rate in first_rate_list: |
| | | if rate >= 0.01: |
| | | count += 1 |
| | | return count / len(first_rate_list) |
| | |
| | | # max60 60天最大量 |
| | | # yesterday 昨天的量 |
| | | import global_util |
| | | import gpcode_manager |
| | | from db import redis_manager |
| | | import tool |
| | | from log import logger_day_volumn |
| | |
| | | for k in keys: |
| | | code = k.split("-")[1] |
| | | global_util.yesterday_volumn[code] = redis.get(k) |
| | | |
| | | |
| | |
| | | |
| | | |
| | | if __name__ == "__main__": |
| | | codes = ["002119"] |
| | | codes = ["000977"] |
| | | for code in codes: |
| | | export_l2_excel(code) |
| | |
| | | keys = redis.keys("juejin_listen_code-*") |
| | | return len(keys) |
| | | |
| | | @classmethod |
| | | def get_previous_trading_date(cls, date): |
| | | account_id, s_id, token = getAccountInfo() |
| | | gmapi.set_token(token) |
| | | return gmapi.get_previous_trading_date("SHSE", date) |
| | | |
| | | |
| | | def trade(code, volume): |
| | | account_id, s_id, token = getAccountInfo() |
| | |
| | | |
| | | # 获取近90天的最大量与最近的量 |
| | | # 获取最近一次涨停/涨停下一个交易日的最大值 |
| | | def get_volumn(code) -> object: |
| | | datas = JueJinManager.get_history_tick_n(code, 60, "open,high,low,close,volume,pre_close,bob") |
| | | def get_volumns_by_code(code, count=60) -> object: |
| | | datas = JueJinManager.get_history_tick_n(code, count, "open,high,low,close,volume,pre_close,bob") |
| | | # 计算 |
| | | datas.sort(key=lambda x: x["bob"], reverse=True) |
| | | return datas |
| | | |
| | | |
| | | # 解析最大量 |
| | | def parse_max_volume(datas): |
| | | max_volume = 0 |
| | | for i in range(len(datas)): |
| | | # 查询涨停 |
| | |
| | | next_volume = 0 |
| | | if i > 0: |
| | | next_volume = datas[i - 1]["volume"] |
| | | return (max(volume, next_volume), max(volume, next_volume)) |
| | | volume = max(volume, next_volume) |
| | | return (volume, volume) |
| | | return (max_volume, max_volume) |
| | | |
| | | |
| | | # 是否有涨停 |
| | | def is_have_limit_up(datas): |
| | | for i in range(len(datas)): |
| | | item = datas[i] |
| | | limit_up_price = float(gpcode_manager.get_limit_up_price_by_preprice(item["pre_close"])) |
| | | if abs(limit_up_price - item["close"]) < 0.01: |
| | | return True |
| | | return False |
| | | |
| | | |
| | | # 首板涨停溢价率 |
| | | def get_limit_up_money_percent(datas): |
| | | datas.sort(key=lambda x: x["bob"]) |
| | | first_rate_list = [] |
| | | for i in range(0, len(datas)): |
| | | item = datas[i] |
| | | limit_up_price = float(gpcode_manager.get_limit_up_price_by_preprice(item["pre_close"])) |
| | | if abs(limit_up_price - item["close"]) < 0.001 and abs( |
| | | limit_up_price - datas[i - 1]["close"]) >= 0.001 and 0 < i < len(datas) - 1: |
| | | # 首板涨停 |
| | | rate = (datas[i + 1]["high"] - datas[i + 1]["pre_close"]) / datas[i + 1]["pre_close"] |
| | | first_rate_list.append(rate) |
| | | if not first_rate_list: |
| | | return 1 |
| | | count = 0 |
| | | for rate in first_rate_list: |
| | | if rate >= 0.01: |
| | | count += 1 |
| | | return count / len(first_rate_list) |
| | | |
| | | |
| | | # 根据涨幅高低分配交易窗口 |
| | |
| | | |
| | | |
| | | if __name__ == '__main__': |
| | | print(get_volumn("002291")) |
| | | datas=(get_volumns_by_code("603083", 150)) |
| | | print(datas) |
| | | print(get_limit_up_money_percent(datas)) |
| | |
| | | if int(total_data[buy_single_index]["val"]["time"].replace(":", "")) <= int( |
| | | buy_time.replace(":", "")): |
| | | # 买入时间在囊括范围内 |
| | | if tool.trade_time_sub(tool.trade_time_add_second(buy_exec_time, range_seconds), |
| | | total_data[buy_index]["val"]["time"]) >= 0: |
| | | if tool.trade_time_sub(tool.trade_time_add_second(buy_exec_time, range_seconds),buy_time) >= 0: |
| | | cancel_num += data["re"] * int(val["num"]) |
| | | |
| | | # 保存数据 |
| | |
| | | return True, total_data[i] |
| | | finally: |
| | | |
| | | l2_log.cancel_debug(code, "S级大单 范围:{}-{} 取消计算结果:{}/{},比例:{} 目标比例:{} 计算时间范围:{}", start_index, end_index, cancel_num, |
| | | buy_num, round(cancel_num / max(buy_num, 1), 2), cancel_rate_threshold,range_seconds) |
| | | l2_log.cancel_debug(code, "S级大单 范围:{}-{} 取消计算结果:{}/{},比例:{} 目标比例:{} 计算时间范围:{}", start_index, end_index, |
| | | cancel_num, |
| | | buy_num, round(cancel_num / max(buy_num, 1), 2), cancel_rate_threshold, range_seconds) |
| | | |
| | | # 保存处理进度与数据 |
| | | cls.__save_compute_data(code, process_index, buy_num, cancel_num) |
| | |
| | | finally: |
| | | l2_log.cancel_debug(code, "H级撤单计算结果 范围:{}-{} 处理进度:{} 取消计算结果:{}/{} 目标撤单比例:{}", start_index, end_index, |
| | | process_index, cancel_num, |
| | | total_nums,cancel_rate_threshold) |
| | | total_nums, cancel_rate_threshold) |
| | | logger_l2_h_cancel.info( |
| | | f"code-{code} H级撤单计算结果 范围:{start_index}-{end_index} 处理进度:{process_index} 目标比例:{cancel_rate_threshold} 取消计算结果:{cancel_num}/{total_nums}") |
| | | # 保存处理进度与数据 |
| | |
| | | if left_count > 0: |
| | | data = total_data[i] |
| | | val = data["val"] |
| | | if val["num"] * float(val["price"]) <= constant.H_CANCEL_MIN_MONEY*100: |
| | | if val["num"] * float(val["price"]) <= constant.H_CANCEL_MIN_MONEY * 100: |
| | | continue |
| | | total_count += left_count |
| | | watch_set.add((i, val["num"], left_count)) |
| | |
| | | if left_count > 0: |
| | | data = total_data[i] |
| | | val = data["val"] |
| | | if val["num"] * float(val["price"]) <= constant.H_CANCEL_MIN_MONEY*100: |
| | | if val["num"] * float(val["price"]) <= constant.H_CANCEL_MIN_MONEY * 100: |
| | | continue |
| | | total_count += left_count |
| | | watch_set.add((i, val["num"], left_count)) |
| | |
| | | if total_count >= MIN_H_COUNT and big_num_count >= constant.H_CANCEL_MIN_BIG_NUM_COUNT: # and total_num >= threshold_num |
| | | finished = True |
| | | l2_log.cancel_debug(code, "获取到H撤监听数据:{},计算截至位置:{},目标计算数量:{}", json.dumps(list(watch_set)), |
| | | total_data[-1]["index"],MIN_H_COUNT) |
| | | total_data[-1]["index"], MIN_H_COUNT) |
| | | break |
| | | |
| | | final_watch_list = list(watch_set) |
| | |
| | | # 计算量 |
| | | volume_rate = code_volumn_manager.get_volume_rate(code) |
| | | volume_rate_index = code_volumn_manager.get_volume_rate_index(volume_rate) |
| | | l2_log.debug(code,"量比:{},量索引:{}",volume_rate,volume_rate_index) |
| | | cls.volume_rate_info[code] = (volume_rate, volume_rate_index) |
| | | # 是否为首板代码 |
| | | is_first_code = gpcode_manager.FirstCodeManager.is_in_first_record(code) |
| | | latest_time = add_datas[len(add_datas) - 1]["val"]["time"] |
| | | # 时间差不能太大才能处理 |
| | | if l2.l2_data_util.L2DataUtil.is_same_time(now_time_str, |
| | | latest_time) and not l2_trade_util.is_in_forbidden_trade_codes( |
| | | code): |
| | | if not l2_trade_util.is_in_forbidden_trade_codes(code): |
| | | # 判断是否已经挂单 |
| | | state = trade_manager.get_trade_state(code) |
| | | start_index = len(total_datas) - len(add_datas) |
| | |
| | | # 已挂单 |
| | | cls.__process_order(code, start_index, end_index, capture_timestamp, is_first_code) |
| | | else: |
| | | # 未挂单 |
| | | cls.__process_not_order(code, start_index, end_index, capture_timestamp, is_first_code) |
| | | # 未挂单,时间相差不大才能挂单 |
| | | if l2.l2_data_util.L2DataUtil.is_same_time(now_time_str, latest_time): |
| | | cls.__process_not_order(code, start_index, end_index, capture_timestamp, is_first_code) |
| | | |
| | | logger_l2_process.info("code:{} 处理数据范围: {}-{} 处理时间:{} 截图时间戳:{}", code, add_datas[0]["index"], |
| | | add_datas[-1]["index"], round(t.time() * 1000) - __start_time, |
| | |
| | | b_need_cancel, b_cancel_data = SecondCancelBigNumComputer.need_cancel(code, buy_single_index, |
| | | buy_exec_index, start_index, |
| | | end_index, total_data, |
| | | code_volumn_manager.get_volume_rate_index( |
| | | buy_volume_rate), |
| | | code_volumn_manager.get_volume_rate_index(buy_volume_rate), |
| | | cls.volume_rate_info[code][1], |
| | | is_first_code) |
| | | if b_need_cancel: |
| | |
| | | logging.exception(e) |
| | | |
| | | # 量比超过1.3的不能买 |
| | | volumn_rate = l2_trade_factor.L2TradeFactorUtil.get_volumn_rate_by_code(code) |
| | | if volumn_rate >= 1.3: |
| | | volumn_rate = cls.volume_rate_info[code][0] |
| | | if not is_first_code and volumn_rate >= 1.3: |
| | | return False, False, "最大量比超过1.3不能买" |
| | | elif is_first_code and volumn_rate >= 1.1: |
| | | return False, False, "首板最大量比超过1.1不能买" |
| | | |
| | | limit_up_time = limit_up_time_manager.get_limit_up_time(code) |
| | | if limit_up_time is not None: |
| | |
| | | |
| | | # 获取最后的安全笔数 |
| | | def get_safe_count(self, code, is_first_code, rate): |
| | | rate = self.__get_rate(code) |
| | | # rate = self.__get_rate(code) |
| | | count, min_count, max_count = self.__get_base_save_count(code, is_first_code) |
| | | # 第4次下单按第一次算 |
| | | # if place_order_count and place_order_count >= 3: |
| | |
| | | # count = min_count |
| | | # if count > max_count: |
| | | # count = max_count |
| | | return int(round(count*(1+rate),0)) |
| | | return int(round(count * (1 + rate), 0)) |
| | | |
| | | # 计算留下来的比例 |
| | | # last_buy_single_index 上一次下单信号起始位置 |
| | |
| | | |
| | | # @unittest.skip("跳过此单元测试") |
| | | def test_trade(self): |
| | | code = "000892" |
| | | code = "603801" |
| | | clear_trade_data(code) |
| | | l2.l2_data_util.load_l2_data(code) |
| | | total_datas = deepcopy(l2.l2_data_util.local_today_datas[code]) |
| | |
| | | logger_l2_trade_buy = __mylogger.get_logger("l2_trade_buy") |
| | | logger_l2_trade_queue = __mylogger.get_logger("l2_trade_queue") |
| | | logger_l2_trade_buy_queue = __mylogger.get_logger("l2_trade_buy_queue") |
| | | logger_l2_trade_buy_progress = __mylogger.get_logger("l2_trade_buy_progress") |
| | | logger_l2_trade_buy_progress = __mylogger.get_logger("l2_trade_buy_progress") |
| | | |
| | | logger_l2_big_data = __mylogger.get_logger("l2_big_data") |
| | | logger_juejin_tick = __mylogger.get_logger("juejin_tick") |
| | |
| | | |
| | | def export_logs(code): |
| | | code_name = gpcode_manager.get_code_name(code) |
| | | date = datetime.datetime.now().strftime("%Y-%m-%d") |
| | | date = "2023-03-20" # datetime.datetime.now().strftime("%Y-%m-%d") |
| | | target_dir = f"D:/logs/gp/l2/export/{code}_{code_name}_{date}" |
| | | if os.path.exists(target_dir): |
| | | shutil.rmtree(target_dir) |
| | | os.makedirs(target_dir) |
| | | log_names = ["l2_process", "l2_trade", "l2_trade_cancel", "l2_process_time", "l2_trade_buy"] |
| | | log_names = ["l2_process", "l2_trade", "l2_trade_cancel", "l2_process_time", "l2_trade_buy", "cancel/h_cancel"] |
| | | # 导出交易日志 |
| | | for log_name in log_names: |
| | | key = f"code={code}" |
| | | if log_name == "l2_process" or log_name == "l2_process_time": |
| | | if log_name == "l2_process" or log_name == "l2_process_time" or log_name == "cancel/h_cancel": |
| | | key = code |
| | | LogUtil.extract_log_from_key(key, f"D:/logs/gp/l2/{log_name}.{date}.log".format(date), |
| | | f"{target_dir}/{log_name}.{code}_{code_name}.{date}.log") |
| | | target_path = f"{target_dir}/{log_name}.{code}_{code_name}.{date}.log" |
| | | # 创建文件夹 |
| | | dir_path = "/".join(target_path.split("/")[:-1]) |
| | | if not os.path.exists(dir_path): |
| | | os.makedirs(dir_path) |
| | | LogUtil.extract_log_from_key(key, f"D:/logs/gp/l2/{log_name}.{date}.log", |
| | | target_path ) |
| | | |
| | | |
| | | if __name__ == '__main__': |
| | | # logger_l2_h_cancel.info("test") |
| | | # logger_l2_process_time.info("test123") |
| | | codes = ["603388"] |
| | | codes = ["603083"] |
| | | for code in codes: |
| | | export_logs(code) |
| | | |
| | |
| | | |
| | | import alert_util |
| | | import client_manager |
| | | import code_nature_analyse |
| | | import code_volumn_manager |
| | | import constant |
| | | import data_process |
| | |
| | | import gpcode_manager |
| | | import authority |
| | | import juejin |
| | | from l2 import l2_data_manager_new, l2_data_manager, l2_data_log, l2_log |
| | | from l2 import l2_data_manager_new, l2_data_manager, l2_data_log, l2_log, code_price_manager |
| | | import l2_data_util |
| | | from l2.cancel_buy_strategy import HourCancelBigNumComputer, L2LimitUpMoneyStatisticUtil |
| | | import l2.l2_data_util |
| | |
| | | import ths_util |
| | | import tool |
| | | from third_data import hot_block_data_process |
| | | from trade import trade_gui, trade_data_manager, trade_manager, l2_trade_util |
| | | from ths import l2_listen_pos_health_manager |
| | | from trade import trade_gui, trade_data_manager, trade_manager, l2_trade_util, deal_big_money_manager |
| | | import l2_code_operate |
| | | from code_data_util import ZYLTGBUtil |
| | | import l2.transaction_progress |
| | | |
| | | from log import logger_l2_error, logger_device, logger_trade_delegate, logger_buy_1_volumn_record, \ |
| | | logger_l2_trade_queue, logger_l2_latest_data, logger_l2_trade_buy_queue, logger_first_code_record, logger_debug |
| | | from trade.trade_queue_manager import THSBuy1VolumnManager, Buy1PriceManager, thsl2tradequeuemanager |
| | | from trade.trade_queue_manager import THSBuy1VolumnManager, thsl2tradequeuemanager |
| | | |
| | | |
| | | class MyTCPServer(socketserver.TCPServer): |
| | |
| | | ths_l2_trade_queue_manager = thsl2tradequeuemanager() |
| | | |
| | | latest_buy1_volumn_dict = {} |
| | | buy1_price_manager = Buy1PriceManager() |
| | | l2_trade_queue_time_dict = {} |
| | | l2_save_time_dict = {} |
| | | l2_trade_buy_queue_dict = {} |
| | |
| | | last_time = {} |
| | | first_tick_datas = [] |
| | | latest_oringin_data = {} |
| | | last_l2_listen_health_time = {} |
| | | |
| | | def setup(self): |
| | | super().setup() # 可以不调用父类的setup()方法,父类的setup方法什么都没做 |
| | |
| | | # level2盘口数据 |
| | | day, client, channel, code, capture_time, process_time, origin_datas, origin_datas_count = l2.l2_data_util.parseL2Data( |
| | | _str) |
| | | last_health_time = self.last_l2_listen_health_time.get((client, channel)) |
| | | # --------------------------------设置L2健康状态-------------------------------- |
| | | if last_health_time is None or __start_time - last_health_time > 1000: |
| | | self.last_l2_listen_health_time[(client, channel)] = __start_time |
| | | # 更新监听位健康状态 |
| | | if origin_datas_count == 0: |
| | | l2_listen_pos_health_manager.set_unhealthy(client, channel) |
| | | else: |
| | | l2_listen_pos_health_manager.set_healthy(client, channel) |
| | | |
| | | l2_log.threadIds[code] = random.randint(0, 100000) |
| | | if True: |
| | |
| | | l2_data_util.save_l2_latest_data_number(code, origin_datas_count) |
| | | # 保存l2数据条数 |
| | | if not origin_datas: |
| | | #or not l2.l2_data_util.is_origin_data_diffrent(origin_datas,self.latest_oringin_data.get(code)): |
| | | # or not l2.l2_data_util.is_origin_data_diffrent(origin_datas,self.latest_oringin_data.get(code)): |
| | | raise Exception("无新增数据") |
| | | # 保存最近的数据 |
| | | self.latest_oringin_data[code] = origin_datas |
| | |
| | | # limit_up_time_manager.save_limit_up_time(d["code"], d["time"]) |
| | | elif type == 22: |
| | | try: |
| | | if int(tool.get_now_time_str().replace(":", "")) < int("092600"): |
| | | if int(tool.get_now_time_str().replace(":", "")) < int("092500"): |
| | | raise Exception('未到接受时间') |
| | | # 首板代码 |
| | | dataList, is_add = data_process.parseGPCode(_str) |
| | |
| | | for data in dataList: |
| | | code = data["code"] |
| | | codes.append(code) |
| | | limit_up_price = gpcode_manager.get_limit_up_price(code) |
| | | if limit_up_price is not None: |
| | | limit_up_price_dict[code] = limit_up_price |
| | | else: |
| | | temp_codes.append(code) |
| | | # data["price"] |
| | | tick_datas.append({"code": code, "price": data["price"], "volume": data["volume"], |
| | | "volumeUnit": data["volumeUnit"]}) |
| | | |
| | | # 保存未筛选的首板代码 |
| | | new_add_codes = gpcode_first_screen_manager.set_target_no_screen_codes(codes) |
| | | for code in new_add_codes: |
| | | if (not l2_trade_util.is_in_forbidden_trade_codes( |
| | | code)) and juejin.JueJinManager.get_lowest_price_rate(code, 15) >= 0.3: |
| | | l2_trade_util.forbidden_trade(code) |
| | | |
| | | if new_add_codes: |
| | | gpcode_manager.set_first_gp_codes_with_data(juejin.JueJinManager.get_gp_latest_info(codes)) |
| | | # 加入首板历史记录 |
| | | gpcode_manager.FirstCodeManager.add_record(new_add_codes) |
| | | logger_first_code_record.info("新增首板:{}", new_add_codes) |
| | | # 获取60天最大记录 |
| | | for code in new_add_codes: |
| | | if code not in global_util.max60_volumn or global_util.max60_volumn.get(code) is None: |
| | | volumes = juejin.get_volumn(code) |
| | | code_volumn_manager.set_histry_volumn(code, volumes[0], volumes[1]) |
| | | # 移除代码 |
| | | listen_codes = gpcode_manager.get_listen_codes() |
| | | for lc in listen_codes: |
| | | if not gpcode_manager.is_in_gp_pool(lc): |
| | | # 移除代码 |
| | | l2_code_operate.L2CodeOperate.get_instance().add_operate(0, lc, "代码被移除") |
| | | |
| | | if temp_codes: |
| | | # 获取涨停价 |
| | | juejin.re_set_price_pres(temp_codes) |
| | | # 重新获取涨停价 |
| | | for code in temp_codes: |
| | | limit_up_price = gpcode_manager.get_limit_up_price(code) |
| | | if limit_up_price is not None: |
| | | limit_up_price_dict[code] = limit_up_price |
| | | # 保存自由流通股本 |
| | | zyltgb_list = [] |
| | | for data in dataList: |
| | |
| | | ZYLTGBUtil.save_list(zyltgb_list) |
| | | global_data_loader.load_zyltgb() |
| | | |
| | | # 保存现价 |
| | | bad_codes = set() |
| | | |
| | | if new_add_codes: |
| | | gpcode_manager.set_first_gp_codes_with_data(juejin.JueJinManager.get_gp_latest_info(codes)) |
| | | # 加入首板历史记录 |
| | | gpcode_manager.FirstCodeManager.add_record(new_add_codes) |
| | | logger_first_code_record.info("新增首板:{}", new_add_codes) |
| | | # 获取60天最大记录 |
| | | for code in codes: |
| | | if code not in global_util.max60_volumn or global_util.max60_volumn.get(code) is None: |
| | | volumes_data = juejin.get_volumns_by_code(code, 150) |
| | | volumes = juejin.parse_max_volume(volumes_data[:60]) |
| | | logger_first_code_record.info("{} 获取到首板60天最大量:{}", code, volumes) |
| | | code_volumn_manager.set_histry_volumn(code, volumes[0], volumes[1]) |
| | | # 判断K线形态 |
| | | is_has_k_format, msg = code_nature_analyse.is_has_k_format( |
| | | gpcode_manager.get_limit_up_price(code), volumes_data) |
| | | if not is_has_k_format: |
| | | logger_first_code_record.info("{}首板K线形态不好,{}", code, msg) |
| | | # 股性不好,就不要加入 |
| | | bad_codes.add(code) |
| | | # 加入禁止交易代码 |
| | | l2_trade_util.forbidden_trade(code) |
| | | break |
| | | else: |
| | | code_nature_analyse.set_record_datas(code, |
| | | gpcode_manager.get_limit_up_price(code), |
| | | volumes_data) |
| | | |
| | | # 移除代码 |
| | | listen_codes = gpcode_manager.get_listen_codes() |
| | | for lc in listen_codes: |
| | | if not gpcode_manager.is_in_gp_pool(lc): |
| | | # 移除代码 |
| | | l2_code_operate.L2CodeOperate.get_instance().add_operate(0, lc, "代码被移除") |
| | | |
| | | # 保存现价 |
| | | if dataList: |
| | | for data in dataList: |
| | | code = data["code"] |
| | | codes.append(code) |
| | | limit_up_price = gpcode_manager.get_limit_up_price(code) |
| | | if limit_up_price is not None: |
| | | limit_up_price_dict[code] = limit_up_price |
| | | else: |
| | | temp_codes.append(code) |
| | | tick_datas.append({"code": code, "price": data["price"], "volume": data["volume"], |
| | | "volumeUnit": data["volumeUnit"]}) |
| | | # 获取涨停价 |
| | | if temp_codes: |
| | | # 获取涨停价 |
| | | juejin.re_set_price_pres(temp_codes) |
| | | # 重新获取涨停价 |
| | | for code in temp_codes: |
| | | limit_up_price = gpcode_manager.get_limit_up_price(code) |
| | | if limit_up_price is not None: |
| | | limit_up_price_dict[code] = limit_up_price |
| | | # 保存现价 |
| | | self.first_tick_datas.clear() |
| | | self.first_tick_datas.extend(tick_datas) |
| | | |
| | |
| | | datas = data_process.parseData(_str) |
| | | channel = datas["channel"] |
| | | code = datas["code"] |
| | | msg = "" |
| | | try: |
| | | |
| | | if not gpcode_manager.is_in_gp_pool(code) and not gpcode_manager.is_in_first_gp_codes(code): |
| | | # 没在目标代码中且没有在首板今日历史代码中 |
| | | raise Exception("代码没在监听中") |
| | | |
| | | data = datas["data"] |
| | | buy_time = data["buyTime"] |
| | | buy_one_price = data["buyOnePrice"] |
| | |
| | | if buy_one_price is None: |
| | | print('买1价没有,', code) |
| | | limit_up_price = gpcode_manager.get_limit_up_price(code) |
| | | |
| | | if limit_up_price is not None: |
| | | code_price_manager.Buy1PriceManager.process(code, buy_one_price, buy_time, limit_up_price) |
| | | _start_time = time.time() |
| | | msg += "买1价格处理:" + f"{_start_time - __start_time} " |
| | | |
| | | buy_queue_result_list = self.tradeBuyQueue.save(code, limit_up_price, buy_one_price, |
| | | buy_time, |
| | | buy_queue) |
| | | msg += "买队列保存:" + f"{time.time() - _start_time} " |
| | | _start_time = time.time() |
| | | |
| | | if buy_queue_result_list: |
| | | raise Exception("测试中断") |
| | | |
| | | # 有数据 |
| | | try: |
| | | buy_one_price_ = decimal.Decimal(round(float(buy_one_price), 2)).quantize( |
| | | decimal.Decimal("0.00")) |
| | | # 获取执行位时间 |
| | | exec_time = None |
| | | buy_single_index, buy_exec_index, compute_index, num, count, max_num_set = l2_data_manager.TradePointManager.get_buy_compute_start_data( |
| | | |
| | | buy_single_index, buy_exec_index, compute_index, num, count, max_num_set, volume_rate = l2_data_manager.TradePointManager.get_buy_compute_start_data( |
| | | code) |
| | | if buy_exec_index: |
| | | if True: |
| | | # 只有下单过后才获取交易进度 |
| | | exec_time = None |
| | | try: |
| | | exec_time = \ |
| | | l2.l2_data_util.local_today_datas.get(code)[buy_exec_index]["val"][ |
| | | "time"] |
| | | if buy_exec_index: |
| | | exec_time = \ |
| | | l2.l2_data_util.local_today_datas.get(code)[buy_exec_index]["val"][ |
| | | "time"] |
| | | except: |
| | | pass |
| | | |
| | | buy_progress_index = self.tradeBuyQueue.compute_traded_index(code, |
| | | buy_one_price_, |
| | | buy_queue_result_list, |
| | |
| | | logger_l2_trade_buy_queue.info("获取成交位置成功: code-{} index-{} 数据-{}", code, |
| | | buy_progress_index, |
| | | json.dumps(buy_queue_result_list)) |
| | | # 计算大单成交额 |
| | | deal_big_money_manager.set_trade_progress(code, buy_progress_index, |
| | | l2.l2_data_util.local_today_datas.get( |
| | | code), |
| | | l2.l2_data_util.local_today_num_operate_map.get( |
| | | code)) |
| | | |
| | | else: |
| | | raise Exception("暂未获取到交易进度") |
| | | msg += "计算成交进度:" + f"{time.time() - _start_time} " |
| | | _start_time = time.time() |
| | | except Exception as e: |
| | | logging.exception(e) |
| | | print("买入队列", code, buy_queue_result_list) |
| | |
| | | code): |
| | | self.l2_trade_buy_queue_dict[code] = buy_queue |
| | | logger_l2_trade_buy_queue.info("{}-{}", code, buy_queue) |
| | | msg += "保存记录日志:" + f"{time.time() - _start_time} " |
| | | _start_time = time.time() |
| | | # 保存最近的记录 |
| | | if self.ths_l2_trade_queue_manager.save_recod(code, data): |
| | | if buy_time != "00:00:00": |
| | | logger_l2_trade_queue.info("{}-{}", code, data) |
| | | self.buy1_price_manager.save(code, buy_one_price) |
| | | need_sync, need_cancel, cancel_msg = self.buy1_volumn_manager.save(code, buy_time, |
| | | int(buy_one_volumn), |
| | | buy_one_price) |
| | | # if need_cancel: |
| | | # l2_data_manager_new.L2TradeDataProcessor.cancel_buy(code, cancel_msg, "trade_queue") |
| | | if need_sync: |
| | | # 同步数据 |
| | | L2LimitUpMoneyStatisticUtil.verify_num(code, int(buy_one_volumn), buy_time) |
| | | # if need_sync: |
| | | # # 同步数据 |
| | | # s = time.time() |
| | | # L2LimitUpMoneyStatisticUtil.verify_num(code, int(buy_one_volumn), buy_time) |
| | | # msg += "量校验:"+f"{time.time()-s} " |
| | | # print(buy_time, buy_one_price, buy_one_volumn) |
| | | |
| | | # print("L2买卖队列",datas) |
| | | msg += "买1处理:" + f"{time.time() - _start_time} " |
| | | _start_time = time.time() |
| | | except: |
| | | pass |
| | | finally: |
| | | space = time.time() - __start_time |
| | | if space > 0.1: |
| | | logger_debug.info("{}成交队列处理时间:{}", code, space) |
| | | logger_debug.info("{}成交队列处理时间:{},{}", code, space, msg) |
| | | |
| | | elif type == 20: |
| | | # 登录 |
| | |
| | | # 现价更新 |
| | | elif type == 40: |
| | | datas = data_process.parse(_str)["data"] |
| | | if datas is None: |
| | | datas = [] |
| | | print("二板现价") |
| | | # 获取暂存的二版现价数据 |
| | | if datas and self.first_tick_datas: |
| | | if self.first_tick_datas: |
| | | datas.extend(self.first_tick_datas) |
| | | if datas is not None: |
| | | print("二板现价数量", len(datas)) |
| | |
| | | # 记录数据 |
| | | logger_buy_1_volumn_record.info("{}-{}", code, data) |
| | | self.latest_buy1_volumn_dict[code] = "{}-{}".format(volumn, price) |
| | | # 保存买1价格 |
| | | self.buy1_price_manager.save(code, price) |
| | | # 校正时间 |
| | | time_ = tool.compute_buy1_real_time(time_) |
| | | # 保存数据 |
| | |
| | | return_str = json.dumps(return_json) |
| | | elif type == 70: |
| | | # 选股宝热门概念 |
| | | datas = data_process.parse(_str)["data"] |
| | | data_json = data_process.parse(_str) |
| | | day = data_json["day"] |
| | | datas = data_json["data"] |
| | | if datas: |
| | | hot_block_data_process.save_datas(datas) |
| | | hot_block_data_process.save_datas(day, datas) |
| | | print(datas) |
| | | elif type == 71: |
| | | # 根据代码获取选股宝热门概念 |
| | | day = tool.get_now_date_str() |
| | | code = data_process.parse(_str)["data"]["code"] |
| | | todays = hot_block_data_process.XGBHotBlockDataManager.list_by_code(code, day) |
| | | today_datas = [] |
| | | if todays: |
| | | for data in todays: |
| | | block = data[2] |
| | | block_datas = hot_block_data_process.XGBHotBlockDataManager.list_by_block(block, day) |
| | | block_datas = list(block_datas) |
| | | # 根据涨停时间排序 |
| | | block_datas.sort(key=lambda d: (d[4] if len(d[4]) > 6 else '15:00:00')) |
| | | for i in range(len(block_datas)): |
| | | if block_datas[i][3] == code: |
| | | today_datas.append( |
| | | {"block_name": block, "block_size": len(block_datas), "index": i, |
| | | "price": block_datas[i][5], "rate": block_datas[i][6]}) |
| | | break |
| | | # 获取前一个交易日 |
| | | last_day = juejin.JueJinManager.get_previous_trading_date(day) |
| | | lasts = hot_block_data_process.XGBHotBlockDataManager.list_by_code(code, last_day) |
| | | last_datas = [] |
| | | if todays: |
| | | for data in lasts: |
| | | block = data[2] |
| | | block_datas = hot_block_data_process.XGBHotBlockDataManager.list_by_block(block, last_day) |
| | | block_datas = list(block_datas) |
| | | # 根据涨停时间排序 |
| | | block_datas.sort(key=lambda d: (d[4] if len(d[4]) > 6 else '15:00:00')) |
| | | for i in range(len(block_datas)): |
| | | if block_datas[i][3] == code: |
| | | last_datas.append( |
| | | {"block_name": block, "block_size": len(block_datas), "index": i, |
| | | "price": block_datas[i][5], "rate": block_datas[i][6]}) |
| | | break |
| | | final_data = {'code': code, 'today': today_datas, 'last_day': last_datas} |
| | | return_str = json.dumps({"code": 0, "data": final_data}) |
| | | pass |
| | | elif type == 201: |
| | | # 加入黑名单 |
| | | data = json.loads(_str) |
| | |
| | | if not name: |
| | | results = juejin.JueJinManager.get_gp_codes_names([code]) |
| | | if results: |
| | | gpcode_manager.CodesNameManager.add_first_code_name(code,results[code]) |
| | | gpcode_manager.CodesNameManager.add_first_code_name(code, results[code]) |
| | | |
| | | return_str = json.dumps({"code": 0}) |
| | | elif type == 202: |
| | |
| | | elif type == 302: |
| | | # 黑名单列表 |
| | | codes = l2_trade_util.WhiteListCodeManager.list_codes() |
| | | datas = [] |
| | | for code in codes: |
| | | name = gpcode_manager.get_code_name(code) |
| | | datas.append(f"{name}:{code}") |
| | | return_str = json.dumps({"code": 0, "data": datas}) |
| | | elif type == 401: |
| | | # 加入想要买 |
| | | data = json.loads(_str) |
| | | codes = data["data"]["codes"] |
| | | for code in codes: |
| | | gpcode_manager.WantBuyCodesManager.add_code(code) |
| | | name = gpcode_manager.get_code_name(code) |
| | | if not name: |
| | | results = juejin.JueJinManager.get_gp_codes_names([code]) |
| | | if results: |
| | | gpcode_manager.CodesNameManager.add_first_code_name(code, results[code]) |
| | | elif type == 402: |
| | | data = json.loads(_str) |
| | | codes = data["data"]["codes"] |
| | | for code in codes: |
| | | gpcode_manager.WantBuyCodesManager.remove_code(code) |
| | | return_str = json.dumps({"code": 0}) |
| | | elif type == 403: |
| | | codes = gpcode_manager.WantBuyCodesManager.list_code() |
| | | datas = [] |
| | | for code in codes: |
| | | name = gpcode_manager.get_code_name(code) |
| | |
| | | result = json.loads(result) |
| | | if result["code"] != 0: |
| | | raise Exception(result["msg"]) |
| | | else: |
| | | # 测速成功 |
| | | client_infos = [] |
| | | for index in range(0, constant.L2_CODE_COUNT_PER_DEVICE): |
| | | client_infos.append((client, index)) |
| | | l2_listen_pos_health_manager.init_all(client_infos) |
| | | |
| | | |
| | | if __name__ == "__main__": |
| | | listen_codes = gpcode_manager.get_listen_codes() |
| | | for lc in listen_codes: |
| | | if not gpcode_manager.is_in_gp_pool(lc): |
| | | # 移除代码 |
| | | l2_code_operate.L2CodeOperate.get_instance().add_operate(0, lc, "代码被移除") |
| | | codes = ["601698"] |
| | | for code in codes: |
| | | volumes_data = juejin.get_volumns_by_code(code, 150) |
| | | volumes_data = volumes_data[1:] |
| | | global_data_loader.load_zyltgb() |
| | | limit_up_price = float(gpcode_manager.get_limit_up_price(code)) |
| | | # 判断股性 |
| | | # is_k_format, msg = code_nature_analyse.is_has_k_format(float(limit_up_price), volumes_data) |
| | | # print(code, is_k_format, msg) |
| | | |
| | | code_nature_analyse.set_record_datas(code, |
| | | limit_up_price, |
| | | volumes_data) |
| | | |
| | | print(code_nature_analyse.get_k_format(float(limit_up_price), volumes_data)) |
| | |
| | | |
| | | |
| | | def __parseData(driver): |
| | | date_element = \ |
| | | driver.find_element(by=By.ID, value="nuxt-layout-container").find_elements(by=By.TAG_NAME, value="time")[0] |
| | | date_elements = date_element.find_elements(by=By.TAG_NAME, value="span") |
| | | month = date_elements[0].text.split(' ')[0][:-1] |
| | | day = date_elements[1].text |
| | | # 获取当前的年 |
| | | year = datetime.datetime.now().strftime("%Y") |
| | | day_str = "{0}-{1:0>2}-{2:0>2}".format(year, int(month), int(day)) |
| | | |
| | | items = driver.find_element(by=By.ID, value="nuxt-layout-container").find_element(by=By.CLASS_NAME, |
| | | value="topgainer-content-left").find_elements( |
| | | by=By.CLASS_NAME, |
| | |
| | | data_list.append((title, total_rate, codes_list)) |
| | | print("----------------------") |
| | | |
| | | return data_list |
| | | return day_str, data_list |
| | | |
| | | |
| | | # 获取热门板块 |
| | |
| | | if int("113000") < int(time_str) < int("130000"): |
| | | continue |
| | | try: |
| | | result = __parseData(driver) |
| | | callback(result) |
| | | day, result = __parseData(driver) |
| | | callback(day, result) |
| | | except Exception as e: |
| | | logging.exception(e) |
| | | |
| | | |
| | | def upload_data(datas): |
| | | def upload_data(day, datas): |
| | | client = socket.socket() # 生成socket,连接server |
| | | ip_port = ("192.168.3.252", 9001) # server地址和端口号(最好是10000以后) |
| | | client.connect(ip_port) |
| | | data = {"type": 70, "data": datas} |
| | | data = {"type": 70, "day": day, "data": datas} |
| | | client.send(json.dumps(data).encode("gbk")) |
| | | client.close() |
| | | |
| | |
| | | # cd D:\workspace\trade\third_data |
| | | # C:\Users\Administrator\AppData\Roaming\Python\Python37\Scripts\pyinstaller.exe hot_block.spec |
| | | if __name__ == "__main__": |
| | | def callback(result): |
| | | upload_data(result) |
| | | def callback(day, result): |
| | | upload_data(day, result) |
| | | pass |
| | | |
| | | |
| | |
| | | |
| | | import tool |
| | | from db import redis_manager |
| | | from db import mysql_data |
| | | |
| | | __redisManager = redis_manager.RedisManager(0) |
| | | |
| | |
| | | return __redisManager.getRedis() |
| | | |
| | | |
| | | class XGBHotBlockDataManager: |
| | | total_datas = [] |
| | | __last_datas={} |
| | | |
| | | @classmethod |
| | | def save(cls,day, datas): |
| | | mysqldb = mysql_data.Mysqldb() |
| | | # 统计代码所属板块 |
| | | code_block_dict = {} |
| | | for data in datas: |
| | | for code_info in data[2]: |
| | | code = code_info[0].split(".")[0] |
| | | if not code_block_dict.get(code): |
| | | code_block_dict[code] = set() |
| | | code_block_dict[code].add(data[0]) |
| | | |
| | | for data in datas: |
| | | for code_info in data[2]: |
| | | code = code_info[0].split(".")[0] |
| | | _id = f"{day}_{data[0]}_{code}" |
| | | |
| | | result = mysqldb.select_one("select count(*) from xgb_hot_block where _id='{}'".format(_id)) |
| | | if not result[0]: |
| | | mysqldb.execute( |
| | | f"insert into xgb_hot_block(_id,_day,_block_name,_code,_limit_up_time,_price,_rate,_update_time) values('{_id}','{day}','{data[0]}','{code}','{code_info[4]}','{code_info[2]}','{code_info[3]}',now())") |
| | | else: |
| | | # 如果上次的数据和这次一样就不更新,否则需要更新数据 |
| | | if cls.__last_datas.get(_id) != code_info: |
| | | # 更新 |
| | | mysqldb.execute(f"update xgb_hot_block set _limit_up_time='{code_info[4]}',_price='{code_info[2]}',_rate='{code_info[3]}' where _id='{_id}'") |
| | | cls.__last_datas[_id] = code_info |
| | | # 获取原来的代码所属板块,删除之前错误的板块 |
| | | old_datas = XGBHotBlockDataManager.list_by_code(code, day) |
| | | if old_datas: |
| | | for d in old_datas: |
| | | if d[2] not in code_block_dict[code]: |
| | | mysqldb.execute(f"delete from xgb_hot_block where _id='{d[0]}'") |
| | | # 将今日数据导入到内存中 |
| | | XGBHotBlockDataManager.total_datas = XGBHotBlockDataManager.list_all(tool.get_now_date_str()) |
| | | |
| | | @staticmethod |
| | | def list_all(day): |
| | | mysqldb = mysql_data.Mysqldb() |
| | | return mysqldb.select_all(f"select * from xgb_hot_block where _day='{day}'") |
| | | |
| | | @staticmethod |
| | | def list_by_code(code, day): |
| | | mysqldb = mysql_data.Mysqldb() |
| | | return mysqldb.select_all(f"select * from xgb_hot_block where _code='{code}' and _day='{day}'") |
| | | |
| | | @staticmethod |
| | | def list_by_block(block_name, day): |
| | | mysqldb = mysql_data.Mysqldb() |
| | | return mysqldb.select_all(f"select * from xgb_hot_block where _block_name='{block_name}' and _day='{day}'") |
| | | |
| | | |
| | | # 获取代码所在板块信息 |
| | | def get_info(code): |
| | | blocks = get_code_blocks(code) |
| | | |
| | | target_block = None |
| | | if blocks: |
| | | for block in blocks: |
| | | if block == '公告' or block == '其他': |
| | | continue |
| | | target_block = block |
| | | break |
| | | if not target_block: |
| | | return None |
| | | |
| | | limit_up_codes_set = set() |
| | | for block in latest_datas: |
| | | if block[0] == target_block: |
| | | for code_data in block[2]: |
| | | if len(code_data[4]) > 6: |
| | | limit_up_codes_set.add(code_data[0].split('.')[0]) |
| | | limit_up_codes_set.discard(code) |
| | | limit_up_count = len(limit_up_codes_set) |
| | | |
| | | total_datas = XGBHotBlockDataManager.total_datas |
| | | codes = set() |
| | | for data in total_datas: |
| | | block = data[2] |
| | | if block != target_block: |
| | | continue |
| | | code = data[3] |
| | | limit_up_time = data[4] |
| | | if len(limit_up_time) > 6: |
| | | codes.add(code) |
| | | codes.discard(code) |
| | | codes.difference(limit_up_codes_set) |
| | | # 炸板个数 |
| | | break_size = len(codes) |
| | | return (limit_up_count,break_size) |
| | | |
| | | |
| | | latest_datas = [] |
| | | |
| | | |
| | | # 保存数据 |
| | | def save_datas(datas): |
| | | def save_datas(day, datas): |
| | | latest_datas = datas |
| | | XGBHotBlockDataManager.save(day, datas) |
| | | code_block_dict = {} |
| | | block_codes_dict = {} |
| | | for block in datas: |
| | |
| | | block_codes.get(block) |
| | | return None |
| | | |
| | | |
| | | if __name__ == "__main__": |
| | | print(get_code_blocks("600468")) |
| | | XGBHotBlockDataManager.total_datas=XGBHotBlockDataManager.list_all("2023-03-23") |
| | | get_info('002230') |
| | |
| | | return date |
| | | |
| | | |
| | | def get_now_date_str(): |
| | | date = datetime.datetime.now().strftime("%Y-%m-%d") |
| | | def get_now_date_str(format="%Y-%m-%d"): |
| | | date = datetime.datetime.now().strftime(format) |
| | | return date |
| | | |
| | | |
New file |
| | |
| | | """ |
| | | 竞价金额管理 |
| | | """ |
| | | import json |
| | | |
| | | import tool |
| | | from db import redis_manager |
| | | |
| | | __redisManager = redis_manager.RedisManager(2) |
| | | |
| | | |
| | | def __get_redis(): |
| | | return __redisManager.getRedis() |
| | | |
| | | |
| | | # 设置竞价资金 |
| | | # 数据格式[(代码,金额)] |
| | | def set_bidding_money(datas): |
| | | money_list = [] |
| | | for data in datas: |
| | | money = 0 |
| | | if data[1].find('亿') > -1: |
| | | money = round(float(data[1][:-1]) * 10000) |
| | | else: |
| | | money = int(data[1][:-1]) |
| | | money_list.append((data[0], money)) |
| | | __get_redis().setex("bidding_money", tool.get_expire(), json.dumps(money_list)) |
| | | |
| | | |
| | | # 获取竞价金额 |
| | | def get_bidding_money(code): |
| | | val = __get_redis().get("bidding_money") |
| | | if not val: |
| | | return None |
| | | vals = json.loads(val) |
| | | for v in vals: |
| | | if v[0] == code: |
| | | return v[1] |
| | | return None |
New file |
| | |
| | | """ |
| | | 成交大单管理 |
| | | """ |
| | | import json |
| | | |
| | | import tool |
| | | from db import redis_manager |
| | | from l2 import l2_data_util, l2_data_source_util |
| | | |
| | | __last_progress = {} |
| | | __redisManager = redis_manager.RedisManager(2) |
| | | |
| | | |
| | | def __get_redis(): |
| | | return __redisManager.getRedis() |
| | | |
| | | |
| | | def __get_cancel_data(code, buy_data, local_today_num_operate_map): |
| | | val = buy_data['val'] |
| | | cancel_datas = local_today_num_operate_map.get( |
| | | "{}-{}-{}".format(val["num"], "1", val["price"])) |
| | | if cancel_datas: |
| | | for cancel_data in cancel_datas: |
| | | buy_index = l2_data_source_util.L2DataSourceUtils.get_buy_index_with_cancel_data(code, cancel_data, |
| | | local_today_num_operate_map) |
| | | if buy_index == buy_data["index"]: |
| | | return cancel_data |
| | | return None |
| | | |
| | | |
| | | # 获取成交计算进度 |
| | | def __get_deal_compute_progress(code): |
| | | val = __get_redis().get(f"deal_compute_info-{code}") |
| | | if val is None: |
| | | return -1, 0 |
| | | val = json.loads(val) |
| | | return val[0], val[1] |
| | | |
| | | |
| | | # 设置成交进度 |
| | | def __set_deal_compute_progress(code, index, money): |
| | | __get_redis().setex(f"deal_compute_info-{code}", tool.get_expire(), json.dumps((index, money))) |
| | | |
| | | |
| | | # 设置成交进度 |
| | | def set_trade_progress(code, progress, total_data, local_today_num_operate_map): |
| | | if __last_progress.get(code) == progress: |
| | | return |
| | | __last_progress[code] = progress |
| | | # 计算从开始位置到成交位置 |
| | | c_index, deal_num = __get_deal_compute_progress(code) |
| | | for i in range(c_index + 1, progress): |
| | | data = total_data[i] |
| | | val = data['val'] |
| | | # 是否有大单 |
| | | if not l2_data_util.is_big_money(val): |
| | | continue |
| | | if l2_data_util.L2DataUtil.is_limit_up_price_buy(val): |
| | | # 是否已经取消 |
| | | cancel_data = __get_cancel_data(code, data, local_today_num_operate_map) |
| | | if cancel_data is None: |
| | | deal_num += val["num"] |
| | | __set_deal_compute_progress(code, progress, deal_num) |
| | | |
| | | |
| | | def get_deal_big_money_num(code): |
| | | compute_index, num = __get_deal_compute_progress(code) |
| | | return num |
New file |
| | |
| | | """ |
| | | 首板代码评分管理 |
| | | """ |
| | | |
| | | # bidding 是否满足竞价 |
| | | # deal_big_money 成交大金额是否满足 |
| | | # code_nature = (是否有涨停,是否有溢价) |
| | | # hot_block(板块中涨停票个数(包含自己),板块炸板票个数) |
| | | # zyltgb自由流通市值是否大于250亿 |
| | | # limit_price 涨停价是否大于100块 |
| | | # limit_up_time 是否10点之前涨停 |
| | | # k_form(15个交易日是否涨幅24.9%,是否破前高,是否超跌,是否接近前高,是否N,是否V) |
| | | import code_nature_analyse |
| | | import global_data_loader |
| | | import global_util |
| | | import gpcode_manager |
| | | import tool |
| | | from third_data import hot_block_data_process |
| | | from trade import l2_trade_factor, deal_big_money_manager, bidding_money_manager |
| | | |
| | | |
| | | def __get_score(zyltgb, limit_price, bidding, k_form, code_nature, hot_block, volume_rate, limit_up_time, |
| | | deal_big_money): |
| | | score = 0 |
| | | score_list = [] |
| | | # 开盘前竞价 |
| | | if bidding: |
| | | score += 25 |
| | | score_list.append(25) |
| | | else: |
| | | score_list.append(0) |
| | | # 大单成交 |
| | | if deal_big_money: |
| | | score += 30 |
| | | score_list.append(30) |
| | | else: |
| | | score_list.append(0) |
| | | # 量 |
| | | volume_score = [0, 40, 50, 40, 30, 10, -150, -1000] |
| | | volume_rates = [0, 0.499, 0.649, 0.799, 0.949, 1.099, 1.249, 1.399] |
| | | for i in range(1, len(volume_rates)): |
| | | if volume_rates[i - 1] <= volume_rate < volume_rates[i]: |
| | | score += volume_score[i - 1] |
| | | score_list.append(volume_score[i - 1]) |
| | | break |
| | | |
| | | # 15个交易日是否涨幅24.9% |
| | | if k_form[0]: |
| | | score += -100 |
| | | score_list.append(-100) |
| | | else: |
| | | score_list.append(0) |
| | | # 是否破前高 |
| | | if k_form[1]: |
| | | score += 50 |
| | | score_list.append(50) |
| | | else: |
| | | score_list.append(0) |
| | | # 是否超跌 |
| | | if k_form[2]: |
| | | score += 40 |
| | | score_list.append(40) |
| | | else: |
| | | score_list.append(0) |
| | | |
| | | # 是否接近前高 |
| | | if k_form[3]: |
| | | score += -50 |
| | | score_list.append(-50) |
| | | else: |
| | | score_list.append(0) |
| | | # 是否N |
| | | if k_form[4]: |
| | | score += 35 |
| | | score_list.append(35) |
| | | else: |
| | | score_list.append(0) |
| | | # 是否V |
| | | if k_form[5]: |
| | | score += 30 |
| | | score_list.append(30) |
| | | else: |
| | | score_list.append(0) |
| | | |
| | | if not code_nature[0]: |
| | | score += 5 |
| | | score_list.append(5) |
| | | else: |
| | | score_list.append(0) |
| | | if code_nature[1]: |
| | | score += 20 |
| | | score_list.append(20) |
| | | else: |
| | | score_list.append(0) |
| | | |
| | | if hot_block[0] >= 2: |
| | | score += 40 |
| | | score_list.append(40) |
| | | else: |
| | | score += 30 |
| | | score_list.append(30) |
| | | if hot_block[1] > 0: |
| | | score += 10 |
| | | score_list.append(10) |
| | | else: |
| | | score_list.append(0) |
| | | |
| | | if zyltgb: |
| | | score += -80 |
| | | score_list.append(-80) |
| | | else: |
| | | score_list.append(0) |
| | | |
| | | if limit_price: |
| | | score += -1000 |
| | | score_list.append(-1000) |
| | | else: |
| | | score_list.append(0) |
| | | |
| | | if limit_up_time: |
| | | score += 20 |
| | | score_list.append(20) |
| | | else: |
| | | score_list.append(0) |
| | | |
| | | return score, score_list |
| | | |
| | | |
| | | def get_score(code, volume_rate, limit_up_time): |
| | | bidding_money = bidding_money_manager.get_bidding_money(code) |
| | | bidding = False |
| | | if bidding_money and bidding_money >= 5000: |
| | | bidding = True |
| | | # 获取自由流通股本 |
| | | zyltgb = global_util.zyltgb_map.get(code) |
| | | if zyltgb is None: |
| | | zyltgb = 100 * 100000000 |
| | | |
| | | k_form = code_nature_analyse.CodeNatureRecordManager.get_k_format(code) |
| | | if k_form is None: |
| | | k_form = [True, False, False, False, False, False] |
| | | code_nature = code_nature_analyse.CodeNatureRecordManager.get_nature(code) |
| | | |
| | | hot_block = hot_block_data_process.get_info(code) |
| | | if hot_block is None: |
| | | hot_block = (1, 0) |
| | | else: |
| | | # 加上自己 |
| | | hot_block = (hot_block[0] + 1, hot_block[1]) |
| | | |
| | | if limit_up_time and tool.trade_time_sub(limit_up_time, "10:00:00") < 0: |
| | | limit_up_time = True |
| | | else: |
| | | limit_up_time = False |
| | | # 获取成交大单 |
| | | deal_big_num = deal_big_money_manager.get_deal_big_money_num(code) |
| | | m = l2_trade_factor.L2TradeFactorUtil.get_base_safe_val(zyltgb) |
| | | limit_price = float(gpcode_manager.get_limit_up_price(code)) |
| | | if deal_big_num * limit_price * 100 > m: |
| | | deal_big_num = True |
| | | else: |
| | | deal_big_num = False |
| | | |
| | | return __get_score(zyltgb >= 250 * 100000000, limit_price > 100, bidding, k_form, code_nature, hot_block, |
| | | volume_rate, limit_up_time, deal_big_num) |
| | | |
| | | |
| | | if __name__ == "__main__": |
| | | global_data_loader.load_zyltgb() |
| | | score = get_score("601698", 1.2, "15:00:01") |
| | | print(score) |
| | |
| | | # 获取需要的大单个数 |
| | | @staticmethod |
| | | def get_big_num_count(volume_rate_index): |
| | | counts = [4, 3, 2, 1, 1, 1, 1] |
| | | counts = [3, 1, 1, 1, 0, 0, 0, 0] |
| | | if volume_rate_index >= len(counts): |
| | | volume_rate_index = -1 |
| | | return counts[volume_rate_index] |
| | |
| | | if yi < 1: |
| | | yi = 1 |
| | | m = 5000000 + (yi - 1) * 500000 |
| | | return round(m) |
| | | return round(m*(1-0.3)) |
| | | |
| | | # 获取行业影响比例 |
| | | # total_limit_percent为统计的比例之和乘以100 |
| | |
| | | return zyltgb |
| | | |
| | | @classmethod |
| | | def compute_m_value(cls, code,volume_rate): |
| | | def compute_m_value(cls, code, volume_rate): |
| | | zyltgb = global_util.zyltgb_map.get(code) |
| | | if zyltgb is None: |
| | | global_data_loader.load_zyltgb() |
| | |
| | | # print("m值获取:", code, round(zyltgb * rate)) |
| | | rate = L2PlaceOrderParamsManager.get_m_val_rate(volume_rate) |
| | | |
| | | return round(zyltgb * (1+rate)), "" |
| | | return round(zyltgb * (1 + rate)), "" |
| | | |
| | | # 获取安全笔数 |
| | | @classmethod |
| | |
| | | # print(L2TradeFactorUtil.get_safe_buy_count("003005")) |
| | | # print(L2TradeFactorUtil.get_rate_factors("003004")) |
| | | # print(L2TradeFactorUtil.factors_to_string("003004")) |
| | | for i in range(2, 151): |
| | | for i in range(2, 15): |
| | | print(i, L2TradeFactorUtil.get_base_safe_val(100000000 * i)) |
| | | # print(L2TradeFactorUtil.get_limit_up_time_rate("11:30:00")) |
| | | # print(L2TradeFactorUtil.get_limit_up_time_rate("13:00:00")) |