コード例 #1
0
ファイル: priceSignals.py プロジェクト: codelol/pstock
class PriceSignals:
    def __init__(self):
        self.m = Metrics()

    def Type1_buy_point_MACD_bullish_divergence(self, data):
        closePrices = [float(x['Close']) for x in data]
        macd_all = self.m.macd_all(closePrices)
        if macd_all == None:
            return False

        macd_fast = macd_all['fast']
        macd_slow = macd_all['slow']
        macd_histo = macd_all['histo']
        if max(macd_slow[0], macd_fast[0], macd_histo[0]) > 0:
            return False
        if macd_histo[0] < macd_histo[1]:
            return False

        #现在判断是否有"下跌-调整-下跌":
        openPrices = [x['Open'] for x in data]
        sr = self.m.support_and_resistance(openPrices, closePrices, 20)
        sr_price = sr['price']
        lower_bound = min(sr_price[0], sr_price[1]) * 0.95
        upper_bound = max(sr_price[0], sr_price[1]) * 1.05

        if closePrices[0] > lower_bound:
            return False

        idx = 2
        while idx < len(sr_price):
            if sr_price[idx] < lower_bound:
                return False
            if sr_price[idx] > upper_bound:
                break
            idx += 1
        if idx == len(sr_price) or sr_price[idx] < lower_bound:
            return False
        sr_idx = sr['idx']

        #phase1 is the first 'down' phase
        phase1_right_idx = sr_idx[idx-1]
        phase1_left_idx = sr_idx[idx]
        phase1_min_idx = numpy.argmin(closePrices[phase1_right_idx: phase1_left_idx])

        #phase3 is the second (last) 'down' phase
        phase3_right_idx = 0
        phase3_left_idx = sr_idx[0]
        phase3_min_idx = numpy.argmin(closePrices[phase3_right_idx:  phase3_left_idx])

        # price should be new low but macd_fast should not
        if closePrices[phase3_min_idx] > closePrices[phase1_min_idx]:
            return False
        if macd_fast[phase3_min_idx] < macd_fast[phase1_min_idx]:
            return False

        return True


    """
    思想:
        在长期的股价低迷之后,出现了突破,短期均线超过长期均线.但是随后出现调整.
        这个调整伴随着缩量, 可能是shorter trap,可以介入.
        因为交易量数据的不准确, 程序中不读取交易量
    算法:
        下列条件必须首先满足, 否则立即返回False:
            最新价格比上一个价格是下降的;
            短期均线(5)在中期均线(10)和长期均线(20)之下
        # 找到三个区间:
            区间1: 从最近的交易开始,往回找,直到短期均线位于中期和长期均线上方
            区间2: 从区间1的分界日开始往回找,往回找,直到短期均线位于中期和长期均线下方
            区间3: 从区间2的分界日开始,往回找,直到短期均线和中期均线均位于长期均线之上
        # 计算区间2的最高价,区间3的最低价, 以及区间3开始的价格(成为最初价)
            区间3的最低价必须低于最初价20%以上,否则不构成"股价低迷"
            区间2的最高价必须高于区间3最低价的5%,否则不成为突破
            如果当前价低于区间2的最高价15%,则是下跌而不是回调
            如果当前价格是三个区间的最低价,则是下跌而不是回调
        # 如果进行到这里,则可以看成是满足条件
    """
    def Type2_buy_point_pullback_after_breakthrough(self, closePrices):
        ema_short = self.m.ema(closePrices, 5)
        ema_mid   = self.m.ema(closePrices, 10)
        ema_long  = self.m.ema(closePrices, 20)
        if closePrices[0] > closePrices[1]:
            return False
        if ema_short[0] > min(ema_mid[0], ema_long[0]):
            return False
        dsize = len(closePrices)
        pos = []
        idx = 0

        #locate end of section 1
        while idx < dsize and ema_short[idx] < max(ema_mid[idx], ema_long[idx]):
            idx += 1
        if idx == dsize:
            return False
        pos.append(idx)

        #locate end of section 2
        while idx < dsize and ema_short[idx] > min(ema_mid[idx], ema_long[idx]):
            idx += 1
        if idx == dsize:
            return False
        pos.append(idx)

        #locate end of section 3
        while idx < dsize and (ema_short[idx] < max(ema_mid[idx], ema_long[idx]) or ema_mid[idx] < ema_long[idx]) :
            idx += 1
        if idx == dsize:
            return False
        pos.append(idx)

        init_price = closePrices[pos[2]]
        low_section3 = min(closePrices[pos[1]:pos[2]])
        high_section2 = max(closePrices[pos[0]:pos[1]])
        if low_section3 > init_price * 0.8 or high_section2 < low_section3 * 1.05 or \
           closePrices[0] < high_section2 * 0.85:
            return False

        if closePrices[0] < min(closePrices[1:pos[2]]):
            return False

        return True

    #MACD底部背驰
    def MACD_Bottom_reversal(self, closePrices):
        macd_all = self.m.macd_all(closePrices)
        if macd_all == None:
            return False

        macd_fast = macd_all['fast']
        macd_slow = macd_all['slow']
        macd_histo = macd_all['histo']
        if max(macd_slow[0], macd_fast[0], macd_histo[0]) > 0:
            return False
        if macd_histo[0] < macd_histo[1]:
            return False

        # MACD底部背离已经出现:
        # 底部背离:依次出现金叉,死叉,金叉。虽然这些叉出现时的价格越来越低,但是对应的macd_fast值越来越高
        # 按照第一类买点的定律,出现第二个金叉时,已经错过了最低买点,所以要求是:
        # 最近一次出现了金叉,死叉,当前
        pos = 0
        while pos < len(closePrices) and macd_histo[pos]<0:
            pos += 1
        if pos == len(closePrices):
            return False
        dead_cross = pos

        pos += 1
        while pos < len(closePrices) and macd_histo[pos]>0:
            pos += 1
        if pos == len(closePrices):
            return False
        gold_cross = pos

        """
        print(str([0, dead_cross, gold_cross]))
        print(str([closePrices[0], closePrices[dead_cross], closePrices[gold_cross]]))
        print(str([macd_fast[0], macd_fast[dead_cross], macd_fast[gold_cross]]))
        """
        #价格更低,但是macd没有更低,这就是一种背离
        if not (closePrices[0] < closePrices[gold_cross] and\
                macd_fast[0] > macd_fast[gold_cross]):
            return False

        return True

    #Note that the 'Open' data of the current day is not reliable, so let's not depend on it
    def Bottom_Up(self, openPrices, closePrices, lows, highs):
        #previous bar must be a nagative bar
        if not (closePrices[1] < openPrices[1]):
            return False
        #current price must be higher than previous close
        if not (closePrices[0] > closePrices[1]):
            return False

        #if any recent close price is higher than ema_5 or ema_10, pass
        #a low price is necessary for profitable reversal
        ema_5  = Metrics().ema(closePrices, 5)
        ema_10 = Metrics().ema(closePrices, 10)
        for idx in range(1, 3):
            if closePrices[idx] > min(ema_5[idx], ema_10[idx]):
                return False

        # look back 300 bars for support and resistence, very old bars are not reliable
        sr = self.m.support_and_resistance(openPrices[:300], closePrices[:300])
        myrange = {'min': lows[1], 'max':max(closePrices[0], highs[1])}
        foundSupport = False
        supportIdx = -1
        for i in range(len(sr['price'])):
            price = sr['price'][i]
            if price > myrange['max']:
                continue
            if price < myrange['min']:
                return False
            idx = sr['idx'][i]
            # 如果之前跌破了找到的这个支撑点,那么这个支撑点已经作废了
            if min(closePrices[2:idx]) < price:
                return False
            foundSupport = True
            supportIdx = idx
            break

        if not foundSupport:
            return False

        prevMax = max(closePrices[1:supportIdx])
        #print(str([supportIdx, prevMax, closePrices[0]]))

        if closePrices[0] > prevMax * 0.9:
            return False

        return True

    def New_High(self, data):
        closePrices = [x['Close'] for x in data]
        highs = [x['High'] for x in data]
        if len(closePrices) < 20:
            return False
        prev_high = max(highs[1:])
        cur_price = closePrices[0]
        #print(str([cur_price, prev_high]))
        if cur_price < prev_high:
            return False

        ema_5 = self.m.ema(closePrices, 5)
        ema_10 = self.m.ema(closePrices, 10)

        # if price increased fast, skip
        limit = 1.02
        if (cur_price > min(ema_5[0], closePrices[1]) * limit) or\
           (ema_5[0] > ema_10[0] * limit):
            return False

        #用支撑线阻力线的位置来判断,价格是否在某区间徘徊
        #如果价格一路上升,是不会有支撑和阻力线的
        openPrices = [x['Open'] for x in data]
        sr = self.m.support_and_resistance(openPrices, closePrices)
        sr_price = sr['price']
        lower_bound = cur_price * 0.95
        count = 0
        for p in range(len(sr_price)):
            if sr_price[p] > lower_bound:
                count += 1
        if count < 2:
            return False

        rsi = self.m.rsi(closePrices)
        if max(rsi[:5]) > 70:
            return False

        macd_all = self.m.macd_all(closePrices)
        macd_fast = macd_all['fast']
        sr_idx = sr['idx']
        if macd_fast[0] < macd_fast[sr_idx[0]]:
            #这是MACD背离
            return False

        return True

    #这个版本是: "整数新高"
    def New_High_Old(self, closePrices, highs):
        if len(closePrices) < 20:
            return False
        prev_high = max(highs[1:])
        cur_price = closePrices[0]
        if cur_price < prev_high:
            return False

        cur_price *= 1.02 #if cur_price is 2% short, print it too, so I can watch it
        if cur_price < 10:
            price_threshold = 1
        elif cur_price < 100:
            price_threshold = 10
        else:
            price_threshold = 100

        if int(closePrices[0] / price_threshold) == int(prev_high / price_threshold):
            return False

        return True
コード例 #2
0
ファイル: priceSignals.py プロジェクト: codelol/pstock
 def __init__(self):
     self.m = Metrics()