def on_market_prepare_open(self, protfolio: Portfolio, today: datetime): """ 市场准备开始(比如:竞价). """ indicator = Indicator(40) for code in self.codes: bars = self.market.getHistory().getKbars(code, 100) indicator.update_bar(bars) count = 20 aroon_down, aroon_up = indicator.aroon(count) need_hold = aroon_up > 50 and aroon_up > aroon_down position = protfolio.getLongPosition(code) if need_hold: if position.pos_total < 1: targetPrice = bars[-1].close_price * 1.05 # 上一个交易日的收盘价作为买如价 ok = protfolio.buyAtPercentage(code, targetPrice, 1) print(f"buy: price = {targetPrice} , {ok}") else: if position.pos_total > 0: targetPrice = bars[-1].close_price * 0.92 # 上一个交易日的收盘价作为买如价 ok = protfolio.sellAll(code, targetPrice) print(f"sell: price = {targetPrice} , {ok}") pass
def computeAll(): from earnmi.data.SWImpl import SWImpl from earnmi.chart.Chart import Chart, IndicatorItem, Signal sw = SWImpl() lists = sw.getSW2List() start = datetime(2018, 5, 1) end = datetime(2020, 8, 17) dataSet = {} class DataItem(object): pass for code in lists: #for code in lists: barList = sw.getSW2Daily(code, start, end) indicator = Indicator() for bar in barList: ##先识别形态 rets = KPattern.matchIndicator(indicator) size = len(rets) if size > 0: """有形态识别出来 """ for item in rets: name = item.name value = item.value dataItem = None if dataSet.__contains__(name): dataItem = dataSet[name] else: dataItem = DataItem() dataItem.values = [] ##形态被识别的值。 dataItem.pcts = [] ##识别之后第二天的盈利情况 dataSet[name] = dataItem ##第二天的收益 pct = (bar.close_price - bar.open_price) / bar.open_price ##收录当前形态 dataItem.values.append(value) dataItem.pcts.append(pct) pass indicator.update_bar(bar) ##打印当前形态 print(f"总共识别出{len(dataSet)}个形态") for key, dataItem in dataSet.items(): values = np.array(dataItem.values) pcts = np.array(dataItem.pcts) * 100 print( f"{key}: len={len(dataItem.values)},values:{values.mean()},pcts:%.2f%%,pcts_std=%.2f" % (pcts.mean(), pcts.std()))
def collectKPattherAndShowChart(): from earnmi.data.SWImpl import SWImpl from vnpy.trader.constant import Exchange from vnpy.trader.constant import Interval sw = SWImpl() lists = sw.getSW2List() start = datetime(2014, 5, 1) end = datetime(2020, 8, 17) bars = [] limitSize = 0 chart = Chart() for code in lists: # for code in lists: barList = sw.getSW2Daily(code, start, end) indicator = Indicator(40) preBar = None yestodayIsMatch = False for i in range(0, len(barList)): bar = barList[i] indicator.update_bar(bar) patternValue = KPattern.encode1KAgo1(indicator) todayIsMatch = 9 == patternValue if todayIsMatch: if indicator.count > 20: chart.show( indicator.makeBars(), savefig=f"imgs/collectKPattherAndShowChart_{limitSize}" ) limitSize += 1 if (limitSize > 50): break pass if yestodayIsMatch: pass preBar = bar yestodayIsMatch = todayIsMatch if (limitSize > 50): break pass
def on_market_prepare_open(self, protfolio: Portfolio, today: datetime): """ 市场准备开始(比如:竞价). """ indicator = Indicator(40) for code in self.codes: bars = self.market.getHistory().getKbars(code, 100) indicator.update_bar(bars) dif, dea, macd_bar = indicator.kdj() ##金叉出现 if (macd_bar[-1] >= 0 and macd_bar[-2] <= 0): tradePrice = bars[-1].close_price * 1.01 # 上一个交易日的收盘价作为买如价 protfolio.buy(code, tradePrice, 1) protfolio.cover(code, tradePrice, 1) ##平仓做空 ##死叉出现 if (macd_bar[-1] <= 0 and macd_bar[-2] >= 0): targetPrice = bars[-1].close_price * 0.99 # 上一个交易日的收盘价作为买如价 protfolio.sell(code, targetPrice, 1) protfolio.short(code, targetPrice, 1) ##开仓做空 pass
def computeAndPrint(bars: []) -> AnalysisData: data = AnalysisData() total_count = len(bars) previous_macd = -1 previouc_kdj = -1 indicator = Indicator(50) for i in range(0, total_count): bar: BarData = bars[i] indicator.update_bar(bar) k_large_than_d = False if indicator.count >= 13: k, d, j = indicator.kdj(fast_period=9, slow_period=3, array=True) k_large_than_d = k[-1] >= d[-1] ##金叉出现 if (k[-1] >= d[-1] and k[-2] <= d[-2]): previouc_kdj = i if indicator.count >= 30: dif, dea, macd_bar = indicator.macd(fast_period=12, slow_period=26, signal_period=9, array=True) ##金叉出现 if (macd_bar[-1] >= 0 and macd_bar[-2] <= 0): previous_macd = i if previouc_kdj > 0: data.count = data.count + 1 if k_large_than_d: data.k_large_than_d_count = data.k_large_than_d_count + 1 dis = previous_macd - previouc_kdj if (dis >= 0 and dis < KDJ_DIS_SIZE): data.kdj_dis[dis] = data.kdj_dis[dis] + 1 return data
def on_bar_per_minute(self, time: datetime, protfolio: Portfolio): """ 市场开市后的每分钟。 """ #每天两点半的后尝试去做交易。 if time.hour == 14 and time.minute == 30: self.__history_bar100 = self.market.getHistory().getKbars( self.code, 100) assert len(self.__history_bar100) == 100 bars = self.__history_bar100 todayBar = self.market.getRealTime().getKBar(self.code) indicator = Indicator(40) indicator.update_bar(bars) dif, dea, macd_bar = indicator.macd(fast_period=12, slow_period=26, signal_period=9, array=True) if (not self.today_has_buy): # 预测金叉 todayBar.close_price = todayBar.close_price * 1.01 indicator.update_bar(todayBar) dif, dea, predict_macd_bar = indicator.macd(fast_period=12, slow_period=26, signal_period=9, array=True) print( f"[{self.market.getToday()}]:bar={macd_bar[-1]},predic_bar={predict_macd_bar[-1]}" ) if (predict_macd_bar[-1] > 0 and macd_bar[-1] <= 0): targetPrice = todayBar.close_price # 上一个交易日的收盘价作为买如价 print(f" gold cross!!!") if protfolio.buy(self.code, targetPrice, 100): self.today_has_buy = True elif (not self.today_has_sell): todayBar.close_price = todayBar.close_price * 0.99 indicator.update_bar(todayBar) dif, dea, predict_macd_bar = indicator.macd(fast_period=12, slow_period=26, signal_period=9, array=True) print( f"[{self.market.getToday()}]:bar={macd_bar[-1]},predic_bar={predict_macd_bar[-1]}" ) if (predict_macd_bar[-1] <= 0 and macd_bar[-1] > 0): targetPrice = todayBar.close_price print(f" dead cross!!!") if protfolio.sell(self.code, targetPrice, 100): self.today_has_sell = True
def findKPatternThatIn3Day(first_day_pct: float = 3, targe_pct=3): sw = SWImpl() lists = sw.getSW2List() start = datetime(2014, 5, 1) end = datetime(2020, 8, 17) dataSet = {} total_count = 0 for code in lists: # for code in lists: barList = sw.getSW2Daily(code, start, end) indicator = Indicator(40) traceItems: ['TraceIn3DayItem'] = [] for bar in barList: ###跟踪数据 toDeleteList = [] for traceItem in traceItems: traceItem.onTraceBar(bar) if traceItem.isFinished(): toDeleteList.append(traceItem) if traceItem.isWanted(): ###归纳到统计里面 dataItem: CountItem = dataSet.get(traceItem.kPattern) if dataItem is None: dataItem = CountItem() dataSet[traceItem.kPattern] = dataItem pct = traceItem.current_sell_pct total_count += 1 dataItem.count_total += 1 dataItem.pct_total += pct if traceItem.isSuccess(): dataItem.count_earn += 1 dataItem.pct_earn += pct pass for traceItem in toDeleteList: traceItems.remove(traceItem) indicator.update_bar(bar) kEncodeValue = KPattern.encode2KAgo1(indicator) if kEncodeValue is None: continue traceItem = TraceIn3DayItem(kEncodeValue, bar) traceItems.append(traceItem) ##打印当前形态 occur_count = 0 print(f"总共分析{total_count}个形态,识别出{len(dataSet)}个形态,有意义的形态有:") max_succ_rate = 0 min_succ_rate = 100 ret_list = [] for key, dataItem in dataSet.items(): success_rate = 100 * dataItem.count_earn / dataItem.count_total if dataItem.count_total < 300: continue if success_rate < 40: continue ret_list.append(key) if dataItem.count_earn > 0: earn_pct = dataItem.pct_earn / dataItem.count_earn else: earn_pct = 0 avg_pct = dataItem.pct_total / dataItem.count_total occur_count += dataItem.count_total occur_rate = 100 * dataItem.count_total / total_count max_succ_rate = max(success_rate, max_succ_rate) min_succ_rate = min(success_rate, min_succ_rate) print( f"{key}: total={dataItem.count_total},suc=%.2f%%,occur_rate=%.2f%%,earn_pct:%.2f%%,avg_pct:%.2f%%)" % (success_rate, occur_rate, earn_pct, avg_pct)) total_occur_rate = 100 * occur_count / total_count print(f"总共:occur_rate=%.2f%%, min_succ_rate=%.2f%%, max_succ_rate=%.2f%%" % (total_occur_rate, min_succ_rate, max_succ_rate)) print(f"{ret_list}")
class TheEngineModel(CoreEngineModel): def __init__(self): self.lasted3Bar = np.array([None, None, None]) self.lasted3BarKdj = np.array([None, None, None]) self.kdjEncoder = FloatEncoder([15, 30, 45, 60, 75, 90]) self.mDateOccurCountMap = {} ##统计产生收集个数的次数 self.sw = SWImpl() def onCollectStart(self, code: str) -> bool: from earnmi.chart.Indicator import Indicator self.indicator = Indicator(34) self.code = code return True def onCollectTrace(self, bar: BarData) -> CollectData: self.indicator.update_bar(bar) self.lasted3Bar[:-1] = self.lasted3Bar[1:] self.lasted3BarKdj[:-1] = self.lasted3BarKdj[1:] k, d, j = self.indicator.kdj(fast_period=9, slow_period=3) self.lasted3Bar[-1] = bar self.lasted3BarKdj[-1] = [k, d, j] timeKey = utils.to_start_date(bar.datetime) if self.mDateOccurCountMap.get(timeKey) is None: self.mDateOccurCountMap[timeKey] = 0 if self.indicator.count >= 30: aroon_down, aroon_up = self.indicator.aroon(n=14, array=False) from earnmi.chart.KPattern import KPattern if aroon_up < aroon_down or aroon_up < 50: return None kPatternValue = KPattern.encode2KAgo1(self.indicator) if not kPatternValue is None: self.mDateOccurCountMap[timeKey] += 1 _kdj_mask = self.kdjEncoder.mask() kPatternValue = kPatternValue * _kdj_mask * _kdj_mask + self.kdjEncoder.encode( k) * _kdj_mask + self.kdjEncoder.encode(d) dimen = Dimension(type=TYPE_2KAGO1, value=kPatternValue) collectData = CollectData(dimen=dimen) collectData.occurBars.append(self.lasted3Bar[-2]) collectData.occurBars.append(self.lasted3Bar[-1]) collectData.occurKdj.append(self.lasted3BarKdj[-2]) collectData.occurKdj.append(self.lasted3BarKdj[-1]) return collectData return None def onCollect(self, data: CollectData, newBar: BarData) -> bool: if len(data.occurBars) < 3: data.occurBars.append(self.lasted3Bar[-1]) data.occurKdj.append(self.lasted3BarKdj[-1]) else: data.predictBars.append(newBar) size = len(data.predictBars) return size >= 2 @abstractmethod def getYLabelPrice(self, cData: CollectData) -> [float, float, float]: bars: ['BarData'] = cData.predictBars if len(bars) > 0: sell_price = -9999999999 buy_price = -sell_price for bar in bars: sell_price = max((bar.high_price + bar.close_price) / 2, sell_price) buy_price = min((bar.low_price + bar.close_price) / 2, buy_price) return sell_price, buy_price return None, None def getYBasePrice(self, cData: CollectData) -> float: return cData.occurBars[-2].close_price def generateXFeature(self, cData: CollectData) -> []: #保证len小于三,要不然就不能作为生成特征值。 if (len(cData.occurBars) < 3): return None occurBar = cData.occurBars[-2] skipBar = cData.occurBars[-1] kdj = cData.occurKdj[-1] sell_pct = 100 * ((skipBar.high_price + skipBar.close_price) / 2 - occurBar.close_price) / occurBar.close_price buy_pct = 100 * ((skipBar.low_price + skipBar.close_price) / 2 - occurBar.close_price) / occurBar.close_price def set_0_between_100(x): if x > 100: return 100 if x < 0: return 0 return x def percent_to_one(x): return int(x * 100) / 1000.0 data = [] data.append(percent_to_one(buy_pct)) data.append(percent_to_one(sell_pct)) data.append(set_0_between_100(kdj[0]) / 100) data.append(set_0_between_100(kdj[2]) / 100) return data
def run(self, bars: list, item: IndicatorItem = None): if (bars[0].datetime > bars[-1].datetime): bars = bars.__reversed__() data = [] index = [] indicator = Indicator() ### 初始化columns columns = ['Open', 'High', 'Low', 'Close', "Volume"] holdbarMaker: HoldBarMaker = None if not item is None: holdbarMaker = item._holdbarMaker if not holdbarMaker is None: holdbarMaker.reset() item_names = item.getNames() item_size = len(item_names) for i in range(item_size): columns.append(item_names[i]) columns.append("signal_buy") columns.append("signal_sell") columns.append("signal_redTag") item_signal_buy_open = False item_signal_sell_open = False item_signal_redTag_open = False item_signal = Signal() ##current_hold_bar: HoldBar = None has_buy = False for bar in bars: index.append(bar.datetime) list = [ bar.open_price, bar.high_price, bar.low_price, bar.close_price, bar.volume ] indicator.update_bar(bar) if not item is None: item_names = item.getNames() item_size = len(item_names) item_signal.reset() item_signal.hasBuy = has_buy item_value = item.getValues(indicator, bar, item_signal) for i in range(item_size): list.append(item_value[item_names[i]]) if item_signal.buy: list.append(bar.low_price * 0.99) item_signal_buy_open = True has_buy = True ##生成一个新的holdbar。 if not holdbarMaker is None: holdbarMaker.onHoldStart(bar) else: ##更新holdBar if not holdbarMaker is None: holdbarMaker.onHoldUpdate(bar) list.append(np.nan) if item_signal.sell: list.append(bar.high_price * 1.01) item_signal_sell_open = True has_buy = False ##结束目前的HoldBar if not holdbarMaker is None: holdbarMaker.onHoldEnd() else: list.append(np.nan) if item_signal.redTag: item_signal_redTag_open = True list.append(bar.low_price * 0.99) else: list.append(np.nan) data.append(list) trades = pd.DataFrame(data, index=index, columns=columns) return trades, item_signal_buy_open, item_signal_sell_open, item_signal_redTag_open
high_price=0, low_price=0) bar4 = BarData(symbol="test", exchange=Exchange.SSE, datetime=None, gateway_name="unkonw", open_price=884, high_price=0, low_price=0) indexes = Indicator(100) assert indexes.inited == False bars55 = buidildBars(55) indexes.update_bar(bars55) assert indexes.count == 55 assert indexes.inited == False assert indexes.open_array[-1] == 54 assert indexes.open_array[-55] == 0 bars42 = buidildBars(42) indexes.update_bar(bars42) assert indexes.count == 97 assert indexes.inited == False assert indexes.open_array[-1] == 41 assert indexes.open_array[-42] == 0 assert indexes.open_array[-43] == 54 indexes.update_bar(bar1) indexes.update_bar(bar2)
def compute_SW_KEncode_parseAlgro1_split( pct_split=[-7, -5, -3, -1.5, -0.5, 0.5, 1.5, 3, 5, 7], extra_split=[1, 2, 3]): from earnmi.data.SWImpl import SWImpl sw = SWImpl() lists = sw.getSW2List() start = datetime(2014, 5, 1) end = datetime(2020, 8, 17) dataSet = {} pct_split = [-7, -5, -3, -1.5, -0.5, 0.5, 1.5, 3, 5, 7] extra_split = [0.5, 1.0, 1.5, 2.0, 2.5, 2.0] total_count = 0 pct_code_count = np.zeros(len(pct_split) + 1) high_extra_pct_code_count = np.zeros(len(extra_split) + 1) low_extra_pct_code_count = np.zeros(len(extra_split) + 1) for code in lists: #for code in lists: barList = sw.getSW2Daily(code, start, end) indicator = Indicator(40) preBar = None for i in range(0, len(barList)): bar = barList[i] indicator.update_bar(bar) if (i > 10): k_code, pct_code, high_extra_pct_code, low_extra_pct_code = KEncode.parseAlgro1( indicator.close[-2], indicator.open[-1], indicator.high[-1], indicator.low[-1], indicator.close[-1], pct_split, extra_split) high_extra_pct_code_count[ high_extra_pct_code] = high_extra_pct_code_count[ high_extra_pct_code] + 1 low_extra_pct_code_count[ low_extra_pct_code] = low_extra_pct_code_count[ low_extra_pct_code] + 1 pct_code_count[pct_code] = pct_code_count[pct_code] + 1 total_count += 1 preBar = bar ##打印当前形态 print(f"pct_split: {pct_split}") print(f"extra_split: {extra_split}") count_list = pct_code_count print(f"应该服从正太分布") print(f"\n:pct_code_count分布,avg = %.4f%%" % (100 / len(count_list))) for codeId in range(0, len(count_list)): item_count = count_list[codeId] item_occur_rate = 100 * item_count / total_count print(f"\t{codeId}: %.4f %% count:%d" % (item_occur_rate, item_count)) count_list = high_extra_pct_code_count print(f"\n:high_extra_pct_code_count分布,avg = %.4f%%" % (100 / len(count_list))) for codeId in range(0, len(count_list)): item_count = count_list[codeId] item_occur_rate = 100 * item_count / total_count print(f"\t{codeId}: %.4f %% count:%d" % (item_occur_rate, item_count)) count_list = low_extra_pct_code_count print(f"\n:low_extra_pct_code_count分布,avg = %.4f%%" % (100 / len(count_list))) for codeId in range(0, len(count_list)): item_count = count_list[codeId] item_occur_rate = 100 * item_count / total_count print(f"\t{codeId}: %.4f %% count:%d" % (item_occur_rate, item_count))
def compute_SW_KPattern_data(): from earnmi.data.SWImpl import SWImpl from earnmi.chart.Chart import Chart, IndicatorItem, Signal sw = SWImpl() lists = sw.getSW2List() start = datetime(2014, 5, 1) end = datetime(2020, 8, 17) dataSet = {} total_count = 0 for code in lists: #for code in lists: barList = sw.getSW2Daily(code, start, end) indicator = Indicator() preBar = None for bar in barList: ##先识别形态 rets = KPattern.matchIndicator(indicator) size = len(rets) if size > 0 and not preBar is None: """有形态识别出来 """ for item in rets: name = item.name value = item.value total_count += 1 dataItem = None if dataSet.__contains__(name): dataItem = dataSet[name] else: dataItem = CountItem() dataItem.values = [] ##形态被识别的值。 dataItem.pcts = [] ##识别之后第二天的盈利情况 dataSet[name] = dataItem ##第二天的收益 short_pct = ((bar.high_price + bar.close_price) / 2 - preBar.close_price) / preBar.close_price #long_pct = ((bar.high_price + bar.close_price) / 2 - preBar.close_price) / preBar.close_price ###pct = (bar.close_price - preBar.close_price) / preBar.close_price ##收录当前形态 dataItem.count_total += 1 dataItem.pct_total += short_pct if short_pct > 0.000001: dataItem.count_earn += 1 dataItem.pct_earn += short_pct dataItem.values.append(value) dataItem.pcts.append(short_pct) pass indicator.update_bar(bar) preBar = bar ##打印当前形态 print(f"总共分析{total_count}个形态,识别出{len(dataSet)}个形态,有意义的形态有:") for key, dataItem in dataSet.items(): if dataItem.count_total < 1000: continue success_rate = 100 * dataItem.count_earn / dataItem.count_total if abs(int(success_rate - 50)) < 5: continue values = np.array(dataItem.values) pcts = np.array(dataItem.pcts) * 100 count = len(values) long_values = [] short_value = [] long_pcts = [] long_ok_cnt = 0 short_pcts = [] short_ok_cnt = 0 for i in range(0, count): v = values[i] if v > 0: long_values.append(v) long_pcts.append(pcts[i]) if pcts[i] >= 0.000001: long_ok_cnt = long_ok_cnt + 1 else: short_value.append(v) short_pcts.append(pcts[i]) if pcts[i] <= -10.000001: short_ok_cnt = short_ok_cnt + 1 long_values = np.array(long_values) short_value = np.array(short_value) long_pcts = np.array(long_pcts) short_pcts = np.array(short_pcts) long_pct = 0 long_std = math.nan long_success = math.nan short_pct = 0 short_std = math.nan short_success = math.nan if len(long_values) > 0: long_pct = long_pcts.mean() long_std = long_pcts.std() long_success = long_ok_cnt / len(long_values) if len(short_value) > 0: short_pct = short_pcts.mean() short_std = short_pcts.std() short_success = short_ok_cnt / len(short_value) print( f"{key}: count={count},suc_reate=%.2f%%,long(size:{len(long_values)},suc=%.2f%%,pcts:%.2f%%,std=%.2f),short(size:{len(short_value)},suc=%.2f%%,pcts:%.2f%%,std=%.2f)" % (success_rate, long_success * 100, long_pct, long_std, short_success * 100, short_pct, short_std)) print("-----------具体情况-----------") outputKeys = ["CDLADVANCEBLOCK"] for key in outputKeys: dataItem = dataSet[key] values = np.array(dataItem.values) pcts = np.array(dataItem.pcts) * 100 count = len(dataItem.values) print( f"{key}: count={count},values:{values.mean()},pcts:%.2f%%,pcts_std=%.2f" % (pcts.mean(), pcts.std())) itemSize = 10 size = int(count / itemSize) if count % itemSize > 0: size = size + 1 for i in range(0, size): lineStr = "" start = itemSize * i end = min(start + itemSize, count) for j in range(start, end): lineStr = lineStr + (f" %4d->%.2f%%," % (values[j], pcts[j])) print(lineStr)
def printKPatterMoreDetail(kPatters=[ 6, 3, 17, 81, 7, 5, 4, 82, 159, 16, 28, 83, 15, 84, 18, 27, 93, 104, 158, 92, 160, 236, 157, 94, 85, 80, 14, 8, 161, 9, 29, 170, 26, 19, 38, 2, 79 ]): from earnmi.data.SWImpl import SWImpl from vnpy.trader.constant import Exchange from vnpy.trader.constant import Interval sw = SWImpl() lists = sw.getSW2List() start = datetime(2014, 5, 1) end = datetime(2020, 8, 17) pct_split = [-7, -5, -3, -1.5, -0.5, 0.5, 1.5, 3, 5, 7] pct_split = [-7, -5, -3, -1.0, 0, 1, 3, 5, 7] pct_split = [-0.5, 0.5] pctEncoder = FloatEncoder(pct_split) kPattersMap = {} for value in kPatters: kPattersMap[value] = True class InnerData(object): kValue: int ## sell_disbute = np.zeros(pctEncoder.mask()) ##卖方力量分布情况 buy_disbute = np.zeros(pctEncoder.mask()) #买方力量分布情况 pass dataSet = {} occurDayMap = {} allTrayDay = 1 for code in lists: # for code in lists: barList = sw.getSW2Daily(code, start, end) indicator = Indicator(40) preBar = None previousIsMatch = False previousPatternVaule = None allTrayDay = max(allTrayDay, len(barList)) for i in range(0, len(barList)): bar = barList[i] indicator.update_bar(bar) patternValue = KPattern.encode1KAgo1(indicator) todayIsMatch = False if not patternValue is None: todayIsMatch = kPattersMap.__contains__(patternValue) if todayIsMatch: dayKey = bar.datetime.year * 13 * 35 + bar.datetime.month * 13 + bar.datetime.day occurDayMap[dayKey] = True pass if previousIsMatch: innerData: InnerData = dataSet.get(previousIsMatch) if innerData is None: innerData = InnerData() innerData.kValue = previousIsMatch dataSet[previousPatternVaule] = innerData sell_pct = 100 * ((bar.high_price + bar.close_price) / 2 - preBar.close_price) / preBar.close_price buy_pct = 100 * ((bar.low_price + bar.close_price) / 2 - preBar.close_price) / preBar.close_price innerData.buy_disbute[pctEncoder.encode(buy_pct)] += 1 innerData.sell_disbute[pctEncoder.encode(sell_pct)] += 1 pass preBar = bar previousIsMatch = todayIsMatch previousPatternVaule = patternValue print(f"所有交易日中,有意义的k线形态出现占比:%.2f%%" % (100 * len(occurDayMap) / allTrayDay)) for kValue, dataItem in dataSet.items(): total_count1 = 0 total_count2 = 0 for cnt in dataItem.sell_disbute: total_count1 += cnt for cnt in dataItem.buy_disbute: total_count2 += cnt assert total_count1 == total_count2 assert total_count1 > 0 print(f"\n\nk:%6d, " % (kValue)) print(f" 卖方价格分布:") for encode in range(0, len(dataItem.sell_disbute)): occurtRate = 100 * dataItem.sell_disbute[encode] / total_count1 print(f" {pctEncoder.descriptEncdoe(encode)}:%.2f%%" % (occurtRate)) print(f" 买方价格分布:") for encode in range(0, len(dataItem.buy_disbute)): occurtRate = 100 * dataItem.buy_disbute[encode] / total_count1 print(f" {pctEncoder.descriptEncdoe(encode)}:%.2f%%" % (occurtRate)) pass
def compute_SW_KEncode_data(): from earnmi.data.SWImpl import SWImpl sw = SWImpl() lists = sw.getSW2List() start = datetime(2014, 5, 1) end = datetime(2020, 8, 17) dataSet = {} total_count = 0 occurKPattenDayMap = {} kBarListTotalDay = 0 for code in lists: #for code in lists: barList = sw.getSW2Daily(code, start, end) indicator = Indicator(40) preBar = None kBarListTotalDay = len(barList) for bar in barList: ##先识别形态 kEncodeValue = KPattern.encode1KAgo1(indicator) if kEncodeValue is None: indicator.update_bar(bar) preBar = bar continue total_count += 1 dataItem: CountItem = None if dataSet.__contains__(kEncodeValue): dataItem = dataSet[kEncodeValue] else: dataItem = CountItem() dataSet[kEncodeValue] = dataItem ##第二天的收益 pct = ((bar.high_price + bar.close_price) / 2 - preBar.close_price) / preBar.close_price ##收录当前形态 #dataItem.values.append(value) dataItem.count_total += 1 dataItem.pct_total += pct if pct > 0.000001: dataItem.count_earn += 1 dataItem.pct_earn += pct indicator.update_bar(bar) preBar = bar occurDayKey = preBar.datetime.year * 13 * 35 + preBar.datetime.month * 35 + preBar.datetime.day occurKPattenDayMap[occurDayKey] = True ##打印当前形态 occur_count = 0 print(f"总共分析{total_count}个形态,识别出{len(dataSet)}个形态,有意义的形态有:") max_succ_rate = 0 min_succ_rate = 100 ret_list = [] for key, dataItem in dataSet.items(): success_rate = 100 * dataItem.count_earn / dataItem.count_total if dataItem.count_total < 500: continue if abs(int(success_rate - 50)) < 10: continue ret_list.append(key) earn_pct = 100 * dataItem.pct_earn / dataItem.count_earn if success_rate < 50: earn_pct = 100 * (dataItem.pct_total - dataItem.pct_earn) / ( dataItem.count_total - dataItem.count_earn) avg_pct = 100 * dataItem.pct_total / dataItem.count_total occur_count += dataItem.count_total occur_rate = 100 * dataItem.count_total / total_count max_succ_rate = max(success_rate, max_succ_rate) min_succ_rate = min(success_rate, min_succ_rate) print( f"{key}: total={dataItem.count_total},suc=%.2f%%,occur_rate=%.2f%%,earn_pct:%.2f%%,avg_pct:%.2f%%)" % (success_rate, occur_rate, earn_pct, avg_pct)) total_occur_rate = 100 * occur_count / total_count total_occur_in_day_rate = 100 * len( occurKPattenDayMap) / kBarListTotalDay ##在所有交易日中,k线形态日出占比: print(f"总共:occur_rate=%.2f%%, min_succ_rate=%.2f%%, max_succ_rate=%.2f%%" f"\n所有交易日中,k线形态日出占比:%.2f%%" % (total_occur_rate, min_succ_rate, max_succ_rate, total_occur_in_day_rate)) print(f"{ret_list}")
def generateSWTrainData(kPatterns: [], start: datetime, end: datetime) -> pd.DataFrame: sw = SWImpl() lists = sw.getSW2List() cloumns = [ "code", "name", "kPattern", "k", "d", "dif", "dea", "macd", "open", "short", "long" ] datas = [] kPatternMap = {} for kPatternValues in kPatterns: kPatternMap[kPatternValues] = True macd_list = [] for code in lists: # for code in lists: name = sw.getSw2Name(code) barList = sw.getSW2Daily(code, start, end) indicator = Indicator(34) preBar = None for bar in barList: ##先识别形态 kEncodeValue = None if indicator.inited: tmpKEncodeValue = KPattern.encode3KAgo1(indicator) if kPatternMap.__contains__(tmpKEncodeValue): kEncodeValue = tmpKEncodeValue if kEncodeValue is None: indicator.update_bar(bar) preBar = bar continue ##昨天的kdj k, d, j = indicator.kdj(array=False) dif, dea, macd = indicator.macd(fast_period=12, slow_period=26, signal_period=9, array=False) ##第二天的收益 short_pct = 100 * ((bar.high_price + bar.close_price) / 2 - preBar.close_price) / preBar.close_price long_pct = 100 * ((bar.low_price + bar.close_price) / 2 - preBar.close_price) / preBar.close_price open_pct = 100 * (bar.open_price - preBar.close_price) / preBar.close_price item = [] item.append(code) item.append(name) item.append(kEncodeValue) item.append(k) item.append(d) item.append(dif) item.append(dea) item.append(macd) #下个k线数据 item.append(open_pct) item.append(short_pct) item.append(long_pct) datas.append(item) macd_list.append(macd) indicator.update_bar(bar) preBar = bar macd_list = np.array(macd_list) print( f"total size : {len(datas)},mean ={macd_list.mean()},max={macd_list.max()},min={macd_list.min()}" ) wxl = pd.DataFrame(datas, columns=cloumns) return wxl
class KDJMovementEngineModel(CoreEngineModel): def __init__(self): self.lasted15Bar = np.array([ None, None, None, None, None, None, None, None, None, None, None, None, None, None, None ]) self.lasted3BarKdj = np.array([None, None, None]) self.lasted3BarMacd = np.array([None, None, None]) self.lasted3BarArron = np.array([None, None]) self.kdjEncoder = FloatEncoder([15, 30, 45, 60, 75, 90]) self.mDateOccurCountMap = {} ##统计产生收集个数的次数 self.sw = SWImpl() def onCollectStart(self, code: str) -> bool: from earnmi.chart.Indicator import Indicator self.indicator = Indicator(34) self.code = code return True def onCollectTrace(self, bar: BarData) -> CollectData: self.indicator.update_bar(bar) self.lasted15Bar[:-1] = self.lasted15Bar[1:] self.lasted3BarKdj[:-1] = self.lasted3BarKdj[1:] self.lasted3BarMacd[:-1] = self.lasted3BarMacd[1:] self.lasted3BarArron[:-1] = self.lasted3BarArron[1:] k, d, j = self.indicator.kdj(fast_period=9, slow_period=3) dif, dea, mBar = self.indicator.macd(fast_period=12, slow_period=26, signal_period=9) aroon_down, aroon_up = self.indicator.aroon(n=14) self.lasted15Bar[-1] = bar self.lasted3BarKdj[-1] = [k, d, j] self.lasted3BarMacd[-1] = [dif, dea, mBar] self.lasted3BarArron[-1] = [aroon_down, aroon_up] if self.indicator.count <= 15: return None #最近15天之内不含停牌数据 if not BarUtils.isAllOpen(self.lasted15Bar): return None #交易日天数间隔超过5天的数据 if BarUtils.getMaxIntervalDay(self.lasted15Bar) >= 5: return None timeKey = utils.to_start_date(bar.datetime) if self.mDateOccurCountMap.get(timeKey) is None: self.mDateOccurCountMap[timeKey] = 0 if self.indicator.count >= 30: k0, d0, j0 = self.lasted3BarKdj[-2] k1, d1, j1 = self.lasted3BarKdj[-1] #金叉产生 goldCross = k0 < d0 and k1 >= d1 if not goldCross: return None kPatternValue = KPattern.encode3KAgo1(self.indicator) if not kPatternValue is None: self.mDateOccurCountMap[timeKey] += 1 dimen = Dimension(type=TYPE_2KAGO1, value=kPatternValue) collectData = CollectData(dimen=dimen) collectData.occurBars = list(self.lasted15Bar[-3:]) collectData.occurKdj = list(self.lasted3BarKdj) collectData.occurExtra['lasted3BarMacd'] = self.lasted3BarMacd collectData.occurExtra[ 'lasted3BarArron'] = self.lasted3BarArron return collectData return None def onCollect(self, data: CollectData, newBar: BarData): #不含停牌数据 if not BarUtils.isOpen(newBar): data.setValid(False) return data.predictBars.append(newBar) size = len(data.predictBars) if size >= 5: data.setFinished() def getYLabelPct(self, cData: CollectData) -> [float, float]: if len(cData.predictBars) < 5: #不能作为y标签。 return None, None bars: ['BarData'] = cData.predictBars basePrice = self.getYBasePrice(cData) highIndex = 0 lowIndex = 0 highBar = cData.predictBars[0] lowBar = cData.predictBars[0] sell_pct = 100 * ((highBar.high_price + highBar.close_price) / 2 - basePrice) / basePrice buy_pct = 100 * ((lowBar.low_price + lowBar.close_price) / 2 - basePrice) / basePrice for i in range(1, len(cData.predictBars)): bar: BarData = cData.predictBars[i] _s_pct = 100 * ( (bar.high_price + bar.close_price) / 2 - basePrice) / basePrice _b_pct = 100 * ( (bar.low_price + bar.close_price) / 2 - basePrice) / basePrice if _s_pct > sell_pct: sell_pct = _s_pct highIndex = i if _b_pct < buy_pct: buy_pct = _b_pct lowIndex = i return sell_pct, buy_pct def getYBasePrice(self, cData: CollectData) -> float: ##以金叉发生的当前收盘价作为基准值。 return cData.occurBars[-2].close_price def generateXFeature(self, cData: CollectData) -> []: #保证len小于三,要不然就不能作为生成特征值。 if (len(cData.occurBars) < 3): return None basePrcie = self.getYBasePrice(cData) ##使用随机森林,所以不需要标准化和归一化 goldCrossBar = cData.occurBars[-2] god_cross_dif, god_cross_dea, god_cross_macd = cData.occurExtra.get( 'lasted3BarMacd')[-2] god_cross_dif = 100 * god_cross_dif / basePrcie god_cross_dea = 100 * god_cross_dea / basePrcie k, d, j = cData.occurKdj[-2] def getSellBuyPct(bar: BarData): s_pct = 100 * ( (bar.high_price + bar.close_price) / 2 - basePrcie) / basePrcie b_pct = 100 * ( (bar.low_price + bar.close_price) / 2 - basePrcie) / basePrcie return s_pct, b_pct s_pct_1, b_pct_1 = getSellBuyPct(cData.occurBars[-3]) s_pct_2, b_pct_2 = getSellBuyPct(cData.occurBars[-2]) s_pct_3, b_pct_3 = getSellBuyPct(cData.occurBars[-1]) data = [] data.append(god_cross_dif) data.append(god_cross_dea) data.append(k) data.append(d) data.append(s_pct_1) data.append(b_pct_1) data.append(s_pct_2) data.append(b_pct_2) data.append(s_pct_3) data.append(b_pct_3) return data
class MyPattherCollector(KPatternCollector): # 收集指定的k线 collectKPatternOnly = True KPattern: [] = [712] pct_split = [-7, -5, -3, -1.5, -0.5, 0.5, 1.5, 3, 5, 7] # pct_split = [-7, -5, -3, -1.0, 0, 1, 3, 5, 7] # pct_split = [-0.5,0.5] pctEncoder = FloatEncoder(pct_split) def __init__(self): self.kPattersMap = {} self.sw = SWImpl() self.dataSet = [] for value in self.KPattern: self.kPattersMap[value] = True def onStart(self, code: str) -> bool: self.indicator = Indicator(40) self.traceCode = code self.traceName = self.sw.getSw2Name(code) return True """ 检查是否追踪某个k线形态,是的话,创建一个最终值对象。 """ def checkIfTrace(self, newBar: BarData) -> TraceIn3DayItem: self.indicator.update_bar(newBar) kEncodeValue = KPattern.encode2KAgo1(self.indicator) if kEncodeValue is None: return None if self.collectKPatternOnly and self.kPattersMap.get( kEncodeValue) is None: return None return TraceIn3DayItem(kEncodeValue, newBar) def onTraceFinish(self, traceItem: TraceIn3DayItem): if traceItem.isWanted(): ##收集数据。 data = [] data.append(self.traceCode) data.append(self.traceName) data.append(traceItem.kPattern) data.append(traceItem.first_buy_pct) data.append(traceItem.fisrt_sell_pct) data.append(traceItem.current_sell_pct) data.append(traceItem.current_buy_pct) self.dataSet.append(data) def onDestroy(self): import pandas as pd cloumns = [ "code", "name", "kPattern", "buy_price", "sell_price", "label_sell_price", "label_buy_price" ] wxl = pd.DataFrame(self.dataSet, columns=cloumns) writer = pd.ExcelWriter('files/sw_train_data_sample.xlsx') wxl.to_excel(writer, sheet_name="sample", index=False) writer.save() writer.close() print(f"dataSize = {len(self.dataSet)}")
class Find_KPattern_skip1_predit2(KBarCollector): print_on_destroy = False def __init__(self, limit_close_pct=1): self.limit_close_pct = limit_close_pct self.success_sell_pct = 2 self.collect_k_count = 0 #收集总数 self.k_count = 0 #满足条件的k线形态总数 self.dataSet = {} pass def onCreate(self): pass def onStart(self, code: str) -> bool: self.indicator = Indicator(40) self.code = code return True def collect(self, bar: BarData) -> TraceData: self.indicator.update_bar(bar) kPatternValue = KPattern.encode2KAgo1(self.indicator) if not kPatternValue is None and self.indicator.count > 20: self.collect_k_count += 1 traceData = Skip1_Predict2_TraceData(kPatternValue, bar) traceData.code = bar.symbol return traceData return None def __between_0_100(self, value: int): if value > 100: return 100 elif value < 0: return 0 return value def onTrace(self, traceData: Skip1_Predict2_TraceData, bar: BarData): startBar = traceData.occurBar if traceData.skipBar is None: k, d, j = self.indicator.kdj(fast_period=9, slow_period=3, array=False) k = self.__between_0_100(k) j = self.__between_0_100(d) traceData.skipBar = bar traceData.indicator_k = k traceData.indicator_j = j close_pct = 100 * (bar.close_price - startBar.close_price) / startBar.close_price if abs(close_pct) > self.limit_close_pct: traceData.isWanted = False traceData.finished = True return sell_pct = 100 * ((bar.high_price + bar.close_price) / 2 - startBar.close_price) / startBar.close_price buy_pct = 100 * ((bar.low_price + bar.close_price) / 2 - startBar.close_price) / startBar.close_price traceData.sell_pct = max(sell_pct, traceData.sell_pct) traceData.buy_pct = min(buy_pct, traceData.buy_pct) traceData.predictBars.append(bar) if (len(traceData.predictBars) >= 2): traceData.isWanted = True traceData.finished = True pass def newCountData(self) -> CountData: dataItem = CountData() dataItem.count_total = 0 dataItem.pct_total = 0 dataItem.count_earn = 0 dataItem.pct_earn = 0 return dataItem def onTraceFinish(self, traceData: Skip1_Predict2_TraceData): if (not traceData.isWanted): return dataItem: CountData = self.dataSet.get(traceData.kPatternValue) if dataItem is None: dataItem = self.newCountData() self.dataSet[traceData.kPatternValue] = dataItem self.doWantedTraceData(traceData, dataItem) pass def doWantedTraceData(self, traceData: Skip1_Predict2_TraceData, countData: CountData): pct = traceData.sell_pct self.k_count += 1 countData.count_total += 1 countData.pct_total += pct isSuccess = pct >= self.success_sell_pct if isSuccess: countData.count_earn += 1 countData.pct_earn += pct def onEnd(self, code: str): pass def onDestroy(self): if not self.print_on_destroy: return dataSet = self.dataSet print( f"总共收集{self.collect_k_count}个形态,共{self.k_count}个满足条件,识别出{len(dataSet)}类形态,有意义的形态有:" ) max_succ_rate = 0 min_succ_rate = 100 ret_list = [] occur_count = 0 for key, dataItem in dataSet.items(): success_rate = 100 * dataItem.count_earn / dataItem.count_total if dataItem.count_total < 300: continue # if success_rate < 40: # continue ret_list.append(key) if dataItem.count_earn > 0: earn_pct = dataItem.pct_earn / dataItem.count_earn else: earn_pct = 0 avg_pct = dataItem.pct_total / dataItem.count_total occur_count += dataItem.count_total occur_rate = 100 * dataItem.count_total / self.collect_k_count max_succ_rate = max(success_rate, max_succ_rate) min_succ_rate = min(success_rate, min_succ_rate) print( f"{key}: total={dataItem.count_total},suc=%.2f%%,occur_rate=%.2f%%,earn_pct:%.2f%%,avg_pct:%.2f%%)" % (success_rate, occur_rate, earn_pct, avg_pct)) total_occur_rate = 100 * occur_count / self.collect_k_count print( f"总共:occur_rate=%.2f%%, min_succ_rate=%.2f%%, max_succ_rate=%.2f%%" % (total_occur_rate, min_succ_rate, max_succ_rate)) print(f"{ret_list}")
def printKPatterMoreDetail(kPatters=[ 535, 359, 1239, 1415, 1072, 712, 1412, 1240, 1413, 888, 2823, 706, 1414, 1064 ]): from vnpy.trader.constant import Exchange from vnpy.trader.constant import Interval sw = SWImpl() lists = sw.getSW2List() start = datetime(2014, 5, 1) end = datetime(2020, 8, 17) pct_split = [-7, -5, -3, -1.5, -0.5, 0.5, 1.5, 3, 5, 7] #pct_split = [-7, -5, -3, -1.0, 0, 1, 3, 5, 7] pct_split = [2] pctEncoder = FloatEncoder(pct_split) kPattersMap = {} for value in kPatters: kPattersMap[value] = True class InnerData(object): kValue: int ## sell_disbute = np.zeros(pctEncoder.mask()) ##卖方力量分布情况 buy_disbute = np.zeros(pctEncoder.mask()) #买方力量分布情况 pass dataSet = {} occurDayMap = {} allTrayDay = 1 for code in lists: # for code in lists: barList = sw.getSW2Daily(code, start, end) indicator = Indicator(40) traceItems: ['TraceIn3DayItem'] = [] allTrayDay = max(allTrayDay, len(barList)) for bar in barList: ###跟踪数据 toDeleteList = [] for traceItem in traceItems: traceItem.onTraceBar(bar) if traceItem.isFinished(): toDeleteList.append(traceItem) if traceItem.isWanted(): occurBar = traceItem.firstBar dayKey = occurBar.datetime.year * 13 * 35 + occurBar.datetime.month * 13 + occurBar.datetime.day occurDayMap[dayKey] = True ###归纳到统计里面 innerData: InnerData = dataSet.get(traceItem.kPattern) if innerData is None: innerData = InnerData() innerData.kValue = traceItem.kPattern dataSet[traceItem.kPattern] = innerData sell_pct = traceItem.current_sell_pct buy_pct = traceItem.current_buy_pct innerData.buy_disbute[pctEncoder.encode(buy_pct)] += 1 innerData.sell_disbute[pctEncoder.encode( sell_pct)] += 1 pass for traceItem in toDeleteList: traceItems.remove(traceItem) indicator.update_bar(bar) kEncodeValue = KPattern.encode2KAgo1(indicator) if kEncodeValue is None or kPattersMap.get(kEncodeValue) is None: continue traceItem = TraceIn3DayItem(kEncodeValue, bar) traceItems.append(traceItem) print(f"所有交易日中,有意义的k线形态出现占比:%.2f%%" % (100 * len(occurDayMap) / allTrayDay)) for kValue, dataItem in dataSet.items(): total_count1 = 0 total_count2 = 0 for cnt in dataItem.sell_disbute: total_count1 += cnt for cnt in dataItem.buy_disbute: total_count2 += cnt assert total_count1 == total_count2 assert total_count1 > 0 print(f"\n\nk:%6d, " % (kValue)) print(f" 卖方价格分布:") for encode in range(0, len(dataItem.sell_disbute)): occurtRate = 100 * dataItem.sell_disbute[encode] / total_count1 print(f" {pctEncoder.descriptEncdoe(encode)}:%.2f%%" % (occurtRate)) print(f" 买方价格分布:") for encode in range(0, len(dataItem.buy_disbute)): occurtRate = 100 * dataItem.buy_disbute[encode] / total_count1 print(f" {pctEncoder.descriptEncdoe(encode)}:%.2f%%" % (occurtRate)) pass
class EngineModel2KAlgo1(CoreEngineModel): def __init__(self): self.lasted3Bar = np.array([None, None, None]) self.lasted3BarKdj = np.array([None, None, None]) self.sw = SWImpl() def onCollectStart(self, code: str) -> bool: from earnmi.chart.Indicator import Indicator self.indicator = Indicator(40) self.code = code return True def onCollectTrace(self, bar: BarData) -> CollectData: self.indicator.update_bar(bar) self.lasted3Bar[:-1] = self.lasted3Bar[1:] self.lasted3BarKdj[:-1] = self.lasted3BarKdj[1:] k, d, j = self.indicator.kdj(fast_period=9, slow_period=3) self.lasted3Bar[-1] = bar self.lasted3BarKdj[-1] = [k, d, j] if self.indicator.count >= 15: from earnmi.chart.KPattern import KPattern kPatternValue = KPattern.encode2KAgo1(self.indicator) if not kPatternValue is None: dimen = Dimension(type=TYPE_2KAGO1, value=kPatternValue) collectData = CollectData(dimen=dimen) collectData.occurBars.append(self.lasted3Bar[-2]) collectData.occurBars.append(self.lasted3Bar[-1]) collectData.occurKdj.append(self.lasted3BarKdj[-2]) collectData.occurKdj.append(self.lasted3BarKdj[-1]) return collectData return None def onCollect(self, data: CollectData, newBar: BarData) -> bool: if len(data.occurBars) < 3: data.occurBars.append(self.lasted3Bar[-1]) data.occurKdj.append(self.lasted3BarKdj[-1]) else: data.predictBars.append(newBar) size = len(data.predictBars) return size >= 2 @abstractmethod def getYLabelPrice(self, cData: CollectData) -> [float, float, float]: bars: ['BarData'] = cData.predictBars if len(bars) > 0: sell_price = -9999999999 buy_price = -sell_price for bar in bars: sell_price = max((bar.high_price + bar.close_price) / 2, sell_price) buy_price = min((bar.low_price + bar.close_price) / 2, buy_price) return sell_price, buy_price return None, None def getYBasePrice(self, cData: CollectData) -> float: return cData.occurBars[-2].close_price def generateXFeature(self, cData: CollectData) -> []: #保证len小于三,要不然就不能作为生成特征值。 if (len(cData.occurBars) < 3): return None occurBar = cData.occurBars[-2] skipBar = cData.occurBars[-1] kdj = cData.occurKdj[-1] sell_pct = 100 * ((skipBar.high_price + skipBar.close_price) / 2 - occurBar.close_price) / occurBar.close_price buy_pct = 100 * ((skipBar.low_price + skipBar.close_price) / 2 - occurBar.close_price) / occurBar.close_price def set_0_between_100(x): if x > 100: return 100 if x < 0: return 0 return x def percent_to_one(x): return int(x * 100) / 1000.0 data = [] data.append(percent_to_one(buy_pct)) data.append(percent_to_one(sell_pct)) data.append(set_0_between_100(kdj[0]) / 100) data.append(set_0_between_100(kdj[2]) / 100) return data
不同的股票价格的macd的数值不同,macd是跟价格相关的。这样不同股票的价格的macd数值就不好做个比较。 所以要标准化,不同价格的macd的值要标准进行可比较。 标准化的步骤就是: macd值处于最后一天的收盘价。 这里统计下中证500的macd标准化之后的数据统计情况 """ if __name__ == "__main__": start = datetime(2015, 10, 1) end = datetime(2020, 9, 30) souces = ZZ500DataSource(start, end) bars,code = souces.nextBars() dif_list = [] dea_list = [] while not bars is None: indicator = Indicator(40) for bar in bars: indicator.update_bar(bar) if indicator.count > 33: dif, dea, macd_bar = indicator.macd(fast_period=12, slow_period=26, signal_period=9, array=False) dif_value = dif/bar.close_price * 100 dea_value = dea / bar.close_price * 100 dif_list.append(dif_value) dea_list.append(dea_value) if abs(dif_value) > 20: print(f"dif:{dif_value},code={code},bar = {bar}") if abs(dea_value) > 20: print(f"dea:{dea_value},code={code},bar = {bar}") bars, code = souces.nextBars() dif_list = np.array(dif_list) dea_list = np.array(dea_list) def_min,def_max = [dea_list.min(),dea_list.max()]