예제 #1
0
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
예제 #2
0
    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)
예제 #3
0
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))
예제 #4
0
    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)
예제 #5
0
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
예제 #6
0
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
예제 #7
0
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
예제 #8
0
    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
예제 #9
0
    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_)
예제 #10
0
 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'
예제 #11
0
    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]))
예제 #12
0
    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'))
예제 #13
0
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()
예제 #14
0
    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
예제 #15
0
    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
예제 #16
0
    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
예제 #17
0
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))
예제 #18
0
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 ''
예제 #19
0
# encoding=utf-8
예제 #20
0
# encoding=utf-8
예제 #21
0
    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
예제 #22
0
파일: Sub.py 프로젝트: PieDi/MoDeng
# encoding=utf-8
예제 #23
0
파일: Sub.py 프로젝트: wjdz99/MoDeng
# coding=utf-8
예제 #24
0
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
예제 #25
0
파일: Sub.py 프로젝트: wx2000qq/MoDeng
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
예제 #26
0
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
예제 #27
0
# encoding=utf-8
예제 #28
0
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
예제 #29
0
# encoding=utf-8
예제 #30
0
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