Ejemplo n.º 1
0
def exclude_analyze(basic, kdata, pick_index, take_index, policy_args):
    """ 根据日线做排除性校验
    """
    max_rise     = __parse_policy_args(policy_args, MAX_RISE)
    max_pclose   = __parse_policy_args(policy_args, MAX_PCLOSE)
    outstanding  = __parse_policy_args(policy_args, OUTSTANDING)

    ### 净资产为负数的
    if basic[dogen.BVPS] < 0:
        logger.debug("Invalid bvps")
        return True

    ### 特征三
    if kdata.iloc[take_index][dogen.P_CLOSE] > max_pclose:
        logger.debug("Too high close price at %s" % kdata.index[take_index])
        return True
    if kdata.iloc[take_index][dogen.P_CLOSE] * basic[dogen.OUTSTANDING] > outstanding:
        logger.debug("Too large outstanding at %s" % kdata.index[take_index])
        return True
    
    ### 特征四
    rise_range = dogen.get_last_rise_range(kdata, max_rise, max_fall=max_rise/2, eIdx=22)
    if rise_range is not None:
        [min_index, max_index, inc_close, get_lhigh, tmp_index] = rise_range
        if max_rise < dogen.caculate_incr_percentage(kdata.iloc[take_index][dogen.P_CLOSE], kdata.iloc[min_index][dogen.P_CLOSE]):
            logger.debug("Too large rise-range")
            return True
        pass

    ### 特征五
    if kdata.iloc[take_index][dogen.MA5] < kdata.iloc[take_index+1][dogen.MA5] and kdata.iloc[take_index][dogen.MA20] < kdata.iloc[take_index+1][dogen.MA20]:
        logger.debug("Invalid MA5&MA20 at %s" % kdata.index[take_index])
        return True

    return False
Ejemplo n.º 2
0
def stock_analyze(basic, kdata, policy_args):
    ### 基本条件选取
    get_index = include_analyze(basic, kdata, policy_args)
    if get_index is None:
        logger.debug("include_analyze() return None")
        return None
    else:
        [pick_index, take_index] = get_index

    ### 排它条件过滤
    if exclude_analyze(basic, kdata, pick_index, take_index, policy_args):
        logger.debug("exclude_analyze() return True")
        return None

    ### 构造结果
    result = {}
    result[dogen.RST_COL_CODE] = basic.name  # 股票代码
    result[dogen.RST_COL_NAME] = basic[dogen.NAME]  #  证券简写
    result[dogen.RST_COL_INDUSTRY] = basic[dogen.INDUSTRY]
    result[dogen.RST_COL_TAKE_TRADE] = kdata.index[take_index]  # 命中交易日
    result[dogen.RST_COL_LAST_CLOSE] = kdata.iloc[0][dogen.P_CLOSE]  # 最后一日收盘价
    result[dogen.RST_COL_OUTSTANDING] = round(
        kdata.iloc[0][dogen.P_CLOSE] * basic[dogen.OUTSTANDING], 2)  # 流通市值
    result[dogen.RST_COL_SCORE] = score_analyze(basic, kdata, pick_index,
                                                take_index, policy_args)  # 打分
    result[dogen.RST_COL_MATCH_TIME] = dogen.datetime_now()  # 选中时间
    result[dogen.RST_COL_INDEX] = '%s_%s' % (
        basic.name, kdata.index[take_index])  # 唯一标识,用于持久化去重

    return result
Ejemplo n.º 3
0
def find_largerise_range(codes, start=None, end=None, save_result=False, args=None):
    """ 查找大涨的股票数据

        参数说明:
            start - 起始日期,未设置默认分析3个月以内的数据
            end - 截止日期
            save_result - 是否保存结果
            args - args[0]表示最少30个点涨幅;arg[1]表示至少包括两个涨停板

        返回结果:
            区间列表如[{item-1}, {item-2}, ... , {itemn-}]
    """
    ### 数据库连接初始化
    db = dogen.DbMongo(uri=mongo_server, database=mongo_database)
    if not db.connect():
        logger.error("Cannot connect to mongo-server %s" % mongo_server)
        return None

    ### 股票代码过滤,如科创板
    codes = dogen.drop_codes(codes)

    ### 依次统计检查
    match_list = []
    for code in codes:
        try:
            ### 从数据库读取basic数据
            basic = db.lookup_stock_basic(code)

            ### 从数据库读取日线数据,必须按索引(日期)降序排列
            if end is None:
                end = dogen.date_today()
            if start is None:
                start = dogen.date_delta(end, -30)
            kdata = db.lookup_stock_kdata(code, start=start, end=end)
            if kdata is None or kdata.index.size <= 0:
                continue
            dogen.drop_fresh_stock_trades(basic, kdata)
            
            ### 统计分析
            if kdata is not None and kdata.index.size > 0:
                logger.debug("Begin in analyzing %s from %s to %s" % (code, start, end))
                match = __statistics_analyze(db, basic, kdata, save_result, args)
                if match is None:
                    continue            
                ### 输出结果
                match_list.extend(match)
                
        except Exception:
            logger.error('Trggered in handling code %s: %s' % (code, traceback.format_exc()))
            continue
        pass

    return match_list
Ejemplo n.º 4
0
def exclude_analyze(basic, kdata, pick_index, take_index, fall_range,
                    policy_args):
    pick_start = __parse_policy_args(policy_args, PICK_START)
    max_take2low = __parse_policy_args(policy_args, MAX_TAKE2LOW)
    max_pclose = __parse_policy_args(policy_args, MAX_PCLOSE)
    outstanding = __parse_policy_args(policy_args, OUTSTANDING)
    [high_index, pick_index, dec_close, get_llow, tmpId] = fall_range

    ### 净资产为负数的
    if basic[dogen.BVPS] < 0:
        logger.debug("Invalid bvps")
        return True

    ### 特征三
    if kdata.iloc[take_index][dogen.P_CLOSE] > max_pclose:
        logger.debug("Too high close price at %s" % kdata.index[take_index])
        return True
    if kdata.iloc[take_index][dogen.P_CLOSE] * basic[
            dogen.OUTSTANDING] > outstanding:
        logger.debug("Too large outstanding at %s" % kdata.index[take_index])
        return True

    ### 特征四
    temp_index = dogen.get_last_column_max(kdata,
                                           dogen.P_CLOSE,
                                           eIdx=pick_index)
    if dogen.caculate_incr_percentage(
            kdata.iloc[temp_index][dogen.P_CLOSE],
            kdata.iloc[pick_index][dogen.P_CLOSE]) > max_take2low:
        logger.debug("Too high close at %s" % kdata.index[temp_index])
        return True

    ### 特征五
    if pick_index + 1 >= pick_start:
        macd = dogen.forecast_macd(kdata[dogen.MACD])
        if kdata.iloc[0][dogen.MACD] < -0.1 and macd < -0.1:
            logger.debug("Invalid MACD at %s" % kdata.index[0])
            return True
        pass

    return False
Ejemplo n.º 5
0
def include_analyze(basic, kdata, policy_args):
    ### 参数解析
    take_valid = __parse_policy_args(policy_args, TAKE_VALID)

    if kdata.index.size <= 0:
        logger.debug("Don't open")
        return None

    ### 特征一
    time_market = time.strftime(
        "%Y-%m-%d", time.strptime(basic.loc['timeToMarket'], "%Y%m%d"))
    if time_market > kdata.index[0] or time_market < kdata.index[-1]:
        logger.debug("Isn't a new-ipo stock")
        return None
    else:
        dogen.drop_fresh_stock_trades(basic, kdata)

    ### 特征二
    if kdata.index.size > take_valid:
        logger.debug("Isn't fresh")
        return None
    else:
        take_index = -1

    return [take_index, take_index]
Ejemplo n.º 6
0
def include_analyze(basic, kdata, policy_args):
    ### 策略参数处理
    hl_valid    = __parse_policy_args(policy_args, HL_VALID)
    take_valid  = __parse_policy_args(policy_args, TAKE_VALID)

    ### 特征一
    index = dogen.get_highlimit_trades(kdata, eIdx=hl_valid+1)
    if index.size == 0:
        logger.debug("Don't match highlimit trades")
        return None
    else:
        pick_trade = index[0]
        ### 若最后一天涨停忽略
        pick_index = kdata.index.get_loc(pick_trade)
        if pick_index == 0:
            logger.debug("Fallback didn't occur")
            return None
        pass

    if kdata.iloc[pick_index-1][dogen.R_CLOSE] > 0 or kdata.iloc[pick_index-1][dogen.VOLUME] < kdata.iloc[pick_index][dogen.VOLUME]:
        ### 涨停后缩量下跌
        list_index = trade_analyze1(basic, kdata, pick_index, policy_args)
    else:
        ### 涨停后首日放量下跌
        list_index = trade_analyze2(basic, kdata, pick_index, policy_args)

    if list_index is not None:
        [pick_index, take_index] = list_index
        if take_index is None or take_index > take_valid:
            logger.debug("Don't match valid fallback trade")
            return None
        pass

    return list_index
Ejemplo n.º 7
0
def trade_analyze2(basic, kdata, pick_index, policy_args):
    min_falls    = __parse_policy_args(policy_args, MIN_FALLS)

    ### 特征二
    if dogen.caculate_incr_percentage(kdata.iloc[pick_index-1][dogen.P_OPEN], kdata.iloc[pick_index][dogen.P_CLOSE]) > 5:
        logger.debug("Too high open price at %s" % kdata.index[pick_index-1])
        return None

    take_index = None
    max_pclose = kdata.iloc[pick_index][dogen.P_CLOSE]*(1-min_falls*0.01)
    if kdata.iloc[pick_index-1][dogen.P_CLOSE] <= max_pclose:
        take_index = pick_index-1
    for temp_index in range(pick_index-2, -1, -1):
        if kdata.iloc[temp_index][dogen.R_CLOSE] > 0 or kdata.iloc[temp_index][dogen.VOLUME] > kdata.iloc[temp_index+1][dogen.VOLUME]:
            if take_index is not None:
                take_index = temp_index
            break
        elif kdata.iloc[temp_index][dogen.P_CLOSE] <= max_pclose:
            take_index = temp_index
        pass

    return [pick_index, take_index]
Ejemplo n.º 8
0
def stock_analyze(basic, kdata, policy_args):
    ### 基本条件选取
    get_index = include_analyze(basic, kdata, policy_args)
    if get_index is None:
        logger.debug("include_analyze() return None")
        return None
    else:
        [pick_index, take_index] = get_index

    ### 排它条件过滤
    if exclude_analyze(basic, kdata, pick_index, take_index, policy_args):
        logger.debug("exclude_analyze() return True")
        return None

    rise_range = dogen.get_last_rise_range(kdata, 0, sIdx=pick_index)
    if rise_range is not None:
        [pick_index, max_index, inc_close, get_lhigh, tmp_index] = rise_range

    ### 构造结果
    result = {}
    result[dogen.RST_COL_CODE] = basic.name  # 股票代码
    result[dogen.RST_COL_NAME] = basic[dogen.NAME]  #  证券简写
    result[dogen.RST_COL_INDUSTRY] = basic[dogen.INDUSTRY]
    result[dogen.RST_COL_START] = kdata.index[pick_index]
    result[dogen.RST_COL_TAKE_TRADE] = kdata.index[take_index]  # 命中交易日
    result[dogen.RST_COL_LAST_CLOSE] = kdata.iloc[0][dogen.P_CLOSE]  # 最后一日收盘价
    result[dogen.RST_COL_OUTSTANDING] = round(
        kdata.iloc[0][dogen.P_CLOSE] * basic[dogen.OUTSTANDING], 2)  # 流通市值
    result[dogen.RST_COL_INC_HL] = dogen.get_highlimit_trades(kdata,
                                                              eIdx=pick_index +
                                                              1).size
    result[dogen.RST_COL_SCORE] = score_analyze(basic, kdata, pick_index,
                                                take_index, policy_args)
    result[dogen.RST_COL_MATCH_TIME] = dogen.datetime_now()  # 选中时间
    result[dogen.RST_COL_INDEX] = '%s_%s' % (
        basic.name, kdata.index[take_index])  # 唯一标识,用于持久化去重

    return result
Ejemplo n.º 9
0
def include_analyze(basic, kdata, policy_args):
    """ 
    """
    ### 参数解析
    take_valid = __parse_policy_args(policy_args, TAKE_VALID)
    pick_valid = __parse_policy_args(policy_args, PICK_VALID)
    min_rise = __parse_policy_args(policy_args, MIN_RISE)
    max_fallen = __parse_policy_args(policy_args, MAX_FALLEN)

    pick_index = 0
    take_index = None

    for temp_index in range(0, take_valid + 1):
        if kdata.iloc[temp_index][
                dogen.P_LOW] <= kdata.iloc[temp_index][dogen.MA20] + 0.01:
            take_index = temp_index
            break
        pass

    if take_index is None:
        logger.debug("Don't get valid take-trade")
        return None
    elif kdata.iloc[take_index][dogen.MA20] < kdata.iloc[take_index +
                                                         1][dogen.MA20]:
        logger.debug("Invalid ma20 at %s" % kdata.index[take_index])
        return None

    for temp_index in range(take_index, kdata.index.size):
        if kdata.iloc[temp_index][dogen.MA5] < kdata.iloc[temp_index][
                dogen.MA20]:
            break
        pick_index = temp_index

    if pick_index < pick_valid:
        return None

    return [pick_index, take_index]
Ejemplo n.º 10
0
def include_analyze(basic, kdata, policy_args):
    ### 策略参数处理
    mini_hl = __parse_policy_args(policy_args, MINI_HL)
    hl_valid = __parse_policy_args(policy_args, HL_VALID)
    take_valid = __parse_policy_args(policy_args, TAKE_VALID)

    ### 特征一
    heap_trade = 0
    if kdata.index.size < hl_valid:
        hl_valid = kdata.index.size
    for temp_index in range(0, hl_valid):
        if kdata.iloc[temp_index][dogen.P_CLOSE] < kdata.iloc[temp_index][
                dogen.L_HIGH]:
            continue
        if kdata.iloc[temp_index +
                      1][dogen.P_CLOSE] < kdata.iloc[temp_index +
                                                     1][dogen.L_HIGH]:
            continue
        pick_index = temp_index
        heap_trade += 1
    if heap_trade != 1:
        logger.debug("Don't include valid serial hl-trade")
        return None
    if pick_index != 0:
        low_index = dogen.get_last_column_min(kdata,
                                              dogen.P_CLOSE,
                                              eIdx=pick_index)
        if kdata.iloc[low_index][dogen.P_CLOSE] > kdata.iloc[pick_index][
                dogen.P_CLOSE]:
            logger.debug("Don't include valid fallback trade")
            return None

        take_index = None
        for temp_index in range(low_index, -1, -1):
            temp_close = dogen.caculate_incr_percentage(
                kdata.iloc[temp_index][dogen.P_CLOSE],
                kdata.iloc[pick_index][dogen.P_CLOSE])
            if temp_close < -3:
                continue
            elif temp_close > 7:
                break
            take_index = temp_index
    else:
        ### 两连板
        take_index = pick_index
    if take_index is None or take_index > take_valid:
        logger.debug("Don't match valid take trade")
        return None

    return [pick_index, take_index]
Ejemplo n.º 11
0
def trade_analyze1(basic, kdata, pick_index, policy_args):
    volume_scale = __parse_policy_args(policy_args, VOLUME_SCALE)
    min_falls    = __parse_policy_args(policy_args, MIN_FALLS)

    ### 取最低回调价
    if (pick_index+1) >= kdata.index.size:
        min_pclose = 0
    else:
        min_pclose = kdata.iloc[pick_index+1][dogen.P_CLOSE]

    ### 特征二
    if kdata.iloc[pick_index-1][dogen.R_CLOSE] > 0:
        pick_index -= 1
        if pick_index == 0:
            logger.debug("Fallback didn't occur")
            return None
        if (kdata.iloc[pick_index+1][dogen.VOLUME] * volume_scale) > kdata.iloc[pick_index][dogen.VOLUME]:
            logger.debug("Too small volume at " + kdata.index[pick_index])
            return None
        if dogen.caculate_incr_percentage(kdata.iloc[pick_index][dogen.P_CLOSE], kdata.iloc[pick_index][dogen.P_OPEN]) <= -5:
            logger.debug("Invalid open&close at %s" % kdata.index[pick_index])
            return None
        pass
    
    take_index = None
    max_pclose = kdata.iloc[pick_index][dogen.P_CLOSE]*(1-min_falls*0.01)
    for temp_index in range(pick_index-1, -1, -1):
        if kdata.iloc[temp_index][dogen.P_CLOSE] < min_pclose:
            logger.debug("Get invalid fall trade at %s" % kdata.index[temp_index])
            return None
        if kdata.iloc[temp_index][dogen.R_CLOSE] > 0 or kdata.iloc[temp_index][dogen.VOLUME] > kdata.iloc[temp_index+1][dogen.VOLUME]:
            if take_index is not None:
                take_index = temp_index
            break
        elif kdata.iloc[temp_index][dogen.P_CLOSE] <= max_pclose:
            take_index = temp_index
        pass

    return [pick_index, take_index]
Ejemplo n.º 12
0
def include_analyze(basic, kdata, policy_args):
    ### 策略参数处理
    mini_hl = __parse_policy_args(policy_args, MINI_HL)
    hl_valid = __parse_policy_args(policy_args, HL_VALID)
    take_valid = __parse_policy_args(policy_args, TAKE_VALID)

    ### 特征一
    index = dogen.get_highlimit_trades(kdata, eIdx=hl_valid + 1)
    if index.size == 0:
        logger.debug("Don't match highlimit trades")
        return None
    else:
        pick_trade = index[0]
        pick_index = kdata.index.get_loc(pick_trade)
        pick_close = kdata.iloc[pick_index][dogen.P_CLOSE]
        mini_index = pick_index + 1
        if mini_index < kdata.index.size:
            mini_close = kdata.iloc[pick_index + 1][dogen.P_CLOSE]
        else:
            mini_close = 0
    if pick_index < mini_hl:
        logger.debug("Invalid hl-trade at %s" % pick_trade)
        return None

    ### 特征二
    take_index = None
    if pick_index < 5 and pick_index >= 3:
        if dogen.caculate_incr_percentage(
                kdata.iloc[0][dogen.P_CLOSE],
                kdata.iloc[pick_index][dogen.P_CLOSE]) > 5:
            logger.debug("Invalid trade at %s" % kdata.index[0])
            return None
        tdata = kdata[0:pick_index]
        tdata = tdata[tdata[dogen.P_CLOSE] < pick_close]
        if tdata.index.size > 0:
            logger.debug("Invalid trade at %s" % tdata.index[0])
            return None
        take_index = 0
    else:
        heap_rises = 0
        for temp_index in range(pick_index - 1, -1, -1):
            temp_close = kdata.iloc[temp_index][dogen.R_CLOSE]
            if temp_close < 0:
                heap_rises = 0
            else:
                heap_rises += temp_close
            if heap_rises >= 5:
                take_index = temp_index
            if temp_close >= 3 and kdata.iloc[temp_index][
                    dogen.P_CLOSE] > kdata.iloc[temp_index][dogen.P_OPEN]:
                take_index = temp_index
            pass
        if take_index is not None:
            ### take_index之后缩量下跌(限一个交易日),也符合策略
            if take_index == 1\
            and kdata.iloc[take_index-1][dogen.R_CLOSE] < 0\
            and kdata.iloc[take_index-1][dogen.VOLUME]  < kdata.iloc[take_index][dogen.VOLUME]:
                take_index -= 1
            ### 最近收盘价比take_index(不能取更新后值)高更新
            elif take_index <= 3\
            and kdata.iloc[0][dogen.R_CLOSE] > 0\
            and kdata.iloc[0][dogen.P_CLOSE] > kdata.iloc[0][dogen.P_OPEN]\
            and kdata.iloc[0][dogen.P_CLOSE] >= kdata.iloc[take_index][dogen.P_CLOSE]:
                take_index = 0
            pass
        pass
    if take_index is None or take_index > take_valid:
        logger.debug("Don't match valid take trade")
        return None

    return [pick_index, take_index]
Ejemplo n.º 13
0
def include_analyze(basic, kdata, policy_args):
    """ 
    """
    ### 参数解析
    take_valid = __parse_policy_args(policy_args, TAKE_VALID)
    pick_valid = __parse_policy_args(policy_args, PICK_VALID)
    min_rise   = __parse_policy_args(policy_args, MIN_RISE)
    max_fallen = __parse_policy_args(policy_args, MAX_FALLEN)

    ### 特征一
    rise_range = dogen.get_last_rise_range(kdata, min_rise, max_fall=max_fallen, eIdx=22)
    if rise_range is None:
        logger.debug("Don't get valid rise-range")
        return None
    else:
        [pick_index, high_index, inc_close, get_lhigh, tmpId] = rise_range
        if pick_index < pick_valid:
            logger.debug("Invalid rise-range from %s" % kdata.index[pick_index])
            return None
        pass

    ### 特征二
    heap_rises = 0
    take_index = None
    for temp_index in range(pick_index, -1, -1):
        temp_close = kdata.iloc[temp_index][dogen.R_CLOSE]
        if temp_close < 0:
            heap_rises = 0
        else:
            heap_rises += temp_close
        if kdata.iloc[temp_index][dogen.MA5] < kdata.iloc[temp_index][dogen.MA20]:
            continue
        if kdata.iloc[temp_index][dogen.MA5] < kdata.iloc[temp_index+1][dogen.MA5]:
            continue
        if kdata.iloc[temp_index][dogen.VOLUME] < kdata.iloc[temp_index+1][dogen.VOLUME]:
            continue
        if heap_rises >= 5:
            if take_index is None or take_index > temp_index:
                take_index = temp_index
            pass
        if temp_close >= 3:
            if take_index is None or take_index > temp_index:
                take_index = temp_index
            pass
        pass
    if take_index is not None:
        high_index = dogen.get_last_column_max(kdata, dogen.P_CLOSE, sIdx=take_index, eIdx=pick_index)
        if high_index != take_index:
            logger.debug("Invalid pclose of take-trade at %s" % kdata.index[take_index])
            return None
        ### take_index之后缩量下跌(限一个交易日),也符合策略
        if take_index == 1\
        and kdata.iloc[take_index-1][dogen.R_CLOSE] < 0\
        and kdata.iloc[take_index-1][dogen.VOLUME]  < kdata.iloc[take_index][dogen.VOLUME]:
            take_index-= 1
        ### 最近收盘价比take_index(不能取更新后值)高更新
        elif take_index <= 3\
        and kdata.iloc[0][dogen.R_CLOSE] > 0\
        and kdata.iloc[0][dogen.P_CLOSE] > kdata.iloc[0][dogen.P_OPEN]\
        and kdata.iloc[0][dogen.P_CLOSE] >= kdata.iloc[take_index][dogen.P_CLOSE]:
            take_index = 0
        pass
    if take_index is None or take_index > take_valid:
        logger.debug("Don't get valid take-trade since %s" % kdata.index[pick_index])
        return None

    return [pick_index, take_index]
Ejemplo n.º 14
0
def match(codes, start=None, end=None, save_result=False, policy_args=None):
    """ 上涨均线策略, 股价维持在某一均线之上,调整回踩均线:
        >>> 基本条件
            一 ma5维持在ma20之上;
            二 买入交易日take-trade,满足条件:
                1) 最低价回踩ma20(如何精细定义???);
            

        >>> 排它条件


        参数说明:
            start - 样本起始交易日(数据库样本可能晚于该日期, 如更新不全);若未指定默认取end-$max_days做起始日
            end - 样本截止交易日(数据库样本可能早于该日期, 如停牌)
            save_result - 保存命中结果
        
        返回结果:
            列表数据如[{item-1}, {item-2}, ..., {item-n}],根据股票的流通市值、收盘价、成交量、涨跌幅等数据决策。
    """
    ### 数据库连接初始化
    db = dogen.DbMongo(uri=mongo_server, database=mongo_database)
    if not db.connect():
        logger.error("Cannot connect to mongo-server %s" % mongo_server)
        return None

    ### 截至日期修正
    expon = db.lookup_stock_kdata(dogen.get_index_of_sh(), end=end)
    if expon is None:
        logger.error("Don't get expon data")
        return None
    else:
        end = expon.index[0]
        start = dogen.date_delta(end,
                                 -__parse_policy_args(policy_args, MAX_TRADES))

    ### 依次策略检查
    match_list = []
    for code in codes:
        try:
            ### 从数据库读取basic数据
            basic = db.lookup_stock_basic(code)
            if dogen.drop_stock_check(code, basic):
                continue

            ### 从数据库读取日线数据,必须按索引(日期)降序排列
            kdata = db.lookup_stock_kdata(code, start=start, end=end)
            if kdata is None:
                continue
            elif kdata.index[0] != end:
                logger.debug("End date don't match")
                continue
            else:
                dogen.drop_fresh_stock_trades(basic, kdata)

            ### 策略分析
            if kdata is not None and kdata.index.size > 0:
                logger.debug("Begin in analyzing %s from %s to %s" %
                             (code, kdata.index[-1], kdata.index[0]))
                match = stock_analyze(basic, kdata, policy_args)
                if match is None:
                    continue
                ### 输出结果
                match_list.append(match)

        except Exception:
            logger.error('Trggered in handling code %s: %s' %
                         (code, traceback.format_exc()))
            continue
        pass

    ### 保存结果到数据库
    if save_result and len(match_list) > 0:
        db.insert_policy_result(__name__.split('.')[-1],
                                match_list,
                                key_name=dogen.RST_COL_INDEX)

    return match_list
Ejemplo n.º 15
0
def update_kdata(codes, full=False, start=None, end=None):
    """ 从网络侧更新股票数据

        参数说明:
            codes - 更新股票列表
            full - 是否进行全量更新
            start - 起始交易日
            end - 截止交易日
        
        返回结果:
            成功更新数据列表
    """
    ### 数据库连接初始化
    db = dogen.DbMongo(uri=mongo_server, database=mongo_database)
    if not db.connect():
        logger.error("Cannot connect to mongo-server %s" % mongo_server)
        return None

    ### 设置截止日期
    if end is None:
        end = dogen.date_today()
    
    ### 下载basic数据
    basics = dogen.download_basics()
    if basics is None:
        db = dogen.DbMongo(uri=mongo_server, database=mongo_database)
        basics = db.lookup_stock_basics()
    
    ### 下载参数指定股票数据
    success_list = []
    for code in codes:
        ### 如果全量下载, 则清除数据库
        try:
            if full:
                db.delete_stock_basic(code=code)
                db.delete_stock_kdata(code)

                from_trade = None
                last_trade = None            
            else:
                ### 读取数据区间
                from_trade, last_trade = db.lookup_stock_kdata_range(code)
        
            ### 区间数据不存在, 默认下载end之前两年数据
            if full or from_trade is None or last_trade is None:
                if start is None:
                    start = dogen.date_delta(end, -365*2)
                pass
            else:
                ### 增量下载需要保证数据处理加工的正确性(MA20/MACD)
                start = dogen.date_delta(last_trade, -90)
        
            ### 下载日线数据
            logger.debug("Begin download %s's kdata from %s to %s." % (code, start, end))
            kdata = dogen.download_kdata(code, start=start, end=end)
            if kdata is None or kdata.index.size <= 0:
                continue

            ### 截取新增数据插入, 数据已存在会导致出错
            if from_trade is not None and last_trade is not None:
                kdata = kdata.loc[(kdata.index<from_trade) | (kdata.index>last_trade)]
            
            ### 写数据库
            if kdata is not None and kdata.index.size > 0:
                ### 非指数写基本信息
                if code.isdigit():
                    basic = basics.loc[code]
                    db.insert_stock_basic(code, basic)
                db.insert_stock_kdata(code, kdata, kdata.index)
                success_list.append(code)

            logger.debug("Success update %s with %d items." % (code, kdata.index.size))
        except Exception:
            logger.error('Trggered in handling code %s: %s' % (code, traceback.format_exc()))
            continue
        pass
        
    return success_list
Ejemplo n.º 16
0
def include_analyze(basic, kdata, policy_args):
    """ 
    """
    ### 参数解析
    take_valid = __parse_policy_args(policy_args, TAKE_VALID)
    pick_start = __parse_policy_args(policy_args, PICK_START)
    pick_end = __parse_policy_args(policy_args, PICK_END)
    min_fallen = __parse_policy_args(policy_args, MIN_FALLEN)

    ### 预处理
    if kdata.iloc[0][dogen.MA5] > kdata.iloc[0][dogen.MA20]:
        logger.debug("Invalid MA5&MA20 at %s" % kdata.index[0])
        return None
    if dogen.get_last_column_min(kdata, dogen.P_CLOSE, eIdx=30) > pick_end:
        logger.debug("Invalid pick-trade")
        return None

    ### 特征一
    fall_range = dogen.get_last_fall_range(kdata,
                                           min_fallen,
                                           max_rise=min_fallen)
    if fall_range is None:
        logger.debug("Don't get valid fall-range")
        return None
    else:
        [high_index, pick_index, dec_close, get_llow, tmpId] = fall_range
        if pick_index >= pick_end:
            logger.debug("Too early pick-trade at %s" %
                         kdata.index[pick_index])
            return None
        tdata = kdata[0:pick_index]
        if tdata[tdata[dogen.MA5] > tdata[dogen.MA20]].index.size > 0:
            logger.debug("Invalid pick-trade at %s" % kdata.index[pick_index])
            return None
        pass

    ### 特征二
    heap_rises = 0
    take_index = None
    if pick_index + 1 < pick_start:
        if pick_index == 1 and kdata.iloc[pick_index][
                dogen.R_CLOSE] < -3 and kdata.iloc[pick_index -
                                                   1][dogen.R_CLOSE] > 0:
            take_index = pick_index
        for temp_index in range(pick_index - 1, -1, -1):
            if kdata.iloc[temp_index][dogen.P_CLOSE] >= dogen.caculate_l_high(
                    kdata.iloc[pick_index][dogen.P_CLOSE]):
                take_index = temp_index
            pass
        rise_range = dogen.get_last_rise_range(kdata, 5, eIdx=pick_index + 1)
        if (rise_range
                is not None) and (dogen.forecast_macd(kdata[dogen.MACD]) >= 0):
            [min_index, max_index, inc_close, get_lhigh, tmpIdx] = rise_range
            if take_index is None or take_index > max_index:
                take_index = max_index
            pass
        pass
    else:
        rise_range = dogen.get_last_rise_range(kdata, 5, eIdx=pick_index + 1)
        if rise_range is not None:
            [min_index, max_index, inc_close, get_lhigh, tmpIdx] = rise_range
            if take_index is None or take_index > max_index:
                take_index = max_index
            pass
        for temp_index in range(pick_index, -1, -1):
            if kdata.iloc[temp_index][dogen.R_CLOSE] >= 3:
                if take_index is None or take_index > temp_index:
                    take_index = temp_index
                pass
            if kdata.iloc[temp_index][dogen.R_AMP] >= 5 and kdata.iloc[
                    temp_index][dogen.R_CLOSE] >= 0:
                if take_index is None or take_index > temp_index:
                    take_index = temp_index
                pass
            pass
        ### MACD点校验
        temp_index = 0
        if (kdata.iloc[temp_index][dogen.MACD] <=
                -0.01) and (dogen.forecast_macd(
                    kdata[temp_index:-1][dogen.MACD]) >= -0.01):
            if take_index is None or take_index > temp_index:
                take_index = temp_index
            pass
        if (kdata.iloc[temp_index][dogen.MACD] >= 0.01) and (
                dogen.forecast_macd(kdata[temp_index:-1][dogen.MACD]) <= 0.01):
            if take_index is None or take_index > temp_index:
                take_index = temp_index
            pass
    if take_index is not None:
        ### take_index之后缩量下跌(限一个交易日),也符合策略
        if take_index == 1\
        and kdata.iloc[take_index-1][dogen.R_CLOSE] < 0\
        and kdata.iloc[take_index-1][dogen.VOLUME]  < kdata.iloc[take_index][dogen.VOLUME]:
            take_index -= 1
        ### 最近收盘价比take_index(不能取更新后值)高更新
        elif kdata.iloc[0][dogen.R_CLOSE] >= 0\
        and kdata.iloc[0][dogen.P_CLOSE] >= kdata.iloc[0][dogen.P_OPEN]\
        and kdata.iloc[0][dogen.P_CLOSE] >= kdata.iloc[take_index][dogen.P_CLOSE]:
            take_index = 0
        ### MACD点校验
        if (kdata.iloc[0][dogen.MACD] <= -0.01) and (dogen.forecast_macd(
                kdata[dogen.MACD]) >= -0.01):
            take_index = 0
        pass
    if take_index is None or take_index > take_valid:
        logger.debug("Don't get valid take-trade since %s" %
                     kdata.index[pick_index])
        return None

    return [pick_index, take_index, fall_range]
Ejemplo n.º 17
0
def update_hot_concept(end=None, num=1, save_result=False):
    """ 找热点概念

        参数:
            start: 开始日期
            end: 截止时间,None取最近交易日
            num: 计算日期数,0表示所有的
 
    """
    db = dogen.DbMongo(uri=mongo_server, database=mongo_database)
    if not db.connect():
        logger.error("Cannot connect to mongo-server %s" % mongo_server)
        return None

    rd = dogen.DbRedis()
    if not rd.connect():
        logger.error("Cannot connect to redis-server %s" % redis_server)
        return None

    ### 获取指数
    expon = db.lookup_stock_kdata(dogen.get_index_of_sh(), end=end)
    if expon is None:
        logger.debug("Don't get valid expon data")
        return None

    ### 截取有效交易日
    if num==0 or num > expon.index.size:
        num = expon.index.size

    ### 清理临时缓存
    rd.clear_hot_concept(expon.index[0:num].to_list())

    ### 读取代码
    codes = db.lookup_stock_codes()

    for code in codes:
        basic = db.lookup_stock_basic(code)
        kdata = db.lookup_stock_kdata(code, end=end)
        indt = dogen.lookup_industry(db, code) # 行业
        cnpt = dogen.lookup_concept(db, code)  # 概念
        if kdata is None or indt is None or cnpt is None:
            continue
        dogen.drop_fresh_stock_trades(basic, kdata)
        for temp_index in range(0, num):
            if (temp_index >= kdata.index.size)\
            or (kdata.iloc[temp_index][dogen.P_CLOSE] < kdata.iloc[temp_index][dogen.L_HIGH]):
                continue
            if (temp_index+1 >= kdata.index.size)\
            or (kdata.iloc[temp_index+1][dogen.P_CLOSE] < kdata.iloc[temp_index+1][dogen.L_HIGH]):
                continue

            rd.incry_hot_concept(kdata.index[temp_index], cnpt)
        pass

    rst = []

    ### 排序获取结果&清除临时数据
    for temp_index in range(0, num):
        hots = rd.fetch_hot_concept(expon.index[temp_index])

        ### 写数据库
        if save_result:
            db.insert_hot_concept(expon.index[temp_index], hots)
        rst.append((expon.index[temp_index], hots))
        rd.clear_hot_concept(expon.index[temp_index])

    return rst
Ejemplo n.º 18
0
def match(codes, start=None, end=None, save_result=False, policy_args=None):
    """ 两连涨停策略, 满足条件:
        >>> 基本条件
            一 两周内两连板上涨;
                1) 存在次板收盘价之下的回调;
                2) 次板非烂板(暂无法判断)
            二 买入信号(take-trade),有效期由take_valid限定:
                1) 收盘价在次板收盘价0.97倍之上,且涨幅小于7%;
        
        >>> 排它条件
            三 股价市值在outstanding(100亿)和maxi_close(50以下)限制范围内
            四 股价成本合理:
                1) 在最近一个月内,最高涨幅由maxi_rise限制; 
    
        参数说明:
            start - 样本起始交易日(数据库样本可能晚于该日期, 如更新不全);若未指定默认取end-$max_days做起始日
            end - 样本截止交易日(数据库样本可能早于该日期, 如停牌)
            save_result - 保存命中结果
        
        返回结果:
            列表数据如[{item-1}, {item-2}, ..., {item-n}],根据股票的流通市值、收盘价、成交量、涨跌幅等数据决策。
    """
    ### 数据库连接初始化
    db = dogen.DbMongo(uri=mongo_server, database=mongo_database)
    if not db.connect():
        logger.error("Cannot connect to mongo-server %s" % mongo_server)
        return None

    ### 截至日期修正
    expon = db.lookup_stock_kdata(dogen.get_index_of_sh(), end=end)
    if expon is None:
        logger.error("Don't get expon data")
        return None
    else:
        end = expon.index[0]
        start = dogen.date_delta(end,
                                 -__parse_policy_args(policy_args, MAX_TRADES))

    ### 依次策略检查
    match_list = []
    for code in codes:
        try:
            ### 从数据库读取basic数据
            basic = db.lookup_stock_basic(code)
            if dogen.drop_stock_check(code, basic):
                continue

            ### 从数据库读取日线数据,必须按索引(日期)降序排列
            kdata = db.lookup_stock_kdata(code, start=start, end=end)
            if kdata is None:
                continue
            elif kdata.index[0] != end:
                logger.debug("End date don't match")
                continue
            else:
                dogen.drop_fresh_stock_trades(basic, kdata)

            ### 策略分析
            if kdata is not None and kdata.index.size > 0:
                logger.debug("Begin in analyzing %s from %s to %s" %
                             (code, kdata.index[-1], kdata.index[0]))
                match = stock_analyze(basic, kdata, policy_args)
                if match is None:
                    continue
                ### 输出结果
                match_list.append(match)

        except Exception:
            logger.error('Trggered in handling code %s: %s' %
                         (code, traceback.format_exc()))
            continue
        pass

    ### 保存结果到数据库
    if save_result and len(match_list) > 0:
        db.insert_policy_result(__name__.split('.')[-1],
                                match_list,
                                key_name=dogen.RST_COL_INDEX)

    return match_list
Ejemplo n.º 19
0
def match(codes, start=None, end=None, save_result=False, policy_args=None):
    """ 反弹策略, 满足条件:
        >>> 基本条件
            一 下跌min_falls以上,最低价之后ma5不大于ma20;
            二 买入信号(take-trade),有效期由take_valid限定:
                1) 最低价后最多5个交易日,单日涨停(不限最小区间长度);
                2) 最低价后至少5个交易日,累积上涨超过5个点,或者单日涨幅超过3个点(MA5上涨);
                3) 最低价后至少5个交易日,保持横盘,出现振幅大于5%的上涨交易日(MA5上涨);

        >>> 排它条件
            三 股价市值在outstanding(100亿)和maxi_close(50以下)限制范围内
            四 pick-trade校验:
                1) pick-trade之后最高价不超过15%;
            五 若当前MACD值低于-0.1,那么其预测值必须大于-0.1

        参数说明:
            start - 样本起始交易日(数据库样本可能晚于该日期, 如更新不全);若未指定默认取end-$max_days做起始日
            end - 样本截止交易日(数据库样本可能早于该日期, 如停牌)
            save_result - 保存命中结果
        
        返回结果:
            列表数据如[{item-1}, {item-2}, ..., {item-n}],根据股票的流通市值、收盘价、成交量、涨跌幅等数据决策。
    """
    ### 数据库连接初始化
    db = dogen.DbMongo(uri=mongo_server, database=mongo_database)
    if not db.connect():
        logger.error("Cannot connect to mongo-server %s" % mongo_server)
        return None

    ### 截至日期修正
    expon = db.lookup_stock_kdata(dogen.get_index_of_sh(), end=end)
    if expon is None:
        logger.error("Don't get expon data")
        return None
    else:
        end = expon.index[0]
        start = dogen.date_delta(end,
                                 -__parse_policy_args(policy_args, MAX_TRADES))

    ### 依次策略检查
    match_list = []
    for code in codes:
        try:
            ### 从数据库读取basic数据
            basic = db.lookup_stock_basic(code)
            if dogen.drop_stock_check(code, basic):
                continue

            ### 从数据库读取日线数据,必须按索引(日期)降序排列
            kdata = db.lookup_stock_kdata(code, start=start, end=end)
            if kdata is None:
                continue
            elif kdata.index[0] != end:
                logger.debug("End date don't match")
                continue
            else:
                dogen.drop_fresh_stock_trades(basic, kdata)

            ### 策略分析
            if kdata is not None and kdata.index.size > 0:
                logger.debug("Begin in analyzing %s from %s to %s" %
                             (code, kdata.index[-1], kdata.index[0]))
                match = stock_analyze(basic, kdata, policy_args)
                if match is None:
                    continue
                ### 输出结果
                match_list.append(match)

        except Exception:
            logger.error('Trggered in handling code %s: %s' %
                         (code, traceback.format_exc()))
            continue
        pass

    ### 保存结果到数据库
    if save_result and len(match_list) > 0:
        db.insert_policy_result(__name__.split('.')[-1],
                                match_list,
                                key_name=dogen.RST_COL_INDEX)

    return match_list
Ejemplo n.º 20
0
def include_analyze(basic, kdata, policy_args):
    """ 
    """
    ### 参数解析
    take_valid = __parse_policy_args(policy_args, TAKE_VALID)
    pick_valid = __parse_policy_args(policy_args, PICK_VALID)
    min_rise = __parse_policy_args(policy_args, MIN_RISE)
    min_fallen = __parse_policy_args(policy_args, MIN_FALLEN)

    ### 预处理
    if kdata.iloc[0][dogen.MA5] > kdata.iloc[0][dogen.MA20]:
        logger.debug("Invalid MA5&MA20 at %s" % kdata.index[0])
        return None

    ### 特征一
    fall_range = dogen.get_last_fall_range(kdata,
                                           min_fallen,
                                           max_rise=min_rise)
    if fall_range is None:
        logger.debug("Don't get valid fall-range")
        return None
    else:
        [high_index, pick_index, dec_close, get_llow, tmpId] = fall_range
        for temp_index in range(high_index, -1, -1):
            if kdata.iloc[temp_index][dogen.MA5] > kdata.iloc[temp_index][
                    dogen.MA20]:
                continue
            break
    rise_range = dogen.get_last_rise_range(kdata,
                                           min_rise,
                                           max_fall=min_fallen,
                                           sIdx=high_index)
    if rise_range is None:
        logger.debug("Don't get valid rise-range")
        return None
    else:
        [from_index, max_index, inc_close, get_lhigh, tmpId] = rise_range
        if max_index != high_index:
            logger.debug("Invalid rise-range from %s to %s" %
                         (kdata.index[from_index], kdata.index[max_index]))
            return None
        if kdata.iloc[pick_index][dogen.P_CLOSE] < kdata.iloc[from_index][
                dogen.P_CLOSE]:
            logger.debug("Invalid pick-trade at %s" % kdata.index[pick_index])
            return None
        pass

    ### 特征二
    heap_rises = 0
    take_index = None
    if pick_index + 1 < pick_valid:
        for temp_index in range(pick_index - 1, -1, -1):
            if kdata.iloc[temp_index][dogen.P_CLOSE] >= dogen.caculate_l_high(
                    kdata.iloc[pick_index][dogen.P_CLOSE]):
                take_index = temp_index
            pass
        pass
    else:
        if dogen.caculate_incr_percentage(kdata.iloc[0][dogen.P_CLOSE],
                                          kdata.iloc[0][dogen.MA5]) < 3:
            for temp_index in range(pick_index, -1, -1):
                if kdata.iloc[temp_index][dogen.R_CLOSE] > 0 and kdata.iloc[
                        temp_index][dogen.R_AMP] >= 5:
                    if take_index is None or take_index > temp_index:
                        take_index = temp_index
                    pass
                pass
            pass
        for temp_index in range(pick_index, -1, -1):
            temp_close = kdata.iloc[temp_index][dogen.R_CLOSE]
            if temp_close < 0:
                heap_rises = 0
            else:
                heap_rises += temp_close
            if kdata.iloc[temp_index][dogen.P_CLOSE] < kdata.iloc[temp_index][
                    dogen.P_OPEN]:
                continue
            if heap_rises >= 5:
                if take_index is None or take_index > temp_index:
                    take_index = temp_index
                pass
            if temp_close >= 3 and kdata.iloc[temp_index][
                    dogen.P_CLOSE] > kdata.iloc[temp_index][dogen.P_OPEN]:
                if take_index is None or take_index > temp_index:
                    take_index = temp_index
                pass
            pass
        ### MACD点校验
        temp_index = 0
        if (kdata.iloc[temp_index][dogen.MACD] >= 0.01) and (
                dogen.forecast_macd(kdata[temp_index:-1][dogen.MACD]) <= 0.01):
            if take_index is None or take_index > temp_index:
                take_index = temp_index
            pass
        if take_index is not None:
            ### take_index之后缩量下跌(限一个交易日),也符合策略
            if take_index == 1\
            and kdata.iloc[take_index-1][dogen.R_CLOSE] < 0\
            and kdata.iloc[take_index-1][dogen.VOLUME]  < kdata.iloc[take_index][dogen.VOLUME]:
                take_index -= 1
            ### 最近收盘价比take_index(不能取更新后值)高更新
            elif take_index <= 3\
            and kdata.iloc[0][dogen.R_CLOSE] > 0\
            and kdata.iloc[0][dogen.P_CLOSE] > kdata.iloc[0][dogen.P_OPEN]\
            and kdata.iloc[0][dogen.P_CLOSE] >= kdata.iloc[take_index][dogen.P_CLOSE]:
                take_index = 0
            pass
        pass
    if take_index is None or take_index > take_valid:
        logger.debug("Don't get valid take-trade since %s" %
                     kdata.index[pick_index])
        return None

    return [pick_index, take_index, rise_range]
Ejemplo n.º 21
0
def exclude_analyze(basic, kdata, pick_index, take_index, rise_range,
                    policy_args):
    min_lhigh = __parse_policy_args(policy_args, MIN_LHIGH)
    pick_valid = __parse_policy_args(policy_args, PICK_VALID)
    max_take2low = __parse_policy_args(policy_args, MAX_TAKE2LOW)
    max_pclose = __parse_policy_args(policy_args, MAX_PCLOSE)
    outstanding = __parse_policy_args(policy_args, OUTSTANDING)
    [from_index, high_index, inc_close, get_lhigh, tmpId] = rise_range

    ### 净资产为负数的
    if basic[dogen.BVPS] < 0.5:
        logger.debug("Invalid bvps")
        return True

    ### 特征三
    if kdata.iloc[take_index][dogen.P_CLOSE] > max_pclose:
        logger.debug("Too high close price at %s" % kdata.index[take_index])
        return True
    if kdata.iloc[take_index][dogen.P_CLOSE] * basic[
            dogen.OUTSTANDING] > outstanding:
        logger.debug("Too large outstanding at %s" % kdata.index[take_index])
        return True

    ### 特征四
    heap_lhigh = 0
    for temp_index in range(high_index, from_index):
        if kdata.iloc[temp_index][dogen.P_CLOSE] >= kdata.iloc[temp_index][
                dogen.L_HIGH]:
            heap_lhigh += 1
        else:
            heap_lhigh = 0
        if heap_lhigh > 1:
            logger.debug("Shouldn't include serial hl-trade")
            return True
        pass
    if kdata[kdata[dogen.P_CLOSE] >= kdata[
            dogen.L_HIGH]].index.size < min_lhigh:
        logger.debug("Don't include %d hl-trade" % min_lhigh)
        return True

    ### 特征七
    if pick_index + 1 >= pick_valid:
        macd = dogen.forecast_macd(kdata[dogen.MACD])
        if kdata.iloc[0][dogen.MACD] < -0.1 and macd < -0.1:
            logger.debug("Invalid MACD at %s" % kdata.index[0])
            return True
        pass

    return False
Ejemplo n.º 22
0
def match(codes, start=None, end=None, save_result=False, policy_args=None):
    """ 涨停上涨策略, 满足条件:
        >>> 基本条件
            一 仅有一个涨停在[min_hl, max_hl]交易区间以内;
            二 买入信号(take-trade),有效期由take_valid限定:
                1) 5日以内收盘价均维持在涨停价以上,且相对涨停价涨幅不高于5个点;
                2) 5日以外累积上涨幅度达5个点或单日涨幅3点以上,且收盘价突破涨停价, 下面情况更新take-trade;
                    a. 若take-trade之后限一个交易日缩量下跌;
                    b. 若take-trade之后最后交易日收盘价突破,更新为买入信号;
        
        >>> 排它条件
            三 股价市值在outstanding(100亿)和maxi_close(50以下)限制范围内
            四 股价成本合理:
                1) 在最近一个月内,最高涨幅由maxi_rise限制; 
            五 take-trade限制:
                1) take-trade交易日收盘价高于涨停价-3%,但不超过回调最低价+15%;
                2) 维持上涨趋势:MA5上涨,MA20上涨
                3) 排除放量上影线
            六 形态限制:
                1) 涨停之后保持碗底弧形上涨趋势, 碗底收盘价低于涨停价-3个点以上,二次拟合系数大于0.008;
                2) 涨停之后回调超过-3之后,只允许一次突破前高;(暂未实现)
            七 碗底之后若放量下跌必须突破开盘价
            八 回调最低价之后交易日必须满足下面条件:
                1) 没有超过7%的单日涨幅
                2) 存在振幅5个点以上交易日
                3) 每三日累积涨幅不超过前一日涨停价

        参数说明:
            start - 样本起始交易日(数据库样本可能晚于该日期, 如更新不全);若未指定默认取end-$max_days做起始日
            end - 样本截止交易日(数据库样本可能早于该日期, 如停牌)
            save_result - 保存命中结果
        
        返回结果:
            列表数据如[{item-1}, {item-2}, ..., {item-n}],根据股票的流通市值、收盘价、成交量、涨跌幅等数据决策。
    """
    ### 数据库连接初始化
    db = dogen.DbMongo(uri=mongo_server, database=mongo_database)
    if not db.connect():
        logger.error("Cannot connect to mongo-server %s" % mongo_server)
        return None

    ### 截至日期修正
    expon = db.lookup_stock_kdata(dogen.get_index_of_sh(), end=end)
    if expon is None:
        logger.error("Don't get expon data")
        return None
    else:
        end = expon.index[0]
        start = dogen.date_delta(end,
                                 -__parse_policy_args(policy_args, MAX_TRADES))

    ### 依次策略检查
    match_list = []
    for code in codes:
        try:
            ### 从数据库读取basic数据
            basic = db.lookup_stock_basic(code)
            if dogen.drop_stock_check(code, basic):
                continue

            ### 从数据库读取日线数据,必须按索引(日期)降序排列
            kdata = db.lookup_stock_kdata(code, start=start, end=end)
            if kdata is None:
                continue
            elif kdata.index[0] != end:
                logger.debug("End date don't match")
                continue
            else:
                dogen.drop_fresh_stock_trades(basic, kdata)

            ### 策略分析
            if kdata is not None and kdata.index.size > 0:
                logger.debug("Begin in analyzing %s from %s to %s" %
                             (code, kdata.index[-1], kdata.index[0]))
                match = stock_analyze(basic, kdata, policy_args)
                if match is None:
                    continue
                ### 输出结果
                match_list.append(match)

        except Exception:
            logger.error('Trggered in handling code %s: %s' %
                         (code, traceback.format_exc()))
            continue
        pass

    ### 保存结果到数据库
    if save_result and len(match_list) > 0:
        db.insert_policy_result(__name__.split('.')[-1],
                                match_list,
                                key_name=dogen.RST_COL_INDEX)

    return match_list
Ejemplo n.º 23
0
def exclude_analyze(basic, kdata, pick_index, take_index, policy_args):
    """ 根据日线做排除性校验
    """
    max_rise = __parse_policy_args(policy_args, MAX_RISE)
    max_take2low = __parse_policy_args(policy_args, MAX_TAKE2LOW)
    min_falls = __parse_policy_args(policy_args, MIN_FALLS)
    max_rclose = __parse_policy_args(policy_args, MAX_RCLOSE)
    min_ramp = __parse_policy_args(policy_args, MIN_RAMP)
    min_polyf2 = __parse_policy_args(policy_args, MIN_POLYF2)
    max_pclose = __parse_policy_args(policy_args, MAX_PCLOSE)
    outstanding = __parse_policy_args(policy_args, OUTSTANDING)

    ### 取回调最低价
    mini_index = dogen.get_last_column_min(kdata,
                                           dogen.P_CLOSE,
                                           sIdx=take_index,
                                           eIdx=pick_index)

    ### 净资产为负数的
    if basic[dogen.BVPS] < 0:
        logger.debug("Invalid bvps")
        return True

    ### 特征三
    if kdata.iloc[take_index][dogen.P_CLOSE] > max_pclose:
        logger.debug("Too high close price at %s" % kdata.index[take_index])
        return True
    if kdata.iloc[take_index][dogen.P_CLOSE] * basic[
            dogen.OUTSTANDING] > outstanding:
        logger.debug("Too large outstanding at %s" % kdata.index[take_index])
        return True

    ### 特征四
    rise_range = dogen.get_last_rise_range(kdata,
                                           max_rise,
                                           max_fall=max_rise / 2,
                                           eIdx=22)
    if rise_range is not None:
        [min_index, max_index, inc_close, get_lhigh, tmp_index] = rise_range
        if max_rise < dogen.caculate_incr_percentage(
                kdata.iloc[take_index][dogen.P_CLOSE],
                kdata.iloc[min_index][dogen.P_CLOSE]):
            logger.debug("Too large rise-range")
            return True
        pass

    ### 特征五
    if pick_index >= 5:
        high_index = pick_index
        if kdata.iloc[pick_index - 1][dogen.R_CLOSE] > 0:
            high_index = pick_index - 1
        if dogen.caculate_incr_percentage(
                kdata.iloc[take_index][dogen.P_CLOSE],
                kdata.iloc[high_index][dogen.P_CLOSE]) < -min_falls:
            logger.debug("Too low P-CLOSE at take-trade %s" %
                         kdata.index[take_index])
            return True
        if kdata.iloc[take_index][dogen.MA5] < kdata.iloc[take_index +
                                                          1][dogen.MA5]:
            logger.debug("Invalid MA20 at %s" % kdata.index[take_index])
            return True
        if kdata.iloc[take_index][dogen.MA20] < kdata.iloc[take_index +
                                                           1][dogen.MA20]:
            logger.debug("Invalid MA20 at %s" % kdata.index[take_index])
            return True
        if kdata.iloc[take_index][
                dogen.VOLUME] > kdata.iloc[take_index + 1][dogen.VOLUME] * 1.1:
            h2l = dogen.caculate_incr_percentage(
                kdata.iloc[take_index][dogen.P_HIGH],
                kdata.iloc[take_index][dogen.P_LOW])
            c2l = dogen.caculate_incr_percentage(
                kdata.iloc[take_index][dogen.P_CLOSE],
                kdata.iloc[take_index][dogen.P_LOW])
            if c2l * 2 < h2l:
                logger.debug("Get up shadow at %s" % kdata.index[take_index])
                return True
            pass
        pass

    ### 特征七
    if pick_index >= 5:
        for temp_index in range(mini_index - 1, -1, -1):
            ### 下跌
            if kdata.iloc[temp_index][dogen.R_CLOSE] >= 0 or kdata.iloc[
                    temp_index + 1][dogen.R_CLOSE] <= 0:
                continue
            if kdata.iloc[temp_index][dogen.VOLUME] <= kdata.iloc[
                    temp_index + 1][dogen.VOLUME]:
                continue
            ### 放量下跌之后未被上涨突破
            maxi_index = dogen.get_last_column_max(kdata,
                                                   dogen.P_CLOSE,
                                                   eIdx=temp_index)
            if maxi_index is None or kdata.iloc[temp_index][
                    dogen.P_OPEN] > kdata.iloc[maxi_index][dogen.P_CLOSE]:
                logger.debug("Invalid fall-trade at %s" %
                             kdata.index[temp_index])
                return True
            pass
        pass

    ### 特征八
    if pick_index >= 5:
        tdata = kdata[0:mini_index]
        if tdata[tdata[dogen.R_AMP] >= min_ramp].index.size <= 0:
            logger.debug(
                "Don't include trade with 5 percentage R-AMP since %s" %
                kdata.index[mini_index])
            return True
        for temp_index in range(mini_index, 0, -1):
            hl_price = dogen.caculate_l_high(
                kdata.iloc[temp_index][dogen.P_CLOSE])
            tdata = kdata[temp_index - 4:temp_index - 1]
            if tdata[tdata[dogen.P_CLOSE] >= hl_price].index.size > 0:
                logger.debug("Too large heap-close from %s to %s" %
                             (tdata.index[-1], tdata.index[0]))
                return True
            pass
        pass

    return False
Ejemplo n.º 24
0
def exclude_analyze(basic, kdata, pick_index, take_index, policy_args):
    max_rclose  = __parse_policy_args(policy_args, MAX_RCLOSE)
    min_ramp    = __parse_policy_args(policy_args, MIN_RAMP)
    max_rise    = __parse_policy_args(policy_args, MAX_RISE)
    max_pclose  = __parse_policy_args(policy_args, MAX_PCLOSE)
    outstanding = __parse_policy_args(policy_args, OUTSTANDING)

    ### 净资产为负数的
    if basic[dogen.BVPS] < 0.1:
        logger.debug("Invalid bvps")
        return True

    ### 特征三
    if kdata.iloc[take_index][dogen.P_CLOSE] > max_pclose:
        logger.debug("Too high close price at %s" % kdata.index[take_index])
        return True
    if kdata.iloc[take_index][dogen.P_CLOSE] * basic[dogen.OUTSTANDING] > outstanding:
        logger.debug("Too large outstanding at %s" % kdata.index[take_index])
        return True

    ### 特征四
    rise_range = dogen.get_last_rise_range(kdata, max_rise, max_fall=max_rise/2, eIdx=22)
    if rise_range is not None:
        [min_index, max_index, inc_close, get_lhigh, tmp_index] = rise_range
        if max_rise < dogen.caculate_incr_percentage(kdata.iloc[take_index][dogen.P_CLOSE], kdata.iloc[min_index][dogen.P_CLOSE]):
            logger.debug("Too large rise-range")
            return True
        pass

    ### 特征五
    tdata = kdata[0:5]
    if tdata[tdata[dogen.R_CLOSE]>0].index.size <= tdata.index.size/2:
        logger.debug("Don't contain enough up trades in last week")
        return True
    if dogen.get_highlimit_trades(tdata).size > 0:
        logger.debug("There is hl trade in last week")
        return True

    ### 特征六
    for temp_index in range(pick_index, -1, -1):
        ### 下跌
        if kdata.iloc[temp_index][dogen.R_CLOSE] >= 0 or kdata.iloc[temp_index+1][dogen.R_CLOSE] <= 0:
            continue
        if kdata.iloc[temp_index][dogen.VOLUME] <= kdata.iloc[temp_index+1][dogen.VOLUME]:
            continue
        ### 放量下跌之后未被上涨突破
        maxi_index = dogen.get_last_column_max(kdata, dogen.P_CLOSE, eIdx=temp_index)
        if maxi_index is None or kdata.iloc[temp_index][dogen.P_OPEN] > kdata.iloc[maxi_index][dogen.P_CLOSE]:
            logger.debug("Invalid fall-trade at %s" % kdata.index[temp_index])
            return True
        pass

    return False