Example #1
0
def handle_duan(fenxing_list: List[Fenxing], pre_duan_state='yi'):
    state = fenxing_list[0].state
    # 1笔区间
    bi1_start = fenxing_list[0].kdata
    bi1_end = fenxing_list[1].kdata
    # 3笔区间
    bi3_start = fenxing_list[2].kdata
    bi3_end = fenxing_list[3].kdata

    if state == 'bi_ding':
        # 向下段,下-上-下

        # 第一笔区间
        range1 = (bi1_end['low'], bi1_start['high'])
        # 第三笔区间
        range3 = (bi3_end['low'], bi3_start['high'])

        # 1,3有重叠,认为第一个段出现
        if intersect(range1, range3):
            return 'down'

    else:
        # 向上段,上-下-上

        # 第一笔区间
        range1 = (bi1_start['low'], bi1_end['high'])
        # 第三笔区间
        range3 = (bi3_start['low'], bi3_end['high'])

        # 1,3有重叠,认为第一个段出现
        if intersect(range1, range3):
            return 'up'

    return pre_duan_state
Example #2
0
File: shape.py Project: zvtvz/zvt
def handle_duan(fenxing_list: List[Fenxing], pre_duan_state="yi"):
    state = fenxing_list[0].state
    # 1笔区间
    bi1_start = fenxing_list[0].kdata
    bi1_end = fenxing_list[1].kdata
    # 3笔区间
    bi3_start = fenxing_list[2].kdata
    bi3_end = fenxing_list[3].kdata

    if state == "bi_ding":
        # 向下段,下-上-下

        # 第一笔区间
        range1 = (bi1_end["low"], bi1_start["high"])
        # 第三笔区间
        range3 = (bi3_end["low"], bi3_start["high"])

        # 1,3有重叠,认为第一个段出现
        if intersect(range1, range3):
            return "down"

    else:
        # 向上段,上-下-上

        # 第一笔区间
        range1 = (bi1_start["low"], bi1_end["high"])
        # 第三笔区间
        range3 = (bi3_start["low"], bi3_end["high"])

        # 1,3有重叠,认为第一个段出现
        if intersect(range1, range3):
            return "up"

    return pre_duan_state
Example #3
0
File: shape.py Project: zvtvz/zvt
def handle_zhongshu(points: list,
                    acc_df,
                    end_index,
                    zhongshu_col="zhongshu",
                    zhongshu_change_col="zhongshu_change"):
    zhongshu = None
    zhongshu_change = None
    interval = None

    if len(points) == 4:
        x1 = points[0][0]
        x2 = points[3][0]

        interval = points[3][2] - points[0][2]

        if points[0][1] < points[1][1]:
            # 向下段
            range = intersect((points[0][1], points[1][1]),
                              (points[2][1], points[3][1]))
            if range:
                y1, y2 = range
                # 记录中枢
                zhongshu = Rect(x0=x1, x1=x2, y0=y1, y1=y2)
                zhongshu_change = abs(y1 - y2) / y1
                acc_df.loc[end_index, zhongshu_col] = zhongshu
                acc_df.loc[end_index, zhongshu_change_col] = zhongshu_change
                points = points[-1:]
            else:
                points = points[1:]
        else:
            # 向上段
            range = intersect((points[1][1], points[0][1]),
                              (points[3][1], points[2][1]))
            if range:
                y1, y2 = range
                # 记录中枢
                zhongshu = Rect(x0=x1, x1=x2, y0=y1, y1=y2)
                zhongshu_change = abs(y1 - y2) / y1

                acc_df.loc[end_index, zhongshu_col] = zhongshu
                acc_df.loc[end_index, zhongshu_change_col] = zhongshu_change
                points = points[-1:]
            else:
                points = points[1:]
    return points, zhongshu, zhongshu_change, interval
Example #4
0
def test_intersect():
    a = (1, 2)
    b = (1.5, 3)
    assert intersect(a, b) == (1.5, 2)
    assert intersect(b, a) == (1.5, 2)

    a = (1, 2)
    b = (3, 4)
    assert intersect(a, b) == None
    assert intersect(b, a) == None

    a = (1, 4)
    b = (2, 3)
    assert intersect(a, b) == (2, 3)
    assert intersect(b, a) == (2, 3)
Example #5
0
    def acc_one(self, entity_id, df: pd.DataFrame, acc_df: pd.DataFrame,
                state: dict) -> (pd.DataFrame, dict):
        self.logger.info(f'acc_one:{entity_id}')
        if pd_is_not_null(acc_df):
            df = df[df.index > acc_df.index[-1]]
            if pd_is_not_null(df):
                self.logger.info(f'compute from {df.iloc[0]["timestamp"]}')
                # 遍历的开始位置
                start_index = len(acc_df)

                acc_df = pd.concat([acc_df, df])

                zen_state = state

                acc_df = acc_df.reset_index(drop=True)
            else:
                self.logger.info('no need to compute')
                return acc_df, state
        else:
            acc_df = df
            # 笔的底
            acc_df['bi_di'] = False
            # 笔的顶
            acc_df['bi_ding'] = False
            # 记录笔顶/底分型的值,bi_di取low,bi_ding取high,其他为None,绘图时取有值的连线即为 笔
            acc_df['bi_value'] = np.NAN

            # 记录临时分型,不变
            acc_df['tmp_ding'] = False
            acc_df['tmp_di'] = False
            # 分型的力度
            acc_df['fenxing_power'] = np.NAN

            acc_df['duan_state'] = 'yi'

            # 段的底
            acc_df['duan_di'] = False
            # 段的顶
            acc_df['duan_ding'] = False
            # 记录段顶/底的值,为duan_di时取low,为duan_ding时取high,其他为None,绘图时取有值的连线即为 段
            acc_df['duan_value'] = np.NAN

            # 记录在确定中枢的最后一个段的终点x1,值为Rect(x0,y0,x1,y1)
            acc_df['zhongshu'] = np.NAN

            acc_df = acc_df.reset_index(drop=True)

            zen_state = ZenState(
                dict(fenxing_list=[],
                     direction=None,
                     can_fenxing=None,
                     can_fenxing_index=None,
                     opposite_count=0,
                     current_duan_state='yi',
                     duans=[],
                     pre_bi=None,
                     pre_duan=None))

            zen_state.fenxing_list: List[Fenxing] = []

            # 取前11条k线,至多出现一个顶分型+底分型
            # 注:只是一种方便的确定第一个分型的办法,有了第一个分型,后面的处理就比较统一
            # start_index 为遍历开始的位置
            # direction为一个确定分型后的方向,即顶分型后为:down,底分型后为:up
            fenxing, start_index, direction = handle_first_fenxing(acc_df,
                                                                   step=11)
            if not fenxing:
                return None, None

            zen_state.fenxing_list.append(fenxing)
            zen_state.direction = direction

            # list of (timestamp,value)
            zen_state.duans = []

        pre_kdata = acc_df.iloc[start_index - 1]
        pre_index = start_index - 1

        tmp_direction = zen_state.direction

        for index, kdata in acc_df.iloc[start_index:].iterrows():
            # print(f'timestamp: {kdata.timestamp}')
            # 临时方向
            tmp_direction = get_direction(kdata,
                                          pre_kdata,
                                          current=tmp_direction)

            # 处理包含关系
            handle_including(one_df=acc_df,
                             index=index,
                             kdata=kdata,
                             pre_index=pre_index,
                             pre_kdata=pre_kdata,
                             tmp_direction=tmp_direction)

            # 根据方向,寻找对应的分型 和 段
            if zen_state.direction == Direction.up:
                tmp_fenxing_col = 'tmp_ding'
                fenxing_col = 'bi_ding'
            else:
                tmp_fenxing_col = 'tmp_di'
                fenxing_col = 'bi_di'

            # 方向一致,延续中
            if tmp_direction == zen_state.direction:
                zen_state.opposite_count = 0
            # 反向,寻找反 分型
            else:
                zen_state.opposite_count = zen_state.opposite_count + 1
                # 第一次反向
                if zen_state.opposite_count == 1:
                    acc_df.loc[pre_index, tmp_fenxing_col] = True
                    acc_df.loc[pre_index, 'fenxing_power'] = fenxing_power(
                        acc_df.loc[pre_index - 1],
                        pre_kdata,
                        kdata,
                        fenxing=tmp_fenxing_col)

                    if pd_is_not_null(zen_state.can_fenxing):
                        # 候选底分型
                        if tmp_direction == Direction.up:
                            # 取小的
                            if pre_kdata['low'] <= zen_state.can_fenxing['low']:
                                zen_state.can_fenxing = pre_kdata
                                zen_state.can_fenxing_index = pre_index

                        # 候选顶分型
                        else:
                            # 取大的
                            if pre_kdata['high'] >= zen_state.can_fenxing[
                                    'high']:
                                zen_state.can_fenxing = pre_kdata
                                zen_state.can_fenxing_index = pre_index
                    else:
                        zen_state.can_fenxing = pre_kdata
                        zen_state.can_fenxing_index = pre_index

                # 分型确立
                if pd_is_not_null(zen_state.can_fenxing):
                    if zen_state.opposite_count >= 4 or (
                            index - zen_state.can_fenxing_index >= 8):
                        acc_df.loc[zen_state.can_fenxing_index,
                                   fenxing_col] = True

                        # 记录笔的值
                        if fenxing_col == 'bi_ding':
                            bi_value = acc_df.loc[zen_state.can_fenxing_index,
                                                  'high']
                        else:
                            bi_value = acc_df.loc[zen_state.can_fenxing_index,
                                                  'low']
                        acc_df.loc[zen_state.can_fenxing_index,
                                   'bi_value'] = bi_value

                        zen_state.pre_bi = (zen_state.can_fenxing_index,
                                            bi_value)

                        zen_state.opposite_count = 0
                        zen_state.direction = zen_state.direction.opposite()
                        zen_state.can_fenxing = None

                        # 确定第一个段
                        if zen_state.fenxing_list != None:
                            zen_state.fenxing_list.append(
                                Fenxing(state=fenxing_col,
                                        kdata=acc_df.loc[
                                            zen_state.can_fenxing_index,
                                            ['open', 'close', 'high', 'low']],
                                        index=zen_state.can_fenxing_index))

                            if len(zen_state.fenxing_list) == 4:
                                duan_state = handle_duan(
                                    fenxing_list=zen_state.fenxing_list,
                                    pre_duan_state=zen_state.current_duan_state
                                )

                                change = duan_state != zen_state.current_duan_state

                                if change:
                                    zen_state.current_duan_state = duan_state

                                    # 确定状态
                                    acc_df.loc[
                                        zen_state.fenxing_list[0].
                                        index:zen_state.fenxing_list[-1].index,
                                        'duan_state'] = zen_state.current_duan_state

                                    duan_index = zen_state.fenxing_list[
                                        0].index
                                    if zen_state.current_duan_state == 'up':
                                        acc_df.loc[duan_index,
                                                   'duan_di'] = True
                                        duan_value = acc_df.loc[duan_index,
                                                                'low']
                                    else:
                                        duan_index = zen_state.fenxing_list[
                                            0].index
                                        acc_df.loc[duan_index,
                                                   'duan_ding'] = True
                                        duan_value = acc_df.loc[duan_index,
                                                                'high']
                                    # 记录段的值
                                    acc_df.loc[duan_index,
                                               'duan_value'] = duan_value

                                    # 记录用于计算中枢的段
                                    zen_state.duans.append(
                                        (acc_df.loc[duan_index,
                                                    'timestamp'], duan_value))

                                    # 计算中枢
                                    if len(zen_state.duans) == 4:
                                        x1 = zen_state.duans[0][0]
                                        x2 = zen_state.duans[3][0]
                                        if zen_state.duans[0][
                                                1] < zen_state.duans[1][1]:
                                            # 向下段
                                            range = intersect(
                                                (zen_state.duans[0][1],
                                                 zen_state.duans[1][1]),
                                                (zen_state.duans[2][1],
                                                 zen_state.duans[3][1]))
                                            if range:
                                                y1, y2 = range
                                                # 记录中枢
                                                acc_df.loc[duan_index,
                                                           'zhongshu'] = Rect(
                                                               x0=x1,
                                                               x1=x2,
                                                               y0=y1,
                                                               y1=y2)
                                                zen_state.duans = zen_state.duans[
                                                    -1:]
                                            else:
                                                zen_state.duans = zen_state.duans[
                                                    1:]
                                        else:
                                            # 向上段
                                            range = intersect(
                                                (zen_state.duans[1][1],
                                                 zen_state.duans[0][1]),
                                                (zen_state.duans[3][1],
                                                 zen_state.duans[2][1]))
                                            if range:
                                                y1, y2 = range
                                                # 记录中枢
                                                acc_df.loc[duan_index,
                                                           'zhongshu'] = Rect(
                                                               x0=x1,
                                                               x1=x2,
                                                               y0=y1,
                                                               y1=y2)
                                                zen_state.duans = zen_state.duans[
                                                    -1:]
                                            else:
                                                zen_state.duans = zen_state.duans[
                                                    1:]

                                    # 只留最后一个
                                    zen_state.fenxing_list = zen_state.fenxing_list[
                                        -1:]
                                else:
                                    # 保持之前的状态并踢出候选
                                    acc_df.loc[
                                        zen_state.fenxing_list[0].index,
                                        'duan_state'] = zen_state.current_duan_state
                                    zen_state.fenxing_list = zen_state.fenxing_list[
                                        1:]

            pre_kdata = kdata
            pre_index = index

        acc_df = acc_df.set_index('timestamp', drop=False)
        return acc_df, zen_state
Example #6
0
    def do_compute(self):
        super().do_compute()
        one_df = self.factor_df

        #     annotation_df format:
        #                                     value    flag    color
        #     entity_id    timestamp

        # 处理分型
        bi_ding = one_df[one_df.bi_ding][['timestamp', 'high']]
        bi_di = one_df[one_df.bi_di][['timestamp', 'low']]

        df1 = bi_ding.rename(columns={"high": "value"})
        df1['flag'] = '顶分型'

        df2 = bi_di.rename(columns={"low": "value"})
        df2['flag'] = '底分型'

        flag_df: pd.DataFrame = pd.concat([df1, df2])
        flag_df = flag_df.sort_values(by=['timestamp'])
        flag_df['entity_id'] = self.entity_ids[0]
        flag_df = flag_df.set_index(['entity_id', 'timestamp'])

        # 处理段
        up = one_df[one_df.duan_di][['timestamp', 'low']]
        down = one_df[one_df.duan_ding][['timestamp', 'high']]
        df1 = up.rename(columns={"low": "value"})
        df2 = down.rename(columns={"high": "value"})

        duan_df: pd.DataFrame = pd.concat([df1, df2])
        duan_df = duan_df.sort_values(by=['timestamp'])
        duan_df['entity_id'] = self.entity_ids[0]
        duan_df = duan_df.set_index(['entity_id', 'timestamp'])

        # 处理中枢
        rects: List[Rect] = []

        # list of (timestamp,value)
        duans = []
        for index, item in duan_df.iterrows():
            duans.append((index[1], item.value))
            if len(duans) == 4:
                x1 = duans[0][0]
                x2 = duans[3][0]
                if duans[0][1] < duans[1][1]:
                    # 向下段
                    range = intersect((duans[0][1], duans[1][1]),
                                      (duans[2][1], duans[3][1]))
                    if range:
                        y1, y2 = range
                    else:
                        duans = duans[1:]
                        continue
                else:
                    # 向上段
                    range = intersect((duans[1][1], duans[0][1]),
                                      (duans[3][1], duans[2][1]))
                    if range:
                        y1, y2 = range
                    else:
                        duans = duans[1:]
                        continue

                rects.append(Rect(x0=x1, x1=x2, y0=y1, y1=y2))
                duans = duans[-1:]

        self.fenxing_value_df = flag_df
        self.duan_value_df = duan_df
        self.zhongshu_rects = rects
Example #7
0
    def transform_one(self, entity_id, df: pd.DataFrame) -> pd.DataFrame:
        # 记录段区间
        if entity_id not in self.entity_duan_intervals:
            self.entity_duan_intervals[entity_id] = []

        df = df.reset_index(drop=True)
        # 笔的底
        df['bi_di'] = False
        # 笔的顶
        df['bi_ding'] = False

        # 记录临时分型,不变
        df['tmp_ding'] = False
        df['tmp_di'] = False

        df['duan_state'] = 'yi'

        # 段的底
        df['duan_di'] = False
        # 段的顶
        df['duan_ding'] = False
        # 记录段顶/底的值,为duan_di时取low,为duan_ding时取high,其他为None,绘图时取有值的连线即为 段
        df['duan_value'] = np.NAN

        # 记录在确定中枢的最后一个段的终点x1,值为Rect(x0,y0,x1,y1)
        df['zhongshu'] = None

        fenxing_list: List[Fenxing] = []

        # 取前11条k线,至多出现一个顶分型+底分型
        # 注:只是一种方便的确定第一个分型的办法,有了第一个分型,后面的处理就比较统一
        # start_index 为遍历开始的位置
        # direction为一个确定分型后的方向,即顶分型后为:down,底分型后为:up
        fenxing, start_index, direction = handle_first_fenxing(df, step=11)
        fenxing_list.append(fenxing)
        # 临时方向
        tmp_direction = direction
        # 候选分型(candidate)
        can_fenxing = None
        can_fenxing_index = None
        # 正向count
        count = 0
        # 反方向count
        opposite_count = 0
        # 目前段的方向
        current_duan_state = 'yi'

        pre_kdata = df.iloc[start_index - 1]
        pre_index = start_index - 1

        # list of (timestamp,value)
        duans = []

        for index, kdata in df.iloc[start_index:].iterrows():
            # print(f'timestamp: {kdata.timestamp}')
            # 临时方向
            tmp_direction = get_direction(kdata,
                                          pre_kdata,
                                          current=tmp_direction)

            # 处理包含关系
            handle_including(one_df=df,
                             index=index,
                             kdata=kdata,
                             pre_index=pre_index,
                             pre_kdata=pre_kdata,
                             tmp_direction=tmp_direction)

            # 根据方向,寻找对应的分型 和 段
            if direction == Direction.up:
                tmp_fenxing_col = 'tmp_ding'
                fenxing_col = 'bi_ding'
            else:
                tmp_fenxing_col = 'tmp_di'
                fenxing_col = 'bi_di'

            # 方向一致,延续中
            if tmp_direction == direction:
                opposite_count = 0
            # 反向,寻找反 分型
            else:
                opposite_count = opposite_count + 1
                # 第一次反向
                if opposite_count == 1:
                    df.loc[pre_index, tmp_fenxing_col] = True

                    if pd_is_not_null(can_fenxing):
                        # 候选底分型
                        if tmp_direction == Direction.up:
                            # 取小的
                            if pre_kdata['low'] <= can_fenxing['low']:
                                can_fenxing = pre_kdata
                                can_fenxing_index = pre_index

                        # 候选顶分型
                        else:
                            # 取大的
                            if pre_kdata['high'] >= can_fenxing['high']:
                                can_fenxing = pre_kdata
                                can_fenxing_index = pre_index
                    else:
                        can_fenxing = pre_kdata
                        can_fenxing_index = pre_index

                # 分型确立
                if pd_is_not_null(can_fenxing):
                    if opposite_count >= 4 or (index - can_fenxing_index >= 8):
                        df.loc[can_fenxing_index, fenxing_col] = True

                        # 记录笔的值
                        if fenxing_col == 'bi_ding':
                            df.loc[can_fenxing_index,
                                   'bi_value'] = df.loc[can_fenxing_index,
                                                        'high']
                        else:
                            df.loc[can_fenxing_index,
                                   'bi_value'] = df.loc[can_fenxing_index,
                                                        'low']

                        opposite_count = 0
                        direction = direction.opposite()
                        can_fenxing = None

                        # 确定第一个段
                        if fenxing_list != None:
                            fenxing_list.append(
                                Fenxing(state=fenxing_col,
                                        kdata=df.loc[can_fenxing_index],
                                        index=can_fenxing_index))

                            if len(fenxing_list) == 4:
                                duan_state = handle_duan(
                                    fenxing_list=fenxing_list,
                                    pre_duan_state=current_duan_state)

                                change = duan_state != current_duan_state

                                if change:
                                    current_duan_state = duan_state

                                    # 确定状态
                                    df.loc[fenxing_list[0].
                                           index:fenxing_list[-1].index,
                                           'duan_state'] = current_duan_state

                                    duan_index = fenxing_list[0].index
                                    if current_duan_state == 'up':
                                        df.loc[duan_index, 'duan_di'] = True
                                        duan_value = df.loc[duan_index, 'low']
                                    else:
                                        duan_index = fenxing_list[0].index
                                        df.loc[duan_index, 'duan_ding'] = True
                                        duan_value = df.loc[duan_index, 'high']
                                    # 记录段的值
                                    df.loc[duan_index,
                                           'duan_value'] = duan_value
                                    # 记录用于计算中枢的段
                                    duans.append(
                                        (df.loc[duan_index,
                                                'timestamp'], duan_value))

                                    # 计算中枢
                                    if len(duans) == 4:
                                        x1 = duans[0][0]
                                        x2 = duans[3][0]
                                        if duans[0][1] < duans[1][1]:
                                            # 向下段
                                            range = intersect(
                                                (duans[0][1], duans[1][1]),
                                                (duans[2][1], duans[3][1]))
                                            if range:
                                                y1, y2 = range
                                                # 记录中枢
                                                df.loc[duan_index,
                                                       'zhongshu'] = Rect(
                                                           x0=x1,
                                                           x1=x2,
                                                           y0=y1,
                                                           y1=y2)
                                                duans = duans[-1:]
                                            else:
                                                duans = duans[1:]
                                        else:
                                            # 向上段
                                            range = intersect(
                                                (duans[1][1], duans[0][1]),
                                                (duans[3][1], duans[2][1]))
                                            if range:
                                                y1, y2 = range
                                                # 记录中枢
                                                df.loc[duan_index,
                                                       'zhongshu'] = Rect(
                                                           x0=x1,
                                                           x1=x2,
                                                           y0=y1,
                                                           y1=y2)
                                                duans = duans[-1:]
                                            else:
                                                duans = duans[1:]

                                    # 只留最后一个
                                    fenxing_list = fenxing_list[-1:]
                                else:
                                    # 保持之前的状态并踢出候选
                                    df.loc[fenxing_list[0].index,
                                           'duan_state'] = current_duan_state
                                    fenxing_list = fenxing_list[1:]

            pre_kdata = kdata
            pre_index = index

        df = df.set_index('timestamp')
        return df
Example #8
0
    df2 = down.rename(columns={"high": "value"})

    duan_df: pd.DataFrame = pd.concat([df1, df2])
    duan_df = duan_df.sort_values(by=['timestamp'])
    duan_df['entity_id'] = 'stock_sz_000338'
    duan_df = duan_df.set_index(['entity_id', 'timestamp'])

    # 处理中枢
    rects = []
    duans = []
    for index, item in duan_df.iterrows():
        if len(duans) == 4:
            x = duans[0][0]
            x1 = duans[3][0]
            if duans[0][1] < duans[1][1]:
                y, y1 = intersect((duans[0][1], duans[1][1]), (duans[2][1], duans[3][1]))
            else:
                y, y1 = intersect((duans[1][1], duans[0][1]), (duans[3][1], duans[2][1]))
            rects.append(((x, y), (x1, y1)))
            duans = []
        else:
            duans.append((index[1], item.value))

    drawer = Drawer(main_df=df, factor_df_list=[flag_df[['value']], duan_df], annotation_df=flag_df)
    fig = drawer.draw_kline(show=False)

    for rect in rects:
        fig.add_shape(type="rect",
                      x0=rect[0][0], y0=rect[0][1], x1=rect[1][0], y1=rect[1][1],
                      line=dict(
                          color="RoyalBlue",