class BollBacktesting(BaseBackTesing): def __init__(self): super().__init__() self.stock_code = None self.offline_stock_action = OfflineStockAction() self.indicator_strategy = IndicatorStrategy() self.boll = None self.stock = None self.buy_date = None def set_stock_code(self, stock_code): self.stock_code = stock_code def is_buy_position(self, history_prices, current_price): all_prices = history_prices avg_vol = all_prices.tail(5)['volume'].mean() # 5日均量 newest_price = all_prices.tail(1) close_price = newest_price['close'] newest_vol = newest_price['volume'] newest_high = newest_price['high'] newest_low = newest_price['low'] newest_open = newest_price['open'] last_high_price = all_prices.tail(2).head(1)['high'] last_close_price = all_prices.tail(2).head(1)['close'] try: if newest_high.item() > last_high_price.item() * 1.03 \ and (close_price.item() - newest_open.item()) > 0.8 * (newest_high.item() - newest_low.item()) \ and (newest_vol.item() > avg_vol.item()): upperband = self.boll['upperband'] middleband = self.boll['middleband'] lowerband = self.boll['lowerband'] if close_price.item() > middleband[len(middleband) - 1] \ and last_close_price.item() < middleband[len(middleband) - 2]: log.info("stock_info: %s(%s) close_price:%.2f, +%.2f%%", self.stock['display_name'], self.stock['stock_code'], close_price.item(), (close_price.item() - last_close_price.item()) / last_close_price.item() * 100) log.info("upper :%.2f; middle: %.2f; lower: %.2f", upperband[len(upperband) - 1], middleband[len(middleband) - 1], lowerband[len(lowerband) - 1]) log.info( "======================================================" ) self.buy_date = datetime.datetime.strptime( str(current_price['trade_day']).split(" ")[0], '%Y-%m-%d') return True except ValueError: print(newest_high) return False return False def buy_action(self, history_prices, current_price): self.buy_position_percent_value(current_price, 1) def is_sell_position(self, history_prices, current_price): if self.buy_date is not None \ and self.position > 0: cur_date = datetime.datetime.strptime( str(current_price['trade_day']).split(" ")[0], '%Y-%m-%d') print((cur_date - self.buy_date).days) if (cur_date - self.buy_date).days > 3: self.buy_date = None log.info("持有超过2天,卖出") return True return False def sell_action(self, history_prices, current_price): self.sell_position_percent_value(current_price, 1) def is_add_position(self, history_prices, current_price): super().is_add_position(history_prices, current_price) def add_position_action(self, history_prices, current_price): super().add_position_action(history_prices, current_price) def is_reduce_position(self, history_prices, current_price): super().is_reduce_position(history_prices, current_price) def reduce_position_action(self, history_prices, current_price): super().reduce_position_action(history_prices, current_price) def is_clear_position(self, history_prices, current_price): if self.position > 0: profit = self.position * current_price['open'] - self.INIT_BALANCE print(profit) if profit < 0 and (-profit) / self.INIT_BALANCE > 0.08: log.info("触及止损,清仓") return True return False def clear_position_action(self, history_prices, current_price): super().sell_position_percent_value(current_price=current_price, percent=1) def buy_fee(self): return super().buy_fee() def sell_fee(self): return super().sell_fee() def end_backtesting(self, history_prices, current_price): if self.position > 0: self.sell_position_percent_value(current_price, 1) def buy_position_percent_value(self, current_price, percent): # 早盘就卖 current_price['close'] = current_price['open'] return super().buy_position_percent_value(current_price, percent) def sell_position_percent_value(self, current_price, percent): return super().sell_position_percent_value(current_price, percent) def run(self): if self.stock_code is None: raise Exception("stock code can not be None") self.stock = pd.DataFrame( self.offline_stock_action.query_by_stock_code(self.stock_code)) total_history_prices = self.offline_stock_action.query_all_history_prices( self.stock_code) upperband, middleband, lowerband = self.indicator_strategy.calculate_boll( total_history_prices['close']) bollinger = { 'upperband': upperband, 'middleband': middleband, 'lowerband': lowerband, 'trade_day': total_history_prices['trade_day'] } self.boll = pd.DataFrame(bollinger) super().run_backtesting(total_history_prices=total_history_prices, start_date=datetime.datetime(2018, 1, 1)) return float( round((self.balance - self.INIT_BALANCE) / self.INIT_BALANCE * 100, 2))
class SimpleBackTesting(BaseBackTesing): def __init__(self): BaseBackTesing.__init__(self) self.stock_code = None self.offline_stock_action = OfflineStockAction() self.bull_up_strategy = BullUpStrategy() self.indicator_strategy = IndicatorStrategy() self.total_dmi = None self.stock = None self.pressure_level = self.MAX_VALUE self.stop_loss_level = 0 pass def set_stock_code(self, stock_code): self.stock_code = stock_code def is_buy_position(self, history_prices, current_price): history_prices = history_prices.append(current_price) # 判断是否是反弹时间点 bull_up_list = self.bull_up_strategy\ .list_bull_up_stock(count=4, up_thread_hold=0.03, stock_list=self.stock, end_day=current_price['trade_day'], prices=history_prices[history_prices['trade_day'] <= current_price['trade_day']], safe_flag=True) if bull_up_list[0].empty is False: self.stock = bull_up_list[0] self.pressure_level = self.stock['pressure_price'] self.stop_loss_level = self.stock['stop_loss_price'] current_dmi = self.total_dmi[self.total_dmi['trade_day'] == current_price['trade_day']] if float(current_dmi['pdi'].tail(1)) > float(current_dmi['mdi'].tail(1)) \ and float(current_dmi['adx'].tail(1)) > 30: return True return False def buy_action(self, history_prices, current_price): self.buy_position_percent_value(current_price=current_price, percent=0.8) def is_sell_position(self, history_prices, current_price): return super().is_sell_position(history_prices, current_price) def sell_action(self, history_prices, current_price): super().sell_action(history_prices, current_price) def is_add_position(self, history_prices, current_price): if float(current_price['close']) > float(self.pressure_level) \ and current_price['volume'] > history_prices.tail(5)['volume'].mean(): return True return super().is_add_position(history_prices, current_price) #放量突破压力位,加仓20% def add_position_action(self, history_prices, current_price): self.stop_loss_level = self.pressure_level self.pressure_level = self.pressure_level * 1.05 self.buy_position_percent_value(current_price=current_price, percent=0.6) def is_reduce_position(self, history_prices, current_price): if int(self.position) > 0 and float(current_price['close']) < float(self.pressure_level)\ < float(current_price['high']): return True return super().is_reduce_position(history_prices, current_price) #遇到压力位如果当天最高价超过,但是收盘没有超过则减仓50% def reduce_position_action(self, history_prices, current_price): self.sell_position_percent_value(current_price=current_price, percent=0.5) def is_clear_position(self, history_prices, current_price): if int(self.position) > 0 and float(current_price['close']) < float(self.stop_loss_level): return True return super().is_clear_position(history_prices, current_price) # 到达止损位,清仓出局 def clear_position_action(self, history_prices, current_price): self.sell_position_percent_value(current_price=current_price, percent=1) def buy_fee(self): return 5 #TODO 暂时固定按5元 def sell_fee(self): return 5 #TODO 暂时固定按5元 def end_backtesting(self, history_prices, current_price): if self.position > 0: self.sell_position_percent_value(current_price=current_price, percent=1) def run(self): if self.stock_code is None: raise Exception("stock code can not be None") self.stock = pd.DataFrame(self.offline_stock_action.query_by_stock_code(self.stock_code)) total_history_prices = self.offline_stock_action.query_all_history_prices( self.stock_code) mdi, pdi, adx = self.indicator_strategy.calculate_dmi(total_history_prices['high'], total_history_prices['low'], total_history_prices['close']) dmis = { 'mdi': mdi, 'pdi': pdi, 'adx': adx, 'trade_day': total_history_prices['trade_day'] } self.total_dmi = pd.DataFrame(dmis) super().run_backtesting(total_history_prices=total_history_prices, start_date=datetime.datetime(2019, 1, 1)) return float(round((self.balance - self.INIT_BALANCE)/self.INIT_BALANCE*100, 2))
class CCIBacktesing(BaseBackTesing): def __init__(self): BaseBackTesing.__init__(self) self.stock_code = None self.offline_stock_action = OfflineStockAction() self.indicator_strategy = IndicatorStrategy() self.cci = None self.stock = None def set_stock_code(self, stock_code): self.stock_code = stock_code def is_buy_position(self, history_prices, current_price): pre_price = history_prices.tail(1) pre_price = pre_price.reset_index(drop=True) try: pre_cci = self.cci[self.cci['trade_day'] == pre_price['trade_day'] [0]] except IndexError: print(pre_price['trade_day'][0]) raise Exception("ERROR") cur_cci = self.cci[self.cci['trade_day'] == current_price['trade_day']] if float(pre_cci['cci']) < 100 < float(cur_cci['cci']): return True return False def buy_action(self, history_prices, current_price): cur_cci = self.cci[self.cci['trade_day'] == current_price['trade_day']] self.buy_position_percent_value( current_price=current_price, percent=round(float(cur_cci['cci']) / 100, 1) - 0.5) def is_sell_position(self, history_prices, current_price): pre_price = history_prices.tail(1) pre_price = pre_price.reset_index(drop=True) pre_cci = self.cci[self.cci['trade_day'] == pre_price['trade_day'][0]] cur_cci = self.cci[self.cci['trade_day'] == current_price['trade_day']] if float(pre_cci['cci']) > 100 > float(cur_cci['cci']): return True return False def sell_action(self, history_prices, current_price): if self.position > 0: self.sell_position_percent_value(current_price=current_price, percent=1) def is_add_position(self, history_prices, current_price): super().is_add_position(history_prices=history_prices, current_price=current_price) def add_position_action(self, history_prices, current_price): super().add_position_action(history_prices=history_prices, current_price=current_price) def is_reduce_position(self, history_prices, current_price): super().is_reduce_position(history_prices=history_prices, current_price=current_price) def reduce_position_action(self, history_prices, current_price): super().reduce_position_action(history_prices=history_prices, current_price=current_price) def is_clear_position(self, history_prices, current_price): if self.position > 0: profit = self.balance - self.INIT_BALANCE if profit < 0 and (-profit) / self.INIT_BALANCE > 0.08: return True return False def clear_position_action(self, history_prices, current_price): super().sell_position_percent_value(current_price=current_price, percent=1) def buy_fee(self): return 5 def sell_fee(self): return 5 def end_backtesting(self, history_prices, current_price): if self.position > 0: self.sell_position_percent_value(current_price=current_price, percent=1) def buy_position_percent_value(self, current_price, percent): super().buy_position_percent_value(current_price, percent) def sell_position_percent_value(self, current_price, percent): super().sell_position_percent_value(current_price, percent) def run(self): if self.stock_code is None: raise Exception("stock code can not be None") self.stock = pd.DataFrame( self.offline_stock_action.query_by_stock_code(self.stock_code)) total_history_prices = self.offline_stock_action.query_all_history_prices( self.stock_code) ccis = self.indicator_strategy.calculate_cci( total_history_prices['high'], total_history_prices['low'], total_history_prices['close']) cci = {'cci': ccis, 'trade_day': total_history_prices['trade_day']} self.cci = pd.DataFrame(cci) super().run_backtesting(total_history_prices=total_history_prices, start_date=datetime.datetime(2018, 1, 1)) return float( round((self.balance - self.INIT_BALANCE) / self.INIT_BALANCE * 100, 2))