Exemplo n.º 1
0
async def summary(code: str,
                  end: Frame,
                  frame: FrameType = FrameType.DAY,
                  win: int = 7):
    sec = Security(code)
    start = tf.shift(end, -(60 + 19), frame)
    bars = await sec.load_bars(start, end, frame)
    end_dt = bars['date'].iat[-1]

    ma5 = np.array(signal.moving_average(bars['close'], 5))
    ma10 = np.array(signal.moving_average(bars['close'], 10))
    ma20 = np.array(signal.moving_average(bars['close'], 20))
    ma60 = np.array(signal.moving_average(bars['close'], 60))

    _ma5, _ma10, _ma20 = ma5[-win:], ma10[-win:], ma20[-win:]

    xlen = 20
    ax_x = [i for i in range(xlen - win, xlen + 1)]  # 回归线的坐标
    # 5日均线及拟合点、预测点
    color = '#b08080'
    lw = 0.5
    err5, coef5, vertex5 = signal.polyfit(_ma5)
    vx, vy = vertex5
    vx = xlen - win + vx
    plt.plot(vx, vy * 0.995, "^", color=color)  # 5日低点

    plt.plot(ma5[-xlen:], color=color, linewidth=lw)  # 均线
    p5 = np.poly1d(coef5)
    y5 = [p5(i) for i in range(win + 1)]

    c0 = bars['close'].iat[-1]
    pred_c = y5[-1] * 5 - bars['close'][-4:].sum()

    plt.gcf().text(0.15, 0.85,
                   f"{code} {end_dt} ^{100 * (pred_c / c0 - 1):.02f}%")
    plt.plot(ax_x, y5, 'o', color=color, mew=0.25, ms=2.5)  # 回归均线

    # 10日均线及回归线
    color = '#00ff80'
    err10, coef10, vertex10 = signal.polyfit(_ma10)
    p10 = np.poly1d(coef10)
    y10 = [p10(i) for i in range(win + 1)]
    plt.plot(ma10[-xlen:], color=color, linewidth=lw)
    plt.plot(ax_x, y10, 'o', color=color, mew=0.25, ms=2.5)

    # 20日均线及回归线
    color = '#00ffff'
    err20, coef20, vertex20 = signal.polyfit(_ma20)
    p20 = np.poly1d(coef20)
    y20 = [p20(i) for i in range(win + 1)]
    plt.plot(ma20[-xlen:], color=color, linewidth=lw)
    plt.plot(ax_x, y20, 'o', color=color, mew=0.25, ms=2.5)

    # 60日均线
    color = "#2222ff"
    plt.plot(ma60[-xlen:], color=color, linewidth=lw)
Exemplo n.º 2
0
    def test_000_something(self):
        """Test something."""
        bars = jq.get_bars('002082.XSHE',
                           30,
                           df=False,
                           fq_ref_date='2020-7-29',
                           end_dt='2020-7-30')
        ma5 = moving_average(bars['close'], 5)
        ma10 = moving_average(bars['close'], 10)
        ma20 = moving_average(bars['close'], 20)

        print(ma5[-5:])
        print(bars['date'][-1], len(ma5), len(ma10), len(ma20))
        for i in range(16, 21):
            err, curve, coef = polyfit(ma5[i:i + 5])
            a, b, c = coef
            axis_x = -b / (2 * a)
            axis_y = (4 * a * c - b * b) / (4 * a)

            print(f"{bars['date'][i+9]} err:{err:.4f},coef:{a:.3f},{b:.3f}"
                  f",{c:.3f}, "
                  f"(x,"
                  f"y):{axis_x:.1f}"
                  f",{axis_y:.2f}")

        print("=" * 5 + "ma10")
        for i in range(11, 16):
            err, curve, coef = polyfit(ma10[i:i + 5])
            a, b, c = coef
            axis_x = -b / (2 * a)
            axis_y = (4 * a * c - b * b) / (4 * a)

            print(
                f"{bars[i+14]['date']} err:{err:.4f}, coef:{a:.3f},{b:.3f},{c:.3f}, "
                f"(x,y):{axis_x:.1f}"
                f",{axis_y:.2f}")

        print("=" * 5 + "ma20")
        for i in range(1, 6):
            err, curve, coef = polyfit(ma20[i:i + 5])
            a, b, c = coef
            axis_x = -b / (2 * a)
            axis_y = (4 * a * c - b * b) / (4 * a)

            print(
                f"{bars[i+24]['date']} err:{err:.4f}, coef:{a:.3f},{b:.3f},{c:.3f}, "
                f"(x,y):{axis_x:.1f}"
                f",{axis_y:.2f}")
Exemplo n.º 3
0
    async def copy(self,
                   code: str,
                   frame_type: Union[str, FrameType],
                   frame: Union[str, Frame],
                   ma_wins=None):
        frame_type = FrameType(frame_type)
        frame = arrow.get(frame, tzinfo=cfg.tz)
        ma_wins = ma_wins or [5, 10, 20]
        fit_win = 7

        stop = frame
        start = tf.shift(stop, -fit_win - max(ma_wins), frame_type)

        sec = Security(code)
        bars = await sec.load_bars(start, stop, frame_type)
        features = []
        for win in ma_wins:
            ma = signal.moving_average(bars['close'], win)
            if len(ma) < fit_win:
                raise ValueError(
                    f"{sec.display_name} doesn't have enough bars for "
                    f"extracting features")

            err, (a, b, c), (vx,
                             _) = signal.polyfit(ma[-fit_win:] / ma[-fit_win])
            features.append((err, (a, b, c), vx))

        return features
Exemplo n.º 4
0
    async def evaluate(self,
                       code,
                       frame_type,
                       flag,
                       ma_win: int = 20,
                       slp=1e-2):
        """
        当股价回归到指定的均线上时,发出信号
        Args:
            code:
            frame_type:
            flag:
            ma:需要监控的均线

        Returns:

        """
        bars = await self.get_bars(code, ma_win + 10, frame_type)
        ma = signal.moving_average(bars['close'], ma_win)

        err, (a, b, c), (vx, _) = signal.polyfit(ma[-7:] / ma[-7])
        p = np.poly1d((a, b, c))
        if (p(11) / p(6) - 1) / 5 < slp:
            return

        sec = Security(code)
        alarm = f"{sec.display_name}触达{ma_win}均线。"
        await emit.emit(Events.sig_long, {"alarm": alarm})
Exemplo n.º 5
0
    async def scan(self, stop: Frame = None):
        start = tf.shift(stop, -26, FrameType.WEEK)
        ERR = {5: 0.008, 10: 0.004, 20: 0.004}

        for code in Securities().choose(['stock']):
            #for code in ['002150.XSHE']:
            sec = Security(code)
            bars = await sec.load_bars(start, stop, FrameType.WEEK)
            if bars[-1]['frame'] != stop:
                raise ValueError("")

            t1, t2, t3 = False, False, False
            params = []
            for win in [5, 10, 20]:
                ma = signal.moving_average(bars['close'], win)
                err, (a, b, c), (vx, _) = signal.polyfit(ma[-7:] / ma[-7])
                if err > ERR[win]:
                    continue

                p = np.poly1d((a, b, c))
                slp3 = round(p(9) / p(6) - 1, 2)

                params.append(np.round([slp3, a, b], 4))
                if win == 5:
                    t1 = slp3 >= 0.03 and a > 0.005
                if win == 10:
                    t2 = slp3 >= 0.02 and (b > abs(10 * a) or a > 0.0005)
                if win == 20:
                    t3 = slp3 >= -1e-6 and a >= 0

            if all([t1, t2, t3]):
                print(sec.display_name, params)
Exemplo n.º 6
0
    def extract_features(self, bars, max_error):
        """

        Args:
            bars:

        Returns:

        """
        ma5 = moving_average(bars['close'], 5)[-5:]
        ma10 = moving_average(bars['close'], 10)[-5:]
        ma20 = moving_average(bars['close'], 20)[-5:]

        feat = []
        for ts in [ma5, ma10, ma20]:
            try:
                err, coef = polyfit(ts)
                # 取系数a和b。对于一次函数,a=0;对于二次函数和指数函数,a,b都存在。c为截距,忽略
                a, b = coef[0], coef[1]
                if np.isnan(a) or np.isnan(b) or np.isnan(err) or err > max_error:
                    raise ValueError
                feat.extend([a, b, -b / (2 * a)])
            except Exception:
                return feat

        return feat
Exemplo n.º 7
0
    async def copy(self, code: str, frame_type: FrameType, start, stop):
        n = tf.count_frames(start, stop, frame_type)
        bars = await self.get_bars(code, n + 20, frame_type, stop)

        feat = features.ma_lines_trend(bars, [5, 10, 20])
        ma5, ma10, ma20 = feat["ma5"][0], feat["ma10"][0], feat["ma20"][0]

        self.max_distance = self.distance(ma5, ma10, ma20)
        err, (a, b) = signal.polyfit(ma20, deg=1)
        self.fitslp_ma20 = a
        self.fiterr_ma20 = err
Exemplo n.º 8
0
    async def evaluate(self,
                       code: str,
                       frame_type: FrameType,
                       dt: Frame = None,
                       win=15):
        sec = Security(code)
        end = dt or arrow.now(tz=cfg.tz)
        start = tf.shift(tf.floor(end, frame_type), -win - 20, frame_type)
        bars = await sec.load_bars(start, end, frame_type)

        if len(bars) < win + 20:
            return

        # 使用股价重心而不是收盘价来判断走势
        o, c = bars[-1]['open'], bars[-1]['close']

        feat = features.ma_lines_trend(bars, [5, 10, 20])
        ma5, ma10, ma20 = feat["ma5"][0], feat["ma10"][0], feat["ma20"][0]

        if np.any(np.isnan(ma5)):
            return

        mas = np.array([ma5[-1], ma10[-1], ma20[-1]])
        # 起涨点:一阳穿三线来确认
        if not (np.all(o <= mas) and np.all(c >= mas)):
            return

        # 三线粘合:三线距离小于self.max_distance
        distance = self.distance(ma5[:-1], ma10[:-1], ma20[:-1])
        if distance > self.max_distance:
            return

        # 月线要拉直,走平或者向上
        err, (a, b) = signal.polyfit((ma20 / ma20[0]), deg=1)
        if err > self.fiterr_ma20 and a < self.fitslp_ma20:
            return

        logger.info("%s",
                    f"{sec.display_name}\t{distance:.3f}\t{a:.3f}\t{err:.3f}")
        await self.fire("long",
                        code,
                        dt,
                        frame_type=frame_type.value,
                        distance=distance)
Exemplo n.º 9
0
    async def scan_1(self,
                     ma_win: int,
                     frame_type: FrameType,
                     a: float = None,
                     b: float = None,
                     err=1e-3,
                     end: Frame = None):
        """
        在所有股票中,寻找指定均线强于拟合均线(a,b,1)的,如果当前收盘价在均线附近,且近期存在
        大阳线,则发出信号
        Returns:

        """
        if a is None:
            err = self.ref_lines[f"ma{ma_win}"].get("err")
            a, b = self.ref_lines[f"ma{ma_win}"].get("coef")

        fit_win = 7
        secs = Securities()
        p = np.poly1d((a, b, 1.0))
        slp3 = p(fit_win - 1 + 3) / p(fit_win - 1) - 1
        count = 0
        for i, code in enumerate(secs.choose(['stock'])):
            if (i + 1) % 500 == 0:
                logger.debug("handled %s", i + 1)
            sec = Security(code)

            bars = await self.get_bars(code, fit_win + 19, frame_type, end)
            ma = signal.moving_average(bars['close'], ma_win)
            err_, (a_, b_,
                   c_), (vx_, _) = signal.polyfit(ma[-fit_win:] / ma[-fit_win])
            if err_ > err:
                continue

            #p_ = np.poly1d((a_,b_,1.0))
            # 如果abs(b) < fit_win * a,曲线(在x不超过fit_win的地方)接近于直线,此时应该比较b
            t5, t10, t20 = False, None, None
            #slp3_5 = p_(fit_win+2)/p_(fit_win-1) - 1
            t5 = a_ >= a * 0.99 and fit_win + 1 >= vx_ >= fit_win - 2
            if t5:
                print(f"{sec.display_name},{vx_:.1f}")
Exemplo n.º 10
0
def ma_lines_trend(bars: np.array, ma_wins: List[int]):
    """
    从bars数据中提取均线的走势特征
    Args:
        bars:
        ma_wins:

    Returns:

    """
    features = {}
    for win in ma_wins:
        ma = signal.moving_average(bars['close'], win)
        fit_win = 7 if win == 5 else 10
        err, (a, b, c), (vx, _) = signal.polyfit(ma[-fit_win:] / ma[-fit_win])
        p = np.poly1d((a, b, c))

        # 预测一周后均线涨幅
        war = p(fit_win + 5 - 1) / p(fit_win - 1) - 1

        features[f"ma{win}"] = [ma, (err, a, b, vx, fit_win, war)]

    return features
Exemplo n.º 11
0
    async def copy(self,
                   code: str,
                   frame_type: FrameType,
                   end: Frame,
                   ma_win=5):
        fit_win = 7

        sec = Security(code)
        start = tf.shift(end, -(ma_win + fit_win), frame_type)
        bars = await sec.load_bars(start, end, frame_type)
        ma = signal.moving_average(bars['close'], ma_win)
        err, (a, b, c), (vx, _) = signal.polyfit(ma[-fit_win:] / ma[-fit_win])
        p = np.poly1d((a, b, c))
        slp3 = p(fit_win + 2) / p(fit_win - 1) - 1
        print(
            f"{sec.display_name}({code})\t{err:.4f}\t{a:.4f}\t{b:.4f}\t{vx:.1f}\
        \t{slp3:.2f}")
        self.ref_lines[f"ma{ma_win}"] = {
            "err": err,
            "coef": (a, b),
            "vx": vx,
            "slp3": slp3
        }
Exemplo n.º 12
0
    async def evaluate(self, code: str, end: Frame):
        """
        最近穿越年线的股票,回归到[5,10,20]日均线时,如果均线形态良好,则提示买入
        Args:
            code:
            end:

        Returns:

        """
        start = tf.shift(tf.floor(end, FrameType.DAY), -26, FrameType.DAY)

        sec = Security(code)

        bars = await sec.load_bars(start, end, FrameType.DAY)
        close = bars['close']
        c0 = close[-1]

        # 检查接近5日均线,要求5日内强于均线,均线不能向下(或者拐头趋势)
        ma = signal.moving_average(close, 5)
        err, (a, b, c), (vx, _) = signal.polyfit(ma[-7:] / ma[-7])

        t1 = np.all(close[-5:] > ma[-5:])
        t2 = err < 3e-3
        t3 = a > 5e-4 or (abs(a) < 1e-5 and b > 1e-3)
        t4 = (c0 - ma[-1] / c0 < 5e-3)
        t5 = vx < 6

        logger.debug("%s 5日:%s, (a,b):%s,%s", sec, [t1, t2, t3, t4, t5], a, b)
        if all([t1, t2, t3, t4, t5]):
            logger.info("fired 5日买入:%s", sec)

            await emit.emit("/alpha/signals/long", {
                "plot":  "crossyear",
                "code":  code,
                "frame": str(end),
                "desc":  "回探5日线",
                "coef":  np.round([a, b], 4),
                "vx":    vx,
                "c":     c0,
                "ma":    ma[-5:]
            })
            return

        # 检查接近20日线买点
        ma = signal.moving_average(close, 20)
        err, (a, b, c), (vx, _) = signal.polyfit(ma[-10:] / ma[-10])

        t1 = err < 3e-3
        t2 = a > 5e-4 or (abs(a) < 1e-5 and b > 5e-3)
        t3 = (c0 - ma[-1]) < 5e-3
        t4 = vx < 9

        logger.debug("%s 20日:%s, (a,b):%s,%s", sec, [t1, t2, t3, t4], a, b)
        if all([t1, t2, t3, t4]):
            logger.info("fired 20日买入:%s", sec)
            await emit.emit("/alpha/signals/long", {
                "plot":  "crossyear",
                "code":  code,
                "frame": str(end),
                "desc":  "回探20日线",
                "coef":  np.round([a, b], 4),
                "vx":    vx,
                "c":     c0,
                "ma":    ma[-5:]
            })
            return

        # 检查是否存在30分钟买点
        start = tf.shift(tf.floor(end, FrameType.MIN30), -30, FrameType.MIN30)
        bars = await sec.load_bars(start, end, FrameType.MIN30)

        close = bars['close']
        ma = signal.moving_average(close, 5)
        err, (a, b, c), (vx, _) = signal.polyfit(ma[-7:] / ma[-7])
        t1 = err < 3e-3
        t2 = a > 5e-4 or (abs(a) < 1e-5 and b > 1e-2)
        t3 = vx < 6

        logger.debug("%s 30分钟:%s, (a,b)", sec, [t1, t2, t3, t4, t5], a, b)
        if all([t1, t2, t3]):
            logger.info("fired 30分钟买入:%s", sec)
            await emit.emit("/alpha/signals/long", {
                "plot":  "crossyear",
                "code":  code,
                "frame": str(end),
                "desc":  "30分钟买点",
                "vx":    vx,
                "c":     c0,
                "ma":    ma[-5:]
            })
Exemplo n.º 13
0
    def screen(self,
               frame,
               end_dt=None,
               adv_lim=25,
               win=7,
               a5=0.02,
               a10=0.001):
        all = []
        fired = []
        if end_dt is None:
            end_dt = arrow.now().datetime

        for i, code in enumerate(stocks.all_stocks()):
            try:
                name = stocks.name_of(code)
                if name.endswith("退"):
                    continue
                if name.find("ST") != -1:
                    continue

                bars = stocks.get_bars(code, 30, frame, end_dt=end_dt)
                if len(bars) == 0:
                    print("get 0 bars", code)
                    continue

                if arrow.get(bars['date'].iat[-1]).date() != arrow.get(
                        end_dt).date():
                    continue

                # 30日涨幅必须小于adv_lim
                if bars['close'].iat[-1] / bars['close'].min(
                ) >= 1 + adv_lim / 100:
                    print(f"{code}涨幅大于", adv_lim)
                    continue

                ma5 = np.array(moving_average(bars['close'], 5))
                ma10 = np.array(moving_average(bars['close'], 10))

                err5, coef5, vertex5 = polyfit(ma5[-win:])
                err10, coef10, vertex10 = polyfit(ma10[-win:])

                vx5, _ = vertex5
                vx10, _ = vertex10
                _a5 = coef5[0]
                _a10 = coef10[0]
                all.append([code, _a5, _a10, vx5, vx10, err5, err10])

                # print(code, round_list([err5, vx, pred_up, y5, ma5[-1], y10, ma10[-1]],3))
                # 如果曲线拟合较好,次日能上涨up%以上,10日线也向上,最低点在win/2以内
                t1 = err5 <= 0.003 and err10 <= 0.003
                t2 = _a5 > a5 and _a10 > a10
                t3 = (win - 1 > vx5 >= win / 2 - 1) and (vx10 < win / 2 - 1)
                if t1 and t2 and t3:
                    c1, c0 = bars['close'].iat[-2], bars['close'].iat[-1]
                    if stocks.check_buy_limit(c1, c0, name):  # 跳过涨停的
                        continue

                    print(f"{stocks.name_of(code)} {code}",
                          [_a5, _a10, vx5, vx10, err5, err10])
                    fired.append([code, _a5, _a10, vx5, vx10, err5, err10])
            except Exception as e:
                print(i, e)
                continue
        return DataFrame(
            data=all,
            columns=['code', 'a5', 'a10', 'vx5', 'vx10', 'err_5', 'err_10'])
Exemplo n.º 14
0
    async def scan(self,
                   frame_type: Union[str, FrameType] = FrameType.DAY,
                   end: Frame = None,
                   codes: List[str] = None):
        logger.info("running momentum scan at %s level", frame_type)
        if end is None:
            end = arrow.now(cfg.tz).datetime

        assert type(end) in (datetime.date, datetime.datetime)

        frame_type = FrameType(frame_type)
        ft = frame_type.value
        codes = codes or Securities().choose(['stock'])
        day_bars = {}
        async for code, bars in Security.load_bars_batch(
                codes, end, 2, FrameType.DAY):
            day_bars[code] = bars

        if len(day_bars) == 0:
            return

        async for code, bars in Security.load_bars_batch(
                codes, end, 11, frame_type):
            if len(bars) < 11:
                continue

            fired = bars[-1]['frame']
            day_bar = day_bars.get(code)
            if day_bar is None:
                continue

            c1, c0 = day_bars.get(code)[-2:]['close']
            cmin = min(bars['close'])

            # 还处在下跌状态、或者涨太多
            if c0 == cmin or (c0 / c1 - 1) > self.baseline(f"up_limit"):
                continue

            ma5 = signal.moving_average(bars['close'], 5)

            err, (a, b, c), (vx, _) = signal.polyfit(ma5[-7:] / ma5[-7])
            # 无法拟合,或者动能不足
            if err > self.baseline(f"ma5:{ft}:err") or a < self.baseline(
                    f"ma5:{ft}:a"):
                continue

            # 时间周期上应该是信号刚出现,还在窗口期内
            vx_range = self.baseline(f"ma5:{ft}:vx")
            if not vx_range[0] < vx < vx_range[1]:
                continue

            p = np.poly1d((a, b, c))
            y = p(9) / p(6) - 1
            # 如果预测未来三周期ma5上涨幅度不够
            if y < self.baseline(f"ma5:{ft}:y"):
                continue

            sec = Security(code)

            if frame_type == FrameType.DAY:
                start = tf.shift(tf.floor(end, frame_type), -249, frame_type)
                bars250 = await sec.load_bars(start, end, frame_type)
                ma60 = signal.moving_average(bars250['close'], 60)
                ma120 = signal.moving_average(bars250['close'], 120)
                ma250 = signal.moving_average(bars250['close'], 250)

                # 上方无均线压制
                if (c0 > ma60[-1]) and (c0 > ma120[-1]) and (c0 > ma250[-1]):
                    logger.info("%s, %s, %s, %s, %s, %s", sec, round(a, 4),
                                round(b, 4), round(vx, 1),
                                round(c0 / c1 - 1, 3), round(y, 3))
                    await self.enter_stock_pool(code,
                                                fired,
                                                frame_type,
                                                a=a,
                                                b=b,
                                                err=err,
                                                y=y,
                                                vx=self.fit_win - vx)
            elif frame_type == FrameType.WEEK:
                await self.enter_stock_pool(code,
                                            fired,
                                            frame_type,
                                            a=a,
                                            b=b,
                                            err=err,
                                            y=y,
                                            vx=self.fit_win - vx)
            elif frame_type == FrameType.MIN30:
                await self.fire_trade_signal('long',
                                             code,
                                             fired,
                                             frame_type,
                                             a=a,
                                             b=b,
                                             err=err,
                                             y=y,
                                             vx=self.fit_win - vx)
Exemplo n.º 15
0
    async def evaluate(self,
                       code: str,
                       frame_type: str = '30m',
                       dt: str = None,
                       win=5,
                       flag='long'):
        """
        如果股价从高点下来,或者从低点上来,则发出信号。高点和低点的确定,由于曲线拟合的原因,
        可能产生上一周期未发出信号,这一周期发出信号,但高点或者低点已在几个周期之前。这里的
        策略是,在新的趋势未形成之前,只报一次
        Args:
            code:
            frame_type: frame_type
            dt:
            win:
            flag:

        Returns:

        """
        stop = arrow.get(dt, tzinfo=cfg.tz) if dt else arrow.now(tz=cfg.tz)
        frame_type = FrameType(frame_type)
        ft = frame_type.value

        bars = await self.get_bars(code, win + self.fit_win, frame_type, stop)

        ma = signal.moving_average(bars['close'], win)
        _ma = ma[-self.fit_win:]
        err, (a, b, c), (vx, _) = signal.polyfit(_ma / _ma[0])

        logger.debug("%s, %s, %s, %s, %s", code, err, a, b, vx)
        if err > self.baseline(f"ma{win}:{ft}:err"):
            self.remember(code, frame_type, "trend", "dunno")
            return

        p = np.poly1d((a, b, c))
        y = p(self.fit_win + 2) / p(self.fit_win - 1) - 1

        previous_status = self.recall(code, frame_type, "trend")

        # 如果b > 10 * a * x,则走势主要由b决定。这里x即fit_win序列,我们向后看3周期
        if abs(b) > 10 * (self.fit_win + 3) * abs(a):
            if b > 0 and previous_status != "long" and flag in [
                    'both', "long"
            ]:
                await self.fire_trade_signal('long',
                                             code,
                                             stop,
                                             frame_type,
                                             a=a,
                                             b=b,
                                             err=err,
                                             vx=vx,
                                             y=y)
            if b < 0 and previous_status != "short" and flag in [
                    'both', "short"
            ]:
                await self.fire_trade_signal('short',
                                             code,
                                             stop,
                                             frame_type,
                                             err=err,
                                             a=a,
                                             b=b,
                                             y=y)
            return

        t1 = int(vx) < self.fit_win - 1

        # 判断是否为看多信号
        t2 = a > self.baseline(f"ma{win}:{ft}:a")
        if t1 and t2 and previous_status != "long" and flag in [
                "long", "both"
        ]:
            await self.fire_trade_signal('long',
                                         code,
                                         stop,
                                         frame_type,
                                         err=err,
                                         a=a,
                                         b=b,
                                         y=y)

        # 判断是否为看空信号
        t2 = a < -self.baseline(f"ma{win}:{ft}:a")
        if t1 and t2 and previous_status != "short" and flag in [
                "short", "both"
        ]:
            await self.fire_trade_signal('short',
                                         code,
                                         stop,
                                         frame_type,
                                         err=err,
                                         a=a,
                                         b=b,
                                         y=y)
Exemplo n.º 16
0
    async def visualize(self, code: Union[str, List[str]], frame: Union[str,
                                                                        Frame],
                        frame_type: Union[str, FrameType]):
        """
        将code列表中的股票的动量特征图象化
        Args:
            code:
            frame:
            frame_type:

        Returns:

        """
        import matplotlib.pyplot as plt

        if isinstance(code, str):
            code = [code]

        col = 4
        row = len(code) // col + 1
        plt.figure(figsize=(5 * row * col, 7))
        plt.subplots_adjust(wspace=0.2, hspace=0.2)

        fit_win = 7
        colors = {"5": '#808080', "10": '#00cc80', "20": '#00ccff'}

        frame = arrow.get(frame)
        frame_type = FrameType(frame_type)
        for i, code in enumerate(code):
            _code = code.split(".")[0]
            start = tf.shift(frame, -25, frame_type)
            bars = await Security(code).load_bars(start, frame, frame_type)

            plt.subplot(len(code) // col + 1, col, i + 1)
            y_lim = 0
            text = ""
            for win in [5, 10, 20]:
                ma = signal.moving_average(bars['close'], win)
                _ma = ma[-fit_win:]

                plt.plot(_ma, color=colors[f"{win}"])

                err, (a, b, c), (vx, _) = signal.polyfit(_ma / _ma[0])
                p = np.poly1d((a * _ma[0], b * _ma[0], c * _ma[0]))
                y = p(fit_win + 2) / p(fit_win - 1) - 1

                y_lim = max(y_lim, np.max(_ma))
                if win == 5:
                    text = f"{_code} a:{a:.4f} b:{b:.4f} vx:{vx:.1f} y:{y:.2f}"

                if err < self.baseline(f"ma{win}:{frame_type.value}:err"):
                    # 如果拟合在误差范围内,则画出拟合线
                    plt.plot([p(i) for i in range(len(_ma))],
                             "--",
                             color=colors[f"{win}"])
                    plt.plot([p(i) for i in range(len(_ma))],
                             "o",
                             color=colors[f"{win}"])

                    if 0 < vx < fit_win:
                        plt.plot([vx], p(vx), 'x')

            plt.plot(0, y_lim * 1.035)
            plt.text(0.1, y_lim * 1.02, text, color='r')