Administrator
5 天以前 1c04204fcbc958a7bdef2394ff939063e56b6404
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
"""
新题材处理器
"""
import constant
from code_attribute import code_nature_analyse
from code_attribute.gpcode_manager import HumanForbiddenManager
from third_data import kpl_util, kpl_data_constant
from trade import l2_trade_util, trade_record_log_util
from trade.buy_radical.block_special_codes_manager import BlockSpecialCodesManager
from utils import tool, global_util
from utils.kpl_data_db_util import KPLLimitUpDataUtil
 
# 新题材的最少涨停个数
__MIN_LIMIT_UP_COUNT = 1
 
 
@tool.singleton
class BeforeBlocksComputer:
    """
    往日题材计算器
    """
 
    def __init__(self):
        self.__before_blocks = set()
        self.__load_data()
 
    def __load_data(self):
        # kpl_results: [( r.`_code`, r.`_day`, r.`_hot_block_name`, r.`_blocks`,  r.`_open`)]
        kpl_results = KPLLimitUpDataUtil.get_latest_block_infos()
        days = set()
        for r in kpl_results:
            # 取14个交易日之内的题材
            days.add(r[1])
        days = list(days)
        days.sort(key=lambda x: int(x.replace("-", "")), reverse=True)
        days = days[:14]
        # {"日期":{ "题材":{代码} }}
        day_block_codes_dict = {}
        for r in kpl_results:
            if r[1] not in days:
                continue
            if r[4]:
                # 不算炸板
                continue
            # 统计每一天的题材
            day = r[1]
            block = kpl_util.filter_block(r[2])
            if block in constant.KPL_INVALID_BLOCKS:
                continue
            if day not in day_block_codes_dict:
                day_block_codes_dict[day] = {}
            if block not in day_block_codes_dict[day]:
                day_block_codes_dict[day][block] = set()
            day_block_codes_dict[day][block].add(r[0])
 
        # 每一天走的板块
        day_block_dict = {}
        for day in day_block_codes_dict:
            for b in day_block_codes_dict[day]:
                if len(day_block_codes_dict[day][b]) >= 3:
                    if day not in day_block_dict:
                        day_block_dict[day] = set()
                    day_block_dict[day].add(b)
        day_block_list = [(d, day_block_dict[d]) for d in day_block_dict]
        day_block_list.sort(key=lambda x: x[0])
        # 过去59天出现的题材
        old_blocks = set()
        for d in day_block_list:
            if d[0] == days[0]:
                continue
            old_blocks |= d[1]
        self.__before_blocks |= old_blocks
 
        # 昨天出现的题材
        # if days[0] == day_block_list[-1][0]:
        #     # 昨天出现的题材
        #     yesterday_blocks = day_block_list[-1][1]
 
    def is_new_block(self, block):
        return block not in self.__before_blocks
 
    def get_old_blocks(self):
        return self.__before_blocks
 
 
def screen_new_blocks_with_limit_up_datas(limit_up_datas):
    """
    从涨停代码筛选出新题材
    @param limit_up_datas:[(代码,涨停原因)]
    @return:{"新题材":{新题材的代码}}
    """
    block_codes_dict = {}
    for d in limit_up_datas:
        b = kpl_util.filter_block(d[1])
        if b not in block_codes_dict:
            block_codes_dict[b] = set()
        block_codes_dict[b].add(d[0])
 
    blocks = set()
    for b in block_codes_dict:
        if b in constant.KPL_INVALID_BLOCKS:
            continue
        if len(block_codes_dict[b]) >= __MIN_LIMIT_UP_COUNT:
            # 涨停代码数大于2个的原因
            blocks.add(b)
    old_blocks = BeforeBlocksComputer().get_old_blocks()
    # 新题材
    new_blocks = blocks - old_blocks
    return {x: block_codes_dict[x] for x in new_blocks}
 
 
def __is_can_add_new_block(code):
    """
    是否可以添加到新板块
    @param code:
    @return:
    """
    zyltgb = global_util.zyltgb_map.get(code)
    if zyltgb and zyltgb < 10e8:
        return False
    k_format = code_nature_analyse.CodeNatureRecordManager().get_k_format_cache(code)
    if zyltgb and zyltgb >= 50e8:
        # 50亿以上的不需要形态突破
        return True
    if not k_format or not k_format[1][0]:
        return False
    return True
 
 
def process_limit_up_list(code_block_dict):
    # 删除变了的原因
    for code in code_block_dict:
        if kpl_data_constant.limit_up_code_new_block_dict.get(code, code_block_dict.get(code)) != code_block_dict.get(
                code):
            # 删除变之前的原因
            if code in kpl_data_constant.limit_up_code_new_block_dict:
                kpl_data_constant.limit_up_code_new_block_dict.pop(code)
                __sync_data_to_special_codes(code)
 
 
def process_new_block_by_limit_up_list(code, block):
    """
    根据涨停列表处理新题材
    @param code_block_dict: 代码涨停原因字典
    @param code:
    @param block:
    @return:
    """
    # 不用删除炸板代码
    if __is_can_add_new_block(code):
        if kpl_data_constant.limit_up_code_new_block_dict.get(code, "") != block:
            # 题材有变化
            kpl_data_constant.limit_up_code_new_block_dict[code] = block
            __sync_data_to_special_codes(code)
            blocks = set()
            for k in kpl_data_constant.limit_up_code_new_block_dict:
                blocks.add(kpl_data_constant.limit_up_code_new_block_dict[k])
            kpl_data_constant.new_blocks = blocks
 
 
def process_new_block_by_component_codes(block, codes, all_new_blocks):
    """
    根据成分股处理新题材
    @param block: 板块
    @param codes: 成分股
    @param all_new_blocks: 所有的新题材
    @return:
    """
    # 清除这个新题材下的代码
    for c in kpl_data_constant.limit_up_component_code_new_blocks_dict:
        if block in kpl_data_constant.limit_up_component_code_new_blocks_dict[c] and c not in codes:
            # 原来的代码中包含该板块,而当前板块的辨识度不包含该代码
            kpl_data_constant.limit_up_component_code_new_blocks_dict[c].discard(block)
 
    # 清除不是新题材的代码
    for c in kpl_data_constant.limit_up_component_code_new_blocks_dict:
        # 原来的板块
        diff = kpl_data_constant.limit_up_component_code_new_blocks_dict[c] - all_new_blocks
        if diff:
            for d in diff:
                kpl_data_constant.limit_up_component_code_new_blocks_dict[c].discard(d)
 
    # 在代码中加入新题材
    for c in codes:
        if __is_can_add_new_block(c):
            if c not in kpl_data_constant.limit_up_component_code_new_blocks_dict:
                kpl_data_constant.limit_up_component_code_new_blocks_dict[c] = set()
            kpl_data_constant.limit_up_component_code_new_blocks_dict[c].add(block)
            __sync_data_to_special_codes(c)
 
 
def __sync_data_to_special_codes(code):
    """
    同步数据到辨识度
    @param code:
    @return:
    """
    blocks = set()
    if code in kpl_data_constant.limit_up_component_code_new_blocks_dict:
        blocks |= kpl_data_constant.limit_up_component_code_new_blocks_dict[code]
    if code in kpl_data_constant.limit_up_code_new_block_dict:
        blocks.add(kpl_data_constant.limit_up_code_new_block_dict[code])
    if blocks and l2_trade_util.is_in_forbidden_trade_codes(code) and not HumanForbiddenManager().is_in_cache(code):
        # 没有人为拉黑才能移黑
        l2_trade_util.remove_from_forbidden_trade_codes(code)
        # 加想买单要从黑名单移除
        trade_record_log_util.add_common_msg(code, "新题材移黑", f"{blocks}")
    # 新板块
    if constant.TEST:
        print(code, kpl_data_constant.limit_up_code_new_block_dict.get(code),
              kpl_data_constant.limit_up_component_code_new_blocks_dict.get(code))
    BlockSpecialCodesManager().set_code_blocks_for_temp(code, blocks)
 
 
def is_can_forbidden(code):
    """
    是否可以拉黑
    @param code:
    @return:
    """
    if kpl_data_constant.has_new_block(code):
        # 有新题材
        return not __is_can_add_new_block(code)
    return True
 
 
if __name__ == "__main__":
    BeforeBlocksComputer()