예제 #1
0
class TestStrategy(unittest.TestCase):
    def __init__(self, method_name):
        unittest.TestCase.__init__(self, method_name)
        self.strategy_bull_up = BullUpStrategy()
        self.indicator_strategy = IndicatorStrategy()
        self.offline_stock_action = OfflineStockAction()

    # def test_bull_up(self):
    # #     log.info("===============================================")
    #     result = self.strategy_bull_up.list_bull_up_stock(count=4, up_thread_hold=0.03)[0]
    #     log.info("===============================================")
    # result = self.strategy_bull_up.list_bull_up_stock(7, 0.03, result)[0]
    # log.info("===============================================")
    # result = self.strategy_bull_up.list_bull_up_stock(8, 0.03, result)[0]
    # log.info("===============================================")

    # def test_stock_concept(self):
    #     self

    # def test_dmi_indicator(self):

    # 找出放量突破布林线中轴
    # 高于昨日最高价3%以上
    # 当日K线实体部分至少占80%的
    # 认为有企稳信号
    def test_bollinger_band(self):
        stocks = self.offline_stock_action.query_all_stock()
        for index, stock in stocks.iterrows():
            all_prices = self.offline_stock_action.query_all_history_prices(
                stock['stock_code'])
            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']
            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, middleband, lowerband = self.indicator_strategy.calculate_boll(
                    all_prices['close'])
                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%%",
                             stock['display_name'], 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(
                        "======================================================"
                    )
            pass
예제 #2
0
 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
예제 #3
0
 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
예제 #4
0
 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
예제 #5
0
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))
예제 #6
0
 def __init__(self):
     self.stock_action = OfflineStockAction()
     self.indicator_strategy = IndicatorStrategy()
     BaseStrategy.__init__(self)
예제 #7
0
class BullUpStrategy(BaseStrategy):
    def __init__(self):
        self.stock_action = OfflineStockAction()
        self.indicator_strategy = IndicatorStrategy()
        BaseStrategy.__init__(self)

    def list_bull_up_stock(self,
                           count,
                           up_thread_hold,
                           stock_list=None,
                           end_day=get_today(),
                           prices=None,
                           safe_flag=False):
        log.debug("当前条件为, %s日下跌之后进行放量反弹,并且超过前日最高价%s%%", str(count - 1),
                  str(up_thread_hold * 100))
        if stock_list is None:
            stock_list = self.stock_action.query_all_stock()
            # stock_code_list = stocks['stock_code']

        result = pd.DataFrame()
        result_price = pd.DataFrame()
        i = 1
        for index, stock in stock_list.iterrows():
            i = i + 1
            if prices is None:
                prices = self.stock_action.query_prices_by_stock_code_time(
                    stock['stock_code'], count=count, end_date=end_day)
            else:
                pass
            if prices is None:
                raise StrategyError(str(count) + "日价格为空")
            ratio = self.is_bull_up(prices, up_thread_hold, count)
            if ratio is not None:
                is_clash_the_top = False
                str_f = "NOTICE ==> %s\n[%s 当前收盘 %s(最高价 %s) 涨幅 %.2f%%(最高涨幅 %.2f%%) " \
                        "建议止损位 %s 压力位 %s"
                if ratio[3] * 100 > 9.6 and ratio[1] * 100 < ratio[3] * 100:
                    is_clash_the_top = True
                    if safe_flag is False:
                        # 忽略掉开板股票
                        log.info(str_f + " 警惕开板风险]", str(stock['stock_code']),
                                 str(stock['display_name']), str(ratio[0]),
                                 str(ratio[2]), ratio[1] * 100, ratio[3] * 100,
                                 ratio[4], ratio[5])

                elif ratio[0] == ratio[2]:
                    log.info(str_f + " 强势光头阳,值得关注]", str(stock['stock_code']),
                             str(stock['display_name']), str(ratio[0]),
                             str(ratio[2]), ratio[1] * 100, ratio[3] * 100,
                             ratio[4], ratio[5])
                else:
                    log.info(str_f + "]", str(stock['stock_code']),
                             str(stock['display_name']), str(ratio[0]),
                             str(ratio[2]), ratio[1] * 100, ratio[3] * 100,
                             ratio[4], ratio[5])

                stock['stop_loss_price'] = ratio[4]
                stock['pressure_price'] = ratio[5]
                if safe_flag is False or is_clash_the_top is False:
                    result = result.append(stock)
                result_price = result_price.append(prices)
        return [result, result_price]

    def is_bull_up(self, prices, thread_hold, count):
        if len(prices) < 4:
            log.warning("%s时间太短", str(prices['stock_code'][0]))
            return None
        prices.sort_values(by="trade_day", ascending=False, inplace=True)
        prices = prices.reset_index(drop=True)
        close_price = prices['close'][0]
        high_price = prices['high'][0]
        last_high = prices['high'][1]
        last_close = prices['close'][1]

        take_profit_price = 0

        i = 1
        while i < len(prices) - 1:
            i = i + 1
            if last_high < prices['high'][i]:
                last_high = prices['high'][i]
            else:
                take_profit_price = last_high
                break

        if i > (count - 1) and prices['volume'][0] > self.calculate_avg_vol(prices) \
                and close_price > prices['high'][1] * (1+thread_hold):
            # TODO 找出来近期高位
            return [
                close_price, close_price / prices['close'][1] - 1, high_price,
                high_price / prices['close'][1] - 1, last_close,
                take_profit_price
            ]

        return None

    @staticmethod
    def calculate_avg_vol(prices):
        avg_volume = prices['volume'].mean()
        return avg_volume
예제 #8
0
 def __init__(self, user_name=config.get_user_name(), pwd=config.get_pwd()):
     OfflineStockAction.__init__(self)
     BaseJQData.__init__(self, user_name, pwd)
예제 #9
0
 def __init__(self, method_name):
     unittest.TestCase.__init__(self, method_name)
     self.indicator_strategy = IndicatorStrategy()
     self.offline_stock_action = OfflineStockAction()
     self.bull_up_strategy = BullUpStrategy()
예제 #10
0
class TestMACDStrategy(unittest.TestCase):
    def __init__(self, method_name):
        unittest.TestCase.__init__(self, method_name)
        self.indicator_strategy = IndicatorStrategy()
        self.offline_stock_action = OfflineStockAction()
        self.bull_up_strategy = BullUpStrategy()

    # def test_dmi(self):
    #     stocks = self.offline_stock_action.get_all_stock()
    #     i = 1
    #     for index, stock in stocks.iterrows():
    #         price = self.offline_stock_action.query_all_history_prices(stock['stock_code'])
    #         m_di, p_di, adx = self.indicator_strategy.calculate_dmi(price['high'], price['low'], price['close'])
    #         if float(p_di.tail(1)) > float(m_di.tail(2).head(1)) \
    #                 and float(adx.tail(1)) > 30:
    #             log.info("NOTICE => %s", stock['stock_code'])
    #             view_bar(i, len(stocks.index))
    #         i += 1

    # def test_list_macd_gold(self):
    #     stocks = self.offline_stock_action.get_all_stock()
    #     log.info("======================================")
    #     for index, stock in stocks.iterrows():
    #         price = self.offline_stock_action.query_all_history_prices(stock['stock_code'])
    #         real = self.indicator_strategy.calculate_rsi(price['close'])
    #         cci = self.indicator_strategy.calculate_cci(price['high'], price['low'], price['close'])
    #         if float(price['paused'].tail(1)) <= 0:
    #             if int(cci.tail(1)) > 100 > int(cci.tail(2).head(1)):
    #                 log.info("NOTICE ==> %s CCI今日超过100", stock['stock_code'])
    #                 macd, macdsignal, macdhist = self.indicator_strategy.calculate_macd(price['close'])
    #                 if float(macdhist.tail(1)) > 0 > float(macdhist.tail(2).head(1)) and float(macd.tail(1)) > 0:
    #                     log.info("\t\tNOTICE ==> %s MACD金叉行情",stock['stock_code'])
    #                 if float(macd.tail(1)) > 0 > float(macd.tail(2).head(1)):
    #                     log.info("\t\tNOTICE ==> %s DIF>0行情", stock['stock_code'])

    # def test_valuations(self):
    #     print(self.stock_action.refresh_valuations())
    #
    def test_concept(self):
        stock_action = StockAction()
        print(stock_action.refresh_concepts())

    def test_refresh_concept_stock(self):
        stock_action = StockAction()
        stock_action.refresh_concept_stocks()

    # def test_concept_stocks(self):
    #     # print(self.stock_action.refresh_concept_stocks())
    #     print(self.offline_stock_action.query_stock_concept('000027.XSHE'))

    def test_all_stock_history_price(self):
        stocks = self.offline_stock_action.query_all_stock()
        stocks_0 = stocks[0:600]
        stocks_1 = stocks[600:1200]
        stocks_2 = stocks[1200:1800]
        stocks_3 = stocks[1800:2400]
        stocks_4 = stocks[2400:3000]
        stocks_5 = stocks[3000:len(stocks)]

        thread_0 = threading.Thread(target=self.append_stock_price,
                                    args=(stocks_0, ))
        thread_1 = threading.Thread(target=self.append_stock_price,
                                    args=(stocks_1, ))
        thread_2 = threading.Thread(target=self.append_stock_price,
                                    args=(stocks_2, ))
        thread_3 = threading.Thread(target=self.append_stock_price1,
                                    args=(stocks_3, ))
        thread_4 = threading.Thread(target=self.append_stock_price1,
                                    args=(stocks_4, ))
        thread_5 = threading.Thread(target=self.append_stock_price1,
                                    args=(stocks_5, ))

        thread_0.setDaemon(True)
        thread_1.setDaemon(True)
        thread_2.setDaemon(True)
        thread_3.setDaemon(True)
        thread_4.setDaemon(True)
        thread_5.setDaemon(True)

        thread_0.start()
        thread_1.start()
        thread_2.start()
        thread_3.start()
        thread_4.start()
        thread_5.start()

        thread_0.join()
        thread_1.join()
        thread_2.join()
        thread_3.join()
        thread_4.join()
        thread_5.join()

    def append_stock_price(self, stocks):
        log.info("%s running", threading.get_ident())
        stock_codes = list(stocks['stock_code'])
        for i in range(len(stock_codes)):
            #view_bar(i+1, len(stock_codes), '(' + str(threading.get_ident())+')')
            stock_action = StockAction()
            stock_action.append_stock_price(stock_codes[i])
        log.info("%s done", threading.get_ident())

    def append_stock_price1(self, stocks):
        log.info("%s running", threading.get_ident())
        stock_codes = list(stocks['stock_code'])
        for i in range(len(stock_codes)):
            #view_bar(i+1, len(stock_codes), '(' + str(threading.get_ident())+')')
            stock_action = StockAction(user_name='****', pwd='****')
            stock_action.append_stock_price(stock_codes[i])
        log.info("%s done", threading.get_ident())
예제 #11
0
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))
예제 #12
0
 def __init__(self, method_name):
     unittest.TestCase.__init__(self, method_name)
     self.offline_stock_action = OfflineStockAction()
예제 #13
0
class TestBacktesing(unittest.TestCase):
    def __init__(self, method_name):
        unittest.TestCase.__init__(self, method_name)
        self.offline_stock_action = OfflineStockAction()

    # def test_simple_backtesting(self):
    #     stocks = self.offline_stock_action.get_all_stock()
    #     sample_stocks = stocks.sample(100)
    #     stock_codes = []
    #     profits = []
    #     for index, stock in sample_stocks.iterrows():
    #         simple_backtesting = SimpleBackTesting()
    #         simple_backtesting.set_stock_code(stock['stock_code'])
    #         profit = simple_backtesting.run()
    #         stock_codes.append(stock['stock_code'])
    #         profits.append(profit)
    #     sample = {
    #         'stock_code': stock_codes,
    #         'profit': profits
    #     }
    #     sample_result = pd.DataFrame(sample)
    #     sample_result.to_excel('./result/simple_backtesting-' +
    #                            str(datetime.datetime.strftime(
    #                                datetime.datetime.now(), '%Y%m%d%H%M%S'
    #                            )) +'.xlsx')

    # def test_cci_backtesting(self):
    #     stocks = self.offline_stock_action.query_all_stock()
    #     sample_stocks = stocks.sample(20)
    #     stock_codes = []
    #     profits = []
    #     for index, stock in sample_stocks.iterrows():
    #         cci_backtesting = CCIBacktesing()
    #         cci_backtesting.set_stock_code(stock['stock_code'])
    #         profit = cci_backtesting.run()
    #         stock_codes.append(stock['stock_code'])
    #         profits.append(profit)
    #     sample = {
    #         'stock_code': stock_codes,
    #         'profit': profits
    #     }
    #     sample_result = pd.DataFrame(sample)
    #     sample_result.to_excel('./result/cci_backtesting-' +
    #                            str(datetime.datetime.strftime(
    #                                datetime.datetime.now(), '%Y%m%d%H%M%S'
    #                            )) +'.xlsx')

    def test_boll_backtesting(self):
        stocks = self.offline_stock_action.query_all_stock()
        sample_stocks = stocks.sample(100)
        stock_codes = []
        profits = []
        for index, stock in sample_stocks.iterrows():
            boll_backtesting = BollBacktesting()
            stock_code = stock['stock_code']
            boll_backtesting.set_stock_code(stock_code)

            profit = boll_backtesting.run()
            stock_codes.append(stock['stock_code'])
            profits.append(profit)
        sample = {'stock_code': stock_codes, 'profit': profits}
        sample_result = pd.DataFrame(sample)
        sample_result.to_excel('./result/boll_backtesting-' + str(
            datetime.datetime.strftime(datetime.datetime.now(),
                                       '%Y%m%d%H%M%S')) + '.xlsx')
예제 #14
0
 def __init__(self, method_name):
     unittest.TestCase.__init__(self, method_name)
     self.index_strategy = IndexCalculatorStategy()
     self.offline_stock_action = OfflineStockAction()
예제 #15
0
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))