def screening(self):
        """
        Method to start the screening once, should be executed in a THREAD.
        :return: nothing, results are saved in the model.
        """
        try:
            if not self._check_if_strategy_can_run():
                return

            self.model.is_background_thread_running.set(True)
            selection_values = self.model.selected_strategies_list.get()
            logger.info("Screening started...")
            self.model.result_stock_data_container_list.clear()
            analysis_params = self.model.analysis_parameters.get()
            results = run_analysis(selection_values,
                                   analysis_params['Strategies'],
                                   analysis_params['OtherParameters'])

            self.model.result_stock_data_container_list.extend(results)
        except Exception as e:
            logger.error("Exception while screening: " + str(e) + "\n" +
                         str(traceback.format_exc()))

        self.model.is_background_thread_running.set(False)
Example #2
0
 def _log_order(self, date, order, text):
     logger.info('---------  NOTIFY ORDER:')
     logger.info(('  {} Order ' + text).format(order.info['name']))
     logger.info(
         '   {}, Status {}: Ref: {}, Size: {}, Price: {}, Position: {}'.
         format(
             date, order.status, order.ref, order.size,
             'NA' if not order.price else round(order.price, 5),
             'NA' if not order.price else round(order.price *
                                                order.size, 5)))
Example #3
0
    def run_test(self,
                 data_file_list,
                 strategy_to_test,
                 backtesting_parameters,
                 analysis_parameters,
                 risk_models,
                 analyzers=[],
                 **kwargs):
        """
        Run method for the wrapper which wrap the ASTA-Framework structure to backtrader structure.
        :param analysis_parameters: dict with analysis parameters for strategy
        :param strategy_to_test: name of the strategy as string
        :param data_file_list: a list with files to read as string
        :param backtesting_parameters: Dict with parameters for testing, the Key "strategy_to_test" contains the strategy class to test.
        :param analyzers: List with class of btanalyzer, ex.: [btanalyzer.TradeAnalyzer]
        :param risk_models: other testing relevant parameters as dict
        :return: backtesting_result_instance final instance, backtrader test result
        """
        cerebro = bt.Cerebro()

        # add the backtrader strategy wrapper, real strategy will be build there with the backtesting_parameters dict
        # backtesting_result_instance.addstrategy(BacktraderStrategyWrapper, all_parameter, news_data)
        cerebro.addstrategy(BacktraderStrategyWrapper,
                            strategy_to_test=strategy_to_test,
                            backtesting_parameters=backtesting_parameters,
                            analysis_parameters=analysis_parameters,
                            risk_model=risk_models,
                            status_update=False,
                            **kwargs)

        # load the data from given file list and add it to backtrader instance
        if isinstance(data_file_list, list):
            for file_path in data_file_list:
                # TODO warum string?
                if isinstance(file_path, str):
                    stock_name = basename(file_path)
                    data = btfeeds.GenericCSVData(
                        name=stock_name,
                        dataname=file_path,
                        dtformat=GlobalVariables.get_stock_data_dtformat(),
                        nullvalue=0.0,
                        datetime=0,
                        open=1,
                        high=2,
                        low=3,
                        close=4,
                        volume=5,
                        openinterest=-1)
                    cerebro.adddata(data, name=data._name)
                else:
                    # compatibility for backtrader pandas data feed
                    cerebro.adddata(file_path, name=file_path._name)

        else:
            raise NotImplementedError("Data must be a list")

        # Set our desired cash start
        cerebro.broker.setcash(backtesting_parameters['initial_cash'])

        for analyzer in analyzers:
            cerebro.addanalyzer(analyzer)

        # Set the commission
        # https://www.backtrader.com/docu/commission-schemes/commission-schemes.html
        # 0.5% of the operation value --> 2500 € --> 12.5 per Buy/Sell
        cerebro.broker.setcommission(
            commission=backtesting_parameters['trade_commission_percent'])
        # Print out the starting conditions
        logger.info('Starting Portfolio Value: %.2f' %
                    cerebro.broker.getvalue())
        logger.info('--------------------')

        backtest_result = cerebro.run()
        analyzers = backtest_result[0].analyzers

        for analyzer in analyzers:
            test = analyzer.get_analysis()
            logger.info(str(analyzer) + ": " + str(test))

        # Print out the final result
        logger.info('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())

        return cerebro, backtest_result
    def identify_stock_name_and_stock_ticker_and_target_price_from_news_nltk_german_classifier(
            self, single_news_to_analyze):
        """
        Identifies a stock name within a news and returns the name and ticker
        :param single_news_to_analyze: news text itself
        :return: {'name': name_to_find, 'ticker': self.tickers[idx]}
                  or " " if no name found
        """

        if single_news_to_analyze is None:
            raise NotImplementedError

        preprocessed_news = self.optimize_text_for_german_tagger(
            single_news_to_analyze)

        # TODO: http://dsspace.wzb.eu/pyug/text_proc_feature_extraction/
        tokens = nltk.word_tokenize(preprocessed_news, language="german")
        tokens_removed_words = [
            t for t in tokens if t.lower() not in self.stopwords
        ]

        # http: // dsspace.wzb.eu / pyug / text_proc_feature_extraction /
        # tmp_tokens = {}
        # for doc_label, doc_tok in tokens_removed_words:
        #     tmp_tokens[doc_label] = []
        #     for t in doc_tok:
        #         t_parts = self.expand_compound_token(t)
        #         tmp_tokens[doc_label].extend(t_parts)

        tags = self.german_tagger.tag(tokens_removed_words)

        noun_tags = ""
        enable_tags = False

        for i in range(len(tags)):
            # TODO gscheider: erst nach dem ersten verb lesen
            if tags[i][1].startswith("V"):
                enable_tags = True
            if enable_tags:
                if tags[i][1].startswith("N"):
                    if i > 1 and tags[i - 1][1].startswith("ADJ"):
                        noun_tags = (tags[i - 1][0] + " " + tags[i][0])
                        break

                    if tags[i][1].startswith("NE") or tags[i][1].startswith(
                            "NN"):
                        noun_tags = (tags[i][0])
                        break

        if noun_tags is not None and len(noun_tags) > 0:
            name_return = ""
            target_price_return = 0
            ticker_return = ""
            stock_exchange_return = ""

            stock_to_check = noun_tags  # [0] --> first tag in list
            price_tuple = [i for i in tags if i[1].startswith("CARD")]

            try:
                name_to_find = self.lookup_stock_abr_in_all_names(
                    stock_to_check)
                idx = self._names.index(name_to_find)
                name_return = self._names[idx]
                ticker_return = self.tickers[idx]
                stock_exchange_return = self.stock_exchanges[idx]

            except Exception as e:  # look up symbol in web instead of list
                try:
                    name_return, ticker_return = get_symbol_and_real_name_from_abbrev_name_from_topforeignstocks(
                        stock_to_check)

                except Exception as e:
                    (", No STOCK found for news: " +
                     str(single_news_to_analyze))

                    return None

            if len(price_tuple) > 0:
                price = price_tuple[len(price_tuple) - 1][0]  # TODO 1: comment
                price = price.replace(",", ".")  # replace german comma
                if CommonUtils.is_float(price):
                    # price_tuple: [0] --> number, [1]--> CD
                    target_price_return = float(price)

            # news_dec = NewsDataContainerDecorator(StockDataContainer(name_return, ticker_return, stock_exchange_return),
            #                                      target_price_return, "", single_news_to_analyze, 0)

            ret = StockNameTickerExchangeAndTargetPrize(
                name_return, ticker_return, stock_exchange_return,
                target_price_return)
            return ret

        logger.info("No STOCK found for news: " + str(single_news_to_analyze))
        return None
def buy_recommendations(broker, stocks, max_num_of_different_stocks_to_buy):
    """
    Automatically buy the recommendations from result list
    :return: -
    """
    from Utils.Logger_Instance import logger

    broker.connect()

    if len(stocks) <= 0:
        return

    try:
        # sort stocks by rank
        sorted_stock_container_list = sorted(stocks,
                                             key=lambda x: x.get_rank(),
                                             reverse=True)

        for i in range(len(sorted_stock_container_list)):
            if max_num_of_different_stocks_to_buy <= 0:  # do not buy more stocks
                logger.info("Max number of stocks to buy reached.")
                return

            # check if there are enough data to create stop buy and stop loss limit orders
            if not are_order_information_available("BUY", sorted_stock_container_list[i]) or \
                    not are_order_information_available("SELL", sorted_stock_container_list[i]):
                logger.info("Not enough information for order available: " +
                            str(sorted_stock_container_list[i]))
                break

            # trade only, if not already traded today
            orders = broker.read_orders()
            date_time_str = None
            # find the last entry
            for curr_order_num in range(len(orders)):
                if orders['stock_ticker'][curr_order_num].startswith(
                        sorted_stock_container_list[i].stock_ticker()):
                    date_time_str = (orders['datetime'][curr_order_num])

            if date_time_str is not None:
                next_day_or_later = is_next_day_or_later(
                    str(datetime.now()), "%Y-%m-%d %H:%M:%S.%f", date_time_str,
                    "%Y-%m-%d %H:%M:%S.%f")
                # do not trade same recommendation again on one day
                if not next_day_or_later:
                    logger.info(
                        "No current recommendations to buy available for " +
                        str(sorted_stock_container_list[i]))
                    break

            # get stock quantity, only even number
            qty = int(sorted_stock_container_list[i].get_position_size())
            # rank < 0 means sell recommendation, > 0 a buy
            if sorted_stock_container_list[i].get_rank() > 0:
                # stop buy limit order
                broker.execute_order(
                    sorted_stock_container_list[i].stock_ticker(), 'LMT',
                    'BUY', qty, sorted_stock_container_list[i].get_stop_buy())
                # stop loss limit order
                broker.execute_order(
                    sorted_stock_container_list[i].stock_ticker(), 'LMT',
                    'SELL', qty,
                    sorted_stock_container_list[i].get_stop_loss())

                max_num_of_different_stocks_to_buy = max_num_of_different_stocks_to_buy - 1

            # get the response
            # TODO without sleep
            sleep(0.5)
            error_message_list = broker.get_and_clear_error_message_list()

            if len(error_message_list) > 0:
                for error_msg in error_message_list:
                    logger.error(
                        "Unexpected response from broker while autotrading: " +
                        str(error_msg))
                    # TODO what to do in case of an error?

    except Exception as e:
        err_msg = "Unexpected Exception while autotrading: " + str(
            e) + "\n" + str(traceback.format_exc())
        logger.error(err_msg)
        print(err_msg)

    broker.disconnect()
Example #6
0
 def log(self, txt, dt=None):
     """ Logging function fot this strategy"""
     dt = dt or self.datas[0].datetime.date(0)
     logger.info('%s, %s' % (dt.isoformat(), txt))
Example #7
0
 def reply_handler(self, msg):
     """Handles of server replies"""
     print("Server Response: %s, %s" % (msg.typeName, msg))
     logger.info("Server Response: %s, %s" % (msg.typeName, msg))
 def load_backtesting_stocks_from_file(self, multi_file_path):
     self.model.available_backtesting_stocks_list.set(multi_file_path)
     logger.info("Backtesting stocks read")
    def backtesting(self):
        """
        Method to start the backtesting once, should be executed in a THREAD.
        :return: nothing, results are saved in the model.
        """
        try:
            strategy_selections = self.model.selected_strategies_list.get()
            selected_backtesting_analyzers_str = self.model.selected_backtesting_analyzers_list.get(
            )
            selected_backtesting_stocks = self.model.selected_backtesting_stocks_list.get(
            )

            if strategy_selections == "" or not len(strategy_selections) is 1:
                messagebox.showerror(
                    "Selection Error",
                    "Please select exactly ONE strategie to run in backtesting!"
                )
                return

            if selected_backtesting_stocks == "" or len(
                    selected_backtesting_stocks) <= 0:
                messagebox.showerror(
                    "Selection Error",
                    "Please select stocks to run in backtesting first!")
                return

            if selected_backtesting_analyzers_str == "" or len(
                    selected_backtesting_analyzers_str) <= 0:
                continue_backtesting = messagebox.askyesno(
                    "Analyzer Selection",
                    "No additional analyzer ist selected! Do you want to start backtesting anyway?"
                )
                if not continue_backtesting:
                    return

            data_backtesting_analyzers = []
            for ana in self.model.available_backtesting_analyzers_list.get():
                for selected_backtesting_analyzer_str in selected_backtesting_analyzers_str:
                    if selected_backtesting_analyzer_str in ana.__name__:
                        data_backtesting_analyzers.append(ana)

            available_backtesting_stocks_data = self.model.available_backtesting_stocks_list.get(
            )
            selected_backtesting_stocks_data = []
            for selected_backtesting_stock_str in selected_backtesting_stocks:
                for available_backtesting_stock_data in available_backtesting_stocks_data:
                    if selected_backtesting_stock_str in available_backtesting_stock_data:
                        selected_backtesting_stocks_data.append(
                            available_backtesting_stock_data)
                        break

            req_params = StrategyFactory.get_required_parameters_with_default_parameters(
            )
            at_objects = w.scrollable_frame_parameters.form.at_objects
            content_others = w.scrollable_frame_parameters.form.get_parameters(
                at_objects)

            if not self.accept_parameters_from_text(content_others,
                                                    req_params):
                messagebox.showerror("Parameter file is not valid!",
                                     "Please choose a valid parameters file!")
                return

            self.model.is_background_thread_running.set(True)
            logger.info("")
            logger.info(
                "*********************************************************************************************"
            )
            logger.info(
                "******************** Backtesting started... *************************************************"
            )

            bf = BacktestingFactory()
            backtesting_parameters = self.model.analysis_parameters.get(
            )["BacktestingParameters"]
            bt_framework_name = backtesting_parameters['BacktestingFramework']
            tbt = bf.prepare(bt_framework_name)
            # get the selection of the first strategy
            analysis_params = self.model.analysis_parameters.get(
            )['Strategies'][strategy_selections[0]]

            # get the risk model value without key
            risk_models = self.model.analysis_parameters.get(
            )['OtherParameters']['RiskModels']
            backtesting_result_instance, backtest_result = tbt.run_test(
                selected_backtesting_stocks_data, strategy_selections[0],
                backtesting_parameters, analysis_params, risk_models,
                data_backtesting_analyzers)

            insert_text_into_gui(self.view.Scrolledtext_analyzer_results,
                                 "",
                                 delete=True,
                                 start=1.0)

            # get items of analyzers and append it to the name
            analyzers = backtest_result[0].analyzers
            for analyzer in analyzers:
                ana_res = analyzer.get_analysis()
                items = list(ana_res.items())
                text_list = []
                for i in items:
                    text = ': '.join(str(e) for e in i)
                    text_list.append(text)

                final_text = '\n'.join(str(e) for e in text_list)
                insert_text_into_gui(
                    self.view.Scrolledtext_analyzer_results,
                    str(analyzer.__class__.__name__) + ":\n" +
                    str(final_text) + "\n\n")

            portvalue = round(backtesting_result_instance.broker.getvalue(), 2)
            pnl = round(portvalue - backtesting_parameters['initial_cash'], 2)

            # Print out the final result
            insert_text_into_gui(
                self.view.Scrolledtext_analyzer_results,
                'Final Portfolio Value: ${}'.format(portvalue) + "\n")
            insert_text_into_gui(
                self.view.Scrolledtext_analyzer_results,
                'Profit/Loss (rounded 2 places): ${}'.format(pnl))

            self.model.backtesting_result_instance.set(
                backtesting_result_instance)

        except Exception as e:
            logger.error("Exception while backtesting: " + str(e) + "\n" +
                         str(traceback.format_exc()))

        self.model.is_background_thread_running.set(False)