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
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
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
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
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]
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
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]
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
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]
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]
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]
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]
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]
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
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
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]
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
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
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
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]
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
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
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
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