admin
2024-02-05 e25a0bad090c444970b48df2713f02d691666b08
看盘功能完善
14个文件已修改
1个文件已添加
560 ■■■■ 已修改文件
kp_html/kp/codes_list.html 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
kp_html/kp/css/banshuping.css 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
kp_html/kp/css/index23-05-04.css 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
kp_html/kp/index23-05-04.html 38 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
kp_html/kp/js/code_list.js 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
kp_html/kp/js/http.js 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
kp_html/kp/js/page.js 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
kp_html/kp/test.html 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
kpl/kpl_data_manager.py 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
main.py 33 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
network_delegate_manager.py 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
res/codes.txt 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
res/setting.conf 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
test/test_transaction.py 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
utils/xgb_api.py 106 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
kp_html/kp/codes_list.html
@@ -70,18 +70,24 @@
                        <thead>
                            <tr v-if="delegated_buy_code_infos.length>0">
                                <td>
                                    <div class="delegated_codes_info scroll-y">
                                    <div class="delegated_codes_info">
                                        <div v-for="(item,index) in delegated_buy_code_infos">
                                            <div>
                                                <div>{{item.code_info[0]}}</div>
                                                <div>{{item.code_info[1]}}</div>
                                            </div>
                                            <div>
                                                <div class="layui-progress" style="background-color: #BBB" :id="'progress_'+item.code_info[0]">
                                                  <div class="layui-progress-bar" lay-percent="{{item.percent+'%'}}" ></div>
                                                <div style="display: flex;justify-content: space-between;align-items: center;">
                                                    <div class="layui-progress" style="background-color: #BBB; width: 88%;" :id="'progress_'+item.code_info[0]">
                                                      <div class="layui-progress-bar" lay-percent="{{item.percent+'%'}}" ></div>
                                                    </div>
                                                    <button class="layui-btn layui-btn-xs" v-on:click="cancel_order(item.code_info[0])">撤单</button>
                                                </div>
                                                <div>
                                                    还有<span :class="{'red':item.left_count <=4}">{{item.left_count}}</span>笔,还有<span>{{item.left_money}}</span>成交到我们
                                                    还有<span :class="{'red':item.left_count <=4}">{{item.left_count}}</span>笔,还有<span>{{item.left_money}}(封单:{{item.buy1_money}})</span>成交到我们
                                                    大单成交:{{item.big_num_count}}笔/{{item.big_num_money}}
                                                </div>
                                            </div>
                                            
@@ -158,39 +164,73 @@
                                </span>
                            </td>
                        </tr>
                    </table>
                    <!-- 今日挂撤记录 -->
                    <table v-if="trade_record">
                        <caption class="table-name">今日挂撤记录</caption>
                        <thead>
                            <tr>
                                <td>是否炸板:<span v-if="trade_record.open_limit_up"> <span><img
                                                src="./images/stop_up.png">&nbsp;</span>炸板&nbsp;&nbsp;
                                        <span class="num-style ">{{trade_record.open_limit_up}}</span></span>
                                    <span v-else class="num-style ">未炸板</span>
                                </td>
                            </tr>
                        </thead>
                        <tr>
                            <td>真实下单位设置</td>
                            <td>
                                <div style="width: 100%;display: flex;justify-content: space-between;flex-wrap: wrap;"
                                    class="scroll-y">
                                    <div class="record-item" style="width: 520px; " v-for="(item,index) in trade_record.records">
                                        <div>{{item[0]}}</div> <div>【{{item[1]}}】{{item[2]}} <a href="javascript:void()"
                                                style='color:red' v-if="item[3]&&item[3].length>0"
                                                @click="show_more_records(item[3])">更多</a></div>
                                    </div>
                                <div style="padding: 3px 1px;">
                                    <button class="layui-btn layui-btn-xs layui-btn-normal" v-on:click="set_real_place_order_index">点击设置</button>
                                </div>
                            </td>
                        </tr>
                    </table>
                    <div class="layui-tab layui-tab-brief">
                      <ul class="layui-tab-title">
                        <li class="layui-this">今日挂撤记录</li>
                        <li>L2不下单原因</li>
                      </ul>
                      <div class="layui-tab-content">
                        <div class="layui-tab-item layui-show">
                            <!-- 今日挂撤记录 -->
                            <table v-if="trade_record">
                                <thead>
                                    <tr>
                                        <td>是否炸板:<span v-if="trade_record.open_limit_up"> <span><img
                                                        src="./images/stop_up.png">&nbsp;</span>炸板&nbsp;&nbsp;
                                                <span class="num-style ">{{trade_record.open_limit_up}}</span></span>
                                            <span v-else class="num-style ">未炸板</span>
                                        </td>
                                    </tr>
                                </thead>
                                <tr>
                                    <td>
                                        <div style="width: 100%;display: flex;justify-content: space-between;flex-wrap: wrap;"
                                            class="scroll-y">
                                            <div class="record-item" style="width: 520px; " v-for="(item,index) in trade_record.records">
                                                <div>{{item[0]}}</div> <div>【{{item[1]}}】{{item[2]}} <a href="javascript:void()"
                                                        style='color:red' v-if="item[3]&&item[3].length>0"
                                                        @click="show_more_records(item[3])">更多</a></div>
                                            </div>
                                        </div>
                                    </td>
                                </tr>
                            </table>
                        </div>
                        <div class="layui-tab-item">
                            <table>
                                <tr v-for="item in l2_cant_buy_reasons">
                                    <td>{{item[0]}}</td>
                                    <td>{{item[1]}}</td>
                                </tr>
                            </table>
                        </div>
                      </div>
                    </div>
                </div>
                <div id="l2" :style="{'visibility':data_type==1?'visible':'hidden'}">
                    <div class="l2-nav">
@@ -269,7 +309,7 @@
                                        <td style="width: 40px;">序号</td>
                                        <td style="width: 80px;">时间</td>
                                        <td style="width: 30px;">金额(万)</td>
                                        <td>价格</td>
                                        <td style="width: 30px;">价格</td>
                                        <td style="width: 45px;">手数</td>
                                        <td style="width: 40px;">类型</td>
                                        <td style="width: 80px;">撤单时间</td>
kp_html/kp/css/banshuping.css
@@ -553,7 +553,7 @@
.delegated_codes_info{
    max-height: 200px;
    height: auto;
}
.delegated_codes_info>div{
kp_html/kp/css/index23-05-04.css
@@ -672,6 +672,48 @@
}
.xgb_info{
    max-height: 40px;
    max-height: 150px;
    padding: 5px;
    line-height: 25px;
}
.xgb_info p{
    overflow: visible;
    overflow-wrap: break-word;
    word-wrap: break-word;
    white-space: normal;
}
.xgb_limit_up{
    width: 100%;
}
.xgb_limit_up tbody>tr{
    height: 50px;
    padding: 10px 5px;
}
.xgb_limit_up thread>tr:first-child{
    height: 20px;
}
.xgb_limit_up tr>td:nth-child(1) div{
    width: 50px;
}
.xgb_limit_up tr>td:nth-child(2) div{
    width: 400px;
    word-break: break-all;
    overflow-wrap: break-word;
}
.xgb_limit_up tr>td:nth-child(3) div{
    width: 500px;
    display: flex !important;
}
.xgb_info .label-style{
    padding: 2px 5px;
    margin: 0 0 5px 5px;
}
kp_html/kp/index23-05-04.html
@@ -18,8 +18,6 @@
    </head>
    <body>
        <div id="body">
            <div class="top">
                <span>
                    <h2 class="bold-content" style="margin-left: 18px; font-size: 20px;">{{code_name}}<span><a
@@ -29,14 +27,40 @@
                                @click="refresh">刷新</a></span>
                    </h2>
                </span>
            </div>
            <div class="xgb_info" >
                <div v-if="xgb_limit_up_reasons">
            <div class="xgb_info scroll-y" >
                <div v-if="xgb_limit_up_reasons" style="height: auto;">
                    <p>板块:<span class="label-style" v-for="item in xgb_limit_up_reasons.blocks">{{item}}</span></p>
                    <p v-if="xgb_limit_up_reasons.zylt">自由流通市值:{{xgb_limit_up_reasons.zylt}}</p>
                    
                    <table class="xgb_limit_up">
                        <thead>
                            <tr>
                                <td>板块</td>
                                <td>原因</td>
                                <td>成分股</td>
                            </tr>
                        </thead>
                        <tbody>
                            <tr v-for="item in xgb_limit_up_reasons.reasons" >
                                <td><div class="red">{{item[0]}}<div></td>
                                <td>
                                    <div >
                                        <p>{{item[1]}}</p>
                                    </div>
                                </td>
                                <td>
                                    <div style="display: flex-block;">
                                            <span class="label-style" v-for="item1 in item[2]">{{item1}} </span>
                                    </div>
                                </td>
                            </tr>
                        </tbody>
                    </table>
                    <p>解读:<span>{{xgb_limit_up_reasons.description}}</span></p>
                    
                <span class="red">{{xgb_limit_up_reasons[0]}}</span>:<span>{{xgb_limit_up_reasons[1]}}</span>
                </div>
            </div>
            
kp_html/kp/js/code_list.js
@@ -60,7 +60,8 @@
            operate_index: -1,
            // 已经委托的买代码信息
            delegated_buy_code_infos:[],
            layui_element:null
            layui_element:null,
            l2_cant_buy_reasons:[],
        },
        watch:{
            delegated_buy_code_infos:function(){
@@ -78,8 +79,10 @@
              });
            
            setInterval(function(){
                app.get_delegated_buy_code_infos();
            },1000*600*5);
                if(is_trade_time()){
                    app.get_delegated_buy_code_infos();
                }
            },1000*5);
        },
        methods: {
            change_data_type: function(type) {
@@ -302,6 +305,7 @@
                    console.log("处理出错")
                    console.log(e)
                }
                 app.get_l2_cant_buy_reasons(code);
            },
            show_more_records: function(items) {
                var str_ = ""
@@ -311,8 +315,41 @@
                });
                alert(str_);
            },
            test: function() {
            set_real_place_order_index: function() {
                // 设置真实下单位
                if(app.code){
                    layer.prompt({
                      formType: 0,
                      value: '',
                      title: '设置真实下单位-'+app.code,
                      area: ['800px', '350px'] //自定义文本域宽高
                    }, function(value, index, elem){
                        try{
                            if(isNaN(value)){
                                layer.msg("请输入数字");
                                return;
                            }else{
                                http_util.set_real_place_order_index(app.code,parseInt(value),function(res){
                                    // 获取到结果
                                    console.log(res);
                                    if(res.code!=0){
                                        layer.msg(res.msg,{icon: 5});
                                    }else{
                                        layer.msg("设置成功",{icon: 1});
                                    }
                                })
                            }
                        }catch(e){
                        }
                        layer.close(index);
                    });
                    //set_real_place_order_index
                }else{
                    layer.msg("请先加载数据");
                }
            },
            need_show:function(item){
                if(app.hidden_canceled&&(item[2][6].indexOf('买撤')>=0||(item[2][8]!=null&&item[2][8].indexOf("-")>0))){
@@ -378,8 +415,23 @@
            load_data:function(){
                if(app.origin_code){
                    app.get_score_data(app.origin_code,null,null);
                    app.get_l2_cant_buy_reasons(app.origin_code);
                }
            },
            cancel_order:function(code){
                http_util.cancel_order(code,function(res){
                    layer.msg("撤单成功");
                });
            },
            get_l2_cant_buy_reasons:function(code){
                http_util.get_l2_cant_buy_reasons(code,function(res){
                    res = JSON.parse(res);
                    if(res.code==0){
                        app.l2_cant_buy_reasons = res.data;
                    }else{
                        app.l2_cant_buy_reasons =[]
                    }
                });
            }
        }
    })
kp_html/kp/js/http.js
@@ -146,15 +146,41 @@
            }
        });
    },
    get_sign:function(data){
        var params=new Array();
        for(key in data){
               if(data[key] instanceof Object || data[key] instanceof Array){
                console.log(typeof data[key])
                params.push(key+"="+JSON.stringify(data[key]))
            }else{
                params.push(key+"="+data[key])
            }
        }
        params.sort()
        params.push("%Yeshi2014@#.")
        var params_str=""
        params.forEach(function(re){
            params_str += re+"&";
        });
        if(params_str.endsWith("&")){
            params_str = params_str.substring(0,params_str.length - 1);
        }
        console.log(params_str)
         md5Hash = crypto.createHash("md5").update(params_str).digest("hex");
         return md5Hash;
    },
    cancel_order: function(code, success) {
        var data = {
            "type": 80,
            "data": {
            type: "cancel_order",
            data: {
                "code": code
            }
        };
        pyjs.socket_request(JSON.stringify(data), function(result) {
        http_util.socket_request(JSON.stringify(data), function(result) {
            console.log("撤单结果",result)
            result = JSON.parse(result);
            if (result.code == 0) {
                success()
@@ -229,6 +255,21 @@
        var params={code:code}
        http_util.http_request("/get_xgb_limit_up_reasons", params, callback);
    },
    set_real_place_order_index:function(code, index, callback){
        data = {type:"common", data: {ctype:"set_real_place_order_index",code:code,index:index},sign:''}
        http_util.socket_request(JSON.stringify(data), function(result) {
            result = JSON.parse(result);
            callback(result);
        });
    },
    get_l2_cant_buy_reasons:function(code, callback){
        var params={code:code}
        console.log("参数",params)
        http_util.http_request("/get_l2_cant_buy_reasons", params, callback);
    }
    
    
     
kp_html/kp/js/page.js
@@ -13,7 +13,7 @@
var app;
$(function() {
    function _resize() {
        var code_info_height = 450
        var code_info_height = 440
        console.log("总高", $(window).height())
        var bottom_height = $(window).height() - code_info_height - 140;
        console.log("底部高", bottom_height)
@@ -281,16 +281,7 @@
                    open_limit_up_count: 10,
                    limit_up_codes: [
                        //(代码,名称,涨停状态(0-无状态 1-涨停 2-炸板),龙几,首板,分值,涨停时间,原因,相同原因代码数量,自由流通,之前的板块)
                        ["000333", "美的集团", 1, "龙1", "首板", "200", "10:00:00", "一季度增长", "1", "12.02亿",
                            '12亿', '',
                            ''
                        ],
                        ["000333", "美的集团", 1, "龙1", "首板", "200", "10:00:00", "一季度增长", "1", "12.02亿",
                            ''
                        ],
                        ["000333", "美的集团", 1, "龙1", "首板", "200", "10:00:00", "一季度增长", "1", "12.02亿",
                            ''
                        ]
                        ["000333", "美的集团", 1, "龙1", "首板", "200", "10:00:00", "一季度增长", "1", "12.02亿",'12亿', '','']
                    ]
                },
                //选中代码信息
@@ -366,7 +357,7 @@
                industry_data_type: 0,
                jingxuan_data_type: 0,
                // 选股宝涨停原因
                xgb_limit_up_reasons:["大金融","1、珠海国企,实控人珠海国资委,珠海金控旗下唯一控股的上市平台,参股优必选等人工智能独角兽公司; 2、公司持有华金证券1.4493%股权"],
                xgb_limit_up_reasons:null,
            },
            watch: {
                want_codes: function() {
@@ -614,6 +605,7 @@
                        res = JSON.parse(res)
                        if(res.code==0){
                            app.xgb_limit_up_reasons = res.data;
                            console.log(app.xgb_limit_up_reasons.reasons)
                        }else{
                            app.xgb_limit_up_reasons = null;
                        }
kp_html/kp/test.html
@@ -1,18 +1,13 @@
<!DOCTYPE html>
<html>
    <script src="js/http.js"></script>
    <body>
        <video src="http://www.test.cn"></video>
        <script>
            function parse_play_url() {
                var videos = document.getElementsByTagName('video');
                if (videos.length <= 0) {
                    hxhapi.onVideoUrl('', '没有获取到video标签');
                    return;
                }
                hxhapi.onVideoUrl(videos.item(0).getAttribute('src'), '');
            }
            parse_play_url();
        var sign = http_util.get_sign({type:"123123"});
        console.log(sign);
        </script>
    </body>
kpl/kpl_data_manager.py
@@ -137,7 +137,7 @@
    def run(self):
        while True:
            try:
                if not tool.is_trade_time(tool.get_now_date_str()):
                if not tool.is_trade_time(tool.get_now_time_str()):
                    continue
                result = kpl_api.getLimitUpInfoNew()
                limit_up_datas = kpl_util.parseLimitUpData(result)
main.py
@@ -1,4 +1,5 @@
import base64
import hashlib
import json
import logging
import multiprocessing
@@ -22,9 +23,9 @@
import constant
import gui_wx
from network_delegate_manager import LocalKanPanNetworkDelegate
from utils import network_util
from utils import network_util, xgb_api
import setting
from utils  import tool
from utils import tool
import win32_util
from juejin_core import JueJinApi
from kpl import kpl_util, kpl_api
@@ -46,8 +47,6 @@
        super().__init__()
        self.__webview = webview
        self.signal_request.connect(self.__request_result_callback)
    def __http_request(self, url, callback_info):
        try:
@@ -85,6 +84,26 @@
    @pyqtSlot(str, str)
    def socket_request(self, text, callback_info):
        print("socket_request", text)
        try:
            text_json = json.loads(text)
            params = []
            for k in text_json:
                if k == "sign":
                    continue
                if type(text_json[k]) == dict or type(text_json[k]) == list:
                    params.append(f"{k}={json.dumps(text_json[k], separators=(',',':'))}")
                else:
                    params.append(f"{k}={text_json[k]}")
            params.sort()
            params.append("%Yeshi2014@#.")
            params_str = "&".join(params)
            md5 = hashlib.md5()
            md5.update(params_str.encode("utf-8"))
            md5_hash = md5.hexdigest()
            text_json["sign"] = md5_hash
            text = json.dumps(text_json)
        except:
            pass
        callback_info = json.loads(callback_info)
        t1 = threading.Thread(target=lambda: self.__socket_request(text, callback_info))
        t1.setDaemon(True)
@@ -449,12 +468,8 @@
        self.messageWindow = MessageWindow()
        self.msgListWindow = MsgListWindow()
        # 开启消息监听
        t1 = threading.Thread(target=self.read_msg)
        # 后台运行
        t1.setDaemon(True)
        t1.start()
        threading.Thread(target=KPLLimitUpDataManager().run, daemon=True).start()
        threading.Thread(target=xgb_api.run, daemon=True).start()
    def closeEvent(self, event):
        event.accept()
network_delegate_manager.py
@@ -232,7 +232,9 @@
        code = ps_dict["code"]
        reasons = xgb_api.get_code_limit_up_reasons(code)
        if reasons:
            response_data = json.dumps({"code": 0, "data": ("、".join(reasons[0]), reasons[1])})
            response_data = json.dumps(
                {"code": 0, "data": {"reasons": reasons[0], "description": reasons[1], "blocks": reasons[2],
                                     "zylt": f"{reasons[3]}亿"}})
        else:
            response_data = json.dumps({"code": 1, "msg": "尚未获取到涨停原因"})
res/codes.txt
@@ -1,3 +1 @@
600228
603787
002186
603825
res/setting.conf
@@ -1,10 +1,10 @@
[config]
stay_on_top = 1
window_info = [[-1711, 194, 1280, 800], [1473, 621, 320, 195]]
xgb_window_info = [-1742, 419, 1291, 912]
xgb_window_info = [61, 277, 1527, 918]
window_watch_float_info = [146, 419, 435, 220]
window_tick_info = [-1497, 356, 1227, 661]
kp_second_window_info = [-960, 127, 678, 971]
window_tick_info = [-1487, 213, 1227, 661]
kp_second_window_info = [-594, 109, 1538, 1017]
code_attribute_window_info = [-650, 315, 291, 278]
client = hxh
float_frame_auto_focus = 1
test/test_transaction.py
New file
@@ -0,0 +1,77 @@
from utils import tool
def __get_transaction_datas():
    transaction_dict = {}
    with open("D:\\文件传输\\交易\\日志文件\\transaction.2024-01-12.log", mode="r") as f:
        lines = f.readlines()
        for line in lines:
            si = line.find("#")
            code = line[si - 6:si]
            value = line[si + 1:]
            if code not in transaction_dict:
                transaction_dict[code] = []
            transaction_dict[code].extend(eval(value))
    return transaction_dict
def __convert_time(time_str):
    time_str = str(time_str)
    if time_str.startswith("9"):
        time_str = f"0{time_str}"
    ms = "{:0<3}".format(time_str[6:])
    time_ = f"{time_str[0:2]}:{time_str[2:4]}:{time_str[4:6]}"
    return f"{time_}", int(ms)
import matplotlib.pyplot as plt
def show_data(datas):
    # 示例数据
    x = [t[0] for t in datas]  # x轴数据
    y = [t[1] for t in datas]  # x轴数据
    # 创建折线图
    plt.plot(x, y)
    # 添加标题和轴标签
    plt.title("折线图示例")
    plt.xlabel("X轴")
    plt.ylabel("Y轴")
    # 显示图形
    plt.show()
if __name__ == "__main__":
    transaction_datas_dict = __get_transaction_datas()
    for k in transaction_datas_dict:
        for d in transaction_datas_dict[k]:
            if d[2] > 10000:
                print(d)
if __name__ == "__main__1":
    code = "603663"
    transaction_datas_dict = __get_transaction_datas()
    datas = transaction_datas_dict.get(code)
    # 100ms计算一次速率
    start_time_ms = None
    total_num = 0
    show_datas=[]
    for d in datas:
        # 转为ms
        time_str, ms = __convert_time(d[3])
        time_as_ms = tool.get_time_as_second(time_str) * 1000 + ms
        if start_time_ms is None:
            start_time_ms = time_as_ms
        total_num += d[2]
        if time_as_ms - start_time_ms >= 100:
            ms = start_time_ms % 1000
            time_str = tool.time_seconds_format(start_time_ms // 1000)
            show_datas.append((f"{time_str}.{ms}",round(int(total_num / (time_as_ms - start_time_ms) * 100) * d[1]/10000, 2)))
            # print(f"{time_str}.{ms}", f"{round(int(total_num / (time_as_ms - start_time_ms) * 100) * d[1]/10000, 2)}w")
            # 结束计算
            total_num = 0
            start_time_ms = None
    show_data(show_datas)
utils/xgb_api.py
@@ -6,34 +6,104 @@
from utils import tool
def get_limit_up_codes_infos():
    url = f"https://flash-api.xuangubao.cn/api/surge_stock/stocks?date={tool.get_now_date_str('%Y%m%d')}&normal=true&uplimit=true"
    response = requests.get(url)
    print(response.text)
    return response.text
class XGBApi:
    @classmethod
    def __base_request_get(cls, url):
        response = requests.get(url)
        return response.text
    @classmethod
    def get_limit_up_codes_infos(cls):
        url = f"https://flash-api.xuangubao.cn/api/surge_stock/stocks?date={tool.get_now_date_str('%Y%m%d')}&normal=true&uplimit=true"
        result = cls.__base_request_get(url)
        result = json.loads(result)
        if result["code"] == 20000:
            items = result["data"]["items"]
            return items
        return None
    @classmethod
    def get_limit_up_reasons(cls):
        url = f"https://flash-api.xuangubao.cn/api/surge_stock/plates"
        result = cls.__base_request_get(url)
        result = json.loads(result)
        if result["code"] == 20000:
            items = result["data"]["items"]
            return items
        return None
    @classmethod
    def get_code_blocks(cls, code):
        symbol = code
        if code.find('00') or code.find('30'):
            symbol += ".SZ"
        elif code.find('60') or code.find('68'):
            symbol += ".SS"
        url = f"https://flash-api.xuangubao.cn/api/stage2/plates_by_any_stock?symbol={symbol}&fields=core_avg_pcp,plate_name"
        result = cls.__base_request_get(url)
        result = json.loads(result)
        if result["code"] == 20000:
            data = result["data"]
            return [data[k]['plate_name'] for k in data]
        return None
__limit_up_codes_infos_cache = None
__limit_up_reasons_dict_cache = {}
def run():
    global __limit_up_codes_infos_cache
    global __limit_up_reasons_dict_cache
    while True:
        try:
            results = XGBApi.get_limit_up_codes_infos()
            if results:
                __limit_up_codes_infos_cache = (results, time.time())
            results = XGBApi.get_limit_up_reasons()
            if results:
                __limit_up_reasons_dict_cache = {k["name"]: k for k in results}
        except:
            pass
        finally:
            time.sleep(3)
# 加载涨停代码
def __load_limit_up_codes():
    global __limit_up_codes_infos_cache
    global __limit_up_reasons_dict_cache
    if __limit_up_codes_infos_cache is None or time.time() - __limit_up_codes_infos_cache[1] > 10:
        items = XGBApi.get_limit_up_codes_infos()
        if items:
            __limit_up_codes_infos_cache = (items, time.time())
        items = XGBApi.get_limit_up_reasons()
        __limit_up_reasons_dict_cache = {k["name"]: k for k in items}
# 获取涨停列表的原因
def get_code_limit_up_reasons(code):
    global __limit_up_codes_infos_cache
    if __limit_up_codes_infos_cache is None or time.time() - __limit_up_codes_infos_cache[1] > 10:
        result = get_limit_up_codes_infos()
        result = json.loads(result)
        if result["code"] == 20000:
            items = result["data"]["items"]
            __limit_up_codes_infos_cache = (items, time.time())
    __load_limit_up_codes()
    if __limit_up_codes_infos_cache:
        for item in __limit_up_codes_infos_cache[0]:
        __limit_up_codes_infos = __limit_up_codes_infos_cache[0]
        for item in __limit_up_codes_infos:
            if item[0].split(".")[0] == code:
                reasons = [x["name"] for x in item[8]]
                return reasons, item[5]
                # 涨停原因:(板块,原因,['成分股名称1','成分股名称2'])
                reasons = [[x["name"], __limit_up_reasons_dict_cache.get(x["name"]).get("description") if x[
                                                                                                              "name"] in __limit_up_reasons_dict_cache else '']
                           for x in item[8]]
                for r in reasons:
                    code_names = []
                    for l in __limit_up_codes_infos:
                        if r[0] in [ll["name"] for ll in l[8]]:
                            code_names.append(l[1])
                    r.append(code_names)
                # 涨停原因
                return reasons, item[5], XGBApi.get_code_blocks(code), round(item[4] / 100000000, 2)
    return None
if __name__ == '__main__':
    print(get_code_limit_up_reasons("002641"))
    print(get_code_limit_up_reasons("002610"))
    print(XGBApi.get_limit_up_codes_infos())