1个文件已删除
5 文件已重命名
20个文件已修改
6个文件已添加
| | |
| | | import json |
| | | import os |
| | | |
| | | import tool |
| | | from utils import tool |
| | | from utils import log_util |
| | | |
| | | |
| | |
| | | import cv2 |
| | | import win32con |
| | | import win32gui |
| | | from matplotlib.animation import FuncAnimation |
| | | |
| | | import constant |
| | | import juejin_data_export |
| | | import ocr_util |
| | | import opencv_util |
| | | from utils import ocr_util |
| | | from utils import opencv_util |
| | | import setting |
| | | import socket_util |
| | | import ths_util |
| | | from utils import socket_util |
| | | from utils import ths_util |
| | | import win32_util |
| | | |
| | | # freeze_support() |
| | |
| | | |
| | | import code_data_manager |
| | | import juejin_core |
| | | import tool |
| | | from utils import tool |
| | | import requests |
| | | |
| | | from sell_processor import TickDataProcess |
| | |
| | | t1.start() |
| | | elif type_ == "juejin_tick_download": |
| | | wx.CallAfter(lambda: JueJinTickDataDownloadFrame().Show()) |
| | | |
| | | |
| | | elif type_ == "exit": |
| | | try: |
| | | jueJinProcess.terminate() |
| | | except: |
| | | pass |
| | | wx.CallAfter(lambda: sys.exit()) |
| | | |
| | | |
| | | |
| | | except Exception as e: |
| | | logging.exception(e) |
| | | |
| | |
| | | import xlwt |
| | | |
| | | import setting |
| | | import tool |
| | | from utils import tool |
| | | |
| | | |
| | | def init(context): |
| | |
| | | |
| | | def on_tick(context, tick): |
| | | print(tick) |
| | | if int(tick['created_at'].strftime("%H:%M:%S").replace(":","")) < int("092500"): |
| | | if int(tick['created_at'].strftime("%H:%M:%S").replace(":", "")) < int("092500"): |
| | | return |
| | | data = parse_tick(tick) |
| | | data = {"type": 0, "data": data} |
| | |
| | | # serv_addr='', backtest_match_mode=0, |
| | | # token=token) |
| | | subscript() |
| | | |
| | | |
| | | |
| | | |
| | | class GPCodeManager: |
| | |
| | | f.write("\n") |
| | | |
| | | |
| | | class JueJinApi: |
| | | __previous_trading_date_cache = {} |
| | | |
| | | # 获取掘金参数 |
| | | @classmethod |
| | | def getJueJinAccountInfo(cls): |
| | | strategy_id, token = setting.get_juejin_params() |
| | | return "", strategy_id, token |
| | | |
| | | @classmethod |
| | | def get_juejin_code_list_with_prefix(cls, codes): |
| | | list = [] |
| | | for d in codes: |
| | | if d[0:2] == '00': |
| | | list.append("SZSE.{}".format(d)) |
| | | elif d[0:2] == '60': |
| | | list.append("SHSE.{}".format(d)) |
| | | return list |
| | | |
| | | @classmethod |
| | | def get_gp_latest_info(cls, codes, fields=None): |
| | | if not codes: |
| | | return [] |
| | | symbols = cls.get_juejin_code_list_with_prefix(codes) |
| | | |
| | | account_id, s_id, token = cls.getJueJinAccountInfo() |
| | | gmapi.set_token(token) |
| | | data = gmapi.get_instruments(symbols=",".join(symbols), fields=fields) |
| | | return data |
| | | |
| | | @classmethod |
| | | def get_history_tick_n(cls, code, count, fields=None): |
| | | symbols = cls.get_juejin_code_list_with_prefix([code]) |
| | | |
| | | account_id, s_id, token = cls.getJueJinAccountInfo() |
| | | gmapi.set_token(token) |
| | | # 前除权 |
| | | results = gmapi.history_n(symbol=symbols[0], frequency="1d", count=count, adjust=1, fields=fields) |
| | | return results |
| | | |
| | | @classmethod |
| | | def get_gp_current_info(cls, codes, fields=''): |
| | | if not codes: |
| | | return [] |
| | | symbols = cls.get_juejin_code_list_with_prefix(codes) |
| | | |
| | | account_id, s_id, token = cls.getJueJinAccountInfo() |
| | | gmapi.set_token(token) |
| | | data = gmapi.current(symbols=",".join(symbols), fields=fields) |
| | | return data |
| | | |
| | | # 获取交易所的代码 |
| | | @classmethod |
| | | def get_exchanges_codes(cls, exchanges): |
| | | |
| | | account_id, s_id, token = cls.getJueJinAccountInfo() |
| | | gmapi.set_token(token) |
| | | return gmapi.get_instruments(exchanges=exchanges, sec_types=[1], skip_suspended=True, skip_st=True, |
| | | fields="symbol,sec_type,sec_id,sec_name,listed_date,sec_level,is_suspended,pre_close") |
| | | |
| | | @classmethod |
| | | def get_previous_trading_date(cls, date): |
| | | account_id, s_id, token = cls.getJueJinAccountInfo() |
| | | gmapi.set_token(token) |
| | | return gmapi.get_previous_trading_date("SHSE", date) |
| | | |
| | | @classmethod |
| | | def get_previous_trading_date_cache(cls, date): |
| | | if date not in cls.__previous_trading_date_cache: |
| | | pre_date = cls.get_previous_trading_date(date) |
| | | if pre_date: |
| | | cls.__previous_trading_date_cache[date] = pre_date |
| | | return cls.__previous_trading_date_cache.get(date) |
| | | |
| | | # 返回指定日期的下个交易日 |
| | | @classmethod |
| | | def get_next_trading_date(cls, date): |
| | | |
| | | account_id, s_id, token = cls.getJueJinAccountInfo() |
| | | gmapi.set_token(token) |
| | | return gmapi.get_next_trading_date("SHSE", date) |
| | | |
| | | @classmethod |
| | | def get_trading_dates(cls, start_date, end_date): |
| | | account_id, s_id, token = cls.getJueJinAccountInfo() |
| | | gmapi.set_token(token) |
| | | return gmapi.get_trading_dates("SHSE", start_date, end_date) |
| | |
| | | import xlwt |
| | | |
| | | import tool |
| | | from utils import tool |
| | | from juejin_core import GPCodeManager |
| | | |
| | | |
| | |
| | | <meta charset="utf-8"> |
| | | <title>看盘端</title> |
| | | <link rel="stylesheet" type="text/css" href="./css/banshuping.css" /> |
| | | <link rel="stylesheet" type="text/css" href="layui/css/layui.css" /> |
| | | <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script> |
| | | <script src="http://cdn.yeshitv.com/js/vue.min.js"></script> |
| | | <script src="js/vconsole.min.js"></script> |
| | |
| | | <script src="js/qwebchannel.js"></script> |
| | | <script src="js/kpl.js"></script> |
| | | <script src="js/http.js"></script> |
| | | <script src="layui/layui.js"></script> |
| | | <style> |
| | | |
| | | </style> |
| | |
| | | |
| | | |
| | | <!-- 交易参数 --> |
| | | |
| | | <table style="position: relative;" > |
| | | <caption class="table-name"> |
| | | <span> |
| | | 买入预期 |
| | | </span> |
| | | <button style="position: absolute;right: 5px;top: 16px;font-size: 14px;" class="btn" v-on:click="get_delegated_buy_code_infos">刷新</button> |
| | | </caption> |
| | | |
| | | <thead> |
| | | <tr v-if="delegated_buy_code_infos.length>0"> |
| | | <td> |
| | | <div class="delegated_codes_info scroll-y"> |
| | | <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> |
| | | <div> |
| | | 还有<span :class="{'red':item.left_count <=4}">{{item.left_count}}</span>笔,还有<span>{{item.left_money}}</span>成交到我们 |
| | | </div> |
| | | </div> |
| | | |
| | | </div> |
| | | </div> |
| | | </td> |
| | | </tr> |
| | | </thead> |
| | | |
| | | </table> |
| | | |
| | | |
| | | |
| | | <table v-if="trade_data"> |
| | | <caption class="table-name">交易参数</caption> |
| | | <caption class="table-name"><span>交易参数</span></caption> |
| | | |
| | | <tr> |
| | | <td>是否可以买入</td> |
| | | <td v-if="trade_data.can_buy_info"> |
| | |
| | | </span> |
| | | </td> |
| | | </tr> |
| | | <tr> |
| | | <td>辨识度信息</td> |
| | | <td><span v-if="trade_data.special_info"> |
| | | |
| | | <span class="num-style ">{{trade_data.special_info[1]}}</span> |
| | | |
| | | </span> |
| | | </td> |
| | | </tr> |
| | | </table> |
| | | |
| | | |
| | |
| | | } |
| | | |
| | | |
| | | .delegated_codes_info{ |
| | | max-height: 200px; |
| | | } |
| | | |
| | | .delegated_codes_info>div{ |
| | | display: flex; |
| | | margin-bottom: 10px; |
| | | align-items: center; |
| | | } |
| | | |
| | | .delegated_codes_info>div>div:first-child{ |
| | | width: 60px; |
| | | } |
| | | |
| | | .delegated_codes_info>div>div:last-child{ |
| | | position: relative; |
| | | width: 410px; |
| | | } |
| | | .delegated_codes_info .layui-progress{ |
| | | margin-bottom: 5px; |
| | | } |
| | | |
| | |
| | | .purple { |
| | | color: #ff80ff; |
| | | } |
| | | .white{ |
| | | color: #fff; |
| | | } |
| | | |
| | | .num-card-color1 { |
| | | background: #ed96f3; |
| | |
| | | |
| | | .market-container { |
| | | width: 520px; |
| | | height: 178px; |
| | | height: 175px; |
| | | word-wrap: break-word; |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | |
| | | padding-left: 10px; |
| | | box-sizing: border-box; |
| | | flex-wrap: wrap; |
| | | z-index: 100; |
| | | } |
| | | |
| | | |
| | |
| | | margin-right: 5px; |
| | | margin-bottom: 3px; |
| | | width: auto; |
| | | max-width: 150px; |
| | | max-width: 200px; |
| | | } |
| | | |
| | | .xgb_info{ |
| | | max-height: 40px; |
| | | padding: 5px; |
| | | } |
| | |
| | | </span> |
| | | |
| | | </div> |
| | | <div class="xgb_info" > |
| | | <div v-if="xgb_limit_up_reasons"> |
| | | |
| | | |
| | | |
| | | <span class="red">{{xgb_limit_up_reasons[0]}}</span>:<span>{{xgb_limit_up_reasons[1]}}</span> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 文档流 第一块 --> |
| | | <div> |
| | | <!-- 右侧板块 --> |
| | |
| | | <td><span class="bold">昨日涨停原因</span></td> |
| | | <td> |
| | | <span class="red">{{yesterday_block_info.reason}}</span> |
| | | <span :class="{'red': yesterday_block_info.reason_rate>0,'green':yesterday_block_info.reason_rate<0,'white':yesterday_block_info.reason_rate==0}">({{yesterday_block_info.reason_rate}}%)</span> |
| | | </td> |
| | | </tr> |
| | | |
| | |
| | | <td class="budinggundong"> |
| | | <div> |
| | | <span v-for="(item,i) in yesterday_block_info.data.yesterday" |
| | | class="label-style" >{{item[1]}}({{item[0]}})</span> |
| | | class="label-style" >{{item[1]}}({{item[0]}})(<span :class="{'red': item[2]>0,'green':item[2]<0,'white':item[2]==0}">{{item[2]}}%</span>) |
| | | </span> |
| | | </div> |
| | | </td> |
| | | </tr> |
| | |
| | | v-on:click="show_want_codes(item[0])"> |
| | | <span class="num-style red">{{item[0]}}({{item[1]}}&{{item[2]}})</span> |
| | | </span> |
| | | |
| | | </div> |
| | | <!-- 左侧 --> |
| | | <div style="float: left;width: 27.5%;margin-right: 0.4%;" class="scroll-y"> |
| | |
| | | <div style="display:flex;justify-content:space-between;align-items:center"> |
| | | |
| | | <div> |
| | | |
| | | <span v-if="item[2]==1"><img src="./images/limit_up.png"></span> |
| | | <span v-else-if="item[2]==2"><img src="./images/stop_up.png"></span> |
| | | <span v-else style="visibility: hidden;"><img |
| | | src="./images/stop_up.png"></span> |
| | | <span v-else-if="item[2]==2">(炸板)</span> |
| | | <span class="num-style" |
| | | :class="{'green': item[0].indexOf('00')!=0&&item[0].indexOf('60')!=0 }">{{item[1]}}</span><span |
| | | class="num-card-red" v-if="item[3]">{{item[3]}}</span><span |
| | | :class="{'green': item[0].indexOf('00')!=0&&item[0].indexOf('60')!=0 }">{{item[1]}}</span> |
| | | |
| | | <span class="num-card-red" v-if="item[3]">{{item[3]}}</span><span |
| | | class="num-card-bule" v-if="item[4]">{{item[4]}}</span><span |
| | | class="score-card-color yellow" v-if="item[5]">{{item[5]}}</span> |
| | | </div> |
| | |
| | | <!-- 弹出框 --> |
| | | <div id="want_code_dialog" style="display: none;"> |
| | | <div v-if="want_codes" class="want_code_content" |
| | | style="display: flex;width: 600px;justify-content: space-between;"> |
| | | style="display: flex;width: 676px;justify-content: space-between;"> |
| | | <div v-for="(item,i) in want_codes" class="item" |
| | | style="display: flex;width: 298px;margin-bottom: 15px;"> |
| | | style="display: flex;width: 335px;margin-bottom: 15px;" v-if="item[8]==1"> |
| | | |
| | | <div><img :style="{'visibility':item[3]==1?'visiable':'hidden'}" style="margin-right:5px;" |
| | | src="./images/stop_up.png"><span |
| | | :class="{'red': item[5],'green': item[0].indexOf('00')!=0&&item[0].indexOf('60')!=0 }">{{item[1]}}({{item[0]}})-{{item[2]}}-{{item[6]}}-{{item[7]}} |
| | | </span><span v-if="item[3]==1">(炸)</span> <span class="red" v-if="item[4]">*</span> </div> |
| | | <img v-if="item[2]==1" class="delete" src="./images/delete.png" |
| | | @click="delete_from_want_codes(i)"> |
| | | </div> |
| | | <div style="width: 100%; height: 1px;background-color: #000;margin-bottom: 5px;"></div> |
| | | <div v-for="(item,i) in want_codes" class="item" |
| | | style="display: flex;width: 335px;margin-bottom: 15px;" v-if="item[8]==0"> |
| | | |
| | | <div><img :style="{'visibility':item[3]==1?'visiable':'hidden'}" style="margin-right:5px;" |
| | | src="./images/stop_up.png"><span |
| | | :class="{'red': item[5]}">{{item[1]}}({{item[0]}})-{{item[2]}}-{{item[6]}}-{{item[7]}} |
| | | </span><span v-if="item[3]==1">(炸)</span> <span class="red" v-if="item[4]">*</span> </div> |
| | | <img v-if="item[2]==1" class="delete" src="./images/delete.png" |
| | |
| | | } |
| | | } |
| | | } |
| | | }) |
| | | |
| | | |
| | | |
| | | }); |
| | | // 获取数据 |
| | | http_util.get_delegated_buy_code_infos(function(result){ |
| | | if (result.code == 0) { |
| | | console.log("已挂买单数据:",result.data); |
| | | } |
| | | }); |
| | | }); |
| | |
| | | h_cancel_indexes: [], |
| | | buy_single_indexes: [], |
| | | l2_code_name: '', |
| | | operate_index: -1 |
| | | operate_index: -1, |
| | | // 已经委托的买代码信息 |
| | | delegated_buy_code_infos:[], |
| | | layui_element:null |
| | | }, |
| | | watch:{ |
| | | delegated_buy_code_infos:function(){ |
| | | if(app.layui_element){ |
| | | setTimeout(()=>{ |
| | | app.layui_element.render(); |
| | | }) |
| | | } |
| | | } |
| | | }, |
| | | mounted:function(){ |
| | | layui.use('element', function(){ |
| | | var element = layui.element; |
| | | app.layui_element=element; |
| | | }); |
| | | |
| | | setInterval(function(){ |
| | | app.get_delegated_buy_code_infos(); |
| | | },1000*600*5); |
| | | }, |
| | | methods: { |
| | | change_data_type: function(type) { |
| | |
| | | }); |
| | | |
| | | }, |
| | | get_delegated_buy_code_infos:function(){ |
| | | // 获取数据 |
| | | http_util.get_delegated_buy_code_infos(function(result){ |
| | | if (result.code == 0) { |
| | | console.log("已挂买单数据:",result.data); |
| | | result.data.forEach(function(e){ |
| | | if(e.total_num>0){ |
| | | e.percent = e.finish_num*100/e.total_num; |
| | | }else{ |
| | | e.percent = 0; |
| | | } |
| | | }); |
| | | app.delegated_buy_code_infos = result.data |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | |
| | | clear_cancel_mark: function() { |
| | | //清除撤单标记 |
| | | app.l_up_cancel_indexes = []; |
| | |
| | | |
| | | pyjs.http_request(path, JSON.stringify(data), JSON.stringify(["http_util.http_request_result", key])); |
| | | }, |
| | | socket_request: function(data, callback) { |
| | | key = "http_callback_" + new Date().getTime() + "_" + Math.round(Math.random() * 100000000); |
| | | http_util.request_callback[key] = callback; |
| | | pyjs.socket_request(data, JSON.stringify(["http_util.http_request_result", key])); |
| | | }, |
| | | |
| | | |
| | | get_score_data: function(code, name, callback) { |
| | |
| | | var params={code:code} |
| | | http_util.http_request("/get_kpl_block_info", params, callback); |
| | | }, |
| | | // 获取已挂买单的信息 |
| | | get_delegated_buy_code_infos:function(callback){ |
| | | data = {type:"common", data: {ctype:"get_delegated_buy_code_infos"},sign:''} |
| | | http_util.socket_request(JSON.stringify(data), function(result) { |
| | | result = JSON.parse(result); |
| | | callback(result); |
| | | }); |
| | | }, |
| | | get_xgb_limit_up_reasons:function(code,callback){ |
| | | var params={code:code} |
| | | http_util.http_request("/get_xgb_limit_up_reasons", params, callback); |
| | | }, |
| | | |
| | | |
| | | |
| | | }; |
| | |
| | | var app; |
| | | $(function() { |
| | | function _resize() { |
| | | var code_info_height = 480 |
| | | var code_info_height = 450 |
| | | console.log("总高", $(window).height()) |
| | | var bottom_height = $(window).height() - code_info_height - 140; |
| | | console.log("底部高", bottom_height) |
| | | $("#body>div:nth-child(2)>div").css("height", code_info_height).css("max-height", code_info_height); |
| | | $("#body>div:nth-child(3)").css("height", bottom_height) |
| | | $("#body>div:nth-child(3)>div:nth-child(2)").css("height", bottom_height - 10) |
| | | $("#body>div:nth-child(3)>div:nth-child(3)").css("height", bottom_height - 60) |
| | | $("#body>div:nth-child(3)>div").css("height", code_info_height).css("max-height", code_info_height); |
| | | $("#body>div:nth-child(4)").css("height", bottom_height) |
| | | $("#body>div:nth-child(4)>div:nth-child(2)").css("height", bottom_height - 10) |
| | | $("#body>div:nth-child(4)>div:nth-child(3)").css("height", bottom_height - 60) |
| | | $(".outer-container").css("height", bottom_height - 180) |
| | | } |
| | | //针对窗口高度做调整 |
| | |
| | | }, |
| | | industry_data_type: 0, |
| | | jingxuan_data_type: 0, |
| | | |
| | | // 选股宝涨停原因 |
| | | xgb_limit_up_reasons:["大金融","1、珠海国企,实控人珠海国资委,珠海金控旗下唯一控股的上市平台,参股优必选等人工智能独角兽公司; 2、公司持有华金证券1.4493%股权"], |
| | | }, |
| | | watch: { |
| | | want_codes: function() { |
| | |
| | | res = JSON.parse(res) |
| | | if (res.code == 0) { |
| | | app.first_info = res.data |
| | | if (app.choose_code.first) { |
| | | app.get_plate_info(app.choose_code.first, is_auto_refresh); |
| | | } else if (app.first_info.limit_up_codes) { |
| | | app.choose_code.first = app.first_info.limit_up_codes[0][0]; |
| | | app.get_plate_info(app.first_info.limit_up_codes[0][0], |
| | | is_auto_refresh); |
| | | } |
| | | // if (app.choose_code.first) { |
| | | // app.get_plate_info(app.choose_code.first, is_auto_refresh); |
| | | // } else if (app.first_info.limit_up_codes) { |
| | | // app.choose_code.first = app.first_info.limit_up_codes[0][0]; |
| | | // app.get_plate_info(app.first_info.limit_up_codes[0][0], |
| | | // is_auto_refresh); |
| | | // } |
| | | } |
| | | }); |
| | | }, |
| | |
| | | app.origin_code = code; |
| | | app.code = code; |
| | | app.code_name = code; |
| | | //请求板块 |
| | | http_util.get_kpl_block_info(code,function(res){ |
| | | console.log("板块请求结果:",res); |
| | | res = JSON.parse(res) |
| | | if(res.code==0){ |
| | | app.kpl_code_info = res.data; |
| | | app.first_info.limit_up_codes.forEach(function(e){ |
| | | if(e[0] == code){ |
| | | app.code_name = e[1] + " " + e[0]; |
| | | } |
| | | }); |
| | | app.get_last_trade_day_reasons(code); |
| | | http_util.get_xgb_limit_up_reasons(code,function(res){ |
| | | console.log("选股宝请求结果:",res); |
| | | res = JSON.parse(res) |
| | | if(res.code==0){ |
| | | app.xgb_limit_up_reasons = res.data; |
| | | }else{ |
| | | app.xgb_limit_up_reasons = null; |
| | | } |
| | | }); |
| | | |
| | | //请求板块 |
| | | setTimeout(function(){ |
| | | http_util.get_kpl_block_info(code,function(res){ |
| | | console.log("板块请求结果:",res); |
| | | res = JSON.parse(res) |
| | | if(res.code==0){ |
| | | app.kpl_code_info = res.data; |
| | | } |
| | | }); |
| | | app.get_last_trade_day_reasons(code); |
| | | },10); |
| | | //init_data(); |
| | | }, |
| | | show_want_codes: function(plate) { |
| | |
| | | |
| | | http_util.get_last_trade_day_reasons(code,function(res){ |
| | | res = JSON.parse(res); |
| | | console.log("板块今日表现:",res) |
| | | if(res.code == 0){ |
| | | app.yesterday_block_info = res.data; |
| | | }else{ |
| | |
| | | import schedule |
| | | import wx |
| | | |
| | | import tool |
| | | from utils import tool |
| | | import kpl_api |
| | | |
| | | |
| | |
| | | import json |
| | | import requests |
| | | |
| | | import tool |
| | | from utils import tool |
| | | |
| | | # 竞价 |
| | | from kpl import kpl_util |
| | | |
| | | DABAN_TYPE_BIDDING = 8 |
| | | # 涨停 |
| | | DABAN_TYPE_LIMIT_UP = 1 |
| | |
| | | return response.text |
| | | |
| | | |
| | | def __getLimitUpInfo(pidType, page, pageSize): |
| | | data = f"Order=0&a=DailyLimitPerformance&st={pageSize}&apiv=w35&Type=4&c=HomeDingPan&PhoneOSNew=1&DeviceID=a38adabb-99ef-3116-8bb9-6d893c846e24&VerSion=5.13.0.0&Index={(page - 1) * pageSize}&PidType={pidType}&" |
| | | result = __base_request("https://apphq.longhuvip.com/w1/api/index.php", data=data) |
| | | return result.text |
| | | |
| | | |
| | | def getLimitUpInfoNew(): |
| | | pids = [(1, "首板"), (2, "2连板"), (3, "3连板"), (4, "4连板"), (5, "")] |
| | | fresults = [] |
| | | for pid_info in pids: |
| | | results = [] |
| | | for i in range(10): |
| | | start_time = time.time() |
| | | result = __getLimitUpInfo(pid_info[0], i + 1, 20) |
| | | print("请求用时", time.time() - start_time) |
| | | result = json.loads(result) |
| | | datas = result["info"][0] |
| | | results.extend(datas) |
| | | day = result["info"][1] |
| | | if len(datas) < 20: |
| | | break |
| | | for r in results: |
| | | if not r[18] and pid_info[1]: |
| | | r[18] = pid_info[1] |
| | | # 替换掉板块名称 |
| | | for i in range(len(r)): |
| | | if type(r[i]) == str: |
| | | r[i] = kpl_util.filter_block(r[i]) |
| | | fresults.extend(results) |
| | | |
| | | return json.dumps({"errcode": 0, "list": fresults}) |
| | | |
| | | |
| | | def test_l2(): |
| | | code = "600981" |
| | | count = 0 |
New file |
| | |
| | | # 开盘啦涨停数据管理 |
| | | import json |
| | | import os |
| | | import threading |
| | | import time |
| | | |
| | | from utils import tool |
| | | from kpl import kpl_util |
| | | from kpl import kpl_api |
| | | |
| | | |
| | | class KPLLimitUpDataManager: |
| | | __instance = None |
| | | limit_up_records_dict = {} |
| | | limit_up_current_dict = {} |
| | | __limit_up_history_datas_cache = {} |
| | | __limit_up_current_datas_cache = {} |
| | | |
| | | def __new__(cls, *args, **kwargs): |
| | | if not cls.__instance: |
| | | cls.__instance = super(KPLLimitUpDataManager, cls).__new__(cls, *args, **kwargs) |
| | | cls.__load_data() |
| | | return cls.__instance |
| | | |
| | | @classmethod |
| | | def __load_data(cls): |
| | | record_apth = cls.__get_record_path() |
| | | current_path = cls.__get_current_path() |
| | | # 获取历史涨停 |
| | | if os.path.exists(record_apth): |
| | | children = os.listdir(record_apth) |
| | | for c in children: |
| | | with open(f"{record_apth}\\{c}", mode="r") as f: |
| | | line = f.readline().strip() |
| | | if line: |
| | | data = json.loads(line) |
| | | cls.limit_up_records_dict[data[0]] = data |
| | | # 获取实时涨停 |
| | | if os.path.exists(current_path): |
| | | with open(current_path, mode="r") as f: |
| | | line = f.readline().strip() |
| | | if line: |
| | | datas = json.loads(line) |
| | | for d in datas: |
| | | cls.limit_up_current_dict[d[0]] = d |
| | | |
| | | def __save_data(self, limit_up_datas): |
| | | record_path = self.__get_record_path() |
| | | current_path = self.__get_current_path() |
| | | if not os.path.exists(record_path): |
| | | os.makedirs(record_path) |
| | | for d in limit_up_datas: |
| | | code = d[0] |
| | | # 保存记录数据 |
| | | with open(f"{record_path}\\{code}.log", mode='w') as f: |
| | | f.write(json.dumps(d)) |
| | | |
| | | with open(current_path, mode='w') as f: |
| | | f.write(json.dumps(limit_up_datas)) |
| | | |
| | | def add_data(self, limit_up_datas): |
| | | temp_limit_up_dict = {} |
| | | for d in limit_up_datas: |
| | | temp_limit_up_dict[d[0]] = d |
| | | self.limit_up_records_dict[d[0]] = d |
| | | self.limit_up_current_dict = temp_limit_up_dict |
| | | # 保存文件 |
| | | threading.Thread(target=self.__save_data, args=(limit_up_datas,), daemon=True).start() |
| | | |
| | | def get_limit_up_current_datas(self): |
| | | temps = [self.limit_up_current_dict[k] for k in self.limit_up_current_dict] |
| | | temps.sort(key=lambda x: x[2], reverse=True) |
| | | return temps |
| | | |
| | | def get_limit_up_history_datas(self): |
| | | temps = [self.limit_up_records_dict[k] for k in self.limit_up_records_dict] |
| | | temps.sort(key=lambda x: x[2], reverse=True) |
| | | return temps |
| | | |
| | | # 从缓存文件获取某天的涨停数据 |
| | | def get_limit_up_current_datas_from_file(self, day): |
| | | current_path = self.__get_current_path(day) |
| | | # 获取实时涨停 |
| | | if os.path.exists(current_path): |
| | | with open(current_path, mode="r") as f: |
| | | line = f.readline().strip() |
| | | if line: |
| | | datas = json.loads(line) |
| | | return datas |
| | | return None |
| | | |
| | | # 从缓存文件获取某天的历史涨停数据 |
| | | def get_limit_up_history_datas__from_file(self, day): |
| | | record_apth = self.__get_record_path(day) |
| | | if os.path.exists(record_apth): |
| | | fdatas = [] |
| | | children = os.listdir(record_apth) |
| | | for c in children: |
| | | with open(f"{record_apth}\\{c}", mode="r") as f: |
| | | line = f.readline().strip() |
| | | if line: |
| | | data = json.loads(line) |
| | | fdatas.append(data) |
| | | return fdatas |
| | | return None |
| | | |
| | | def get_limit_up_history_datas_cache(self, day): |
| | | if day not in self.__limit_up_history_datas_cache: |
| | | results = self.get_limit_up_history_datas__from_file(day) |
| | | if results: |
| | | self.__limit_up_history_datas_cache[day] = results |
| | | return self.__limit_up_history_datas_cache.get(day) |
| | | |
| | | def get_limit_up_current_datas_cache(self, day): |
| | | if day not in self.__limit_up_current_datas_cache: |
| | | results = self.get_limit_up_current_datas_from_file(day) |
| | | if results: |
| | | self.__limit_up_current_datas_cache[day] = results |
| | | return self.__limit_up_current_datas_cache.get(day) |
| | | |
| | | @classmethod |
| | | def __get_record_path(cls, day=None): |
| | | base_path = cls.__get_base_path(day) |
| | | return f"{base_path}\\record" |
| | | |
| | | @classmethod |
| | | def __get_current_path(cls, day=None): |
| | | base_path = cls.__get_base_path(day) |
| | | return f"{base_path}\\limit_up.log" |
| | | |
| | | @classmethod |
| | | def __get_base_path(cls, day=None): |
| | | if not day: |
| | | day = tool.get_now_date_str() |
| | | return f"{os.getcwd()}\\datas\\{day}" |
| | | |
| | | def run(self): |
| | | while True: |
| | | try: |
| | | if not tool.is_trade_time(tool.get_now_date_str()): |
| | | continue |
| | | result = kpl_api.getLimitUpInfoNew() |
| | | limit_up_datas = kpl_util.parseLimitUpData(result) |
| | | KPLLimitUpDataManager().add_data(limit_up_datas) |
| | | except: |
| | | pass |
| | | finally: |
| | | time.sleep(3) |
| | | |
| | | |
| | | if __name__ == '__main__': |
| | | print(KPLLimitUpDataManager().get_limit_up_current_datas()) |
| | | print(KPLLimitUpDataManager().get_limit_up_history_datas()) |
| | | input() |
New file |
| | |
| | | import json |
| | | |
| | | |
| | | def __parseLimitUpItemData(data): |
| | | # (代码, 名称, 首次涨停时间, 最近涨停时间, 几板, 涨停原因, 板块, 实际流通, 主力净额, 涨停原因代码, 涨停原因代码数量) |
| | | return data[0], data[1], data[4], data[4], data[18], data[5], data[12], data[13], data[8], data[19], data[20] |
| | | |
| | | |
| | | def parseLimitUpData(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 = __parseLimitUpItemData(d) |
| | | if pdata: |
| | | fresult_.append(pdata) |
| | | return fresult_ |
| | | |
| | | |
| | | def parseMarketIndustry(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_: |
| | | # (代码,名称,涨幅,主力净额) |
| | | fresult_.append((d[0], d[1], d[3], d[6])) |
| | | return fresult_ |
| | | |
| | | |
| | | def parseMarketJingXuan(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_: |
| | | # (代码,名称,强度,主力净额) |
| | | fresult_.append((d[0], d[1], d[2], d[6])) |
| | | return fresult_ |
| | | |
| | | |
| | | def filter_block(block): |
| | | if not block: |
| | | return block |
| | | return block.replace("概念", "") |
| | |
| | | import datetime |
| | | import decimal |
| | | import time |
| | | from threading import Thread |
| | | |
| | | |
| | |
| | | return datetime.datetime.now().strftime("%Y-%m-%d") |
| | | |
| | | |
| | | def money_desc(money): |
| | | if abs(money) > 100000000: |
| | | return f"{round(money / 100000000, 2)}亿" |
| | | else: |
| | | return f"{round(money / 10000, 2)}万" |
| | | |
| | | |
| | | def time_format(timestamp): |
| | | if timestamp: |
| | | return time.strftime("%H:%M:%S", time.localtime(int(timestamp))) |
| | | return "" |
| | | |
| | | if __name__ == "__main__": |
| | | print(trade_time_sub("13:00:00", "11:30:00")) |
| | | print(trade_time_sub("13:00:00", "11:29:00")) |
| | |
| | | import time |
| | | from multiprocessing import freeze_support |
| | | import sys |
| | | from urllib.parse import urlparse, parse_qs |
| | | |
| | | import torch |
| | | import win32gui |
| | | from PyQt5.QtGui import QFont, QPalette, QColor, QTextOption |
| | |
| | | |
| | | import constant |
| | | import gui_wx |
| | | import network_util |
| | | from network_delegate_manager import LocalKanPanNetworkDelegate |
| | | from utils import network_util |
| | | import setting |
| | | import tool |
| | | from utils import tool |
| | | import win32_util |
| | | from juejin_core import JueJinApi |
| | | from kpl import kpl_util, kpl_api |
| | | from kpl.kpl_data_manager import KPLLimitUpDataManager |
| | | |
| | | freeze_support() |
| | | |
| | |
| | | self.__webview = webview |
| | | self.signal_request.connect(self.__request_result_callback) |
| | | |
| | | |
| | | |
| | | def __http_request(self, url, callback_info): |
| | | try: |
| | | result = network_util.http_get(url) |
| | | # 代理请求结果 |
| | | result, need_delegate = LocalKanPanNetworkDelegate.http_delegate_request(url) |
| | | if not need_delegate: |
| | | result = network_util.http_get(url) |
| | | print("请求结果:", result) |
| | | self.signal_request.emit(callback_info[0], callback_info[1], result) |
| | | return result |
| | | except Exception as e: |
| | | logging.exception(e) |
| | | |
| | | def __socket_request(self, text, callback_info): |
| | | try: |
| | | result = network_util.socket_request(text) |
| | | print("请求结果:", result) |
| | | self.signal_request.emit(callback_info[0], callback_info[1], result) |
| | | return result |
| | |
| | | t1.setDaemon(True) |
| | | t1.start() |
| | | |
| | | @pyqtSlot(str, result=str) |
| | | def socket_request(self, text): |
| | | @pyqtSlot(str, str) |
| | | def socket_request(self, text, callback_info): |
| | | print("socket_request", text) |
| | | return network_util.socket_request(json.loads(text)) |
| | | callback_info = json.loads(callback_info) |
| | | t1 = threading.Thread(target=lambda: self.__socket_request(text, callback_info)) |
| | | t1.setDaemon(True) |
| | | t1.start() |
| | | |
| | | # 获取客户端ID |
| | | @pyqtSlot(result=str) |
| | |
| | | self.signal_update_kpl.emit(datas) |
| | | |
| | | def set_target_code(self, code): |
| | | print("set_target_code") |
| | | print("set_target_code", code) |
| | | # 测试 |
| | | self.webview.page().runJavaScript(f"app.set_target_code('{code}')") |
| | | |
| | | def closeEvent(self, event): |
| | |
| | | view_ = menubar.addMenu('&打开分时') |
| | | view_.aboutToShow.connect(__show_main_callback) |
| | | |
| | | |
| | | def __init__(self, wx_pipe): |
| | | super().__init__() |
| | | self.wx_pipe = wx_pipe |
| | |
| | | # 后台运行 |
| | | t1.setDaemon(True) |
| | | t1.start() |
| | | threading.Thread(target=KPLLimitUpDataManager().run, daemon=True).start() |
| | | |
| | | def closeEvent(self, event): |
| | | event.accept() |
New file |
| | |
| | | """ |
| | | 网络代理管理器 |
| | | """ |
| | | # 本地看盘网络代理 |
| | | import decimal |
| | | import json |
| | | import time |
| | | from urllib.parse import parse_qs, urlparse |
| | | |
| | | from juejin_core import JueJinApi |
| | | from kpl import kpl_util, kpl_api |
| | | from kpl.kpl_data_manager import KPLLimitUpDataManager |
| | | from utils import tool, xgb_api |
| | | |
| | | |
| | | class LocalKanPanNetworkDelegate: |
| | | # 保存代码涨幅 |
| | | __code_limit_rate_dict = {} |
| | | |
| | | # HTTP代理请求 |
| | | @classmethod |
| | | def http_delegate_request(cls, url): |
| | | if url.startswith("/kpl/get_limit_up_list"): |
| | | return cls.__get_limit_up_list(url) |
| | | |
| | | elif url.startswith("/kpl/get_market_data"): |
| | | return cls.__get_market_data(url) |
| | | |
| | | elif url.startswith("/get_last_trade_day_reasons"): |
| | | return cls.__get_last_trade_day_reasons(url) |
| | | |
| | | elif url.startswith("/get_xgb_limit_up_reasons"): |
| | | return cls.__get_xgb_limit_up_reasons(url) |
| | | return None, False |
| | | |
| | | @classmethod |
| | | def __get_limit_up_list(cls, url): |
| | | # (代码, 名称, 首次涨停时间, 最近涨停时间, 几板, 涨停原因, 板块, 实际流通, 主力净额, 涨停原因代码, 涨停原因代码数量) |
| | | records = KPLLimitUpDataManager().get_limit_up_history_datas() |
| | | currents = KPLLimitUpDataManager().get_limit_up_current_datas() |
| | | current_codes = [d[0] for d in currents] |
| | | fresult = [] |
| | | # 计算涨停时间排序 |
| | | record_reason_dict = {} |
| | | current_reason_dict = {} |
| | | for r in records: |
| | | if r[5] not in record_reason_dict: |
| | | record_reason_dict[r[5]] = [] |
| | | record_reason_dict[r[5]].append(r) |
| | | for r in currents: |
| | | if r[5] not in current_reason_dict: |
| | | current_reason_dict[r[5]] = [] |
| | | current_reason_dict[r[5]].append(r) |
| | | |
| | | for k in record_reason_dict: |
| | | record_reason_dict[k].sort(key=lambda x: x[2]) |
| | | |
| | | for r in records: |
| | | if r[0] in current_codes: |
| | | limit_up_state = 1 |
| | | else: |
| | | limit_up_state = 2 |
| | | rank = 0 |
| | | for i in range(len(record_reason_dict[r[5]])): |
| | | if record_reason_dict[r[5]][i][0] == r[0]: |
| | | rank = i |
| | | # (代码, 名称, 涨停状态(0 - 无状态 1-涨停 2-炸板), 龙几, 首板, 分值, 涨停时间, 原因, 相同原因代码数量, 自由流通, 涨停原因是否变化,涨停原因的流入净额,下单简介) |
| | | fresult.append((r[0], r[1], limit_up_state, f"龙{rank + 1}", r[4], 0, |
| | | tool.time_format(int(r[2])), r[5], r[10], tool.money_desc(r[7]), |
| | | '', '', '')) |
| | | |
| | | # (板块名称,涨停代码数量,炸板数量,涨停时间) |
| | | limit_up_reason_statistic_info = [(k, len(record_reason_dict[k]), len(record_reason_dict[k]) - len( |
| | | current_reason_dict.get(k) if k in current_reason_dict else []), |
| | | record_reason_dict[k][0][5]) for k in record_reason_dict] |
| | | limit_up_reason_statistic_info.sort(key=lambda x: x[1] - x[2]) |
| | | limit_up_reason_statistic_info.reverse() |
| | | result = json.dumps({"code": 0, "data": {"limit_up_count": len(currents), |
| | | "open_limit_up_count": len(records) - len(currents), |
| | | "limit_up_reason_statistic": limit_up_reason_statistic_info, |
| | | "limit_up_codes": fresult}}) |
| | | return result, True |
| | | |
| | | @classmethod |
| | | def __get_market_data(cls, url): |
| | | ps_dict = dict([(k, v[0]) for k, v in parse_qs(urlparse(url).query).items()]) |
| | | type_ = int(ps_dict['type']) |
| | | result = [] |
| | | if type_ == 0: |
| | | # 行业,主力净额倒序 |
| | | result = kpl_api.getMarketIndustryRealRankingInfo(True) |
| | | result = kpl_util.parseMarketIndustry(result) |
| | | elif type_ == 1: |
| | | # 行业,主力净额顺序 |
| | | result = kpl_api.getMarketIndustryRealRankingInfo(False) |
| | | result = kpl_util.parseMarketIndustry(result) |
| | | elif type_ == 2: |
| | | # 精选,主力净额倒序 |
| | | result = kpl_api.getMarketJingXuanRealRankingInfo(True) |
| | | result = kpl_util.parseMarketJingXuan(result) |
| | | elif type_ == 3: |
| | | # 精选,主力净额顺序 |
| | | result = kpl_api.getMarketJingXuanRealRankingInfo(False) |
| | | result = kpl_util.parseMarketJingXuan(result) |
| | | fresult = [] |
| | | forbidden_plates = [] |
| | | for d in result: |
| | | d = list(d) |
| | | d.append(1 if d[1] in forbidden_plates else 0) |
| | | fresult.append(d) |
| | | response_data = json.dumps({"code": 0, "data": fresult}) |
| | | return response_data, True |
| | | |
| | | @classmethod |
| | | def get_codes_limit_rate(cls, codes): |
| | | return cls.__get_codes_limit_rate(codes) |
| | | |
| | | # 获取昨日收盘价 |
| | | __pre_close_cache = {} |
| | | |
| | | @classmethod |
| | | def __get_codes_limit_rate(cls, codes): |
| | | latest_info_codes = set() |
| | | for code in codes: |
| | | if code not in cls.__pre_close_cache: |
| | | latest_info_codes.add(code) |
| | | if latest_info_codes: |
| | | datas = JueJinApi.get_gp_latest_info(latest_info_codes, fields="sec_id,pre_close") |
| | | for data in datas: |
| | | code = data["sec_id"] |
| | | pre_close = data['pre_close'] |
| | | cls.__pre_close_cache[code] = pre_close |
| | | |
| | | current_info = JueJinApi.get_gp_current_info(codes, fields="symbol,price") |
| | | now_prices = [(c["symbol"].split(".")[1], c["price"]) for c in current_info] |
| | | f_results = [] |
| | | for data in now_prices: |
| | | code = data[0] |
| | | price = data[1] |
| | | pre_price = float(cls.__pre_close_cache.get(code)) |
| | | rate = round((price - pre_price) * 100 / pre_price, 2) |
| | | f_results.append((code, rate)) |
| | | f_results.sort(key=lambda tup: tup[1]) |
| | | f_results.reverse() |
| | | return f_results |
| | | |
| | | @classmethod |
| | | def __get_limit_rate_list(cls, codes): |
| | | if not codes: |
| | | return [] |
| | | need_request_codes = set() |
| | | if tool.trade_time_sub(tool.get_now_time_str(), "09:30:00") < 0: |
| | | need_request_codes |= set(codes) |
| | | else: |
| | | now_time = time.time() |
| | | for c in codes: |
| | | if c not in cls.__code_limit_rate_dict: |
| | | need_request_codes.add(c) |
| | | elif now_time - cls.__code_limit_rate_dict[c][1] > 60: |
| | | need_request_codes.add(c) |
| | | if need_request_codes: |
| | | _limit_rate_list = cls.__get_codes_limit_rate(list(need_request_codes)) |
| | | for d in _limit_rate_list: |
| | | cls.__code_limit_rate_dict[d[0]] = (d[1], time.time()) |
| | | return [(c_, cls.__code_limit_rate_dict[c_][0]) for c_ in codes] |
| | | |
| | | @classmethod |
| | | def __get_last_trade_day_reasons(cls, url): |
| | | # 获取 昨日涨停数据 |
| | | ps_dict = dict([(k, v[0]) for k, v in parse_qs(urlparse(url).query).items()]) |
| | | code = ps_dict["code"] |
| | | # 获取昨日涨停数据 |
| | | day = JueJinApi.get_previous_trading_date_cache(tool.get_now_date_str()) |
| | | # (代码, 名称, 首次涨停时间, 最近涨停时间, 几板, 涨停原因, 板块, 实际流通, 主力净额, 涨停原因代码, 涨停原因代码数量) |
| | | limit_up_records = KPLLimitUpDataManager().get_limit_up_history_datas_cache(day) |
| | | if not limit_up_records: |
| | | limit_up_records = [] |
| | | reasons = [] |
| | | for d in limit_up_records: |
| | | if d[0] == code: |
| | | reasons.append(d) |
| | | # 获取代码的原因 |
| | | if reasons: |
| | | reasons = list(reasons) |
| | | reasons.sort(key=lambda x: x[9]) |
| | | reason = reasons[-1][5] |
| | | # 获取涨停数据 |
| | | datas = KPLLimitUpDataManager().get_limit_up_current_datas_cache(day) |
| | | # (代码,名称,首次涨停时间,最近涨停时间,几板,涨停原因,板块,实际流通,主力净额,涨停原因代码,涨停原因代码数量) |
| | | yesterday_result_list = [] |
| | | percent_rate = 0 |
| | | if datas: |
| | | yesterday_codes = set() |
| | | for d in datas: |
| | | if d[5] == reason: |
| | | yesterday_codes.add(d[0]) |
| | | # 获取涨幅 |
| | | limit_rate_list = cls.__get_limit_rate_list(yesterday_codes) |
| | | limit_rate_dict = {} |
| | | if limit_rate_list: |
| | | total_rate = 0 |
| | | for d in limit_rate_list: |
| | | limit_rate_dict[d[0]] = d[1] |
| | | total_rate += d[1] |
| | | percent_rate = round(total_rate / len(limit_rate_list), 2) |
| | | |
| | | for d in datas: |
| | | if d[5] == reason: |
| | | yesterday_codes.add(d[0]) |
| | | if d[0] != code: |
| | | # (代码,名称, 涨幅) |
| | | yesterday_result_list.append((d[0], d[1], limit_rate_dict.get(d[0]))) |
| | | |
| | | current_limit_up_list = KPLLimitUpDataManager().get_limit_up_current_datas() |
| | | current_result_list = [] |
| | | if current_limit_up_list: |
| | | for c in current_limit_up_list: |
| | | if c[5] == reason and c[0] != code: |
| | | current_result_list.append((c[0], c[1])) |
| | | response_data = json.dumps({"code": 0, "data": {"reason": reason, "reason_rate": percent_rate, |
| | | "data": {"yesterday": yesterday_result_list, |
| | | "current": current_result_list}}}) |
| | | else: |
| | | response_data = json.dumps({"code": 1, "msg": "昨日未涨停"}) |
| | | |
| | | return response_data, True |
| | | |
| | | @classmethod |
| | | def __get_xgb_limit_up_reasons(cls, url): |
| | | # 获取 昨日涨停数据 |
| | | ps_dict = dict([(k, v[0]) for k, v in parse_qs(urlparse(url).query).items()]) |
| | | 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])}) |
| | | else: |
| | | response_data = json.dumps({"code": 1, "msg": "尚未获取到涨停原因"}) |
| | | |
| | | return response_data, True |
| | | |
| | | |
| | | if __name__ == "__main__": |
| | | codes = ["002523", "603095"] |
| | | datas = LocalKanPanNetworkDelegate.get_codes_limit_rate(codes) |
| | | datas = LocalKanPanNetworkDelegate.get_codes_limit_rate(codes) |
| | | print(datas) |
| | |
| | | 002445 |
| | | 600228 |
| | | 603787 |
| | | 002186 |
| | |
| | | [config] |
| | | stay_on_top = 1 |
| | | window_info = [[-1711, 194, 1280, 800], [1473, 621, 320, 195]] |
| | | xgb_window_info = [60, 80, 1115, 858] |
| | | xgb_window_info = [-1742, 419, 1291, 912] |
| | | window_watch_float_info = [146, 419, 435, 220] |
| | | window_tick_info = [-1371, 218, 1227, 661] |
| | | kp_second_window_info = [397, 140, 721, 843] |
| | | window_tick_info = [-1497, 356, 1227, 661] |
| | | kp_second_window_info = [-960, 127, 678, 971] |
| | | code_attribute_window_info = [-650, 315, 291, 278] |
| | | client = hxh |
| | | float_frame_auto_focus = 1 |
| | |
| | | import juejin_core |
| | | import tool |
| | | from utils import tool |
| | | |
| | | |
| | | class TickDataProcess: |
New file |
| | |
| | | import base64 |
| | | import ssl |
| | | |
| | | from cryptography.hazmat.primitives import serialization, hashes |
| | | from cryptography.hazmat.primitives.asymmetric import padding, rsa |
| | | |
| | | def decrypt_ssl(): |
| | | context = ssl.SSLContext(ssl.PROTOCOL_TLS) |
| | | |
| | | # 加载证书和密钥 |
| | | context.load_cert_chain(certfile='D:/文件传输/交易/接口解析/com.aiyu.kaipanla.cert.pem', keyfile='D:/文件传输/交易/接口解析/PrivateKey1.pem') |
| | | # 使用 SSL 上下文创建一个解密器对象 |
| | | decrypter = context.decryptor() |
| | | |
| | | # 加密的文本字符串 |
| | | encrypted_data = b'\xb0\x1d\x96\x82\xcd\x7f\xf2Q' |
| | | |
| | | # 解码加密的文本 |
| | | decrypted_data = decrypter.update(encrypted_data) + decrypter.finalize() |
| | | |
| | | # 打印解码后的文本 |
| | | print(decrypted_data) |
| | | |
| | | if __name__ == '__main__': |
| | | k =[1,0] |
| | | is_s = True if k and k[1] else False |
| | | print(is_s) |
| | | |
| | | if __name__ == '__main__1': |
| | | with open("D:\\文件传输\\交易\\接口解析\\PrivateKey1.pem", "rb") as key_file: |
| | | private_key = serialization.load_pem_private_key( |
| | | key_file.read(), |
| | | password=None, |
| | | ) |
| | | print(private_key) |
| | | with open("D:\\文件传输\\交易\\接口解析\\PublicKey.pem", "rb") as key_file: |
| | | public_key = serialization.load_pem_public_key( |
| | | key_file.read(), |
| | | ) |
| | | print(public_key) |
| | | |
| | | content = b"" |
| | | for i in range(10): |
| | | content += b"Hello World 123123" |
| | | |
| | | encrypted = public_key.encrypt(content, padding.OAEP( |
| | | mgf=padding.MGF1(algorithm=hashes.SHA256()), |
| | | algorithm=hashes.SHA256(), |
| | | label=None |
| | | )) |
| | | |
| | | print(encrypted) |
| | | decrypted = private_key.decrypt(encrypted, padding.OAEP( |
| | | mgf=padding.MGF1(algorithm=hashes.SHA256()), |
| | | algorithm=hashes.SHA256(), |
| | | label=None |
| | | )) |
| | | |
| | | print(decrypted) |
| | |
| | | |
| | | from loguru import logger |
| | | |
| | | import tool |
| | | from utils import tool |
| | | |
| | | |
| | | class MyLogger: |
File was renamed from network_util.py |
| | |
| | | import requests |
| | | |
| | | import constant |
| | | from utils import socket_util |
| | | |
| | | SOCKET_PORT = 9001 |
| | | SOCKET_PORT = 11008 |
| | | # B类 |
| | | HTTP_PORT = 9004 |
| | | |
| | | |
| | | # A类 |
| | | # HTTP_PORT = 9005 |
| | | |
| | |
| | | client = socket.socket() # 生成socket,连接server |
| | | ip_port = (constant.SERVER_HOST, SOCKET_PORT) # server地址和端口号(最好是10000以后) |
| | | client.connect(ip_port) |
| | | client.send(json.dumps(data).encode("utf-8")) |
| | | if type(data) != str: |
| | | client.send(socket_util.load_header(json.dumps(data).encode("utf-8"))) |
| | | else: |
| | | client.send(socket_util.load_header(data.encode("utf-8"))) |
| | | # 读取内容 |
| | | result = client.recv(102400) |
| | | result, header = socket_util.recv_data(client) |
| | | print("socket_request结果:", result) |
| | | client.close() |
| | | return result.decode("gbk") |
| | | return result |
| | | |
| | | |
| | | def http_get(path): |
New file |
| | |
| | | """ |
| | | socket工具类 |
| | | """ |
| | | |
| | | # 添加数据头 |
| | | import base64 |
| | | import hashlib |
| | | import json |
| | | import socket |
| | | import ssl |
| | | |
| | | import rsa |
| | | |
| | | |
| | | def md5_encrypt(value): |
| | | md5 = hashlib.md5() |
| | | md5.update(value.encode('utf-8')) |
| | | return md5.hexdigest() |
| | | |
| | | |
| | | def create_socket(addr, port): |
| | | client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 生成socket,连接server |
| | | client.connect((addr, port)) |
| | | return client |
| | | |
| | | |
| | | def load_header(data_bytes): |
| | | slen = '##%08d' % len(data_bytes) |
| | | return slen.encode("utf-8") + data_bytes |
| | | |
| | | |
| | | # 接收数据,去除头 |
| | | def recv_data(sk): |
| | | data = "" |
| | | header_size = 10 |
| | | buf = sk.recv(1024) |
| | | header_str = buf[:header_size] |
| | | if buf: |
| | | buf = buf.decode('utf-8') |
| | | if buf.startswith("##"): |
| | | content_length = int(buf[2:10]) |
| | | received_size = 0 |
| | | # 加上读取头的数据 |
| | | received_size += len(buf[header_size:]) |
| | | data += buf[header_size:] |
| | | while not received_size == content_length: |
| | | r_data = sk.recv(10240) |
| | | received_size += len(r_data) |
| | | data += r_data.decode('utf-8') |
| | | else: |
| | | data = sk.recv(1024 * 1024) |
| | | data = buf + data.decode('utf-8') |
| | | return data, header_str |
| | | |
| | | |
| | | # 客户端参数加密 |
| | | def encryp_client_params_sign(dataJson): |
| | | if type(dataJson) != dict: |
| | | return dataJson |
| | | str_list = [] |
| | | for k in dataJson: |
| | | if type(dataJson[k]) == dict: |
| | | str_list.append(f"{k}={json.dumps(dataJson[k], separators=(',', ':'))}") |
| | | else: |
| | | str_list.append(f"{k}={dataJson[k]}") |
| | | str_list.sort() |
| | | str_list.append("%Yeshi2014@#.") |
| | | dataJson["sign"] = md5_encrypt("&".join(str_list)) |
| | | return dataJson |
| | | |
| | | |
| | | # 客户端密码加密验证 |
| | | def is_client_params_sign_right(dataJson): |
| | | if type(dataJson) != dict: |
| | | return False |
| | | sign = dataJson["sign"] |
| | | dataJson.pop("sign") |
| | | str_list = [] |
| | | for k in dataJson: |
| | | if type(dataJson[k]) == dict: |
| | | str_list.append(f"{k}={json.dumps(dataJson[k], separators=(',', ':'))}") |
| | | else: |
| | | str_list.append(f"{k}={dataJson[k]}") |
| | | str_list.sort() |
| | | str_list.append("%Yeshi2014@#.") |
| | | new_sign = md5_encrypt("&".join(str_list)) |
| | | # print("加密前字符串","&".join(str_list)) |
| | | if sign == new_sign: |
| | | return True |
| | | else: |
| | | return False |
| | | |
| | | |
| | | # 端口是否被占用 |
| | | def is_port_bind(port): |
| | | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
| | | result = sock.connect_ex(('127.0.0.1', port)) |
| | | if result == 0: |
| | | return True |
| | | else: |
| | | return False |
| | | |
| | | |
| | | def test_rsa(): |
| | | def format_rsa(private_key_bytes): |
| | | private_key_bytes = private_key_bytes.replace(b"\r\n", b"").replace(b"\n", b"") |
| | | fbytes = [] |
| | | row = len(private_key_bytes) // 64 |
| | | if len(private_key_bytes) % 64 > 0: |
| | | row += 1 |
| | | |
| | | for i in range(0, row): |
| | | if i != row - 1: |
| | | fbytes.append(private_key_bytes[i * 64:(i + 1) * 64]) |
| | | else: |
| | | fbytes.append(private_key_bytes[i * 64:]) |
| | | fbs = b'-----BEGIN RSA PRIVATE KEY-----\n'+b"\n".join(fbytes)+b'\n-----END RSA PRIVATE KEY-----\n' |
| | | return fbs |
| | | |
| | | # with open("D:\\项目\\三方工具\\dubbo\\dubbo-admin\\dubbo-admin-ui\\node_modules\\public-encrypt\\test\\test_rsa_privkey.pem", mode='rb') as f: |
| | | # private_key_data = f.read() |
| | | # print(private_key_data) |
| | | |
| | | |
| | | with open("D:\\文件传输\\交易\\接口解析\\PrivateKey", mode='rb') as f: |
| | | private_key_data = f.read() |
| | | private_key_data = format_rsa(private_key_data) |
| | | |
| | | results = [] |
| | | with open("D:\\文件传输\\交易\\日志文件\\hex.txt", mode='r') as f: |
| | | lines = f.readlines() |
| | | for line in lines: |
| | | if not line: |
| | | continue |
| | | results.append(line[8:].strip()) |
| | | |
| | | hex_bytes = bytes.fromhex("".join(results)) |
| | | |
| | | print(private_key_data.decode()) |
| | | # 将私钥字符串解码为 RSA 私钥对象 |
| | | private_key = rsa.PrivateKey._load_pkcs1_der(private_key_data) |
| | | |
| | | # 将 base64 编码的字符串解码为 bytes,并进行 RSA 解密 |
| | | encrypted_data = hex_bytes |
| | | decrypted_data = rsa.decrypt( |
| | | encrypted_data, |
| | | private_key |
| | | ) |
| | | |
| | | # 将解密后的 bytes 对象转换为字符串 |
| | | decrypted_data_str = decrypted_data.decode() |
| | | print(decrypted_data_str) |
| | | |
| | | |
| | | if __name__ == "__main__": |
| | | test_rsa() |
| | | |
| | | if __name__ == "__main__1": |
| | | results = [] |
| | | with open("D:\\文件传输\\交易\\日志文件\\hex.txt", mode='r') as f: |
| | | lines = f.readlines() |
| | | for line in lines: |
| | | if not line: |
| | | continue |
| | | results.append(line[8:].strip()) |
| | | |
| | | hex_bytes = bytes.fromhex("".join(results)) |
| | | # SSL解码 |
| | | context = ssl.SSLContext(ssl.PROTOCOL_TLS) |
| | | with open("D:/文件传输/交易/接口解析/com.aiyu.kaipanla.cert.pem", mode='r') as f: |
| | | print(f.readlines()) |
| | | |
| | | context.load_cert_chain(certfile='D:/文件传输/交易/接口解析/com.aiyu.kaipanla.cert.pem') |
| | | decrypter = context.decryptor() |
| | | decrypted_data = decrypter.update(hex_bytes) + decrypter.finalize() |
| | | # 打印解码后的文本 |
| | | print(decrypted_data) |
| | | |
| | | # client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 生成socket,连接server |
| | | # client.connect(("appsockapp.longhuvip.com", 14000)) |
| | | # client.send(hex_bytes) |
| | | # print("返回数据", client.recv(10240)) |
File was renamed from tool.py |
| | |
| | | import datetime |
| | | import decimal |
| | | import time |
| | | from threading import Thread |
| | | |
| | | |
| | |
| | | # return "10:20:00" |
| | | |
| | | |
| | | def get_now_date_str(): |
| | | def get_now_date_str(format="%Y-%m-%d"): |
| | | # TODO 测试 |
| | | return datetime.datetime.now().strftime("%Y-%m-%d") |
| | | return datetime.datetime.now().strftime(format) |
| | | |
| | | |
| | | def money_desc(money): |
| | | if abs(money) > 100000000: |
| | | return f"{round(money / 100000000, 2)}亿" |
| | | else: |
| | | return f"{round(money / 10000, 2)}万" |
| | | |
| | | |
| | | def time_format(timestamp): |
| | | if timestamp: |
| | | return time.strftime("%H:%M:%S", time.localtime(int(timestamp))) |
| | | return "" |
| | | |
| | | |
| | | if __name__ == "__main__": |
New file |
| | |
| | | import json |
| | | import time |
| | | |
| | | import requests |
| | | |
| | | 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 |
| | | |
| | | |
| | | __limit_up_codes_infos_cache = None |
| | | |
| | | |
| | | # 获取涨停列表的原因 |
| | | 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()) |
| | | if __limit_up_codes_infos_cache: |
| | | for item in __limit_up_codes_infos_cache[0]: |
| | | if item[0].split(".")[0] == code: |
| | | reasons = [x["name"] for x in item[8]] |
| | | return reasons, item[5] |
| | | return None |
| | | |
| | | |
| | | if __name__ == '__main__': |
| | | print(get_code_limit_up_reasons("002641")) |
| | | print(get_code_limit_up_reasons("002610")) |