Administrator
2023-04-26 d1bf04791ad095b17660a1f383b7a12f0a59b1d1
优化H撤/融入网页看盘页面/开盘啦数据应用
12个文件已修改
5个文件已添加
1956 ■■■■ 已修改文件
constant.py 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
data_export_util.py 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
gpcode_first_screen_manager.py 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
gui.py 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
juejin.py 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
l2/cancel_buy_strategy.py 40 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
l2/l2_data_manager_new.py 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
l2_trade_test.py 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
output/code_info_output.py 449 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
output/css/index.css 250 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
output/index.html 467 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server.py 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
third_data/block_info.py 210 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
third_data/data_server.py 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
third_data/kpl_data_manager.py 154 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
third_data/kpl_util.py 128 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
trade/first_code_score_manager.py 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
constant.py
@@ -1,7 +1,7 @@
# 是否为测试
TEST = False
TEST = True
# 是否允许交易
TRADE_ENABLE = True
TRADE_ENABLE = False
# 水下捞累计连续水下时间最小值
UNDER_WATER_PRICE_TIME_AS_SECONDS = 1200
# 大单金额(单位为百)
@@ -9,6 +9,8 @@
# 大单笔数
BIG_MONEY_NUM = 7888
CACHE_PATH = "D:/trade_cache"
# S撤比例
S_CANCEL_MIN_MONEY = 98
S_CANCEL_SECOND_RATE = 0.59
data_export_util.py
@@ -207,4 +207,4 @@
if __name__ == "__main__":
    export_l2_excel("600072")
    export_l2_excel("002864")
gpcode_first_screen_manager.py
@@ -7,7 +7,7 @@
import tool
from db import redis_manager
from third_data import hot_block_data_process
from third_data import  block_info
__redisManager = redis_manager.RedisManager(0)
@@ -134,9 +134,9 @@
        if now_rate <= 6:
            return True, "炸板后,涨幅小于6%"
    # TODO 是否有同概念的票已经买入成功
    blocks = hot_block_data_process.get_code_blocks(code)
    blocks = block_info.get_code_blocks(code)
    if blocks and len(blocks) == 1:
        codes = hot_block_data_process.get_block_codes(blocks[0])
        codes = block_info.get_block_codes(blocks[0])
        if codes:
            pass
gui.py
@@ -22,6 +22,7 @@
from trade import l2_trade_util
from trade.l2_trade_factor import L2TradeFactorUtil
from ocr import ocr_server
from third_data import  data_server
from server import *
import l2.l2_data_util
@@ -60,6 +61,13 @@
    t1.setDaemon(True)
    t1.start()
    t1 = threading.Thread(target=createDataServer)
    # 后台运行
    t1.setDaemon(True)
    t1.start()
    laddr = "", 9001
    tcpserver = MyThreadingTCPServer(laddr, MyBaseRequestHandle, pipe_juejin=pipe_juejin)  # 注意:参数是MyBaseRequestHandle
    # tcpserver.handle_request()  # 只接受一个客户端连接
@@ -71,6 +79,10 @@
    tcpserver = ocr_server.run("", 9002)
    tcpserver.serve_forever()
def createDataServer():
    print("create OCRServer")
    tcpserver = data_server.run("", 9004)
    tcpserver.serve_forever()
def startJueJin(pipe):
    juejin.JueJinManager(pipe).start()
@@ -85,6 +97,7 @@
        self.serverProcess = multiprocessing.Process(target=createServer, args=(p1, gs_server_pipe,))
        self.jueJinProcess = multiprocessing.Process(target=startJueJin, args=(p2,))
        self.ocrServerProcess = multiprocessing.Process(target=createOCRServer)
        self.p1 = p1
        self.p2 = p2
@@ -120,6 +133,7 @@
        self.jueJinProcess.start()
        self.serverProcess.start()
        self.ocrServerProcess.start()
        L2CodeOperate.get_instance()
        # 客户端队列操作
        process = multiprocessing.Process(target=L2CodeOperate.run())
juejin.py
@@ -73,7 +73,7 @@
    global_data_loader.load_volumn()
    # 9点25之前删除所有代码
    if tool.trade_time_sub(tool.get_now_time_str(), "09:25:00") <= 0 or True:
    if tool.trade_time_sub(tool.get_now_time_str(), "09:25:00") <= 0:
        # 删除L2监听代码
        gpcode_manager.clear_listen_codes()
        # 删除首板代码
l2/cancel_buy_strategy.py
@@ -65,7 +65,8 @@
    def __compute_left_big_num(cls, code, buy_single_index, start_index, end_index, total_data, volume_rate_index):
        # 点火大单数量
        fire_count = cls.__sCancelParamsManager.get_max_exclude_count(volume_rate_index)
        return cls.compute_left_big_num(code, buy_single_index, start_index, end_index, total_data, fire_count, constant.S_CANCEL_MIN_MONEY)
        return cls.compute_left_big_num(code, buy_single_index, start_index, end_index, total_data, fire_count,
                                        constant.S_CANCEL_MIN_MONEY)
    # 计算未撤的总手数
    @classmethod
@@ -273,6 +274,23 @@
        val = json.loads(val)
        return val[0], val[1], val[2], val[3], val[4]
    # 保存已经撤单的监听位置
    @classmethod
    def __add_watch_canceled_index(cls, code, index):
        key = f"h_cancel_watch_canceled_indexs-{code}"
        cls.__getRedis().sadd(key, index)
        cls.__getRedis().expire(key, tool.get_expire())
    @classmethod
    def __get_watch_canceled_index(cls, code):
        key = f"h_cancel_watch_canceled_indexs-{code}"
        return cls.__getRedis().smembers(key)
    @classmethod
    def __del_watch_canceled_index(cls, code):
        key = f"h_cancel_watch_canceled_indexs-{code}"
        cls.__getRedis().delete(key)
    # 保存成交进度
    @classmethod
    def __save_traded_progress(cls, code, origin_process_index, latest_process_index):
@@ -311,20 +329,22 @@
    @classmethod
    def __clear_data(cls, code):
        ks = ["h_cancel_compute_data-{}".format(code), f"h_cancel_watch_indexs_exec-{code}",
              f"h_cancel_watch_indexs-{code}", f"h_cancel_traded_progress-{code}"]
              f"h_cancel_watch_indexs-{code}", f"h_cancel_traded_progress-{code}",
              f"h_cancel_watch_canceled_indexs-{code}"]
        for key in ks:
            cls.__getRedis().delete(key)
    @classmethod
    def need_cancel(cls, code, buy_exec_index, start_index, end_index, total_data, local_today_num_operate_map,
    def need_cancel(cls, code, buy_single_index, buy_exec_index, start_index, end_index, total_data,
                    local_today_num_operate_map,
                    buy_volume_index, volume_index,
                    is_first_code):
        time_space = tool.trade_time_sub(total_data[start_index]["val"]["time"],
                                         total_data[buy_exec_index]["val"]["time"])
        if time_space >= constant.S_CANCEL_EXPIRE_TIME - 1:
            # 开始计算需要监控的单
            cls.__compute_watch_indexs_after_exec(code, buy_exec_index, total_data, local_today_num_operate_map,
                                                  buy_volume_index)
            cls.__compute_watch_indexs_after_single(code, buy_single_index, buy_exec_index, total_data,
                                                    local_today_num_operate_map, buy_volume_index)
        # 守护30s以外的数据
        if time_space <= constant.S_CANCEL_EXPIRE_TIME:
@@ -374,6 +394,8 @@
                                                                                                     local_today_num_operate_map)
                    if buy_index is not None and buy_index in watch_indexs_dict:
                        cancel_num += data["re"] * val["num"]
                        # 加入
                        cls.__add_watch_canceled_index(code, f"{buy_index}-{val['num']}")
                        rate__ = round(cancel_num / total_nums, 2)
                        if rate__ > cancel_rate_threshold:
                            indexs__ = list(watch_indexs_dict.keys())
@@ -390,6 +412,8 @@
                                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}")
            # H撤已撤订单
            logger_l2_h_cancel.info( f"code-{code} H撤已撤订单:{cls.__get_watch_canceled_index(code)}")
            # 保存处理进度与数据
            cls.__save_compute_data(code, process_index, cancel_num)
        return False, None
@@ -503,8 +527,8 @@
    # 计算执行位置之后的需要监听的数据
    @classmethod
    def __compute_watch_indexs_after_exec(cls, code, buy_exec_index, total_data, local_today_num_operate_map,
                                          buy_volume_index):
    def __compute_watch_indexs_after_single(cls, code, buy_single_index, buy_exec_index, total_data,
                                            local_today_num_operate_map, buy_volume_index):
        watch_list, process_index_old, total_count_old, big_num_count_old, finish = cls.__get_watch_index_set_after_exec(
            code)
        if watch_list and finish:
@@ -523,7 +547,7 @@
        # H撤单
        MIN_H_COUNT = cls.__hCancelParamsManager.get_max_watch_count(buy_volume_index)
        for i in range(buy_exec_index, total_data[-1]["index"] + 1):
        for i in range(buy_single_index, total_data[-1]["index"] + 1):
            if i <= process_index_old:
                continue
            process_index = i
l2/l2_data_manager_new.py
@@ -11,21 +11,19 @@
import gpcode_manager
import industry_codes_sort
import l2_data_util
import l2_trade_test
import limit_up_time_manager
from db import redis_manager
import ths_industry_util
import tool
from third_data import hot_block, hot_block_data_process
from trade import trade_data_manager, trade_manager, trade_queue_manager, l2_trade_factor, l2_trade_util, \
from trade import  trade_manager, trade_queue_manager, l2_trade_factor, l2_trade_util, \
    trade_result_manager, first_code_score_manager
from l2 import safe_count_manager, l2_data_manager, l2_data_log, l2_log, l2_data_source_util, code_price_manager
from l2.cancel_buy_strategy import SecondCancelBigNumComputer, HourCancelBigNumComputer, L2LimitUpMoneyStatisticUtil, \
    L2LimitUpSellStatisticUtil
from l2.l2_data_manager import L2DataException, TradePointManager
from l2.l2_data_util import local_today_datas, L2DataUtil, load_l2_data, local_today_num_operate_map, local_latest_datas
from l2.l2_data_util import local_today_datas, L2DataUtil, local_today_num_operate_map, local_latest_datas
import l2.l2_data_util
from log import logger_l2_trade, logger_l2_trade_cancel, logger_l2_trade_buy, logger_l2_process, logger_l2_error, \
from log import logger_l2_trade_buy, logger_l2_process, \
    logger_place_order_score
# TODO l2数据管理
@@ -363,7 +361,7 @@
        def h_cancel():
            _start_time = round(t.time() * 1000)
            try:
                b_need_cancel, b_cancel_data = HourCancelBigNumComputer.need_cancel(code, buy_exec_index, start_index,
                b_need_cancel, b_cancel_data = HourCancelBigNumComputer.need_cancel(code,buy_single_index, buy_exec_index, start_index,
                                                                                    end_index, total_data,
                                                                                    local_today_num_operate_map.get(
                                                                                        code),
l2_trade_test.py
@@ -87,7 +87,7 @@
    # @unittest.skip("跳过此单元测试")
    def test_trade(self):
        code = "002607"
        code = "603819"
        clear_trade_data(code)
        l2.l2_data_util.load_l2_data(code)
        total_datas = deepcopy(l2.l2_data_util.local_today_datas[code])
output/code_info_output.py
@@ -19,12 +19,15 @@
import log
import tool
from l2 import l2_data_manager, l2_data_util, transaction_progress, l2_data_manager_new, code_price_manager
from third_data import hot_block_data_process
from third_data import kpl_data_manager, kpl_util
from trade import first_code_score_manager, l2_trade_factor, trade_manager, l2_trade_util
from trade.l2_trade_factor import L2TradeFactorUtil
import trade.deal_big_money_manager
from jinja2 import Environment, FileSystemLoader
base_output_content = {}
__kplDataManager = kpl_data_manager.KPLDataManager()
def __get_base_html_content():
@@ -40,113 +43,38 @@
    return f"<head><style>{base_output_content['css']}</style></head>"
def __format_data(code_info, score_info, buy_params_info, xgb_code_info, xgb_infos, codes_score, trade_info):
    html = __get_base_html_content()
    html += "<body>"
    html += f"<h2>{code_info[1]} {code_info[0]}    ({code_info[2]})</h2><br>"
    if score_info:
        html += "<b>-----买前评分-------</b><br>"
        score_types = ["换手量能", "竞价强度", "资金力度", "日线形态", "历史股性", "板块热度", "上板时间", "市值大小", "股价大小"]
        html += "<table>"
        for i in range(0, len(score_info[1])):
            html += f"<tr><td>{score_types[i]}</td><td>{score_info[1][i]}</td><td>{score_info[2][i]}</td></tr>"
        html += f"<tr><td><b>评分求和:</td><td>{score_info[0]}</b></td><td></td></tr>"
        html += f"</table><br>"
    html += "\n"
    if buy_params_info:
        html += "<b><br>-----交易参数-------<br></b><table>"
        titles = ["买入意愿", "安全笔数", "动态M值", "买前大单", "成交进度", "买入信号", "买入执行位"]
        for i in range(0, len(titles)):
            html += f"<tr><td>{titles[i]}:</td><td>{buy_params_info[i]}</td></tr>"
        html += "</table><br>"
    html += "\n"
    if xgb_code_info:
        html += "<b><br>-----选股宝---------<br></b>"
        xgb_code_info_dates = ["今天", "昨天", "前天", "之前"]
        for i in range(0, len(xgb_code_info)):
            if xgb_code_info[i]:
                html += f"{xgb_code_info_dates[i]}:<br>"
                for info in xgb_code_info[i]:
                    if i == 0:
                        html += f"【<font color='red'>{info[0]}</font>】,共【<font color='red'>{info[1]}</font>】只票涨停<br>第【<font color='red'>{info[2]}</font>】涨停,现价【<font color='red'>{info[3]}</font>】元,涨幅【<font color='red'>{info[4]}</font>】<br><br>"
                    else:
                        html += f"【{info[0]}】,共【{info[1]}】只票涨停<br>第【{info[2]}】涨停,现价【{info[3]}】元,涨幅【{info[4]}】<br><br>"
    html += "\n"
    if codes_score[0]:
        html += "<b>-----主动买入-------</b><br>"
        html += "<table>"
        for i in range(0, len(codes_score[0])):
            if i % 3 == 0:
                html += "<tr>"
            html += f"<td><font color='red'>{'*' if codes_score[0][i][3] else ''}{codes_score[0][i][1]}({codes_score[0][i][0]}):{codes_score[0][i][2]}</font></td>"
            if i % 3 == 2 or i == len(codes_score[0]) - 1:
                html += "</tr>"
        html += "</table><br>\n"
    if codes_score[1]:
        html += "<b>-----被动买入-------</b><br>"
        html += "<table>"
        for i in range(0, len(codes_score[1])):
            if i % 3 == 0:
                html += "<tr>"
            html += f"<td><font color='#000080'>{'*' if codes_score[1][i][3] else ''}{codes_score[1][i][1]}({codes_score[1][i][0]}):{codes_score[1][i][2]}</font></td>"
            if i % 3 == 2 or i == len(codes_score[1]) - 1:
                html += "</tr>"
        html += "</table><br>\n"
    if codes_score[2] and False:
        html += "<b>-----不买入-------</b><br>"
        html += "<table>"
        for i in range(0, len(codes_score[2])):
            if i % 4 == 0:
                html += "<tr>"
            html += f"<td>{codes_score[2][i][1]}:{codes_score[2][i][2]}</td>"
            if i % 4 == 3 or i == len(codes_score[1]) - 1:
                html += "</tr>"
        html += "</table><br>\n"
    if trade_info:
        html += "<b>-----今日挂撤记录-------</b><br>"
        html += "<br>今日是否炸板:"
        if trade_info[0] is not None:
            html += f"炸板-{trade_info[0]}"
        else:
            html += f"未炸板"
        if trade_info[1]:
            html += "<table>"
            for i in range(0, len(trade_info[1])):
                if i % 2 == 0:
                    html += "<tr>"
                html += f"<td>{trade_info[1][i]}</td>"
                if i % 2 == 1 or i == len(codes_score[0]) - 1:
                    html += "</tr>"
            html += "</table><br>"
        html += "<br>\n"
    if xgb_infos:
        html += "<b><br>-----市场热度-------<br></b><table>"
        for info in xgb_infos:
            html += f"<tr><td>{info[0]}<br><div style=''>{info[1]}</div></td></tr>"
        html += "</table>"
    html += "<br><br>"
    html += "</body>"
    return html
def render(params):
    env = Environment(loader=FileSystemLoader('D:/workspace/trade/output'))
    css = env.get_template('css/index.css')
    params["css"] = css.render()
    template = env.get_template('index.html')
    html_content = template.render(params)
    return html_content
def get_output_html(code):
    def money_desc(money):
        if money > 100000000:
            return f"{round(money / 100000000, 2)}亿"
        else:
            return f"{round(money / 10000, 2)}万"
    params = {
        "base_url": "http://192.168.3.252/kp/",
    }
    day = tool.get_now_date_str()
    is_target_code = gpcode_manager.FirstCodeManager.is_in_first_record(code)
    code_extra_infos=[]
    code_extra_infos = []
    if l2_trade_util.BlackListCodeManager.is_in(code):
        code_extra_infos.append("黑名单")
    if l2_trade_util.WhiteListCodeManager.is_in(code):
        code_extra_infos.append("白名单")
    # 获取白名单,黑名单
    if trade_manager. gpcode_manager.WantBuyCodesManager.is_in(code):
    if trade_manager.gpcode_manager.WantBuyCodesManager.is_in(code):
        code_extra_infos.append("想买单")
    params["code_name"] = f"{gpcode_manager.get_code_name(code)} {code}  ({','.join(code_extra_infos)})"
    code_info = [code, gpcode_manager.get_code_name(code),",".join(code_extra_infos)]
    score_info = None
    buy_params_info = None
    xgb_infos = None
@@ -155,6 +83,7 @@
        l2_data_util.load_l2_data(code)
        total_datas = l2_data_util.local_today_datas.get(code)
    if is_target_code:
        params["score_data"] = {}
        limit_up_price = gpcode_manager.get_limit_up_price(code)
        limit_up_time = limit_up_time_manager.get_limit_up_time(code)
        volume_rate, volume_info = code_volumn_manager.get_volume_rate(code, True)
@@ -162,22 +91,24 @@
                                                                                    True)
        ################################买前评分################################
        # ["换手量能", "竞价强度", "资金力度", "K线形态", "历史股性", "板块热度", "上板时间", "市值大小","股价大小"]
        score_list_new = []
        score_source_list_new = []
        # 换手量能
        score_list_new.append(score_list[6])
        # 获取当前量信息
        max_60, yest = code_volumn_manager.get_histry_volumn(code)
        today = code_volumn_manager.get_today_volumn(code)
        score_source_list_new.append(
            f"实时量【{round(int(today) / 1000000, 2)}万手】÷前高量【{round(max_60[0] / 1000000, 2)}万手-{max_60[1]}】=【{round(score_source_list[6] * 100, 2)}%】")
        params["score_data"]["volume"] = {"score": score_list[6], "now": f"{round(int(today) / 1000000, 2)}",
                                          "high": {"num": round(max_60[0] / 1000000, 2), "date": max_60[1]},
                                          "rate": round(score_source_list[6] * 100, 2)}
        # 竞价强度
        score_list_new.append(score_list[2])
        score_source_list_new.append(f"开盘啦今日委停【{score_source_list[2] if score_source_list[2] else 0}万】")
        params["score_data"]["bidding"] = {"score": score_list[2],
                                           "money": (score_source_list[2] if score_source_list[2] else 0)}
        # 资金力度
        deal_indexes = trade.deal_big_money_manager.get_traded_indexes(code)
        deal_info = ""
        params["score_data"]["deal_big_money"] = {"score": score_list[8], "money": score_source_list[8][0] // 10000,
                                                  "base_money": score_source_list[8][1] // 10000}
        if deal_indexes:
            temps = []
            for index in deal_indexes:
@@ -186,10 +117,11 @@
            start_index = temps[0]
            end_index = temps[-1]
            deal_info = f"【{total_datas[start_index]['val']['time']}&{total_datas[start_index]['val']['num']}手-{total_datas[end_index]['val']['time']}&{total_datas[end_index]['val']['num']}手】,"
            params["score_data"]["deal_big_money"]["start"] = {"time": total_datas[start_index]['val']['time'],
                                                               "num": total_datas[start_index]['val']['num']}
            params["score_data"]["deal_big_money"]["end"] = {"time": total_datas[end_index]['val']['time'],
                                                             "num": total_datas[end_index]['val']['num']}
        score_list_new.append(score_list[8])
        score_source_list_new.append(
            f"{deal_info}<br>累计金额【{score_source_list[8][0] // 10000}万】&固定m值【{score_source_list[8][1] // 10000}万】")
        # K线形态
        k_score = 0
        k_source = []
@@ -200,31 +132,31 @@
        for k in range(0, len(score_source_list[3])):
            if k == 0:
                if score_source_list[3][k][0]:
                    k_source.append("【涨幅过高】")
                    k_source.append("涨幅过高")
            elif k == 1:
                if score_source_list[3][k][0]:
                    k_source.append("【突破前高】")
                    k_source.append("突破前高")
            elif k == 2:
                if score_source_list[3][k][0]:
                    k_source.append("【超跌补涨】")
                    k_source.append("超跌补涨")
            elif k == 3:
                if score_source_list[3][k][0]:
                    k_source.append(f"【逼近前高-{score_source_list[3][k][1]}】")
                    k_source.append(f"逼近前高-{score_source_list[3][k][1]}】")
            elif k == 4:
                if score_source_list[3][k][0]:
                    k_source.append("【N字型】")
                    k_source.append("N字型")
            elif k == 5:
                if score_source_list[3][k][0]:
                    k_source.append("【V字型】")
                    k_source.append("V字型")
            elif k == 6:
                if not score_source_list[3][k][0]:
                    k_source.append("【不满足任何形态】")
                    k_source.append("不满足任何形态")
            elif k == 7:
                if score_source_list[3][k][0]:
                    k_source.append("【天量大阳】")
                    k_source.append("天量大阳")
        score_list_new.append(k_score)
        score_source_list_new.append("/".join(k_source))
        params["score_data"]["k_form"] = {"score": k_score, "datas": k_source}
        # 历史股性
        nature_score = 0
        nature_source = []
@@ -245,12 +177,10 @@
                else:
                    nature_source.append(f"无首板炸板")
        score_list_new.append(nature_score)
        score_source_list_new.append(",".join(nature_source))
        params["score_data"]["code_nature"] = {"score": nature_score, "data_desc": ",".join(nature_source)}
        # 板块热度
        hot_block_score = 0
        hot_block_source = []
        for k in score_list[5]:
            hot_block_score += k
        hot_block_source_data = score_source_list[5]
@@ -271,38 +201,26 @@
                # 高位版信息
                "high_block_infos": [],
            }
            if k == "block_codes_rates_info":
                hot_block_source.append(f"平均涨幅:【{round(hot_block_source_data[k][0]/hot_block_source_data[k][1],2)}%】")
            elif k == "limit_up_codes_count":
                hot_block_source.append(f"板块涨停数量:【{hot_block_source_data[k]}】")
            elif k == "target_block_info":
                hot_block_source.append(f"板块涨幅:【{hot_block_source_data[k][1]}%】")
            elif k == "limit_up_index":
                hot_block_source.append(f"第【{hot_block_source_data[k]+1}】只涨停")
            elif k == "high_block_infos":
                for info in hot_block_source_data[k]:
                    hot_block_source.append(f"{info[0][1]}{info[1]}")
            if k == "target_block_info":
                hot_block_source.append(f"【{hot_block_source_data[k][0]}】概念出现【{hot_block_source_data[k][2]}】次")
        score_list_new.append(hot_block_score)
        score_source_list_new.append(",".join(hot_block_source))
        params["score_data"]["hot_block"] = {"score": hot_block_score,"limit_up_index":hot_block_source_data['limit_up_index']+1,
                                             "block_name": hot_block_source_data['target_block_info'][0],
                                             "limit_up_count": hot_block_source_data['limit_up_codes_count'],
                                             "open_limit_up_count": hot_block_source_data['break_size']}
        # 上板时间
        score_list_new.append(score_list[7])
        score_source_list_new.append(f"上板时间【{score_source_list[7]}】")
        params["score_data"]["limit_up_time"] = {"score": score_list[7], "time": score_source_list[7]}
        # 市值大小
        score_list_new.append(score_list[0])
        score_source_list_new.append(f"自由市值【{round(score_source_list[0] / 100000000, 2)}亿】")
        params["score_data"]["zyltgb"] = {"score": score_list[0], "value": round(score_source_list[0] / 100000000, 2)}
        # 股价大小
        score_list_new.append(score_list[1])
        score_source_list_new.append(f"现价【{score_source_list[1]}】元")
        params["score_data"]["limit_up_price"] = {"score": score_list[1], "price": score_source_list[1]}
        score_info = (score, score_list_new, score_source_list_new)
        params["score_data"]["total_score"] = score
        # zyltgb, limit_price, bidding, k_form, code_nature, hot_block, volume_rate, limit_up_time,
        # deal_big_money
        ###############################下单信息###############################
        params["score_data"]["trade_data"] = {}
        # 获取买入意愿
        volume_rate = score_source_list[6]
        __L2PlaceOrderParamsManager = l2_trade_factor.L2PlaceOrderParamsManager(code, True, volume_rate,
@@ -316,26 +234,23 @@
                                                                                         volume_rate),
                                                                                     ((score, score_list),
                                                                                      score_source_list))
        buy_params_info = []
        if -1 < __L2PlaceOrderParamsManager.score_index < 3:
            temp = "<font color='red'>【主动买入】"
            params["score_data"]["trade_data"]["start"] = {"desc": "主动买入"}
            if __L2PlaceOrderParamsManager.score_index == 0:
                temp += "***"
                params["score_data"]["trade_data"]["start"]["count"] = 3
            elif __L2PlaceOrderParamsManager.score_index == 1:
                temp += "**"
                params["score_data"]["trade_data"]["start"]["count"] = 2
            else:
                temp += "*"
            temp += "</font>"
            buy_params_info.append(temp)
                params["score_data"]["trade_data"]["start"]["count"] = 1
        elif __L2PlaceOrderParamsManager.score_index < 0:
            buy_params_info.append("【不执行买入】")
            params["score_data"]["trade_data"]["start"] = {"desc": "不执行买入", "count": 0}
        else:
            buy_params_info.append("【被动买入】")
            params["score_data"]["trade_data"]["start"] = {"desc": "被动买入", "count": 0}
        # 安全笔数
        safe_count = __L2PlaceOrderParamsManager.get_safe_count()
        base_safe_count, min_count, max_count = L2TradeFactorUtil.get_safe_buy_count(code, True)
        buy_params_info.append(f"固定安全笔数【{base_safe_count}】笔,衰减后安全笔数【{safe_count}】笔")
        params["score_data"]["trade_data"]["safe_count"] = {"base": base_safe_count, "now": safe_count}
        # 动态M值
        m = __L2PlaceOrderParamsManager.get_m_val()
        zyltgb = global_util.zyltgb_map.get(code)
@@ -343,133 +258,103 @@
            global_data_loader.load_zyltgb()
            zyltgb = global_util.zyltgb_map.get(code)
        base_m = L2TradeFactorUtil.get_base_safe_val(zyltgb)
        buy_params_info.append(f"固定M值【{base_m / 10000}万】,动态M值【{m[0] / 10000}万】    ")
        params["score_data"]["trade_data"]["m"] = {"base": base_m // 10000, "now": m[0] // 10000},
        # 买前大单
        big_num = __L2PlaceOrderParamsManager.get_big_num_count()
        base_big_num = __base_L2PlaceOrderParamsManager.get_big_num_count()
        buy_params_info.append(f"固定买前大单【{base_big_num}】笔,衰减后买前大单【{big_num}】笔")
        params["score_data"]["trade_data"]["big_num"] = {"base": base_big_num, "now": big_num}
        # 成交进度
        trade_progress, is_default = transaction_progress.TradeBuyQueue().get_traded_index(code)
        if trade_progress is None or trade_progress < 0 or is_default:
            buy_params_info.append("未识别")
            # buy_params_info.append("未识别")
            pass
        else:
            data = total_datas[trade_progress]
            buy_params_info.append(
                f"【{data['val']['time']}】、【{data['val']['num']}手】、【{round(data['val']['num'] * float(data['val']['price']) * 100 / 10000, 1)}万】")
            params["score_data"]["trade_data"]["trade_progress"] = {"time": data['val']['time'],
                                                                    "num": data['val']['num'], "money": round(
                    data['val']['num'] * float(data['val']['price']) * 100 / 10000, 1)}
        # 买入信号
        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_single_index is None:
            buy_params_info.append("无信号")
            # buy_params_info.append("无信号")
            pass
        else:
            data = total_datas[buy_single_index]
            buy_params_info.append(
                f"【{data['val']['time']}】、【{data['val']['num']}手】、【{round(data['val']['num'] * float(data['val']['price']) * 100 / 10000, 1)}万】")
            params["score_data"]["trade_data"]["buy_single"] = {"time": data['val']['time'], "num": data['val']['num'],
                                                                "money": round(data['val']['num'] * float(
                                                                    data['val']['price']) * 100 / 10000, 1)}
        if buy_exec_index is None or buy_exec_index < 0:
            buy_params_info.append("未下单")
            # buy_params_info.append("未下单")
            pass
        else:
            data = total_datas[buy_exec_index]
            buy_params_info.append(
                f"【{data['val']['time']}】、【{data['val']['num']}手】、【{round(data['val']['num'] * float(data['val']['price']) * 100 / 10000, 1)}万】")
            params["score_data"]["trade_data"]["buy_exec"] = {"time": data['val']['time'], "num": data['val']['num'],
                                                              "money": round(data['val']['num'] * float(
                                                                  data['val']['price']) * 100 / 10000, 1)}
    ##############################选股宝##################################
    xgb_code_info = []
    for i in range(0, 4):
        xgb_datas = hot_block_data_process.XGBHotBlockDataManager.list_by_code(code, day)
        datas = []
        if xgb_datas:
            for data in xgb_datas:
                block = data[2]
                block_datas = hot_block_data_process.XGBHotBlockDataManager.list_by_block(block, day)
                block_datas = list(block_datas)
                limit_up_count = 0
                limit_up_time = None
                for d in block_datas:
                    if len(d[4]) > 6:
                        limit_up_count += 1
                        if d[3] == code:
                            limit_up_time = d[4]
                # 根据涨停时间排序
                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:
                        datas.append(
                            (block, limit_up_count, (i + 1) if limit_up_time is not None else (limit_up_count + 1),
                             block_datas[i][5], block_datas[i][6]))
                        break
        xgb_code_info.append(datas)
        day = juejin.JueJinManager.get_previous_trading_date(day)
    params["xgb_code_infos"] = []
    ##############################热门风口##################################
    xgb_infos = []
    xgb_latest_datas = hot_block_data_process.XGBHotBlockDataManager.latest_datas
    if not xgb_latest_datas:
        xgb_infos.append('暂未获取到数据')
    else:
        # 获取今日的所有数据
        datas_record = hot_block_data_process.XGBHotBlockDataManager.list_all(tool.get_now_date_str())
        datas_record_dict = {}
        for data in datas_record:
            block = data[2]
            if block not in datas_record_dict:
                datas_record_dict[block] = []
            # 代码,代码名称,涨停时间,首次涨停时间
            datas_record_dict[block].append((data[3], data[9], data[4], data[8], block))
        for block in xgb_latest_datas:
            limit_up_count = 0
            codes = datas_record_dict.get(block[0])
            for code_data in block[2]:
                if len(code_data[4]) > 6:
                    limit_up_count += 1
            # 获取板块中的代码
            block_codes_set = set()
            for d in block[2]:
                _code = d[0][1].split(".")[0]
                block_codes_set.add(_code)
    params["xgb_infos"] = []
            if codes:
                codes_data_html = "<table><tr>"
                count = 0
                for code_data in codes:
                    if code_data[4] != block[0]:
                        # 不是该板块数据
                        continue
                    count += 1
                    codes_data_html += "<td style = 'text-decoration:underline;'>"
                    # 如果代码涨停时间或者没有在最新的代码中
                    if (len(code_data[2]) < 6 or code_data[0] not in block_codes_set) and len(code_data[3]) > 6:
                        # 炸板
                        codes_data_html += f"<font color='#000080'>{code_data[1]}:{code_data[0]}&nbsp;&nbsp;</font>"
                    elif len(code_data[2]) > 6:
                        # 涨停
                        codes_data_html += f"<font color='#FF3232'>{code_data[1]}:{code_data[0]}&nbsp;&nbsp;</font>"
                    else:
                        codes_data_html += f"{code_data[1]}:{code_data[0]}&nbsp;&nbsp;"
                    codes_data_html += "</td>"
                    if count % 4 == 0:
                        codes_data_html += "</tr><tr>"
                codes_data_html += "</tr></table>"
                _info = (f"***【{block[0]}】,涨幅【{block[1]}】,共【{limit_up_count}】个涨停", codes_data_html)
                is_target_block = False
                if xgb_code_info:
                    for _code_info in xgb_code_info[0]:
                        if len(_code_info) > 0 and _code_info[0] == block[0]:
                            is_target_block = True
                            break
                if is_target_block:
                    xgb_infos.insert(0, _info)
                else:
                    xgb_infos.append(_info)
    # 返回主动买,被动买,不买的列表(代码, 名称, 得分, 是否涨停)
    codes_score = __load_codes_scores()
    params["initiative_buy_codes"] = []
    for d in codes_score[0]:
        params["initiative_buy_codes"].append(
            {"name": d[1], "code": d[0], "score": d[2], "limit_up": d[3], "open_limit_up": d[4]})
    params["passive_buy_codes"] = []
    for d in codes_score[1]:
        params["passive_buy_codes"].append(
            {"name": d[1], "code": d[0], "score": d[2], "limit_up": d[3], "open_limit_up": d[4]})
    trade_info = __load_trade_record(code, total_datas)
    return __format_data(code_info, score_info, buy_params_info, xgb_code_info, xgb_infos, codes_score, trade_info)
    params["trade_record"] = {"open_limit_up": trade_info[0], "records": trade_info[2]}
    ##############################开盘啦相关信息##################################
    params["kpl_industry_rank"] = []
    params["kpl_best_feng_kou"] = []
    params["kpl_feng_kou"] = []
    params["kpl_feng_xiang"] = []
    best_fengkou = __kplDataManager.get_data(kpl_util.KPLDataType.BEST_FENG_KOU)
    fengkou = __kplDataManager.get_data(kpl_util.KPLDataType.FENG_KOU)
    fengxiang = __kplDataManager.get_data(kpl_util.KPLDataType.FENG_XIANG)
    rank_infos = __kplDataManager.get_data(kpl_util.KPLDataType.INDUSTRY_RANK)
    # (代码,名称,强度,涨幅,热门板块,所有板块)
    if best_fengkou:
        for r in best_fengkou:
            hot_block = "、".join(r[4].split("、")[:2])
            params["kpl_best_feng_kou"].append(
                {"name": r[1], "weight": r[2], "money": money_desc(r[2]), "rate": r[3], "hot_block": hot_block,
                 "hot_block_all": r[5]})
    if fengkou:
        fengkou = fengkou[:30]
        for r in fengkou:
            # 市场风口
            # (代码,名称,涨幅,主力净额,风口概念)
            params["kpl_feng_kou"].append(
                {"name": r[1], "money": money_desc(r[3]), "rate": r[2], "block": r[4]})
    if fengxiang:
        for r in fengxiang:
            # 风向标
            # (代码, 名称, 现价, 涨幅, 板块, 300万大单净额, 主力净额, 自由市值)
            params["kpl_feng_xiang"].append(
                {"name": r[1], "money_300w": money_desc(r[5]), "money_main": money_desc(r[6]), "rate": r[3],
                 "block": r[4]})
    if rank_infos:
        for r in rank_infos:
            params["kpl_industry_rank"].append({"name": r[1], "money": money_desc(r[2]), "rate": r[3]})
    return render(params)
def __load_codes_scores():
@@ -494,12 +379,14 @@
        code_name = gpcode_manager.get_code_name(code)
        # 获取现价,判断是否涨停
        current_price_info = global_util.cuurent_prices.get(code)
        limit_up_info = code_price_manager.Buy1PriceManager.get_limit_up_info(code)
        is_limit_up = True
        open_limit_up = limit_up_info[0] and limit_up_info[1]
        if current_price_info is not None and not current_price_info[1]:
            is_limit_up = False
        else:
            is_limit_up = True
        scores_list.append((code, code_name, scores[code], is_limit_up))
        scores_list.append((code, code_name, scores[code], is_limit_up, open_limit_up))
    scores_list.sort(key=lambda x: x[2], reverse=True)
    fscores_list = [[], [], []]
    for score in scores_list:
@@ -520,12 +407,13 @@
    # 获取炸板信息
    limit_up_info = code_price_manager.Buy1PriceManager.get_limit_up_info(code)
    break_time = limit_up_info[1]
    records =[]
    records = []
    try:
        records = log.load_buy_score_recod(code)
    except:
        pass
    records_new = []
    records_new_data = []
    index = 0
    if records:
        try:
@@ -537,6 +425,7 @@
                    index += 1
                    temp = f"第{index}次下单:【{time_}】&【{data['score']}分】,{data.get('desc')}"
                    records_new.append(temp)
                    records_new_data.append({"type": 1, "index": index, "time": time_, "score": data['score']})
                elif type == 'S撤':
                    # index':378 , 'rate':0.51 , 'target_rate':0.49
                    pass
@@ -556,12 +445,64 @@
                elif type == '撤单':
                    temp = f"第{index}次撤单:【{time_}】{data['msg']}"
                    records_new.append(temp)
                    records_new_data.append({"type": 0, "time": time_, "desc": data['msg']})
        except:
            pass
    return break_time, records_new
    return break_time, records_new, records_new_data
if __name__ == '__main__':
    st="8天3板"
    print(st[-2:-1])
    datas = {
        "base_url": "http://192.168.3.122/kp/",
        "code_name": "天域生态 002255",
        "score_data": {"volume": {"score": 20, "now": "12", "high": {"num": "56", "date": "2023-04-13"}},
                       "bidding": {"score": 10, "money": "4563"},
                       "deal_big_money": {"score": 10, "money": 0, "base_money": 456.5,
                                          "start": {"time": "09:00:00", "num": 1456},
                                          "end": {"time": "09:00:00", "num": 1456}},
                       "k_form": {"score": 10, "datas": ["破前高", "超跌补涨", "涨幅过高"]},
                       "code_nature": {"score": 10, "data_desc": "涨停次数2次"},
                       "hot_block": {"score": 10, "block_name": "影视", "limit_up_count": 10, "open_limit_up_count": 2},
                       "limit_up_time": {"score": 10, "time": "09:56:00"},
                       "zyltgb": {"score": 10, "value": "12.5"},
                       "limit_up_price": {"score": 10, "price": "6.35"},
                       "total_score": "210"
                       },
        "trade_data": {"star": {"desc": "被动买入", "count": 0},
                       "safe_count": {"base": 12, "now": 2},
                       "m": {"base": 1200, "now": 1000},
                       "big_num": {"base": 10, "now": 2},
                       "trade_progress": {"time": "09:12:12", "num": 1111, "money": "12.56"},
                       "buy_single": {"time": "09:12:12", "num": 1111, "money": "12.56"},
                       "buy_exec": {"time": "09:12:12", "num": 1111, "money": "12.56"}
                       },
        "xgb_code_infos": [{"date": "今天", "blocks": [
            {"name": "影视", "limit_up_count": 2, "index": 1, "price": "12.00", "rate": "+10.00%"},
            {"name": "文旅", "limit_up_count": 3, "index": 2, "price": "12.00", "rate": "+10.00%"},
        ]}],
        "initiative_buy_codes": [
            {"name": "测试1", "code": "000123", "score": 125, "limit_up": True, "open_limit_up": True},
            {"name": "测试2", "code": "000123", "score": 125, "limit_up": False, "open_limit_up": True},
            {"name": "测试2", "code": "000123", "score": 125, "limit_up": False, "open_limit_up": True},
            {"name": "测试2", "code": "000123", "score": 125, "limit_up": False, "open_limit_up": False}
        ],
        "passive_buy_codes": [{"name": "测试1", "code": "000123", "score": 125},
                              {"name": "测试2", "code": "000123", "score": 125},
                              {"name": "测试2", "code": "000123", "score": 125},
                              {"name": "测试2", "code": "000123", "score": 125}
                              ],
        "trade_record": {"open_limit_up": "10:00:03", "records": [
            {"type": 1, "index": 1, "time": "11:00:00", "score": 12},
            {"type": 0, "time": "11:26:00", "desc": "H撤撤单"}
        ]},
        "xgb_infos": [{"block": {"name": "测试1", "rate": "+12.00%", "limit_up_count": 10},
                       "codes": [
                           {"limit_up": True, "name": "测试代码", "code": "000654"},
                           {"limit_up": True, "name": "测试代码", "code": "000654"},
                           {"limit_up": True, "name": "测试代码", "code": "000654"},
                           {"limit_up": False, "name": "测试代码", "code": "000654"},
                       ]}]
    }
    print(render(datas))
output/css/index.css
New file
@@ -0,0 +1,250 @@
body,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
p,
blockquote,
dl,
dt,
dd,
ul,
ol,
li,
pre,
form,
fieldset,
legend,
button,
input,
textarea,
th,
td {
    margin: 0;
    padding: 0;
}
ul,
ol {
    list-style: none;
}
a {
    text-decoration: none;
}
a:hover {
    text-decoration: underline;
}
button,
input,
select,
textarea {
    font-size: 100%;
}
table {
    border-collapse: collapse;
    border-spacing: 0;
}
body {
    max-width: 540px;
    font-size: 13px;
    color: #FFFFFF;
    background: #191921;
    font-family: Microsfot YaHei;
}
.top {
    width: 540px;
    height: 50px;
    /* padding-left: 15px; */
    line-height: 50px;
    font-size: 20px;
    background: #3E3E57;
}
.table-name {
    height: 40px;
    line-height: 40px;
    padding-left: 10px;
    margin-top: 12px;
    font-size: 16px;
    font-weight: 600;
    background: #2F2F3E;
}
.table-title {
    height: 40px;
    font-size: 16px;
    font-weight: 600;
}
table tr td {
    font-size: 13px;
    padding: 0px 8px;
}
table {
    width: 100%;
    border-collapse: collapse;
    /* margin: 0 auto; */
    /* text-align: center; */
}
table td {
    height: 20px;
    /* border: 1px solid #191921; */
}
table tr:nth-child(odd) {
    background: #343444;
}
table tr:nth-child(even) {
    background: #2F2F3E;
}
table tr:hover {
    background: #3e3e57;
}
.td-max {
    width: 100%;
}
.num-style {
    min-width: 40px;
    max-width: 0px;
    padding: 0px 3px;
    height: 22px;
    line-height: 22px;
    font-size: 13px;
    font-weight: 400;
    background: #21212B;
    border-radius: 5px;
    text-align: center;
}
.bold {
    font-size: 16px;
    font-weight: 600;
}
.red {
    color: #FE033F;
}
.green {
    color: #1CF088;
}
.yellow {
    color: #FFEC17;
}
.num-card-color1 {
    background: #843960;
}
.num-card-color2 {
    background: #866F3D;
}
.num-card-color3 {
    background: #3C5F8B;
}
.score-card-color {
    min-width: 40px;
    max-width: 0px;
    padding: 0px 2px;
    height: 22px;
    line-height: 22px;
    font-size: 13px;
    font-weight: 400;
    background: #9B7A15;
    border-radius: 5px;
    text-align: center;
}
.icon-null {
    float: left;
    width: 10px;
    height: 10px;
    margin-right: 4px;
    /* background: #191921; */
}
.button-blue {
    display: block;
    /* float: left; */
    width: 106px;
    height: 30px;
    margin-top: -35px;
    margin-left: 419px;
    border-radius: 5px;
    line-height: 30px;
    font-size: 14px;
    background: #2059E5;
    text-align: center;
}
.button-blue:hover {
    background: #477cff;
}
.button-blue:active {
    color: #000000;
    background: #002070;
}
table .sub_title{
    text-align: center;
    font-size: 16px;
}
table .content{
    text-align:center;
    vertical-align: top;
}
.content table{
    width: 250px;
}
.content tr td{
    font-size: 12px !important;
    padding: 0 !important;
    max-width: 70px !important;
    width: 70px !important;
}
.kpl tr td{
    padding: 0 !important;
    max-width: 70px !important;
    width: 70px !important;
}
.table-fxb{
    width: 280px !important;
}
.table-fxb tr td:first-child{
    width: 90px !important;
}
.table-fxb tr td:nth-child(2){
    width: 50px !important;
    background: #1CF088;
}
.table-ins{
    width: 200px;
}
output/index.html
New file
@@ -0,0 +1,467 @@
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>看盘端</title>
        <style>
        {{css}}
        </style>
    </head>
    <body>
        <div class="top">
            <span>
                <h2 style="margin-left: 18px; font-size: 20px;">{{code_name}}</h2>
            </span>
        </div>
        {% if score_data %}
        <div class="table-name">买前评分</div>
        <table>
            <tr>
                <td>换手量能</td>
                <td>
                    <div class="num-style">{{score_data.volume.score}}</div>
                </td>
                <td style="margin: 0 auto;">实时量<span class="num-style">{{score_data.volume.now}}万手</span>
                    <hr width="240" align="left">前高量<span
                        class="num-style">{{score_data.volume.high.num}}万手</span>&nbsp;&nbsp;
                    <span class="num-style">{{score_data.volume.high.date}}</span>
                </td>
                <td>
                    <div class="num-style">{{score_data.volume.rate}}%</div>
                </td>
            </tr>
            <tr>
                <td>竞价强度</td>
                <td>
                    <div class="num-style">{{score_data.bidding.score}}</div>
                </td>
                <td>开盘啦今日委停</td>
                <td>
                    <span class="num-style">{{score_data.bidding.money}}万</span>
                </td>
            </tr>
            <tr>
                <td>资金力度</td>
                <td>
                    <div class="num-style">{{score_data.deal_big_money.score}}</div>
                </td>
                <td>
                    {% if score_data.deal_big_money.start%}
                    <span class="num-style">{{score_data.deal_big_money.start.time}}</span>&nbsp;
                    <span class="num-style">{{score_data.deal_big_money.start.num}}手</span>---
                    {% endif %}
                    {% if score_data.deal_big_money.end%}
                    <span class="num-style">{{score_data.deal_big_money.end.time}}</span>&nbsp;
                    <span class="num-style">{{score_data.deal_big_money.end.num}}手</span>
                    {% endif %}
                    <br>累计金额<span
                        class="num-style">{{score_data.deal_big_money.money}}万</span>&nbsp;&nbsp;&nbsp;&nbsp;固定M值<span
                        class="num-style">{{score_data.deal_big_money.base_money}}万</span>
                </td>
                <td></td>
            </tr>
            <tr>
                <td>日线形态</td>
                <td>
                    <div class="num-style">{{score_data.k_form.score}}</div>
                </td>
                <td>
                    {% for k in score_data.k_form.datas %}
                    {% if loop.index0%3==0 %}
                    <span class="num-style num-card-color1">{{k}}</span>
                    {% elif loop.index0%3==1 %}
                    <span class="num-style num-card-color2">{{k}}</span>
                    {% elif loop.index0%3==2 %}
                    <span class="num-style num-card-color3">{{k}}</span>
                    {%endif%}
                    {% endfor%}
                </td>
                <td></td>
            </tr>
            <tr>
                <td>历史股性</td>
                <td>
                    <div class="num-style">{{score_data.code_nature.score}}</div>
                </td>
                <td>{{score_data.code_nature.data_desc}}</td>
                <td>
                    <div class="num-style">1.0</div>
                </td>
            </tr>
            <tr>
                <td>板块热度</td>
                <td>
                    <div class="num-style">{{score_data.hot_block.score}}</div>
                </td>
                <td>
                    <span class="num-style">【{{score_data.hot_block.block_name}}】</span>
                    共<span class="num-style bold red">{{score_data.hot_block.limit_up_count}}</span>个涨停,
                    第<span class="num-style bold red">{{score_data.hot_block.limit_up_index}}</span>个涨停
                    ,共
                    <span class="num-style bold green">{{score_data.hot_block.open_limit_up_count}}</span>
                    个炸板
                </td>
                <td></td>
            </tr>
            <tr>
                <td>上板时间</td>
                <td>
                    <div class="num-style">{{score_data.limit_up_time.score}}</div>
                </td>
                <td></td>
                <td><span class="num-style">{{score_data.limit_up_time.time}}</span></td>
            </tr>
            <tr>
                <td>市值大小</td>
                <td>
                    <div class="num-style">{{score_data.zyltgb.score}}</div>
                </td>
                <td>自由市值</td>
                <td><span class="num-style">{{score_data.zyltgb.value}}亿</span></td>
            </tr>
            <tr>
                <td>股价大小</td>
                <td>
                    <div class="num-style">{{score_data.limit_up_price.score}}</div>
                </td>
                <td>现价</td>
                <td><span class="num-style">{{score_data.limit_up_price.price}}元</span></td>
            </tr>
            <tr>
                <td>评分求和</td>
                <td>
                    <div class="num-style bold red">{{score_data.total_score}}</div></b>
                </td>
                <td></td>
                <td></td>
            </tr>
        </table>
        {% endif %}
        {% if trade_data %}
        <div class="table-name">交易参数</div>
        <table>
            <tr>
                <td>买入意愿</td>
                <td>
                    {% if trade_data.star.count>0 %}
                    <span class="bold yellow">{{trade_data.star.desc}}</span>
                    {% else %}
                    <span class="bold">{{trade_data.star.desc}}</span>
                    {% endif %}
                    {% for i in range(0,trade_data.star.count) %}
                    <img src="{{base_url}}images/star.png" / style="margin-left: 3px;"></span>
                    {% endfor %}
                </td>
            </tr>
            <tr>
                <td>安全笔数</td>
                <td>固定安全笔数<span class="num-style ">{{trade_data.safe_count.base}}</span>笔,衰减后安全笔数<span
                        class="num-style ">{{trade_data.safe_count.now}}</span>笔</td>
            </tr>
            <tr>
                <td>动态M值</td>
                <td>固定M值<span class="num-style ">{{trade_data.m.base}}万</span>&nbsp;&nbsp;&nbsp;动态M值<span
                        class="num-style ">{{trade_data.m.now}}万</span></td>
            </tr>
            <tr>
                <td>买前大单</td>
                <td>固定买前大单<span class="num-style ">{{trade_data.big_num.base}}</span>笔,衰减后买前大单<span
                        class="num-style ">{{trade_data.big_num.now}}</span>笔
                </td>
            </tr>
            <tr>
                <td>成交进度</td>
                <td>
                    {% if trade_data.trade_progress %}
                    <span class="num-style ">{{trade_data.trade_progress.time}}</span>&nbsp;
                    <span class="num-style ">{{trade_data.trade_progress.num}}手</span>&nbsp;
                    <span class="num-style ">{{trade_data.trade_progress.money}}万</span>
                    {% endif %}
                </td>
            </tr>
            <tr>
                <td>买入信号</td>
                <td>
                    {% if trade_data.buy_single %}
                    <span class="num-style ">{{trade_data.buy_single.time}}</span>&nbsp;
                    <span class="num-style ">{{trade_data.buy_single.num}}手</span>&nbsp;
                    <span class="num-style ">{{trade_data.buy_single.money}}万</span>
                    {% endif %}
                </td>
            </tr>
            <tr>
                <td>买入执行位</td>
                <td>
                    {% if trade_data.buy_exec %}
                    <span class="num-style ">{{trade_data.buy_exec.time}}</span>&nbsp;
                    <span class="num-style ">{{trade_data.buy_exec.num}}手</span>&nbsp;
                    <span class="num-style ">{{trade_data.buy_exec.money}}万</span>
                    {% else %}
                    <span class="num-style red bold">未下单</span>
                    {% endif %}
                </td>
            </tr>
        </table>
        {% endif %}
        <div class="table-name">选股宝</div>
        <table>
            {% for k in xgb_code_infos %}
            <tr>
                <td>{{k.date}}</td>
                <td>
                    <div>
                        {% for b in k.blocks %}
                        <span class="num-style ">{{b.name}}</span>&nbsp;共<span
                            class="num-style bold red">{{b.limit_up_count}}</span>只票涨停
                        <br>
                        第<span class="num-style bold red">{{b.index}}</span>涨停,现价<span
                            class="num-style bold red">{{b.price}}</span>元,涨幅<span
                            class="num-style bold red">{{b.rate}}</span>
                        <br>
                        {% endfor %}
                    </div>
                </td>
            </tr>
            {% endfor %}
        </table>
        <div class="table-name"><span class="table-title">主动买入</span><span class="button-blue">加入看盘</span></div>
        <table>
            {% for k in initiative_buy_codes %}
            {% if loop.index0 % 3 ==0 %}
            <tr>
                {% endif %}
                <td>
                    {% if k.limit_up %}
                    <span><img src="{{base_url}}images/limit_up.png"></span>
                    {% elif k.open_limit_up %}
                    <span><img src="{{base_url}}images/stop_up.png"></span>
                    {% else %}
                    <span class="icon-null"></span>
                    {% endif %}
                    <span class="num-style">{{k.name}}</span>
                    <span class="num-style">{{k.code}}</span>
                    <span class="score-card-color yellow">{{k.score}}</span>
                </td>
                {% if loop.index0 % 3 ==2 %}
            </tr>
            {% elif loop.last %}
            </tr>
            {% endif %}
            {% endfor %}
        </table>
        <div class="table-name"><span class="table-title">被动买入</span><span class="button-blue">加入看盘</span></div>
        <table>
            {% for k in passive_buy_codes %}
            {% if loop.index0 % 3 ==0 %}
            <tr>
                {% endif %}
                <td>
                    {% if k.limit_up %}
                    <span><img src="{{base_url}}images/limit_up.png"></span>
                    {% elif k.open_limit_up %}
                    <span><img src="{{base_url}}images/stop_up.png"></span>
                    {% else %}
                    <span class="icon-null"></span>
                    {% endif %}
                    <span class="num-style">{{k.name}}</span>
                    <span class="num-style">{{k.code}}</span>
                    <span class="score-card-color yellow">{{k.score}}</span>
                </td>
                {% if loop.index0 % 3 ==2 %}
            </tr>
            {% elif loop.last %}
            </tr>
            {% endif %}
            {% endfor %}
        </table>
        <div class="table-name">今日挂撤记录</div>
        <table>
            <tr>
                <td>是否炸板</td>
                {% if trade_record.open_limit_up %}
                <td><span><img src="{{base_url}}images/stop_up.png">&nbsp;</span>炸板&nbsp;&nbsp;
                    <span class="num-style ">{{trade_record.open_limit_up}}</span>
                </td>
                {% else %}
                <td>
                    <span class="num-style ">未炸板</span>
                </td>
                {% endif %}
                <td></td>
                <td></td>
            </tr>
            {% for k in trade_record.records %}
            {% if loop.index0 % 2 ==0 %}
            <tr>
                {% endif %}
                {% if k.type ==1 %}
                <td>第{{k.index}}次</td>
                <td>下单:<span class="num-style ">{{k.time}}</span> <span
                        class="score-card-color yellow">{{k.score}}</span></td>
                {% else %}
                <td>撤单:<span class="num-style ">{{k.time}}</span></td>
                <td>{{k.desc}}</td>
                {% endif %}
                {% if loop.index0 % 3 ==2 %}
            </tr>
            {% elif loop.last %}
            </tr>
            {% endif %}
            {% endfor %}
        </table>
        <div class="table-name">市场热度</div>
        <table>
            {% for k in xgb_infos %}
            <tr style="background: #2c2c64;">
                <td colspan="3"><span class="num-style bold red">{{k.block.name}}</span>&nbsp;&nbsp;&nbsp;&nbsp;涨幅<span
                        class="num-style bold red">{{k.block.rate}}</span>
                    ,共
                    <span
                        class="num-style bold red">{{k.block.limit_up_count}}</span>个涨停---------------------------------------
                </td>
            </tr>
            <table>
                {% for code_info in k.codes %}
                {% if loop.index0 % 3 ==0 %}
                <tr>
                    {% endif %}
                    <td>
                        {% if code_info.limit_up %}
                        <span><img src="{{base_url}}images/limit_up.png"></span>
                        {% else %}
                        <span><img src="{{base_url}}images/limit_up.png" style="visibility: hidden;"></span>
                        {% endif %}
                        <!--                     <span class="icon-null"></span> -->
                        <span class="num-style">{{code_info.name}}</span>
                        <span class="num-style">{{code_info.code}}</span>
                        <!-- <span class="score-card-color yellow">228</span> -->
                    </td>
                    {% if loop.index0 % 3 ==2 %}
                </tr>
                {% elif loop.last %}
                </tr>
                {% endif %}
                {% endfor %}
            </table>
            {% endfor %}
        </table>
        <div class="table-name">开盘啦数据</div>
        <table class="kpl">
            <tr>
                <td class="sub_title">最强风口</td>
                <td class="sub_title">市场风口</td>
            </tr>
            <tr>
                <td class="content">
                    <table>
                        <thead>
                            <tr>
                                <td>股票名称</td>
                                <td>强度</td>
                                <td>涨跌幅</td>
                                <td>所属板块</td>
                            </tr>
                        </thead>
                        <tbody>
                        <tr></tr>
                            {% for code_info in kpl_best_feng_kou %}
                            <tr>
                                <td>{{code_info.name}}</td>
                                <td>{{code_info.weight}}</td>
                                <td>{{code_info.rate}}%</td>
                                <td>{{code_info.hot_block}}</td>
                            </tr>
                            {% endfor %}
                        </tbody>
                    </table>
                </td>
                <td class="content">
                    <table>
                        <thead>
                            <tr>
                                <td>股票名称</td>
                                <td>主力净额</td>
                                <td>涨跌幅</td>
                                <td>风口概念</td>
                            </tr>
                        </thead>
                        <tbody>
                            {% for code_info in kpl_feng_kou %}
                            <tr>
                                <td>{{code_info.name}}</td>
                                <td>{{code_info.money}}</td>
                                <td>{{code_info.rate}}%</td>
                                <td>{{code_info.block}}</td>
                            </tr>
                            {% endfor %}
                        </tbody>
                    </table>
                </td>
            </tr>
            <tr>
                <td class="sub_title">风向标</td>
                <td class="sub_title">行业涨幅</td>
            </tr>
            <tr>
                <td class="content">
                    <table class = "table-fxb">
                        <thead>
                            <tr>
                                <td>股票名称</td>
                                <td>涨跌幅</td>
                                <td>所属板块</td>
                                <td>300W净额</td>
                                <td>主力净额</td>
                            </tr>
                        </thead>
                        <tbody>
                            {% for code_info in kpl_feng_xiang %}
                            <tr>
                                <td>{{code_info.name}}</td>
                                <td>{{code_info.rate}}%</td>
                                <td>{{code_info.block}}</td>
                                <td>{{code_info.money_300w}}</td>
                                <td>{{code_info.money_main}}</td>
                            </tr>
                            {% endfor %}
                        </tbody>
                    </table>
                </td>
                <td class="content">
                    <table class = "table-ins">
                        <thead>
                            <tr>
                                <td>行业名称</td>
                                <td>主力净额</td>
                                <td>涨跌幅</td>
                            </tr>
                        </thead>
                        <tbody>
                            {% for code_info in kpl_industry_rank %}
                            <tr>
                                <td>{{code_info.name}}</td>
                                <td>{{code_info.money}}</td>
                                <td>{{code_info.rate}}%</td>
                            </tr>
                            {% endfor %}
                        </tbody>
                    </table>
                </td>
            </tr>
        </table>
    </body>
</html>
server.py
@@ -32,7 +32,7 @@
import ths_util
import tool
from output import code_info_output
from third_data import hot_block_data_process
from third_data import hot_block_data_process, block_info
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, \
    first_code_score_manager, current_price_process_manager
@@ -719,12 +719,12 @@
                    # 根据代码获取选股宝热门概念
                    day = tool.get_now_date_str()
                    code = data_process.parse(_str)["data"]["code"]
                    todays = hot_block_data_process.XGBHotBlockDataManager.list_by_code(code, day)
                    todays =block_info.KPLLimitUpDataRecordManager.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 = block_info.KPLLimitUpDataRecordManager.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'))
@@ -736,12 +736,12 @@
                                    break
                    # 获取前一个交易日
                    last_day = juejin.JueJinManager.get_previous_trading_date(day)
                    lasts = hot_block_data_process.XGBHotBlockDataManager.list_by_code(code, last_day)
                    lasts = block_info.KPLLimitUpDataRecordManager.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 = block_info.KPLLimitUpDataRecordManager.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'))
@@ -760,7 +760,7 @@
                    data_dict = {}
                    for i in range(0, 2):
                        day = juejin.JueJinManager.get_previous_trading_date(day)
                        data_list = list(hot_block_data_process.XGBHotBlockDataManager.list_all(day))
                        data_list = list(block_info.KPLLimitUpDataRecordManager.list_all(day))
                        codes_set = set()
                        if data_list:
                            for d in data_list:
third_data/block_info.py
New file
@@ -0,0 +1,210 @@
"""
板块信息
"""
import datetime
import juejin
import tool
from third_data import kpl_util, kpl_data_manager
from third_data.kpl_data_manager import KPLLimitUpDataRecordManager, KPLDataManager
__before_block_dict = {}
__kplDataManager = KPLDataManager()
def __load_before_block(code):
    if code not in __before_block_dict:
        blocks = KPLLimitUpDataRecordManager.get_latest_blocks(code)
        if blocks:
            blocks = blocks[0].split(',')
            __before_block_dict[code] = blocks
    return __before_block_dict.get(code)
def __get_code_from_code_info(code_info):
    code = code_info[0][1].split(".")[0]
    return code
# (代码, 名称, 首次涨停时间, 最近涨停时间, 几板, 涨停原因, 板块, 实际流通, 主力净额)
def __get_blocks(code, limit_up_datas):
    blocks = []
    for data in limit_up_datas:
        if data[0] == code:
            block = data[5]
            if block in kpl_data_manager.INVALID_BLOCKS:
                continue
            blocks.append(block)
    return blocks
def __is_has_high_code(block, latest_datas):
    for data in latest_datas:
        if block == data[5]:
            if data[4] != "首板":
                return True, data
    return False, None
__blocks_dict = {}
def get_latest_block(day_count=15):
    now_day = tool.get_now_date_str()
    if now_day in __blocks_dict:
        return __blocks_dict[now_day]
    now_date = datetime.datetime.now()
    end_date = juejin.JueJinManager.get_previous_trading_date(tool.get_now_date_str())
    start_date = now_date - datetime.timedelta(days=(day_count * 2 + 10))
    start_date = start_date.strftime("%Y-%m-%d")
    days = juejin.JueJinManager.get_trading_dates(start_date, end_date)
    days = days[0 - day_count:]
    results = KPLLimitUpDataRecordManager.list_blocks_with_day(days)
    __blocks_dict[now_day] = results
    return results
# 获取代码所属板块
def get_code_blocks(code):
    latest_datas = __kplDataManager.get_data(kpl_util.KPLDataType.LIMIT_UP)
    blocks = __get_blocks(code, latest_datas)
    return blocks
# 获取代码所在板块信息
def get_info(code):
    latest_datas = __kplDataManager.get_data(kpl_util.KPLDataType.LIMIT_UP)
    blocks = __get_blocks(code, latest_datas)
    if not blocks:
        blocks = __load_before_block(code)
    latest_blocks_info = get_latest_block(15)
    # 统计板块出现次数
    # 获取目标板块
    target_block = None
    if blocks:
        for block in blocks:
            if block in kpl_data_manager.INVALID_BLOCKS:
                continue
            target_block = block
            break
    if not target_block:
        return None
    # 统计板块中的平均涨幅
    total_rates = 0
    total_count = 0
    target_block_rate = 0
    # if latest_datas:
    #     for b in latest_datas:
    #         if b[5] != target_block:
    #             continue
    #         if b[1]:
    #             target_block_rate = float(b[1].strip().replace("%", ''))
    #         for code_info in b[2]:
    #             code__ = __get_code_from_code_info(code_info)
    #             rate = float(code_info[3].strip().replace("%", ''))
    #             if code__ != code:
    #                 total_rates += rate
    #                 total_count += 1
    # 统计板块出现的次数
    target_block_histry_count = 0
    if blocks:
        for block_info in latest_blocks_info:
            if block_info[0] != target_block:
                continue
            target_block_histry_count += 1
    # 是否出现过高位板
    high_block_infos = []
    for block in blocks:
        if block in kpl_data_manager.INVALID_BLOCKS:
            continue
        if latest_datas:
            has_high, high_code_info = __is_has_high_code(block, latest_datas)
            if has_high:
                high_block_info = (high_code_info[1], high_code_info[4])
                high_block_infos.append(high_block_info)
    limit_up_codes_info_set = set()
    # 板块下的代码数量
    block_codes_set = set()
    if KPLLimitUpDataRecordManager.total_datas is None:
        KPLLimitUpDataRecordManager.load_total_datas()
    if KPLLimitUpDataRecordManager.total_datas:
        for d in KPLLimitUpDataRecordManager.total_datas:
            if d[2] == target_block:
                code_ = d[3]
                limit_up_codes_info_set.add((code_, d[5]))
                block_codes_set.add(code_)
    # 获取涨停的顺序
    limit_up_index = -1
    limit_up_codes_info_list = list(limit_up_codes_info_set)
    limit_up_codes_info_list.sort(key=lambda x: x[1])
    for i in range(0, len(limit_up_codes_info_list)):
        if limit_up_codes_info_list[i][0] == code:
            limit_up_index = i
    if limit_up_index < 0:
        limit_up_index = len(limit_up_codes_info_list)
    # 涨停代码集合
    limit_up_codes_set = set([k[0] for k in limit_up_codes_info_list])
    limit_up_codes_set.discard(code)
    block_codes_set.discard(code)
    limit_up_codes_count = len(block_codes_set)
    # 获取炸板数据
    open_limit_up_datas = __kplDataManager.get_data(kpl_util.KPLDataType.OPEN_LIMIT_UP)
    break_codes = set()
    re_limit_codes = set()
    # 炸板:
    # (代码,名称,涨幅,板块,实际流通)
    for data in open_limit_up_datas:
        blocks = set(data[3].split("、"))
        if target_block not in blocks:
            continue
        code_ = data[0]
        break_codes.add(code_)
    # 统计回封
    for data in latest_datas:
        if data[5] != target_block:
            continue
        # 回封
        if data[2] != data[3]:
            re_limit_codes.add(data[0])
    # 排除自己
    break_codes.discard(code)
    # 排除已经涨停的代码
    break_codes = break_codes.difference(limit_up_codes_set)
    # 炸板个数
    break_size = len(break_codes)
    # 炸板回封数量
    re_limit_up_size = len(re_limit_codes)
    fresult = {
        # 目标板块信息(板块名称,板块涨幅,历史板块出现次数)
        "target_block_info": (target_block, target_block_rate, target_block_histry_count),
        # 涨停顺序
        "limit_up_index": limit_up_index,
        # 涨停代码数量
        "limit_up_codes_count": limit_up_codes_count,
        # 板块代码涨幅信息
        "block_codes_rates_info": (total_rates, total_count),
        # 炸板代码数量
        "break_size": break_size,
        # 炸板回封数量
        "re_limit_up_size": re_limit_up_size,
        # 高位版信息
        "high_block_infos": high_block_infos,
    }
    return fresult
if __name__ == "__main__":
    get_info("603133")
third_data/data_server.py
New file
@@ -0,0 +1,126 @@
import base64
import json
import logging
import socketserver
import time
from http.server import BaseHTTPRequestHandler
import cv2
import tool
from l2 import code_price_manager
from third_data import kpl_util, kpl_data_manager
from third_data.kpl_data_manager import KPLDataManager
from third_data.kpl_util import KPLDataType
import urllib.parse as urlparse
from trade import bidding_money_manager
class DataServer(BaseHTTPRequestHandler):
    ocr_temp_data = {}
    __kplDataManager = KPLDataManager()
    def do_GET(self):
        path = self.path
        self.send_response(200)
        # 发给请求客户端的响应数据
        self.send_header('Content-type', 'application/json')
        self.end_headers()
        self.wfile.write("".encode())
    def do_POST(self):
        path = self.path
        url = urlparse.urlparse(path)
        if url.path == "/upload_kpl_data":
            # 接受开盘啦数据
            params = self.__parse_request()
            result_str = self.__process_kpl_data(params)
            self.__send_response(result_str)
    def __process_kpl_data(self, data):
        type_ = data["type"]
        print("开盘啦type:",type_)
        if type_ == KPLDataType.BIDDING.value:
            result_list = kpl_util.parseDaBanData(data["data"], kpl_util.DABAN_TYPE_LIMIT_UP)
            # 竞价取前20
            if result_list:
                result_list.sort(key=lambda x: x[2])
                result_list.reverse()
                result_list = result_list[:20]
                bs = []
                for d in result_list:
                    bs.append((d[0], f"{d[2] // 10000 }万"))
                bidding_money_manager.set_bidding_money(bs[:10])
                self.__kplDataManager.save_data(type_, result_list)
        elif type_ == KPLDataType.LIMIT_UP.value:
            result_list = kpl_util.parseDaBanData(data["data"], kpl_util.DABAN_TYPE_LIMIT_UP)
            if result_list:
                # 保存涨停时间
                for d in result_list:
                    code = d[0]
                    if code.find("00") == 0 or code.find("60") == 0:
                        limit_up_time = time.strftime("%H:%M:%S", time.localtime(d[2]))
                        code_price_manager.Buy1PriceManager.set_limit_up_time(code, limit_up_time)
                self.__kplDataManager.save_data(type_, result_list)
                kpl_data_manager.KPLLimitUpDataRecordManager.save_record(tool.get_now_date_str(),result_list)
        elif type_ == KPLDataType.OPEN_LIMIT_UP.value:
            result_list = kpl_util.parseDaBanData(data["data"], kpl_util.DABAN_TYPE_OPEN_LIMIT_UP)
            if result_list:
                self.__kplDataManager.save_data(type_, result_list)
        elif type_ == KPLDataType.LIMIT_DOWN.value:
            result_list = kpl_util.parseDaBanData(data["data"], kpl_util.DABAN_TYPE_LIMIT_DOWN)
            if result_list:
                self.__kplDataManager.save_data(type_, result_list)
        elif type_ == KPLDataType.EVER_LIMIT_DOWN.value:
            result_list = kpl_util.parseDaBanData(data["data"], kpl_util.DABAN_TYPE_EVER_LIMIT_DOWN)
            if result_list:
                self.__kplDataManager.save_data(type_, result_list)
        elif type_ == KPLDataType.FENG_KOU.value:
            fdata = data["data"]
            result_list = kpl_util.parseFengKou(fdata)
            result_list.sort(key=lambda x: x[3])
            result_list.reverse()
            self.__kplDataManager.save_data(type_, result_list)
        elif type_ == KPLDataType.BEST_FENG_KOU.value:
            result_list = kpl_util.parseBestFengKou(data["data"])
            if result_list:
                self.__kplDataManager.save_data(type_, result_list)
            # 保存最强风口
        elif type_ == KPLDataType.FENG_XIANG.value:
            result_list = kpl_util.parseFengXiang(data["data"])
            # 保存风向数据
            if result_list:
                self.__kplDataManager.save_data(type_, result_list)
        elif type_ == KPLDataType.INDUSTRY_RANK.value:
            result_list = kpl_util.parseIndustryRank(data["data"])
            # 保存风向数据
            if result_list:
                self.__kplDataManager.save_data(type_, result_list)
        return json.dumps({"code": 0})
    def __send_response(self, data):
        # 发给请求客户端的响应数据
        self.send_response(200)
        self.send_header('Content-type', 'application/json')
        self.end_headers()
        self.wfile.write(data.encode())
    def __parse_request(self):
        params = {}
        datas = self.rfile.read(int(self.headers['content-length']))
        _str = str(datas, encoding="gbk")
        # print(_str)
        params = json.loads(_str)
        return params
def run(addr, port):
    handler = DataServer
    httpd = socketserver.TCPServer((addr, port), handler)
    print("HTTP server is at: http://%s:%d/" % (addr, port))
    httpd.serve_forever()
if __name__ == "__main__":
    run("0.0.0.0", 9004)
third_data/kpl_data_manager.py
New file
@@ -0,0 +1,154 @@
import json
import os
import constant
import tool
# 开盘啦历史涨停数据管理
from db import mysql_data
from l2 import code_price_manager
from third_data import kpl_util
INVALID_BLOCKS = ["一季报增长", "二季报增长", "三季报增长", "四季报增长", "业绩增长", "中报增长", "年报增长", "年报预增", "无", "次新股", "ST摘帽", "超跌", "股权转让",
                  "并购重组"]
class KPLLimitUpDataRecordManager:
    total_datas = None
    latest_datas = {}
    @classmethod
    def save_record(cls, day, records):
        # 统计代码所属板块
        code_block_dict = {}
        for data in records:
            blocks = set(data[5].split("、"))
            code = data[0]
            for b in blocks:
                if not code_block_dict.get(code):
                    code_block_dict[code] = set()
                code_block_dict[code].add(b)
        # 涨停数据记录
        mysqldb = mysql_data.Mysqldb()
        for d in records:
            # (代码, 名称, 首次涨停时间, 最近涨停时间, 几板, 涨停原因, 板块, 实际流通, 主力净额)
            code = d[0]
            _id = f"{day}_{code}_{d[5]}"
            result = mysqldb.select_one("select * from kpl_limit_up_record where _id='{}'".format(_id))
            if not result:
                mysqldb.execute(
                    f"insert into kpl_limit_up_record(_id,_day,_hot_block_name,_code,_code_name,_limit_up_time,_blocks,_latest_limit_up_time,_update_time,_create_time) values('{_id}','{day}','{d[5]}','{d[0]}','{d[1]}','{d[2]}','{d[6]}','{d[3]}',now(),now())")
            else:
                if _id in cls.latest_datas and json.dumps(cls.latest_datas.get(_id)) != json.dumps(d):
                    mysqldb.execute(
                        f"update kpl_limit_up_record set _latest_limit_up_time='{d[3]}',_limit_up_time='{d[2]}' ,_update_time=now() where _id='{_id}'")
                    cls.latest_datas[_id] = d
            cls.latest_datas[_id] = d
            # 获取原来的代码所属板块,删除之前错误的板块
            old_datas = KPLLimitUpDataRecordManager.list_by_code(code, day)
            if old_datas:
                for dd in old_datas:
                    if dd[2] not in code_block_dict[code]:
                        mysqldb.execute(f"delete from kpl_limit_up_record where _id='{dd[0]}'")
                        if dd[0] in cls.latest_datas:
                            cls.latest_datas.pop(dd[0])
        cls.total_datas = KPLLimitUpDataRecordManager.list_all(tool.get_now_date_str())
    @classmethod
    def load_total_datas(cls):
        cls.total_datas = KPLLimitUpDataRecordManager.list_all(tool.get_now_date_str())
    @staticmethod
    def list_all(day):
        mysqldb = mysql_data.Mysqldb()
        return mysqldb.select_all(f"select * from kpl_limit_up_record where _day='{day}'")
    @staticmethod
    def list_by_code(code, day):
        mysqldb = mysql_data.Mysqldb()
        return mysqldb.select_all(f"select * from kpl_limit_up_record 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 kpl_limit_up_record where _hot_block_name='{block_name}' and _day='{day}'")
    @staticmethod
    def list_blocks_with_day(days):
        mysqldb = mysql_data.Mysqldb()
        sql = "select _hot_block_name,_day from kpl_limit_up_record where "
        wheres = []
        for day in days:
            wheres.append(f"_day = '{day}'")
        sql += " or ".join(wheres)
        sql += " group by _hot_block_name,_day"
        results = mysqldb.select_all(sql)
        return results
    @staticmethod
    def get_latest_blocks(code):
        wheres = []
        for b in INVALID_BLOCKS:
            wheres.append(f"hb.`_hot_block_name` != '{b}'")
        wheres = " and ".join(wheres)
        sql = f"SELECT GROUP_CONCAT(_hot_block_name) FROM (SELECT hb.`_hot_block_name`,hb.`_day` FROM `kpl_limit_up_record` hb WHERE hb.`_code`='{code}' AND {wheres} ORDER BY hb.`_day` DESC LIMIT 10) a  GROUP BY a._day ORDER BY a._day DESC LIMIT 1"
        mysqldb = mysql_data.Mysqldb()
        return mysqldb.select_one(sql)
class KPLDataManager:
    __latest_datas = {}
    def __save_in_file(self, key, datas):
        name = f"{tool.get_now_date_str()}_{key}.log"
        path = f"{constant.CACHE_PATH}/{name}"
        with open(path, 'w') as f:
            f.write(json.dumps(datas))
    def __get_from_file(self, key):
        name = f"{tool.get_now_date_str()}_{key}.log"
        path = f"{constant.CACHE_PATH}/{name}"
        if not os.path.exists(path):
            return None
        with open(path, 'r') as f:
            lines = f.readlines()
            if lines:
                return json.loads(lines[0])
        return None
    def save_data(self, type, datas):
        self.__latest_datas[type] = datas
        self.__save_in_file(type, datas)
    def get_data(self, type):
        type = type.value
        if type in self.__latest_datas:
            return self.__latest_datas[type]
        result = self.__get_from_file(type)
        if result is not None:
            self.__latest_datas[type] = result
        return result
def load_history_limit_up():
    for file_name in os.listdir("D:/kpl/his"):
        if file_name.find("HisDaBanList_1.log") < 0:
            continue
        day = file_name[:10]
        with open(f"D:/kpl/his/{file_name}", 'r', encoding="utf-16") as f:
            lines = f.readlines()
            line = lines[0]
            result = json.loads(line)
            list_ = kpl_util.parseDaBanData(result, kpl_util.DABAN_TYPE_LIMIT_UP)
            KPLLimitUpDataRecordManager.save_record(day, list_)
            print(day, list_)
if __name__ == "__main__":
    load_history_limit_up()
third_data/kpl_util.py
@@ -1,3 +1,4 @@
import enum
import json
@@ -44,36 +45,129 @@
# (代码,名称,涨幅,板块,实际流通)
# (0,1,4,11,15)
TYPE_BIDDING = 8
TYPE_LIMIT_UP = 1
TYPE_OPEN_LIMIT_UP = 2
TYPE_LIMIT_DOWN = 3
TYPE_EVER_LIMIT_DOWN = 5
DABAN_TYPE_BIDDING = 8
DABAN_TYPE_LIMIT_UP = 1
DABAN_TYPE_OPEN_LIMIT_UP = 2
DABAN_TYPE_LIMIT_DOWN = 3
DABAN_TYPE_EVER_LIMIT_DOWN = 5
def __parseItemData(data, type):
    if type == TYPE_BIDDING:
class KPLDataType(enum.Enum):
    BIDDING = "biddings"
    LIMIT_UP = "limit_up"
    OPEN_LIMIT_UP = "open_limit_up"
    LIMIT_DOWN = "limit_down"
    EVER_LIMIT_DOWN = "ever_limit_down"
    FENG_KOU = "feng_kou"
    BEST_FENG_KOU = "best_feng_kou"
    FENG_XIANG = "feng_xiang"
    INDUSTRY_RANK = "industry_rank"
def __parseDaBanItemData(data, type):
    if type == DABAN_TYPE_BIDDING:
        return data[0], data[1], data[18], data[11], data[22], data[15]
    elif type == TYPE_LIMIT_UP:
    elif type == DABAN_TYPE_LIMIT_UP:
        return data[0], data[1], data[6], data[25], data[9], data[16], data[11], data[15], data[12]
    elif type == TYPE_OPEN_LIMIT_UP:
    elif type == DABAN_TYPE_OPEN_LIMIT_UP:
        return data[0], data[1], data[4], data[11], data[15]
    elif type == TYPE_LIMIT_DOWN:
    elif type == DABAN_TYPE_LIMIT_DOWN:
        return data[0], data[1], data[11], data[15]
    elif type == TYPE_EVER_LIMIT_DOWN:
    elif type == DABAN_TYPE_EVER_LIMIT_DOWN:
        return data[0], data[1], data[4], data[11], data[15]
    return None
def parseData(data, type):
    data = json.loads(data)
    if data["errcode"] != 0:
# 最强风口
# (代码,名称,强度,涨幅,热门板块,所有板块)
def __parseBestFengKouItemData(data):
    return data[0], data[1], data[2], data[4], data[12], data[10]
# 市场风口
# (代码,名称,涨幅,主力净额,风口概念)
def __parseFengKouItemData(data):
    return data[0], data[1], data[3], data[7], data[11]
# 风向标
# (代码, 名称, 现价, 涨幅, 板块, 300万大单净额, 主力净额, 自由市值)
def __parseFengXiangBiaoItemData(data):
    return data[0], data[1], data[5], data[6], data[4], data[-3], data[13], data[10]
# 行业涨幅
# (代码,名称,主力净额,涨跌幅)
def __parseIndustry_rank(data):
    return data[0], data[1], data[6], data[3]
def parseDaBanData(data, type_):
    if type(data) == str:
        data = json.loads(data)
    if int(data["errcode"]) != 0:
        raise Exception(f"解析数据出错,errcode:{data['errcode']}")
    list_ = data["list"]
    fresult_ = []
    for d in list_:
        pdata = __parseItemData(d, type)
        pdata = __parseDaBanItemData(d, type_)
        if pdata:
            fresult_ .append(pdata)
    return fresult_
            fresult_.append(pdata)
    return fresult_
def parseFengKou(data):
    if type(data) == str:
        data = json.loads(data)
    if int(data["errcode"]) != 0:
        raise Exception(f"解析数据出错,errcode:{data['errcode']}")
    list_ = data["List"]
    fresult_ = []
    for d in list_:
        pdata = __parseFengKouItemData(d)
        if pdata:
            fresult_.append(pdata)
    return fresult_
def parseBestFengKou(data):
    if type(data) == str:
        data = json.loads(data)
    if int(data["errcode"]) != 0:
        raise Exception(f"解析数据出错,errcode:{data['errcode']}")
    list_ = data["List"]
    fresult_ = []
    for d in list_:
        pdata = __parseBestFengKouItemData(d)
        if pdata:
            fresult_.append(pdata)
    return fresult_
def parseFengXiang(data):
    if type(data) == str:
        data = json.loads(data)
    if int(data["errcode"]) != 0:
        raise Exception(f"解析数据出错,errcode:{data['errcode']}")
    list_ = data["list"]
    fresult_ = []
    for d in list_:
        pdata = __parseFengXiangBiaoItemData(d)
        if pdata:
            fresult_.append(pdata)
    return fresult_
def parseIndustryRank(data):
    if type(data) == str:
        data = json.loads(data)
    if int(data["errcode"]) != 0:
        raise Exception(f"解析数据出错,errcode:{data['errcode']}")
    list_ = data["list"]
    fresult_ = []
    for d in list_:
        pdata = __parseIndustry_rank(d)
        if pdata:
            fresult_.append(pdata)
    return fresult_
trade/first_code_score_manager.py
@@ -16,8 +16,16 @@
import global_util
import gpcode_manager
import tool
from third_data import hot_block_data_process
from third_data import block_info
from trade import l2_trade_factor, deal_big_money_manager, bidding_money_manager
# 获取几板
def __get_ban_count(str_):
    for i in range(len(str_)-1, -1, -1):
        if str_[i].isnumeric():
            return int(str_[i])
    return 0
def __get_score(zyltgb, limit_price, bidding, k_form, code_nature, hot_block, volume_rate, limit_up_time,
@@ -28,7 +36,7 @@
        if zyltgb_y <= 80:
            score_list.append(max(int(round(0.5 * zyltgb_y - 10, 0)), -10))
        else:
            score_list.append(max(int(round(30 - 5 * ((zyltgb_y-80)//20), 0)), -10))
            score_list.append(max(int(round(30 - 5 * ((zyltgb_y - 80) // 20), 0)), -10))
    else:
        score_list.append(0)
@@ -114,32 +122,48 @@
    # 板块 - 代码平均涨幅
    __average_rate = round(hot_block["block_codes_rates_info"][0] / hot_block["block_codes_rates_info"][1], 2)
    if hot_block["target_block_info"][0] == "无板块":
        hot_block_score.append(5)
    else:
        hot_block_score.append(min(int(round(__average_rate * 2 - 10)), 10))
    # 板块 - 涨停只数
    if hot_block["limit_up_codes_count"] <= 1:
        hot_block_score.append(1)
    else:
        hot_block_score.append(max(12 - hot_block["limit_up_codes_count"], 2))
    # 板块 - 板块涨幅
    hot_block_score.append(min(int(round(hot_block["target_block_info"][1] * 2)), 10))
    # 板块 - 第几只涨停
    if hot_block["limit_up_index"] <= 0:
        # 无板块的板块得分只能是25
        hot_block_score.append(25)
        # 补充多余数据
        for i in range(10):
            hot_block_score.append(0)
    else:
        hot_block_score.append(max(60 - hot_block["limit_up_index"] * 5, 10))
    # 板块 - 高位板
    high_score = 0
    for high_info in hot_block["high_block_infos"]:
        c_count = int(high_info[1][-2:-1])
        high_score += min(2 * c_count - 2, 10)
    hot_block_score.append(high_score)
    # 板块 - 板块历史出现次数
    if hot_block["target_block_info"][2] <= 1:
        hot_block_score.append(10)
    else:
        hot_block_score.append(max(-3 * hot_block["target_block_info"][2] + 20, -10))
        if hot_block["target_block_info"][0] == "无板块":
            hot_block_score.append(5)
        else:
            hot_block_score.append(min(int(round(__average_rate * 2 - 10)), 10))
        # 板块 - 涨停只数
        #--先注释设置为0
        # if hot_block["limit_up_codes_count"] <= 1:
        #     hot_block_score.append(1)
        # else:
        #     hot_block_score.append(max(12 - hot_block["limit_up_codes_count"], 2))
        hot_block_score.append(0)
        # 板块 - 板块涨幅
        # hot_block_score.append(min(int(round(hot_block["target_block_info"][1] * 2)), 10))
        #--先注释设置为0
        hot_block_score.append(0)
        # 板块 - 第几只涨停
        if hot_block["limit_up_index"] <= 0:
            hot_block_score.append(0)
        else:
            hot_block_score.append(max(90 - hot_block["limit_up_index"] * 10, 0))
        # 板块 - 高位板
        high_score = 0
        for high_info in hot_block["high_block_infos"]:
            c_count = __get_ban_count(high_info[1])
            high_score += min(2 * c_count - 2, 10)
        hot_block_score.append(high_score)
        # 板块 - 板块历史出现次数
        if hot_block["target_block_info"][2] <= 1:
            hot_block_score.append(10)
        else:
            hot_block_score.append(max(-3 * hot_block["target_block_info"][2] + 20, -10))
    score_list.append(hot_block_score)
    # --------------- 板块结束-----------------
@@ -232,7 +256,7 @@
    code_nature = code_nature_analyse.CodeNatureRecordManager.get_nature(code)
    source_datas.append(code_nature)
    hot_block = hot_block_data_process.get_info(code)
    hot_block = block_info.get_info(code)
    if hot_block is None:
        hot_block = {
            # 目标板块信息(板块名称,板块涨幅,历史板块出现次数)