def check_single_stk_hour_idx_wx(stk_code, source='jq', debug=False): """ 打印常用指标 """ stk_df = get_k_data_JQ(stk_code, count=120, end_date=add_date_str(get_current_date_str(), 1), freq='30m') # 按升序排序 stk_df = stk_df.sort_values(by='datetime', ascending=True) """ 增加指标 'RSI5', 'RSI12', 'RSI30' 'SAR' 'slowk', 'slowd' 'upper', 'middle', 'lower' 'MOM' """ # 删除volume为空值的情况! stk_df = stk_df.loc[ stk_df.apply(lambda x: not (int(x['volume']) == 0), axis=1), :] # 计算index stk_df = add_stk_index_to_df(stk_df).tail(60) result_analysis = [] # 检查SAR sar_tail_origin = stk_df.tail(2) sar_tail = sar_tail_origin.copy() sar_tail['compare'] = sar_tail_origin.apply( lambda x: x['SAR'] - x['close'], axis=1) if sar_tail.head(1)['compare'].values[0] * sar_tail.tail( 1)['compare'].values[0] < 0: if sar_tail.tail(1)['SAR'].values[0] < sar_tail.tail( 1)['close'].values[0]: title_tmp = stk_code + ' ' + code2name( stk_code) + ' 注意 SAR 指标翻转,后续数小时可能上涨!' result_analysis.append(title_tmp) GenPic.set_background_color(bc='b_r') else: title_tmp = stk_code + ' ' + code2name( stk_code) + ' 注意 SAR 指标翻转,后续数小时可能下跌!' result_analysis.append(title_tmp) # 打印过程日志 if debug: txt_name = 'hour_index' # 打印原始数据 debug_print_txt(txt_name, stk_code, stk_df.to_string() + '\n\n') # 打印结果 debug_print_txt(txt_name, stk_code, '结果:\n' + str(result_analysis) + '\n\n') return result_analysis
def bs_judge(self): if (self.current_price - self.b_p_min > self.thh_sale) & ( (self.current_price - self.b_p_min) / self.b_p_min >= self.pcr): str_temp = "\n触发卖出网格!可以考虑卖出! \n" + self.stk_code + code2name(self.stk_code) + \ '\n当前价格:' + str(self.current_price) + \ '\n上次买入价格:' + str(self.b_p_min) + \ '\n买入网格大小:' + '%0.3f' % self.thh_buy + \ '\n卖出网格大小:' + '%0.3f' % self.thh_sale + \ '\n最小操作幅度:' + '%0.3f' % self.pcr + \ '\n上次闪动价格:' + str(self.opt_record.get_config_value('last_prompt_point'))[:4] self.bs_note(str_temp) elif (self.current_price - self.last_p < -self.thh_buy) & ( (self.current_price - self.last_p) / self.b_p_min <= -self.pcr): str_temp = "\n触发买入网格!可以考虑买入!\n" + self.stk_code + code2name(self.stk_code) + \ '\n当前价格:' + str(self.current_price) + \ '\n上次价格:' + str(self.last_p) + \ '\n买入网格大小:' + '%0.2f' % self.thh_buy + \ '\n卖出网格大小:' + '%0.2f' % self.thh_sale + \ '\n最小操作幅度:' + '%0.3f' % self.pcr + \ '\n上次闪动价格:' + str(self.opt_record.get_config_value('last_prompt_point'))[:4] self.bs_note(str_temp) else: str_ = self.stk_code + ':未触发任何警戒线!\n' self.add_msg(str_) debug_print_txt('stk_judge', self.stk_code, str_, self.debug)
def hour_analysis(pipe_master): """ 小时监测(闲置) :return: """ debug_print_txt('main_log', '', 'begin hour_analysis \n', True) debug_print_txt('hour_analysis', '', '\n' + '进入小时判断' + '\n') for stk in list( set(read_config()['buy_stk'] + read_config()['concerned_stk'] + read_config()['index_stk'])): # 阈值条件不满足,该stk直接pass if not read_opt_json(stk, opt_record_file_url)['has_flashed_flag']: pipe_master.send( (MSG_UPDATE_NUM_A, code2name(stk) + '阈值条件不满足,不进行拐点检测\n')) debug_print_txt('hour_analysis', '', '\n' + code2name(stk) + '阈值条件不满足,不进行拐点检测\n') continue hour_idx_str = check_single_stk_hour_idx_wx(stk, source='jq', debug=True) if len(hour_idx_str): for str_tmp in hour_idx_str: pipe_master.send( (NOTE_UPDATE_NUM_A, change_font_color(str_tmp))) # 打印日志 debug_print_txt('hour_analysis', '', '\n' + str(hour_idx_str)) # flash pipe_master.send((FLASH_WINDOW_NUM, None))
def fluctuate_judge(self): l_pp = self.opt_record.get_config_value('last_prompt_point') c_p = self.current_price thh_b = self.thh_buy thh_s = self.thh_sale str_ = '\n\n------------------------------------------------------------\n' \ 'last_pp:%s current_price:%s b_thh:%s s_thh:%s' % ( str(l_pp)[:4], str(c_p)[:4], str(thh_b)[:4], str(thh_s)[:4]) debug_print_txt('fluctuate_judge', self.stk_code, str_ + '\n', self.debug) # 若lpp为None,则将当前p设置为lpp,并返回 if pd.isnull(self.opt_record.get_config_value('last_prompt_point')) | \ (self.opt_record.get_config_value('last_prompt_point') == -1): self.opt_record.set_config_value('last_prompt_point', self.current_price) debug_print_txt('fluctuate_judge', self.stk_code, 'Result: Last_prompt_opint is null or -1' + '\n', self.debug) return elif (self.current_price - self.opt_record.get_config_value('last_prompt_point') > self.thh_sale) & \ (self.opt_record.get_config_value('last_prompt_point') != -1): str_temp = "当前价格距离上次提示的价格的上涨幅度超过卖出网格!\n " + self.stk_code + code2name(self.stk_code) + \ '\n当前价格:' + str(self.current_price) + \ '\n上次买入价格:' + str(self.b_p_min) + \ '\n买入网格大小:' + '%0.3f' % self.thh_buy + \ '\n卖出网格大小:' + '%0.3f' % self.thh_sale + \ '\n最小操作幅度:' + '%0.3f' % self.pcr + \ '\n上次闪动价格:' + str(self.opt_record.get_config_value('last_prompt_point'))[:4] self.add_note(str_temp) debug_print_txt('fluctuate_judge', self.stk_code, 'Result: fluctuate is triggered for sale!' + '\n', self.debug) # 设置上次闪动价格 self.opt_record.set_config_value('last_prompt_point', self.current_price) elif (self.current_price - self.opt_record.get_config_value('last_prompt_point') < -self.thh_buy) & \ (self.opt_record.get_config_value('last_prompt_point') != -1): str_temp = "当前价格距离上次提示的价格的下跌幅度超过买入网格!\n" + self.stk_code + code2name(self.stk_code) + \ '\n当前价格:' + str(self.current_price) + \ '\n上次价格:' + str(self.last_p) + \ '\n买入网格大小:' + '%0.2f' % self.thh_buy + \ '\n卖出网格大小:' + '%0.2f' % self.thh_sale + \ '\n最小操作幅度:' + '%0.3f' % self.pcr + \ '\n上次闪动价格:' + str(self.opt_record.get_config_value('last_prompt_point'))[:4] self.add_note(str_temp) debug_print_txt('fluctuate_judge', self.stk_code, 'Result: fluctuate is triggered for buy!' + '\n', self.debug) # 设置上次闪动价格 self.opt_record.set_config_value('last_prompt_point', self.current_price)
def print_k_to_pdf(c, stk_code, date): """ 将一只股票的走势图打印到pdf中的一页 :param c: :param stk_code: :param date: :return: """ """ --------------------------------- 打印小时线图片 ------------------------------------ """ c.setFont("song", 10) c.drawString(20, letter[1] - 20, stk_code + ' ' + code2name(stk_code) + ' ' + '小时走势图') c.setLineWidth(3) c.line(10, h - 24, w - 10, h - 24) # 插入小时macd图 image_file = PIL.Image.open(sea_select_pic_dir + date + '/' + 'h_' + stk_code + '.png') c.drawImage(ImageReader(image_file), x=w * 0.05, y=h * 0.65, height=0.3 * h, width=0.45 * w, preserveAspectRatio=True) # 插入小时指标图 image_file = PIL.Image.open(sea_select_pic_dir + date + '/' + 'h_idx_' + stk_code + '.png') c.drawImage(ImageReader(image_file), x=w * 0.5, y=h * 0.65, height=0.3 * h, width=0.45 * w, preserveAspectRatio=True) """ --------------------------------- 打印日线图片 ------------------------------------ """ c.setFont("song", 10) c.drawString(20, h * 0.65, stk_code + ' ' + code2name(stk_code) + ' ' + '日线走势图') c.setLineWidth(3) c.line(10, h * 0.65 - 4, w - 10, h * 0.65 - 4) # 插入日线macd图 image_file = PIL.Image.open(sea_select_pic_dir + date + '/' + 'd_' + stk_code + '.png') c.drawImage(ImageReader(image_file), x=w * 0.05, y=h * 0.35, height=0.3 * h, width=0.45 * w, preserveAspectRatio=True) # 插入日线指标图 image_file = PIL.Image.open(sea_select_pic_dir + date + '/' + 'd_idx_' + stk_code + '.png') c.drawImage(ImageReader(image_file), x=w * 0.5, y=h * 0.35, height=0.3 * h, width=0.45 * w, preserveAspectRatio=True) """ --------------------------------- 打印周月线图片 ------------------------------------ """ c.setFont("song", 10) c.drawString(20, h * 0.35, stk_code + ' ' + code2name(stk_code) + ' ' + '周/月走势图') c.setLineWidth(3) c.line(10, h * 0.35 - 4, w - 10, h * 0.35 - 4) # 插入周线图 image_file = PIL.Image.open(sea_select_pic_dir + date + '/' + 'wm_' + stk_code + '.png') c.drawImage(ImageReader(image_file), x=w * 0.05, y=h * 0.05, height=0.3 * h, width=0.45 * w, preserveAspectRatio=True) c.showPage() return c
def check_single_stk_hour_idx_sub(stk_df, stk_code, debug=False): """ 打印常用指标 """ # 按升序排序 stk_df = stk_df.sort_values(by='datetime', ascending=True) """ 增加指标 'RSI5', 'RSI12', 'RSI30' 'SAR' 'slowk', 'slowd' 'upper', 'middle', 'lower' 'MOM' """ result_analysis = [] # 检查SAR sar_tail_origin = stk_df.tail(2) sar_tail = sar_tail_origin.copy() sar_tail['compare'] = sar_tail_origin.apply( lambda x: x['SAR'] - x['close'], axis=1) if sar_tail.head(1)['compare'].values[0] * sar_tail.tail( 1)['compare'].values[0] < 0: if sar_tail.tail(1)['SAR'].values[0] < sar_tail.tail( 1)['close'].values[0]: title_tmp = stk_code + ' ' + code2name( stk_code) + ' 注意 SAR 指标翻转,后续数小时可能上涨!' result_analysis.append(title_tmp) GenPic.set_background_color(bc='b_r') else: title_tmp = stk_code + ' ' + code2name( stk_code) + ' 注意 SAR 指标翻转,后续数小时可能下跌!' result_analysis.append(title_tmp) # 打印过程日志 if debug: txt_name = 'hour_index' # 打印原始数据 debug_print_txt(txt_name, stk_code, stk_df.to_string() + '\n\n') # 打印结果 debug_print_txt(txt_name, stk_code, '结果:\n' + str(result_analysis) + '\n\n') return result_analysis
def check_stk_list_middle_level(stk_list): """ 检测一系列stk的中期水平 :param stk_list: :param threshold: :return: """ if not os.path.exists(data_dir + 'middlePeriodHourData.json'): update_middle_period_hour_data() # 读取历史小时数据 with open(data_dir + 'middlePeriodHourData.json', 'r') as f: dict = json.load(f) r = [(x, (1 - check_single_stk_middle_level(x, dict) / 100) * 100) for x in list(set(stk_list))] r_df = pd.DataFrame(data=r, columns=['code', 'level_value']) r_df['name'] = r_df.apply(lambda x: code2name(x['code']), axis=1) r_df_sort = r_df.sort_values(by='level_value', ascending=True).head(12) r_df_sort['level'] = r_df_sort.apply( lambda x: '%0.2f' % x['level_value'] + '%', axis=1) r_df_sort = r_df_sort.loc[:, ['name', 'level']].reset_index(drop=True) return r_df_sort
def __init__(self, stk_code, opt_record_, debug=False): self.opt_record = opt_record_ self.stk_code = stk_code self.debug = debug self.str_gui = { 'note': '', 'msg': '' } self.add_msg('\n\n\n------------------------------------------\n' + code2name(stk_code) + ':开始进入本周期判断!\n') self.opt_record_stk = {} self.current_price = -1 self.last_p = -1 self.b_p_min = -1 # self.money_each_opt = 5000 # self.buy_amount = math.floor((self.money_each_opt / self.current_price) / 100) * 100 self.thh_sale = 0 self.thh_buy = 0 self.has_flashed_flag = False self.pcr = 0 self.opt_record_stk = opt_record_.opt_record_stk
def cal_reseau(self, rsv): """ 调节 buy 和 sale 的threshold """ """ 实时计算网格大小 """ reseau = Reseau() earn_threshold_unit = reseau.get_single_stk_reseau(self.stk_code) stk_name = code2name(self.stk_code) rsv.msg = '' rsv_stk = rsv.get_stk_rsv(self.stk_code) if len(rsv.msg) > 0: self.add_msg(rsv.msg + '\n') self.thh_sale = earn_threshold_unit * 2 * rsv_stk self.thh_buy = earn_threshold_unit * 2 * (1 - rsv_stk) self.buy_price =self.current_price - self.thh_buy self.sell_price = self.thh_sale + self.current_price str1_ = '\nearn_threshold_unit:' + '%0.3f' % earn_threshold_unit + '\nrsv_stk:' + '%0.3f' % rsv_stk + '\nthh_buy = earn_threshold_unit * 2 * (1 - rsv_stk)' +'\n' self.add_msg(str1_) str2_ = '\nstk_code:' + self.stk_code +'\ncurrent_price:' + '%0.3f' % self.current_price + '\n' + stk_name + ' 真卖 5000 ' + '%0.3f' % self.sell_price + '\n' + stk_name + ' 真买 5000 ' + '%0.3f' % self.buy_price + '\n' self.add_msg(str2_) #self.add_note(str2_) str_ = '\n卖出网格大小:' + '%0.3f' % self.thh_sale + '\n买入网格大小:' + '%0.3f' % self.thh_buy + '\n' debug_print_txt('stk_judge', self.stk_code, str_, self.debug) self.add_msg(str_)
def get_filter_result(self): """ 获取当前 self.stk_list_ss :return: """ if len(self.stk_list_ss) == 0: return '\n已无符合条件的标的!\n' else: return '\n' + str([(x.stk_code, code2name(x.stk_code)) for x in self.stk_list_ss]) + '\n'
def add_row_name(self, stk_code_list): """ 添加行名称 :param stk_code_list: :return: """ for info in stk_code_list: self.my_grid4.SetRowLabelValue(info[0], code2name(info[1]))
def cat_stk(kind, tc): """ 查看相关stk列表 :param kind: :return: """ stk_list = read_config()[kind] stk_name = str([code2name(x) for x in stk_list]) text_append_color(tc, stk_name.replace('[', '').replace(']', '').replace(',', '\n'))
def plot_opt(stk_code, opt_record, tc): if len(opt_record) == 0: text_append_color(tc, code2name(stk_code) + ':没有操作记录!') return df = pd.DataFrame(opt_record).set_index('date_time') # 筛选 df = df[df['stk_code'] == stk_code] if df.empty: text_append_color(tc, code2name(stk_code) + ':没有操作记录!') # 计算上下限 df['sale_pot'] = df.apply(lambda x: x['p_last'] + x['sale_reseau'], axis=1) df['buy_pot'] = df.apply(lambda x: x['p_last'] + x['buy_reseau'], axis=1) df.loc[:, ['p_last', 'p_now', 'buy_pot', 'sale_pot']].plot(style=['*', '*', '^--', '^--']) plt.show()
def cal_stk_rsv_rank(self, stk_code, m_days, history_length=400): df = get_k_data_JQ(stk_code, count=history_length, end_date=get_current_date_str()) debug_print_txt('rsv_cal', '', code2name(stk_code) + '开始计算rsv:', True) rsv = self.cal_rsv_rank_sub(df, m_days) debug_print_txt('rsv_cal', '', '最终rsv:' + '%0.3f' % rsv, True) return rsv
def get_stk_rsv(self, stk_code): """ 获取一只股票的RSV :return: """ if stk_code in self.rsv.keys(): return self.rsv[stk_code] else: self.msg = stk_code + code2name(stk_code) + 'rsv值不存在,临时下载!' rsv = self.cal_stk_rsv_rank(stk_code, 5) self.rsv[stk_code] = rsv return rsv
def get_opt_record_json(self): """ 判断该股票的opt_record配置是否正常 :return: """ # 如果没有相应的json文件,不进行判断,直接返回 if pd.isnull(self.opt_record_stk) | (not bool(self.opt_record_stk)): str_ = code2name(self.stk_code) + '没有历史操作记录,不进行阈值判断!\n' debug_print_txt('stk_judge', self.stk_code, '函数 judge_single_stk:' + str_, self.debug) self.add_msg(str_) return False elif len(self.opt_record_stk['b_opt']) == 0: str_ = code2name(self.stk_code) + '没有历史操作记录,不进行阈值判断!\n' debug_print_txt('stk_judge', self.stk_code, '函数 judge_single_stk:' + str_, self.debug) self.add_msg(str_) return False else: return True
def on_timer_pic(win, pool, debug=False): """ 图片定时器响应函数(闲置) :return: """ global last_upt_t upt_flag, last_upt_t = is_time_h_macd_update(last_upt_t) wx.PostEvent(win, ResultEvent(id=LAST_TIME_UPDATE_ID, data=last_upt_t)) if not upt_flag: wx.PostEvent(win, ResultEvent(id=MSG_UPDATE_ID_A, data='图片更新定时器:“小时图片”更新时间点未到!\n')) return # 清屏 wx.PostEvent(win, ResultEvent(id=NOTE_UPDATE_ID_S, data='检测时间:' + get_current_datetime_str() + '\n\n')) # 生成更新的图片 wx.PostEvent(win, ResultEvent(id=MSG_UPDATE_ID_A, data='开始更新小时图片...\n')) pic_dict = {'h_macd': gen_kind_pic('h', pool), 'h_idx': gen_kind_pic('h_idx', pool)} wx.PostEvent(win, ResultEvent(id=HOUR_UPDATE_ID, data=pic_dict)) wx.PostEvent(win, ResultEvent(id=MSG_UPDATE_ID_A, data='小时图片更新完成!\n')) # 拐点检测 window_flash_flag = False for stk in list(set(read_config()['buy_stk'] + read_config()['concerned_stk'] + read_config()['index_stk'])): # 阈值条件不满足,该stk直接pass if not read_opt_json(stk, opt_record_file_url)['threshold_satisfied_flag']: wx.PostEvent(win, ResultEvent(id=MSG_UPDATE_ID_A, data=code2name(stk) + '阈值条件不满足,不进行拐点检测\n')) continue hour_idx_str = check_single_stk_hour_idx_wx(stk, source='jq', debug=True) if len(hour_idx_str): window_flash_flag = True for str_tmp in hour_idx_str: wx.PostEvent(win, ResultEvent(id=NOTE_UPDATE_ID_A, data=change_font_color(str_tmp))) # 窗口闪烁 if window_flash_flag: wx.PostEvent(win, ResultEvent(id=FLASH_WINDOW_ID, data=None)) wx.PostEvent(win, ResultEvent(id=MSG_UPDATE_ID_A, data=note_sar_inflection_point))
def checkSingleStkHourMACD_wx(stk_code, source='jq'): df_30, df_60 = gen_hour_macd_values(stk_code, source=source, title='') l_60 = df_60.tail(3)['MACD'].values l_30 = df_30.tail(3)['MACD'].values if l_60[1] == np.min(l_60): title_str = '60分钟开始上涨' sts = 1 elif l_60[1] == np.max(l_60): title_str = '60分钟开始下跌' sts = 2 elif l_30[1] == np.max(l_30): title_str = '30分钟开始下跌' sts = 3 elif l_30[1] == np.min(l_30): title_str = '30分钟开始上涨' sts = 4 else: title_str = '当前无拐点' sts = 0 # 避免重复发图! if stk_code in MACD_min_last.keys(): if MACD_min_last[stk_code] != sts: send_pic = True MACD_min_last[stk_code] = sts else: send_pic = False else: send_pic = True MACD_min_last[stk_code] = sts if send_pic & (sts != 0): return code2name(stk_code) + '-' + title_str + '\n' else: return ''
# encoding=utf-8
def prepare_trade_record(self, input_str, json_file_url_): # 返回字符串 return_str = [] # 已有文件,打开读取 if os.path.exists(json_file_url_): with open(json_file_url_, 'r') as _f: _opt_record = json.load(_f) else: _opt_record = {} # 解析输入 stk_code, opt, amount, p = input_str.split(' ') #stk_code = name2code(stk_name) stk_name = code2name(stk_code) p, amount = float(p), float(amount) # 对输入格式进行检查 #debug_print_txt('main_log', '', input_str +' ' + json_file_url_ + 'inside prepare_trade_record \n',True) if amount % 100 != 0: #tc.AppendText('格式错误!参考格式:\n美的集团 卖出 400 51.3') return if stk_code in _opt_record.keys(): opt_r_stk = _opt_record[stk_code] else: opt_r_stk = { 'b_opt': [], 's_opt': [], 'b_suggest': None, 's_suggest': None, 'p_last': None, 'has_flashed_flag': False, 'total_earn': 0, 'last_prompt_point': -1 } # 初步只支持每日一次操作 if opt_r_stk['has_flashed_flag'] == True: return if opt == '买入': opt_r_stk['b_opt'].clear() opt_r_stk['b_opt'].append(dict(time=get_current_datetime_str(), p=p, amount=amount, status='PRICE', entrust_no=0)) opt_r_stk['b_suggest'] = stk_name + ' 真买 ' + '%0.0f' % amount + ' ' + str(p) if opt == '卖出': #if len(opt_r_stk['b_opt']) > 0: opt_r_stk['s_opt'].clear() opt_r_stk['s_opt'].append(dict(time=get_current_datetime_str(), p=p, amount=amount, status='PRICE', entrust_no=0)) opt_r_stk['s_suggest'] = stk_name + ' 真卖 ' + '%0.0f' % amount + ' ' + str(p) #opt_r_stk, earn_this = sale_stk_sub(opt_r_stk, amount, p, tc) #return_str.append('earn:' + str(earn_this) + '\n') opt_r_stk['p_last'] = p opt_r_stk['has_flashed_flag'] = False # 保存数据 _opt_record[stk_code] = opt_r_stk with open(json_file_url_, 'w') as _f: #json.dump(_opt_record, _f) json.dump(_opt_record, _f, ensure_ascii=False, indent = 2, separators=(',', ': ')) # 返回 #debug_print_txt('main_log', '', stk_code +' end of prepare_trade_record \n',True) return return_str
# coding=utf-8
def JudgeSingleStk(stk_code, stk_amount_last, qq, debug=False, gui=False): str_gui = {'note': '', 'msg': ''} # 获取该stk的实时价格,如果是大盘指数,使用聚宽数据,否则有限使用tushare if stk_code in ['sh', 'sz', 'cyb']: current_price = get_current_price_JQ(stk_code) else: try: current_price = get_RT_price(stk_code, source='ts') except: str_gui = myPrint(str_gui, stk_code + '获取实时price失败!', method={ True: 'gm', False: 'n' }[gui]) return str_gui # 获取上次price stk_price_last = readLastP(stk_code) if stk_price_last < 0: saveLastP(stk_code, current_price) stk_price_last = current_price # 实时计算价差 price_diff = current_price - stk_price_last price_diff_ratio = price_diff / stk_price_last if debug: str_gui = myPrint(str_gui, '\n\n' + stk_code + ':\np_now:' + str(current_price) + '\np_last:' + str(stk_price_last) + '\np_change_ratio:' + str(price_diff_ratio), method={ True: 'gm', False: 'n' }[gui]) if current_price == 0.0: str_gui = myPrint(str_gui, stk_code + 'price==0.0! 返回!', method={ True: 'gm', False: 'n' }[gui]) return str_gui buy_amount = math.floor((money_each_opt / current_price) / 100) * 100 # 实时计算网格大小 earn_threshold_unit = getSigleStkReseau(stk_code) # 调节 buy 和 sale 的threshold if stk_code in RSV_Record.keys(): thh_sale = earn_threshold_unit * 2 * RSV_Record[stk_code] thh_buy = earn_threshold_unit * 2 * (1 - RSV_Record[stk_code]) else: RSV_Record[stk_code] = calRSVRank(stk_code, 5) / 100 thh_sale = earn_threshold_unit * 2 * RSV_Record[stk_code] thh_buy = earn_threshold_unit * 2 * (1 - RSV_Record[stk_code]) # 计算其离心度分数 try: # rank9, _, _, _ = calRealtimeRankWithGlobal(stk_code=stk_code) rank9 = -1 except: rank9 = -1 if debug: str_gui = myPrint(str_gui, stk_code + ':\np_change:' + str(price_diff * stk_amount_last) + '\nthreshold:' + str(earn_threshold_unit) + '\nthh_sale:' + str(thh_sale) + '\nthh_buy:' + str(thh_buy), method={ True: 'gm', False: 'n' }[gui]) if price_diff > thh_sale: # if JudgePChangeRatio(stk_code, price_diff_ratio): str_temp = "触发卖出网格!可以考虑卖出! "+stk_code + code2name(stk_code) +\ '\nAmount:' + str(stk_amount_last) +\ '\n当前价格:' + str(current_price) +\ '\n上次价格:' + str(stk_price_last) +\ '\n买入网格大小:' + '%0.2f' % thh_buy +\ '\n卖出网格大小:' + '%0.2f' % thh_sale # '\nM9_rank:' + str('%0.2f' % rank9) str_gui = myPrint(str_gui, str_temp, method={ True: 'gn', False: 'qq' }[gui], towho=qq) if not gui: sendHourMACDToQQ(stk_code, qq, source='jq') # 更新本地价格 saveLastP(stk_code, current_price) elif price_diff < -thh_buy: str_temp = "触发买入网格!可以考虑买入!" + stk_code + code2name(stk_code) +\ '\nAmount:' + str(buy_amount) +\ '\n当前价格:' + str(current_price) +\ '\n上次价格:' + str(stk_price_last) +\ '\n买入网格大小:' + '%0.2f' % thh_buy +\ '\n卖出网格大小:' + '%0.2f' % thh_sale # '\nM9_rank:' + str('%0.2f' % rank9) str_gui = myPrint(str_gui, str_temp, method={ True: 'gn', False: 'qq' }[gui], towho=qq) if not gui: sendHourMACDToQQ(stk_code, qq, source='jq') saveLastP(stk_code, current_price) else: str_gui = myPrint(str_gui, stk_code + ':未触发任何警戒线!', method={ True: 'gm', False: 'n' }[gui]) # 波动检测 change_flag, str_gui = JudgePChangeRatio(stk_code, price_diff_ratio, str_gui=str_gui, gui=gui) if change_flag: str_temp = "波动推送! " + stk_code + code2name(stk_code) +\ '\nAmount:' + str(buy_amount) +\ '\n当前价格:' + str(current_price) +\ '\n上次价格:' + str(stk_price_last) +\ '\n买入网格大小:' + '%0.2f' % thh_buy +\ '\n卖出网格大小:' + '%0.2f' % thh_sale # '\nM9_rank:' + str('%0.2f' % rank9) str_gui = myPrint(str_gui, str_temp, method={ True: 'gn', False: 'qq' }[gui], towho=qq) if not gui: sendHourMACDToQQ(stk_code, qq, source='jq') return str_gui
def stk_sea_select(stk_code, towho, tc, debug_plot=False): try: # 获取今天的情况,涨幅没有超过3%的不考虑 # df_now = get_k_data_JQ(stk_code, count=2, end_date=get_current_date_str()).reset_index() # # if (df_now.tail(1)['close'].values[0]-df_now.head(1)['close'].values[0])/df_now.head(1)['close'].values[0] < -0.05: # print('函数week_MACD_stray_judge:' + stk_code + '涨幅不够!') # return False, pd.DataFrame() """ ------------------------ 下载原始数据 ------------------------------- """ df = get_k_data_JQ(stk_code, count=400, end_date=get_current_date_str()).reset_index() if len(df) < 350: print('函数week_MACD_stray_judge:' + stk_code + '数据不足!') return False, pd.DataFrame() # 规整 df_floor = df.tail(math.floor(len(df) / 20) * 20 - 19) """ ------------------------ 判断周线是否达标 ------------------------------- """ # 增加每周的星期几 df_floor['day'] = df_floor.apply(lambda x: calendar.weekday( int(x['date'].split('-')[0]), int(x['date'].split('-')[1]), int(x['date'].split('-')[2])), axis=1) # 增加每周的星期几 df_floor['day'] = df_floor.apply(lambda x: calendar.weekday( int(x['date'].split('-')[0]), int(x['date'].split('-')[1]), int(x['date'].split('-')[2])), axis=1) # 隔着5个取一个 if df_floor.tail(1)['day'].values[0] != 4: df_floor_slice_5 = pd.concat( [df_floor[df_floor.day == 4], df_floor.tail(1)], axis=0) else: df_floor_slice_5 = df_floor[df_floor.day == 4] # 计算周线指标 df_floor_slice_5['MACD'], df_floor_slice_5[ 'MACDsignal'], df_floor_slice_5['MACDhist'] = talib.MACD( df_floor_slice_5.close, fastperiod=6, slowperiod=12, signalperiod=9) # 判断周线的走势,周线不是底部,直接返回 MACD_5 = df_floor_slice_5.tail(3)['MACD'].values if not (MACD_5[1] == np.min(MACD_5)): tc.AppendText(stk_code + code2name(stk_code) + ':“周线”不符合要求!') return False """ ------------------------ 判断月线是否达标 ------------------------------- """ # 隔着20个取一个(月线) df_floor_slice_20 = df_floor.loc[::20, :] # 计算指标 df_floor_slice_20['MACD'], df_floor_slice_20[ 'MACDsignal'], df_floor_slice_20['MACDhist'] = talib.MACD( df_floor_slice_20.close, fastperiod=4, slowperiod=8, signalperiod=9) # 获取最后的日期 date_last = df_floor_slice_5.tail(1)['date'].values[0] # 判断月线的走势,不符合条件直接返回 MACD_20 = df_floor_slice_20.tail(4)['MACD'].values if not ((MACD_20[1] != np.max(MACD_20)) & (MACD_20[2] != np.max(MACD_20))): tc.AppendText(stk_code + code2name(stk_code) + ':“月线”不符合要求!') return False """ ------------------------ 判断日线SAR是否达标 ------------------------------- """ # 判断日线SAR指标 df_floor['SAR'] = talib.SAR(df_floor.high, df_floor.low, acceleration=0.05, maximum=0.2) if df_floor.tail(1)['SAR'].values[0] > df_floor.tail( 1)['SAR'].values[0]: tc.AppendText(stk_code + code2name(stk_code) + ':“日线SAR指标”不符合要求!') return False """ ------------------------ 判断半小时SAR是否达标 ------------------------------- """ df_half_hour = get_k_data_JQ(stk_code, count=120, end_date=add_date_str( get_current_date_str(), 1), freq='30m') # 判断日线SAR指标 df_half_hour['SAR'] = talib.SAR(df_half_hour.high, df_half_hour.low, acceleration=0.05, maximum=0.2) if df_half_hour.tail(1)['SAR'].values[0] > df_half_hour.tail( 1)['SAR'].values[0]: tc.AppendText(stk_code + code2name(stk_code) + ':“半小时SAR指标”不符合要求!') return False # 符合要求,返回True tc.AppendText(stk_code + code2name(stk_code) + ':符合要求!') return True except Exception as e: tc.AppendText(stk_code + '出错:\n' + str(e)) return False
def gen_Day_Pic(stk_df, stk_code=''): """ 函数功能:给定stk的df,已经确定stk当前处于拐点状态,需要将当前stk的信息打印成图片,便于人工判断! :param stk_df 从tushare下载下来的原生df :param root_save_dir 配置文件中定义的存储路径 :return: 返回生成图片的路径 """ """ 规划一下都画哪些图 1、该stk整体走势,包括60日均线、20日均线和收盘价 2、stk近几天的MACD走势 """ """ 在原数据的基础上增加均线和MACD """ # 按升序排序 stk_df = stk_df.sort_values(by='date', ascending=True) stk_df['M20'] = stk_df['close'].rolling(window=20).mean() stk_df['M60'] = stk_df['close'].rolling(window=60).mean() stk_df['MACD'], stk_df['MACDsignal'], stk_df['MACDhist'] = talib.MACD(stk_df.close, fastperiod=12, slowperiod=26, signalperiod=9) # 检查日级别的MACD是否有异常 attention = False MACD_list = stk_df.tail(3)['MACD'].values if MACD_list[1] == np.min(MACD_list): attention = True # 设置背景红 set_background_color('b_r') elif MACD_list[1] == np.max(MACD_list): attention = True # 设置背景绿 set_background_color('b_g') else: set_background_color() fig, ax = plt.subplots(nrows=4, ncols=1) ax[0].plot(range(0, len(stk_df['date'])), stk_df['M20'], 'b--', label='20日均线', linewidth=1) ax[0].plot(range(0, len(stk_df['date'])), stk_df['M60'], 'r--', label='60日均线', linewidth=1) ax[0].plot(range(0, len(stk_df['date'])), stk_df['close'], 'g*--', label='收盘价', linewidth=0.5, markersize=1) ax[1].bar(range(0, len(stk_df['date'])), stk_df['MACD'], label='MACD') # 准备下标 xticklabels_all_list = list(stk_df['date'].sort_values(ascending=True)) xticklabels_all_list = [x.replace('-', '')[2:] for x in xticklabels_all_list] for ax_sig in ax[0:2]: ax_sig = addXticklabel_list(ax_sig, xticklabels_all_list, 30, rotation=45) ax_sig.legend(loc='best', fontsize=5) # 画出最近几天的情况(均线以及MACD) stk_df_current = stk_df.tail(plot_current_days_amount) ax[2].plot(range(0, len(stk_df_current['date'])), stk_df_current['M20'], 'b--', label='20日均线', linewidth=2) ax[2].plot(range(0, len(stk_df_current['date'])), stk_df_current['M60'], 'r--', label='60日均线', linewidth=2) ax[2].plot(range(0, len(stk_df_current['date'])), stk_df_current['close'], 'g*-', label='收盘价', linewidth=1, markersize=5) ax[3].bar(range(0, len(stk_df_current['date'])), stk_df_current['MACD'], label='MACD') # 设置标题并返回分析结果 result_analysis = [] if MACD_list[1] == np.min(MACD_list): title_tmp = stk_code + ' ' + code2name(stk_code) + ' 日级别 MACD 低点!后续数天可能上涨!' ax[0].set_title(title_tmp) result_analysis.append(title_tmp) elif MACD_list[1] == np.max(MACD_list): title_tmp = stk_code + ' ' + code2name(stk_code) + ' 日级别 MACD 高点!后续数天可能下跌!' ax[0].set_title(title) result_analysis.append(title_tmp) # 准备下标 xticklabels_all_list = list(stk_df_current['date'].sort_values(ascending=True)) xticklabels_all_list = [x.replace('-', '')[2:] for x in xticklabels_all_list] for ax_sig in ax[2:4]: ax_sig = addXticklabel_list(ax_sig, xticklabels_all_list, 30, rotation=45) ax_sig.legend(loc='best', fontsize=5) fig.tight_layout() # 调整整体空白 plt.subplots_adjust(wspace=0, hspace=1) # 调整子图间距 # plt.close() return fig, ax, attention, result_analysis
def gen_Idx_Pic(stk_df, stk_code=''): """ 打印常用指标 """ # 按升序排序 stk_df = stk_df.sort_values(by='date', ascending=True) """ 增加指标 'RSI5', 'RSI12', 'RSI30' 'SAR' 'slowk', 'slowd' 'upper', 'middle', 'lower' 'MOM' """ stk_df = addStkIndexToDf(stk_df).tail(60) set_background_color(bc='w') result_analysis = [] # 检查SAR attention = False sar_tail_origin = stk_df.tail(2) sar_tail = sar_tail_origin.copy() sar_tail['compare'] = sar_tail_origin.apply(lambda x: x['SAR'] - x['close'], axis=1) title_tmp = stk_code + ' ' + code2name(stk_code) if sar_tail.head(1)['compare'].values[0] * sar_tail.tail(1)['compare'].values[0] < 0: if sar_tail.tail(1)['SAR'].values[0] < sar_tail.tail(1)['close'].values[0]: title_tmp = stk_code + ' ' + code2name(stk_code) + ' 注意 SAR 指标翻转,后续数天可能上涨!' result_analysis.append(title_tmp) set_background_color(bc='b_r') else: title_tmp = stk_code + ' ' + code2name(stk_code) + ' 注意 SAR 指标翻转,后续数天可能下跌!' result_analysis.append(title_tmp) set_background_color(bc='b_g') attention = True fig, ax = plt.subplots(nrows=5, ncols=1) ax[0].plot(range(0, len(stk_df['date'])), stk_df['RSI5'], 'b--', label='RSI5线', linewidth=1) ax[0].plot(range(0, len(stk_df['date'])), stk_df['RSI12'], 'r--', label='RSI12线', linewidth=1) ax[0].plot(range(0, len(stk_df['date'])), stk_df['RSI30'], 'g*--', label='RSI30', linewidth=0.5, markersize=1) ax[0].plot(range(0, len(stk_df['date'])), [20 for a in range(len(stk_df['date']))], 'b--', linewidth=0.3) ax[0].plot(range(0, len(stk_df['date'])), [80 for a in range(len(stk_df['date']))], 'b--', linewidth=0.3) ax[0].set_ylim(0, 100) ax[1].plot(range(0, len(stk_df['date'])), stk_df['SAR'], 'r--', label='SAR', linewidth=0.5, markersize=1) ax[1].plot(range(0, len(stk_df['date'])), stk_df['close'], 'g*--', label='close', linewidth=0.5, markersize=1) ax[2].plot(range(0, len(stk_df['date'])), stk_df['slowk'], 'g*--', label='slowk', linewidth=0.5, markersize=1) ax[2].plot(range(0, len(stk_df['date'])), stk_df['slowd'], 'r*--', label='slowd', linewidth=0.5, markersize=1) ax[2].plot(range(0, len(stk_df['date'])), [20 for a in range(len(stk_df['date']))], 'b--', linewidth=0.3) ax[2].plot(range(0, len(stk_df['date'])), [80 for a in range(len(stk_df['date']))], 'b--', linewidth=0.3) ax[2].set_ylim(0, 100) ax[3].plot(range(0, len(stk_df['date'])), stk_df['upper'], 'r*--', label='布林上线', linewidth=0.5, markersize=1) ax[3].plot(range(0, len(stk_df['date'])), stk_df['middle'], 'b*--', label='布林均线', linewidth=0.5, markersize=1) ax[3].plot(range(0, len(stk_df['date'])), stk_df['lower'], 'g*--', label='布林下线', linewidth=0.5, markersize=1) ax[4].plot(range(0, len(stk_df['date'])), stk_df['MOM'], 'g*--', label='MOM', linewidth=0.5, markersize=1) # 准备下标 xlabel_series = stk_df.apply(lambda x: x['date'][2:].replace('-', ''), axis=1) ax[0] = addXticklabel(ax[0], xlabel_series, 40, rotation=45) ax[1] = addXticklabel(ax[1], xlabel_series, 40, rotation=45) ax[2] = addXticklabel(ax[2], xlabel_series, 40, rotation=45) ax[3] = addXticklabel(ax[3], xlabel_series, 40, rotation=45) ax[4] = addXticklabel(ax[4], xlabel_series, 40, rotation=45) for ax_sig in ax: ax_sig.legend(loc='best', fontsize=5) fig.tight_layout() # 调整整体空白 plt.subplots_adjust(wspace=0, hspace=0) # 调整子图间距 ax[0].set_title(title_tmp) return fig, ax, attention, result_analysis
def rpl_stk_hour_page(canvas_para, stk_code): """ 函数功能:在pdf中增加bk信息,篇幅为一整页,或者更多,以页为单位 :param stk_code: :param days: 用于指示近期的期限,比如近30天 :return: """ # 插入字符串,用以表明stk代码及名称 canvas_para.setFont("song", 10) if stk_code in ['sh', 'sz', 'cyb']: stk_name = stk_code else: stk_name = code2name(stk_code) # 打印stk代码和名字 canvas_para.drawString(20, letter[1] - 10, stk_code + ' ' + stk_name + ' ' + '小时数据') # 准备数据 df_stk = get_k_data_JQ(stk_code, start_date=add_date_str(get_current_date_str(), -200), freq='30m') df_stk['date'] = df_stk.reset_index().index df_stk = df_stk.reset_index(drop=True) close = extract_point_from_df_date_x(df_stk, 'date', 'close', timeAxis='year') data = [tuple(close)] data_name = ['close'] drawing_ave = gen_lp_drawing(data=data, data_note=data_name, height=letter[1] * 0.1, line_width=0.5, marker_size=2, time_axis='year') renderPDF.draw(drawing=drawing_ave, canvas=canvas_para, x=10, y=letter[1] * 0.85) # 按时间降序排序,方便计算MACD df_stk = df_stk.sort_values(by='date', ascending=True) # 加入各种指标 df_stk = add_stk_index_to_df(df_stk) # 去除空值,截取最新数据 df_stk = df_stk.dropna(axis=0, how='any').tail(40) close = extract_point_from_df_date_x(df_stk, 'date', 'close', timeAxis='year') sar = extract_point_from_df_date_x(df_stk, 'date', 'SAR', timeAxis='year') MACD = extract_point_from_df_date_x(df_stk, 'date', 'MACD', timeAxis='year') data = [tuple(close), tuple(sar)] data_name = ['close', 'sar'] drawing_ave = gen_lp_drawing(data=data, data_note=data_name, height=letter[1] * 0.1, line_width=1.5, marker_size=5, time_axis='year') renderPDF.draw(drawing=drawing_ave, canvas=canvas_para, x=10, y=letter[1] * 0.7) drawing_MACD = gen_bar_drawing(data=MACD, data_note=['MACD'], height=letter[1] * 0.1) renderPDF.draw(drawing=drawing_MACD, canvas=canvas_para, x=10, y=letter[1] * 0.5) # 整理kdj信息 slowk = extract_point_from_df_date_x(df_stk, 'date', 'slowk', timeAxis='year') slowd = extract_point_from_df_date_x(df_stk, 'date', 'slowd', timeAxis='year') data_kdj = [tuple(slowk), tuple(slowd)] data_kdj_note = ['k', 'd'] drawing_kdj = gen_lp_drawing(data=data_kdj, data_note=data_kdj_note, height=letter[1] * 0.1, time_axis='year') renderPDF.draw(drawing=drawing_kdj, canvas=canvas_para, x=10, y=letter[1] * 0.4) # 画图RSI信息 RSI5 = extract_point_from_df_date_x(df_stk, 'date', 'RSI5', timeAxis='year') RSI12 = extract_point_from_df_date_x(df_stk, 'date', 'RSI12', timeAxis='year') RSI30 = extract_point_from_df_date_x(df_stk, 'date', 'RSI30', timeAxis='year') data_RSI = [tuple(RSI5), tuple(RSI12), tuple(RSI30)] data_RSI_note = ['RSI5', 'RSI12', 'RSI30'] drawing_RSI = gen_lp_drawing(data=data_RSI, data_note=data_RSI_note, height=letter[1] * 0.1, time_axis='year') renderPDF.draw(drawing=drawing_RSI, canvas=canvas_para, x=10, y=letter[1] * 0.25) # 画图布林线 upper = extract_point_from_df_date_x(df_stk, 'date', 'upper', timeAxis='year') middle = extract_point_from_df_date_x(df_stk, 'date', 'middle', timeAxis='year') lower = extract_point_from_df_date_x(df_stk, 'date', 'lower', timeAxis='year') data_BOLL = [tuple(upper), tuple(middle), tuple(lower)] data_BOLL_note = ['上线', '中线', '下线'] drawing_BOLL = gen_lp_drawing(data=data_BOLL, data_note=data_BOLL_note, height=letter[1] * 0.1, time_axis='year') renderPDF.draw(drawing=drawing_BOLL, canvas=canvas_para, x=10, y=letter[1] * 0.1) canvas_para.showPage() return canvas_para