예제 #1
0
 def test_logger():
     """
     tests the logger creation
     :return: nothing
     """
     logger = TraderBase.setup_logger("auto_trader")
     assert logger is not None
     logger = TraderBase.setup_logger(None)
     assert logger is not None
예제 #2
0
    def test_date_gen_for_back_test(self):
        """
        Tests the date generator / splitter
        :return:
        """
        from_date, to_date = get_from_to_dates(None, None)
        assert from_date is None and to_date is None
        config = TraderBase.get_config()
        logger = TraderBase.setup_logger("autotrader")
        db_tool = StockDataBase(config["sql"], logger)
        db_tool.connect()
        db_tool.session.query(Plot).delete()
        db_tool.session.query(Parameter).delete()
        db_tool.session.query(Signal).delete()

        stock = db_tool.session.query(Stock).first()
        with freeze_time("2017-10-02 09:54"):
            my_signal = Signal(
                profit_in_percent=1,
                name="TestSignal",
                status=2,
                date=datetime.datetime.now(),
                refresh_date=datetime.datetime.now(),
            )
            stock.signal.append(my_signal)
        with freeze_time("2017-08-02  09:33"):
            my_signal = Signal(
                profit_in_percent=1,
                name="TestSignal",
                status=2,
                date=datetime.datetime.now(),
                refresh_date=datetime.datetime.now(),
            )
            stock.signal.append(my_signal)

        with freeze_time("2017-10-02"):
            my_dates_tasks = [get_from_to_dates(db_tool, [idx, 8]) for idx in range(8)]
            assert len(my_dates_tasks) == 8
            my_dates_tasks_back = []
            for from_date, to_date in my_dates_tasks:
                for my_date in BackTestingStrategy.date_range(from_date, to_date):
                    my_dates_tasks_back.append(my_date)

            my_first_date = db_tool.session.query(Signal.date).order_by(Signal.date).first()
            my_dates_orig = [my_date for my_date in
                             BackTestingStrategy.date_range(my_first_date[0],
                                                            datetime.datetime.now())]
            # assert len(my_dates_orig) == len(my_dates_tasks_back)
            # for idx, my_date_back in enumerate(my_dates_tasks_back):
            #    assert my_date_back == my_dates_orig[idx]
        db_tool.session.rollback()
예제 #3
0
    def __do_limit(self, stock, order_data: dict, portfolio):
        if "size" not in order_data or "price" not in order_data or order_data['price'] == -1\
                or "buysell" not in order_data:
            raise RuntimeError("Order data is not correct")

        price, price_complete, commission = self.__calculate_price(order_data['price'], order_data,
                                                                   order_data["buysell"] == 1)

        if order_data["buysell"] == 0 and portfolio.cash + price_complete < 0:
            raise RuntimeError("Insufficient Funds: Price {} is higher than cash {}".format(
                price_complete,
                portfolio.cash))

        time_zone = TraderBase.get_timezone()
        now = datetime.datetime.now(time_zone)

        my_order = Orders(
            status=Status.confirmed,
            order_type=OrderType.limit,
            order_uuid=str(uuid.uuid4()),
            size=order_data["size"]*-1 if order_data["buysell"] == 1 else order_data["size"],
            price=price,
            price_complete=price_complete,
            commission=commission,
            stock_id=stock.id,
            signal_id=order_data.get('signal_id'),
            expire_date=datetime.datetime.now(time_zone) +
                        datetime.timedelta(hours=self.expire_in_hours),
            is_sell=True if order_data["buysell"] == 1 else False,
            date=now
        )
        return my_order
예제 #4
0
    def __do_market(self, stock, order_data: dict, portfolio):
        if "size" not in order_data or "buysell" not in order_data:
            raise RuntimeError("Order data is not correct")

        # get live data
        prices = self.get_last_price(stock)
        # get last stock price by database
        if not prices:
            raise RuntimeError("Couldnt collect price")

        last_price = prices

        price, price_complete, commission = self.__calculate_price(last_price, order_data,
                                                                   order_data["buysell"] == 1)
        if order_data["buysell"] != 1 and (portfolio.cash + price_complete) < 0:
            raise RuntimeError("Insufficient Funds: Price {} is higher"
                               " than cash {}.".format(price, portfolio.cash))
        time_zone = TraderBase.get_timezone()
        now = datetime.datetime.now(time_zone)
        my_order = Orders(
            status=Status.completed,
            order_type=OrderType.market,
            order_uuid=str(uuid.uuid4()),
            size=order_data["size"]*-1 if order_data["buysell"] == 1 else order_data["size"],
            price=price,
            price_complete=price_complete,
            commission=commission,
            stock_id=stock.id,
            signal_id=order_data.get('signal_id'),
            is_sell=True if order_data["buysell"] == 1 else False,
            date=now
            )
        return my_order
예제 #5
0
 def __handle_open_orders(self):
     """
     Get all open orders and check if desired price matches with historical stock prices
     :return:
     """
     portfolio = self.get_portfolio_object()
     # only take complete orders
     orders = [order for order in portfolio.orders if order.status == Status.confirmed]
     time_zone = TraderBase.get_timezone()
     now = datetime.datetime.now(time_zone)
     for order in orders:
         price = self.db_tool.session.query(Series)\
             .filter(order.stock_id == Series.stock_id) \
             .filter(Series.date.between(order.date, now)) \
             .filter(order.price >= Series.pricehigh)\
             .order_by(Series.date.asc()).first()
         if price:
             order.status = Status.completed
             order.date = price.date
             self.connect_related_order(order)
         else:
             diff = now - order.date.replace(tzinfo=time_zone)
             hours = diff.total_seconds() / 60
             if hours >= self.expire_in_hours:
                 self.logger.info("Order is expired because limit {} for {} "
                                  "was not reached during the day".
                                  format(order.price, order.stock_id))
                 order.status = Status.expired
                 portfolio.cash -= order.price_complete
예제 #6
0
 def test_gen_signal():
     """
     Tests two stocks with freezed data set
     """
     config = TraderBase.get_config()
     db_tool = Db(config['sql'], TEST_LOGGER)
     db_tool.connect()
     symbols = [["LHA", 0.6, 2], ["MRK", 0.4, 0]]
     for symbol in symbols:
         stock = db_tool.session.query(Stock).filter(
             symbol[0] == Stock.symbol).first()
         arguments = {
             'stock': stock,
             'name': 'StockIsHot2Month',
             'bars': None,
             'threshold_buy': 0.8,
             'threshold_sell': 0.5,
             'intervals': [7, 30],
             'secure_value': 0.84,
             'lookback': 2
         }
         my_filter = Sih(arguments, TEST_LOGGER)
         bars = stock.get_bars(my_filter.look_back_date(),
                               output_type=BARS_NUMPY)
         my_filter.set_bars(bars)
         status = my_filter.analyse()
         TEST_LOGGER.info("%s score is: %s and status %s", symbol[0],
                          my_filter.get_calculation(), status)
         npt.assert_almost_equal(my_filter.get_calculation(),
                                 symbol[1],
                                 decimal=4)
         assert symbol[2] == status
         db_tool.session.close()
예제 #7
0
    def compare_excepted_with_results():
        """
        Tests two stocks with freezed data set
        """
        config = TraderBase.get_config()
        db_tool = Db(config['sql'], TestBase.TEST_LOGGER)
        db_tool.connect()
        symbols = TestBase.test_stocks
        excepted_results = TestBase.test_excepted_results
        results = []
        # collect results
        for symbol in symbols:
            stock = db_tool.session.query(Stock).filter(
                symbol == Stock.symbol).first()
            for param in TestBase.test_params:
                results.append(TestBase.calculate_profit(stock, None, param))

        # compare calculated results with excepted results
        for idx, result in enumerate(results):
            TestBase.TEST_LOGGER.info("Profit is %s and status %s", result[0],
                                      result[1])
            assert result[1] == excepted_results[idx][
                1], "Test%s: %s != %s" % (idx, result[1],
                                          excepted_results[idx][1])
        db_tool.session.close()
예제 #8
0
 def test_gen_signal():
     """
     Tests two stocks with freezed data set
     """
     config = TraderBase.get_config()
     db_tool = Db(config['sql'], TEST_LOGGER)
     db_tool.connect()
     symbols = [["LHA", 5, 0], ["MRK", -6, 0]]
     for symbol in symbols:
         stock = db_tool.session.query(Stock).filter(
             symbol[0] == Stock.symbol).first()
         arguments = {
             'stock': stock,
             'name': Pr.NAME,
             'bars': stock.get_bars(output_type=BARS_NUMPY),
             'threshold_buy': 10,
             'threshold_sell': 5,
             'intervals': None,
             'lookback': 2
         }
         my_filter = Pr(arguments, TEST_LOGGER)
         status = my_filter.analyse()
         TEST_LOGGER.info("%s score is: %s and status %s", symbol[0],
                          my_filter.get_calculation(), status)
         assert symbol[1] == my_filter.get_calculation()
         assert symbol[2] == status
         db_tool.session.close()
예제 #9
0
    def setUpClass(cls):
        cls.config = TraderBase.get_config()

        cls.db = StockDataBase(cls.config['sql'], TEST_LOGGER)
        cls.db.connect()
        arguments = {"db_tool": cls.db}
        cls.client = DegiroClient(cls.config['degiro'], arguments, TEST_LOGGER)
        cls.client.login()
예제 #10
0
    def build_indicator(self, arguments):
        stock_id = arguments["stock_id"]
        stock_index = arguments["stock_index"]
        stock_symbol = arguments["stock_symbol"]
        stock_bars = arguments["stock_bars"]
        self.logger.info("Analyse %s:%s" % (stock_index, stock_symbol))
        return_code = 0
        indicators = []
        for indicator in ind.INDICATORS:
            if indicator.SHORT_NAME in self.signal_to_builds or 'ALL' in self.signal_to_builds:
                indicators.append(indicator(indicator.ARGUMENTS, self.logger))

        for indicator in indicators:
            self.logger.info("Execute filter %s" % indicator.name)
            if indicator.SHORT_NAME in ["SO", "SOM2", "SOM3"]:
                optimizer_values = itertools.product(
                    range(3, int(self.look_back / 2)),
                    range(3, int(self.look_back / 2)),
                    range(3, int(self.look_back / 2)))
            else:
                optimizer_values = itertools.combinations(
                    range(5, int(self.look_back / 2)), indicator.param_count)
            profit_max, param_max, status = Optimizer(
                self.logger).run_optimizer(optimizer_values, indicator,
                                           stock_bars)
            self.logger.info(
                "Signal %s(%s) earns %s for %s and has status code %s" %
                (indicator.name, param_max, profit_max, stock_symbol, status))
            if not param_max:
                self.logger.warning("no results for %s", indicator)
                continue
            # save to bulk data storage
            db_signal = Signal(
                profit_in_percent=float(profit_max),
                name=indicator.name,
                status=status,
                info=self.look_back,
                date=datetime.datetime.now(TraderBase.get_timezone()),
                refresh_date=datetime.datetime.now(TraderBase.get_timezone()))
            self.__add_signal_to_bulk(stock_id, db_signal)
            self.__add_parameter_to_bulk(db_signal, param_max)
            self.__add_plot_to_bulk(indicator, param_max, db_signal)
        return return_code
예제 #11
0
 def test_config():
     """
     tests the config creation by environment variable and root project dir
     :return: nothing
     """
     # test with config.ini in project root
     main_config = TraderBase.get_config()
     assert main_config is not None
     # test with environment variable
     file_config = open('config_test_unittest.ini', 'wt', encoding='utf-8')
     test_value = "[test]\ntest_value = 123456"
     file_config.write(test_value)
     file_config.close()
     old_config_path = os.environ["CONFIG_FILE"]
     os.environ["CONFIG_FILE"] = "config_test_unittest.ini"
     main_config = TraderBase.get_config()
     assert main_config['test']['test_value'] == '123456'
     os.environ.pop("CONFIG_FILE")
     os.environ["CONFIG_FILE"] = old_config_path
예제 #12
0
 def setUpClass(cls):
     """
     create test basics
     :return:
     """
     cls.config = TraderBase.get_config()
     cls.test_logger = logging.getLogger()
     cls.test_logger.setLevel(logging.WARNING)
     cls.db_tool = Db(cls.config['sql'], cls.test_logger)
     cls.db_tool.connect()
     assert 'PYCHARM' in os.environ or cls.config['sql']['address'] == 'mysqltest'
예제 #13
0
    def test_get_stocks(self):
        """
        Test stocks splitter
        :return:
        """
        stocks = get_stocks(None, None)
        assert 'ALL' in stocks and len(stocks) == 1
        config = TraderBase.get_config()
        logger = TraderBase.setup_logger("autotrader")
        db_tool = StockDataBase(config["sql"], logger)
        db_tool.connect()
        my_stocks = db_tool.session.query(Stock.id).all()
        my_stocks_orig = [my_stock[0] for my_stock in my_stocks if my_stock]
        my_stocks_tasks = []
        for idx in range(8):
            my_stocks_tasks += get_stocks(db_tool, [idx, 8])

        assert len(my_stocks) == len(my_stocks_tasks)
        for idx, stock_orig in enumerate(my_stocks_orig):
            assert stock_orig == my_stocks_tasks[idx]
예제 #14
0
    def __is_exchange_open(exchange: str):
        """

        :param exchange:
        :return:
        """
        time_zone = TraderBase.get_timezone()
        date_now = datetime.datetime.now(time_zone)
        if exchange == 'XETR':
            if date_now.isoweekday() in range(1, 6) and date_now.hour in range(9, 17):
                return True
        elif exchange == 'XFRA':
            if date_now.isoweekday() in range(1, 6) and date_now.hour in range(8, 20):
                return True
        return False
예제 #15
0
    def get_last_price(self, stock_object, time_zone=None):
        """
        Get last price of stock symbol
        :param stock_object: symbol of stock like ADS
        :param time_zone tz
        :return: last price or None
        """
        time_zone = TraderBase.get_timezone()
        if self.client:
            return self.client.get_last_price(stock_object)
        # get last stock price by database
        price = self.db_tool.session.query(Series)\
            .join(Stock)\
            .filter(Stock.id == stock_object.id)\
            .filter(Series.date <= datetime.datetime.now(time_zone))\
            .order_by(-Series.date).first()

        if not price:
            return None
        return price.priceclose
예제 #16
0
 def check_consistency():
     """
     Checks if results are stable. The method must produce same values after n runs.
     """
     config = TraderBase.get_config()
     db_tool = Db(config['sql'], TestBase.TEST_LOGGER)
     db_tool.connect()
     stock = db_tool.session.query(Stock).filter(
         Stock.symbol == TestBase.test_stocks[1]).first()
     status_list = []
     profits_list = []
     for _ in range(100):
         profit, status = TestBase.calculate_profit(stock,
                                                    TestBase.test_strategy,
                                                    TestBase.test_params)
         status_list.append(status)
         profits_list.append(profit)
     # check if profit elements are equal and status elements are equal
     assert status_list.count(status_list[0]) == len(status_list)
     assert profits_list.count(profits_list[0]) == len(profits_list)
     db_tool.session.close()
예제 #17
0
 def __build(self, my_filter, stock):
     bars = stock.get_bars(my_filter.look_back_date(),
                           datetime.datetime.now(),
                           output_type=BARS_NUMPY)
     if my_filter.look_back_date() is None or bars.size:
         my_filter.set_bars(bars)
         my_filter.set_stock(stock)
         strategy_status = my_filter.analyse()
         strategy_value = my_filter.get_calculation()
         tz = TraderBase.get_timezone()
         stock.filter.append(
             Filter(value=strategy_value,
                    name=my_filter.name,
                    status=strategy_status,
                    date=datetime.datetime.now(tz)))
         if strategy_status == BaseFilter.BUY:
             self.logger.debug("Buy %s", stock.symbol)
         elif strategy_status == BaseFilter.HOLD:
             self.logger.debug("Hold %s", stock.symbol)
         else:
             self.logger.debug("Do not buy Stock %s ", stock.symbol)
예제 #18
0
 def setUpClass(cls):
     """
     create test basics
     :return:
     """
     cls.config = TraderBase.get_config()
     cls.test_logger = logging.getLogger()
     cls.test_logger.setLevel(logging.WARNING)
     cls.db_tool = Db(cls.config['sql'], cls.test_logger)
     cls.db_tool.connect()
     cls.portfolio_name = "TestDemoSimpleMarket"
     arguments_broker = {
         "portfolio_name": cls.portfolio_name,
         "portfolio_user": "******",
         "database_data": True,
         "db_tool": cls.db_tool,
         "cash": 20000000
     }
     cls.broker = DemoBroker(cls.config, arguments_broker, cls.test_logger)
     assert 'PYCHARM' in os.environ or cls.config['sql'][
         'address'] == 'mysqltest'
예제 #19
0
    def __get_signals_to_update(db_tool, signal_max_age):
        time_zone = TraderBase.get_timezone()
        # at first we need all signals in a date range of 6 days
        all_signals_in_date_range = db_tool.session.query(Signal).\
            filter(Signal.date.between(datetime.now(time_zone) - timedelta(days=signal_max_age),
                                       datetime.now(time_zone)))

        # older signals connected with a order must also be refreshed
        sub_orders = db_tool.session.query(
            Orders.signal_id
        )\
            .filter(Orders.is_sell == 0)\
            .filter(Orders.orders_id.is_(None))\
            .group_by(Orders.signal_id).\
            subquery('t3')

        signals_with_order = db_tool.session.query(Signal).join(
            sub_orders, Signal.id == sub_orders.c.signal_id)
        update_new_signals = all_signals_in_date_range.union_all(
            signals_with_order)
        my_result = update_new_signals.all()
        return my_result
예제 #20
0
 def test_levermann():
     """
     Tests two stocks with freezed data set
     """
     config = TraderBase.get_config()
     db_tool = Db(config['sql'], TEST_LOGGER)
     db_tool.connect()
     symbols = [["LHA", 1, 0], ["MRK", -1, 0]]
     for symbol in symbols:
         stock = db_tool.session.query(Stock).filter(
             symbol[0] == Stock.symbol).first()
         arguments = {
             'stock':
             stock,
             'name':
             Ls.NAME,
             'bars':
             stock.get_bars(start=datetime.datetime(2016, 6, 1, 0, 0),
                            end=datetime.datetime(2017, 9, 1, 0, 0),
                            output_type=BARS_NUMPY),
             'threshold_buy':
             7,
             'threshold_sell':
             2,
             'intervals':
             None,
             'lookback':
             12
         }
         my_filter = Ls(arguments, TEST_LOGGER)
         status = my_filter.analyse()
         TEST_LOGGER.info("%s score is: %s - %s", symbol[0],
                          my_filter.get_calculation(), status)
         assert symbol[1] == my_filter.get_calculation(),\
             " Calc: %s != %s" % (symbol[1], my_filter.get_calculation())
         assert symbol[2] == status, " Status: %s != %s" % (symbol[2],
                                                            status)
     db_tool.session.close()
예제 #21
0
def autotrader_app():
    """
    Main entry point for autotrader application
    :return:
    """
    # print usage when no option is given
    parsed_args = get_arg_parse(sys.argv[1:])
    exit_code = 0

    if not parsed_args:
        return False

    if parsed_args.config:
        config = TraderBase.get_config(parsed_args.config)
        logger = TraderBase.setup_logger("autotrader")
        db_tool = StockDataBase(config["sql"], logger)
        db_tool.connect()

        print("Autotrader {}".format(VERSION))
        if parsed_args.app:
            build_app_db(logger, db_tool)
        if parsed_args.dump:
            build_yaml_file(db_tool)
        if parsed_args.install is not None:
            datasource = DegiroClient(config['degiro'], {"db_tool": None},
                                      logger)
            arguments = {
                'stocks_to_update': ['ALL'],  # For UpdateDataBaseStocks
                'update_stocks': False,  # For UpdateDataBaseStocks
                'update_sheets': True,  # For UpdateDataBaseStocks
                'db_tool': db_tool,
                'datasource': datasource
            }
            exit_code += CreateAndFillDataBase(config, arguments,
                                               logger).build()
            exit_code += UpdateDataBaseStocks(config, arguments,
                                              logger).build()
        if parsed_args.update is not None:
            arguments = {
                'stocks_to_update':
                parsed_args.update,
                'update_stocks':
                True,
                'update_sheets':
                False,
                'db_tool':
                db_tool,
                'datasource':
                DegiroClient(config['degiro'], {"db_tool": db_tool}, logger)
            }
            exit_code += UpdateDataBaseStocks(config, arguments,
                                              logger).build()
        if parsed_args.updatesheets is not None:
            arguments = {
                'stocks_to_update':
                parsed_args.updatesheets,
                'update_stocks':
                False,
                'update_sheets':
                True,
                'db_tool':
                db_tool,
                'datasource':
                DegiroClient(config['degiro'], {"db_tool": db_tool}, logger)
            }
            exit_code += UpdateDataBaseStocks(config, arguments,
                                              logger).build()
        if parsed_args.backup is not None:
            raise NotImplementedError
        if parsed_args.filter is not None:
            arguments = {'db_tool': db_tool}
            exit_code += BuildFilters(arguments, logger).build()
        if parsed_args.rebuild_filter is not None:
            from_date, to_date = get_from_to_dates(db_tool, parsed_args.task)
            arguments = {
                'db_tool': db_tool,
                "from_date": from_date,
                "to_date": to_date,
                'filters': parsed_args.rebuild_filter
            }
            exit_code += RecreateFilters(arguments, logger).build()
        if parsed_args.delete_filter is not None:
            arguments = {
                'db_tool': db_tool,
                'filters': parsed_args.delete_filter
            }
            my_recreate = RecreateFilters(arguments, logger)
            my_recreate.delete_old_filter()
        if parsed_args.delete_backtest_strategy is not None:
            arguments_broker = {
                "portfolio_name": "",
                "portfolio_user": "******",
                "database_data": True,
                "db_tool": db_tool,
                "cash": 2000
            }
            arguments = {
                'strategies': ["ALL"],
                'broker': DemoBroker(config, arguments_broker, logger),
                'strategy_name_prefix': 'B',
                'db_tool': db_tool
            }
            StartStrategy(config, arguments, logger).recreate_all_strategies()
            arguments["broker"].commit_work()
        if parsed_args.delete_demo_strategy is not None:
            arguments_broker = {
                "portfolio_name": "",
                "portfolio_user": "******",
                "database_data": True,
                "db_tool": db_tool,
                "cash": 2000
            }
            arguments = {
                'strategies': ["ALL"],
                'broker': DemoBroker(config, arguments_broker, logger),
                'strategy_name_prefix': 'D',
                'db_tool': db_tool
            }
            StartStrategy(config, arguments, logger).recreate_all_strategies()
            arguments["broker"].commit_work()
        if parsed_args.signals is not None:
            # split all stocks in almost equal pieces and get part of split by task id
            my_stocks = get_stocks(db_tool, parsed_args.task)
            arguments = {
                'signals': ["ALL"],
                'stocks': my_stocks,
                "look_back": 300,
                'db_tool': db_tool
            }
            exit_code += BuildIndicators(config, arguments, logger).build()
        if parsed_args.quicksignals is not None:
            # split all stocks in almost equal pieces and get part of split by task id
            my_stocks = get_stocks(db_tool, parsed_args.task)
            arguments = {
                'signals': ["ALL"],
                'stocks': my_stocks,
                "look_back": 300,
                'db_tool': db_tool
            }
            exit_code += BuildIndicatorsQuick(config, arguments,
                                              logger).build()
        if parsed_args.live:
            arguments_broker = {
                "portfolio_name": "degiro",
                "portfolio_user": "******",
                "database_data": False,
                "db_tool": db_tool
            }
            degiro = DegiroClient(config["degiro"], arguments_broker, logger)
            degiro.login()
            arguments = {
                'strategies': ["SecureHotH6MonthT50V40"],
                'broker': degiro,
                'strategy_name_prefix': 'L',
                'db_tool': db_tool
            }
            exit_code += StartStrategy(config, arguments, logger).build()
        if parsed_args.strategy is not None:
            arguments_broker = {
                "portfolio_name": "",
                "portfolio_user": "******",
                "database_data": False,
                "db_tool": db_tool,
                "cash": 2000
            }
            arguments = {
                'strategies': parsed_args.strategy,
                'broker': DemoBroker(config, arguments_broker, logger),
                'strategy_name_prefix': 'D',
                'db_tool': db_tool
            }
            exit_code += StartStrategy(config, arguments, logger).build()
            arguments["broker"].commit_work()
        if parsed_args.back_test_strategy is not None:
            arguments_broker = {
                "portfolio_name": "",
                "portfolio_user": "******",
                "database_data": True,
                "db_tool": db_tool,
                "cash": 2000
            }
            backtest_days = int(config['autotrader']['backtest_days'])
            from_date, to_date = datetime.datetime.now() + datetime.timedelta(days=-backtest_days), \
                datetime.datetime.now()
            arguments = {
                "strategies": ["ALL"],
                'stocks': ["ALL"],
                "signals": ["ALL"],
                'db_tool': db_tool,
                "broker": DemoBroker(config, arguments_broker, logger),
                "from_date": from_date,
                "to_date": to_date
            }
            exit_code += BackTestingStrategy(config, arguments, logger).build()
            arguments["broker"].commit_work()
    if parsed_args.version:
        print(VERSION)
    return exit_code
예제 #22
0
 See the License for the specific language governing permissions and
 limitations under the License.
"""
import unittest
import logging
from autotrader.base.trader_base import TraderBase
from autotrader.broker.degiro.degiro_client import DegiroClient
from autotrader.datasource.database.stock_database import StockDataBase
from autotrader.datasource.database.stock_schema import BARS_NUMPY, BARS_PANDAS, Stock
from autotrader.tool.database.create_and_fill_database import CreateAndFillDataBase
from autotrader.tool.database.update_database_stocks import UpdateDataBaseStocks

TEST_LOGGER = logging.getLogger()
TEST_LOGGER.setLevel(logging.WARNING)

CONFIG = TraderBase.get_config()
CONFIG['sql']['database'] = 'testdatabase'
DB = StockDataBase(CONFIG['sql'], TEST_LOGGER)


class TestDataBase(unittest.TestCase):
    """
    Test suite for database installer
    """

    @staticmethod
    def test_1_install_db():
        """
        test install db
        :return:
        """
예제 #23
0
from fnmatch import filter

from freezegun import freeze_time
from int_date import to_date
from sqlalchemy.orm import query

from autotrader.base.trader_base import TraderBase
from autotrader.broker.degiro.degiro_client import DegiroClient
from autotrader.broker.degiro.degiro_config_helper import DegiroConfigHelper
from autotrader.datasource.database.stock_database import StockDataBase
from autotrader.datasource.database.stock_schema import OrderType, Orders, \
    Status, Stock, Signal

TEST_LOGGER = logging.getLogger()
TEST_LOGGER.setLevel(logging.WARNING)
tz = TraderBase.get_timezone()


class TestDegiro(unittest.TestCase):
    """
    Degiro test suite
    """
    @classmethod
    def setUpClass(cls):
        cls.config = TraderBase.get_config()

        cls.db = StockDataBase(cls.config['sql'], TEST_LOGGER)
        cls.db.connect()
        arguments = {"db_tool": cls.db}
        cls.client = DegiroClient(cls.config['degiro'], arguments, TEST_LOGGER)
        cls.client.login()
예제 #24
0
 def get_plot(self):
     """
     Generate plot data for highcharts
     :return: json series string
     """
     tz = TraderBase.get_timezone()
     series_list = [{
         "name":
         "Price",
         "data":
         [[int(self.times[idx].replace(tzinfo=tz).timestamp()) * 1000, x]
          for idx, x in enumerate(self.open)],
         "id":
         'dataseries'
     }, {
         "type": 'flags',
         "data": [],
         "onSeries": 'dataseries',
         "shape": 'circlepin',
         "width": 20
     }]
     # we have to generate the siganl again
     signal = self.generate_signals()
     for idx, val in enumerate(signal):
         timestamp = int(self.times[idx + self.signal_shift].replace(
             tzinfo=tz).timestamp()) * 1000
         if val == 1:
             series_list[1]["data"].append({
                 "x": timestamp,
                 "title": 'B',
                 "text": 'Buy',
                 "color": "#155724",
                 "fillColor": "#c3e6cb",
                 "style": {
                     "fontFamily": 'monospace',
                     "color": "#155724"
                 }
             })
         elif val == -1:
             series_list[1]["data"].append({
                 "x": timestamp,
                 "title": 'S',
                 "text": 'Sell',
                 "color": "#721c24",
                 "fillColor": "#f8d7da",
                 "style": {
                     "fontFamily": 'monospace',
                     "color": "#721c24"
                 }
             })
     indicators = self.get_indicators()
     for idx, val in enumerate(indicators):
         data_shift = len(series_list[0]["data"]) - val.size
         indicator_values = [None for _ in range(data_shift)]
         for idx2, val2 in enumerate(val):
             timestamp = int(self.times[idx2 + data_shift].replace(
                 tzinfo=tz).timestamp()) * 1000
             indicator_values.append([timestamp, val2])
         series_list.append({
             "yAxis": 1,
             "name": "Graph" + str(idx),
             "data": indicator_values
         })
     my_json_str = json.dumps(series_list)
     my_pack_str = base64.b64encode(
         zlib.compress(my_json_str.encode("utf-8"), 9))
     size_str = sys.getsizeof(my_json_str)
     size_pack = sys.getsizeof(my_pack_str)
     debug_msg = "Size before {} and size after {}. {}".format(
         size_str, size_pack, 1 - size_pack / size_str)
     self.logger.debug(debug_msg)
     return my_pack_str
예제 #25
0
 def setUpClass(cls):
     cls.config = TraderBase.get_config()
     cls.db_tool = Db(cls.config['sql'], TEST_LOGGER)
     cls.db_tool.connect()
예제 #26
0
    def test_8_back_testing(self):
        """
        test the back testing tool for strategies
        :return:
        """
        tz = TraderBase.get_timezone()
        logging.basicConfig(level=logging.DEBUG)
        date_now = datetime.datetime.now(tz=tz)
        date_fake_starts = date_now - datetime.timedelta(days=150)
        config = TraderBase.get_config()
        my_parameter = [Parameter(value=5), Parameter(value=6)]
        signal_list = self.create_fake_signals(
            -2, date_fake_starts, [1], 'UltimateOscillatorCrossEmaSignal',
            my_parameter)
        assert signal_list
        assert len(signal_list) == 1
        my_plot = Plot()
        my_plot.add_plot_to_data({})
        signal_list[0].plot.append(my_plot)
        self.db_tool.commit()
        arguments_broker = {
            "portfolio_name": "",
            "portfolio_user": "******",
            "database_data": True,
            "db_tool": self.db_tool,
            "cash": 2000
        }
        arguments = {
            "strategies": ["SimpleMarket40"],
            "signals": ["Uoe"],
            "stocks": [1],
            "look_back": 400,
            "db_tool": self.db_tool,
            "broker": DemoBroker(config, arguments_broker, self.test_logger),
            "from_date": date_fake_starts,
            "to_date": date_now
        }
        BackTestingStrategy(config, arguments, self.test_logger).build()
        arguments["broker"].commit_work()
        json_data = self.db_tool.session.query(Plot).\
            filter(Plot.signal_id == signal_list[0].id).first()
        assert json_data.data
        json_data = json_data.get_plot()
        assert json_data != '{}'
        # todo analyse more functions with default datetime.now() arguments
        # todo solve monday not tlrade issue
        tz = TraderBase.get_timezone()
        sell_date = [
            datetime.datetime.fromtimestamp(int(data["x"]) / 1000, tz=tz)
            for data in json_data[1]["data"] if data["text"] == "Sell"
        ]
        buy_date = [
            datetime.datetime.fromtimestamp(int(date["x"]) / 1000, tz=tz)
            for date in json_data[1]["data"] if date["text"] == "Buy"
        ]
        assert sell_date and buy_date
        # now we check if strategy really bought stocky by signal
        sell_date = [
            item for item in sell_date if date_now >= item >= date_fake_starts
        ]
        buy_date = [
            item for item in buy_date if date_now >= item >= date_fake_starts
        ]
        assert sell_date and buy_date
        # remove first sell signal if younger than first buy signal
        if sell_date[0] < buy_date[0]:
            sell_date.pop(0)

        my_orders_buy = [
            x[0] for x in self.db_tool.session.query(Orders.date).filter(
                Orders.is_sell == 0).order_by(Orders.date).all()
        ]
        my_orders_sell = [
            x[0] for x in self.db_tool.session.query(Orders.date).filter(
                Orders.is_sell == 1).order_by(Orders.date).all()
        ]
        assert len(my_orders_buy) == len(buy_date)
        assert len(my_orders_sell) == len(sell_date)

        def check_date(date_list1, date_list2):
            """
            returns false if date in list is unequal
            :param date_list1:
            :param date_list2:
            :return:
            """
            for idx, my_date1 in enumerate(date_list1):
                if my_date1.replace(
                        tzinfo=tz).date() != date_list2[idx].date():
                    return False
            return True
        assert check_date(my_orders_buy, buy_date), \
            " The given date lists are not equal %s %s" % (my_orders_buy, buy_date)
        assert check_date(my_orders_sell, sell_date), \
            " The given date lists are not equal %s %s" % (my_orders_sell, sell_date)