Beispiel #1
0
    def test_run_two_days_two_traders(self):
        stock_exchange = StockExchange()
        stock_market_data = StockMarketData([Company.A, Company.B], [Period.TESTING]).deepcopy_first_n_items(2)
        trader1 = BuyAndHoldTrader()
        trader2 = BuyAndHoldTrader()
        result = stock_exchange.run(stock_market_data, [trader1, trader2])

        # test final day
        final_day = stock_market_data.get_most_recent_trade_day()
        self.assertEqual(final_day, Date(2012, 1, 4))

        # test final portfolio1
        final_portfolio1 = result[trader1][final_day]
        self.assertIsNotNone(final_portfolio1)
        self.assertEqual(final_portfolio1.cash, 24.807061999999974)
        self.assertEqual(final_portfolio1.get_stock(Company.A), 14)
        self.assertEqual(final_portfolio1.get_stock(Company.B), 3)
        self.assertEqual(final_portfolio1.get_value(stock_market_data), 1005.0684910000001)

        # test final portfolio2
        final_portfolio2 = result[trader2][final_day]
        self.assertIsNotNone(final_portfolio2)
        self.assertEqual(final_portfolio2.cash, 24.807061999999974)
        self.assertEqual(final_portfolio2.get_stock(Company.A), 14)
        self.assertEqual(final_portfolio2.get_stock(Company.B), 3)
        self.assertEqual(final_portfolio2.get_value(stock_market_data), 1005.0684910000001)
    def trade(self, portfolio: Portfolio,
              stock_market_data: StockMarketData) -> List[Order]:
        """
        Generate actions to be taken on the "stock market"
    
        Args:
          portfolio : current Portfolio of this traders
          stock_market_data : StockMarketData for evaluation

        Returns:
          A OrderList instance, may be empty never None
        """
        assert portfolio is not None
        assert stock_market_data is not None

        if self.__bought_stocks:
            return []
        else:
            self.__bought_stocks = True

            # Calculate how many cash to spend per company
            company_list = stock_market_data.get_companies()

            # Invest (100 // `len(companies)`)% of cash into each stock
            order_list = []
            for company in company_list:
                available_cash_per_stock = portfolio.cash / len(company_list)
                most_recent_price = stock_market_data.get_most_recent_price(
                    company)
                amount_to_buy = available_cash_per_stock // most_recent_price
                order_list.append(Order(OrderType.BUY, company, amount_to_buy))
            return order_list
Beispiel #3
0
    def __init__(self, expert_a, expert_b, stock_market_data: StockMarketData,
                 portfolio: Portfolio):
        """
        Constructor  
        Args:
          expert_a : expert opinion from analyst A
          expert_b : expert opinion from analyst B 
          portfolio : current Portfolio of this traders
          stock_market_data : StockMarketData for evaluation
        """
        # get composition of current portfolio
        self.noStockA = portfolio.get_stock(Company.A)
        self.noStockB = portfolio.get_stock(Company.B)
        self.Cash = portfolio.cash
        # most important information: minimum cash neccessary to buy one addtional share: if set to 100 or any fixed value,the zig zag curve in the evalution set is occuring
        # when set to max no zigzag can be seen
        self.min_cash_to_buy = max(
            stock_market_data.get_most_recent_price(Company.A),
            stock_market_data.get_most_recent_price(Company.B))

        # get votes from experts opinions
        company_list = stock_market_data.get_companies()
        for company in company_list:
            if company == Company.A:
                stock_data_a = stock_market_data[Company.A]
                vote_a = expert_a.vote(stock_data_a)
            elif company == Company.B:
                stock_data_b = stock_market_data[Company.B]
                vote_b = expert_b.vote(stock_data_b)
            else:
                assert False

        self.expertOpinionA = vote_a
        self.expertOpinionB = vote_b
    def test_get_most_recent_price(self):
        """
        Tests: StockMarketData#get_most_recent_price

        Read the stock market data and check if the last available stock price is determined correctly
        """
        stock_market_data = StockMarketData([Company.A, Company.B],
                                            [Period.TRAINING, Period.TESTING])
        self.assertEqual(stock_market_data.get_most_recent_price(Company.A),
                         stock_market_data[Company.A].get_last()[1])
    def run(self,
            data: StockMarketData,
            traders: List[ITrader],
            offset: int = 0) -> Dict[ITrader, Dict[Date, Portfolio]]:
        """
        Runs the stock exchange over the given stock market data for the given traders.
        :param data: The complete stock market data
        :param traders: A list of all traders
        :param offset: The number of trading days which a will be skipped before (!) trading starts
        :return: The main data structure, which stores one portfolio per trade day, for each traders
        """
        assert data is not None
        assert traders is not None

        # initialize the main data structure: Dictionary over traders, that stores each traders's portfolio per day
        # data structure type is Dict[ITrader, Dict[Date, Portfolio]]
        trade_dates = data.get_trade_days()
        assert trade_dates  # must not be empty
        assert 0 <= offset < len(trade_dates)  # offset must be feasible
        self.__complete_stock_market_data = data
        self.__trader_portfolios = {
            trader: {
                trade_dates[offset]: Portfolio(self.__cash)
            }
            for trader in traders
        }

        # iterate over all trade days minus 1, because we don't trade on the last day
        for tick in range(offset, len(trade_dates) - 1):
            logger.debug(
                f"Stock Exchange: Current tick '{tick}' means today is '{trade_dates[tick]}'"
            )
            if tick % 365 == 1:
                print(trade_dates[tick])
            # build stock market data until today
            current_stock_market_data = data.deepcopy_first_n_items(tick + 1)

            # iterate over all traders
            for trader in traders:
                # get the traders's order list by giving him a copy (to prevent cheating) of today's portfolio
                todays_portfolio = self.__trader_portfolios[trader][
                    trade_dates[tick]]
                current_order_list = trader.trade(
                    copy.deepcopy(todays_portfolio), current_stock_market_data)

                # execute order list and save the result as tomorrow's portfolio
                tomorrows_portfolio = copy.deepcopy(todays_portfolio)
                tomorrows_portfolio.update_with_order_list(
                    current_stock_market_data, current_order_list)
                self.__trader_portfolios[trader][trade_dates[
                    tick + 1]] = tomorrows_portfolio

        return self.__trader_portfolios
Beispiel #6
0
def main_print_model_performance():
    """
    Just prints the final portfolio value and v score (return % per trading day)
    for training and testing data set for different traders.
    """
    stock_market_data_train = StockMarketData([Company.A, Company.B],
                                              [Period.TRAINING])
    # stock_market_data_train = stock_market_data_train.deepcopy_first_n_items(
    #     int(stock_market_data_train.get_row_count() / 5))
    stock_market_data_test = StockMarketData([Company.A, Company.B],
                                             [Period.TESTING])
    bah_trader = BuyAndHoldTrader(name='buy and hold')
    tt_trader1 = TrustingTrader(ObscureExpert(Company.A),
                                ObscureExpert(Company.B), 'green',
                                'trust experts, prefer A')
    tt_trader2 = TrustingTrader2(ObscureExpert(Company.A),
                                 ObscureExpert(Company.B), 'limegreen',
                                 'trust experts for sell only')
    dql_trader = deep_q_learning_trader.DeepQLearningTrader(
        ObscureExpert(Company.A), ObscureExpert(Company.B), True, False, 'red')
    all_traders = [bah_trader, tt_trader1, tt_trader2, dql_trader]
    trader_names = []
    for trader in all_traders:
        if isinstance(trader, deep_q_learning_trader.DeepQLearningTrader
                      ) and trader.plot_name is not None:
            trader_name = trader.plot_name
        else:
            trader_name = trader.get_name()
        trader_names.append(trader_name)
    max_trader_name_length = max((len(name) for name in trader_names))
    for trader, trader_name in zip(all_traders, trader_names):
        is_first_line = True
        for dataset, dataset_name, starting_cash in [
            (stock_market_data_train, 'train', 10000.0),
            (stock_market_data_test, 'test', 2000.0)
        ]:
            stock_exchange = StockExchange(starting_cash)
            stock_exchange.run(dataset, [trader])
            p = stock_exchange.get_final_portfolio_value(trader)
            samples = dataset.get_row_count()
            v = 100.0 * (math.pow(p / starting_cash, 1 / samples) - 1.0)
            if is_first_line:
                header = ('{: <' + str(max_trader_name_length) +
                          '}').format(trader_name)
            else:
                header = ' ' * max_trader_name_length
            header += f' ({dataset_name: <5}): '
            print(f'{header}{v:.5f}% return per trading day'
                  f' (final portfolio value of {p:.1e})')
            is_first_line = False
            if isinstance(trader, BuyAndHoldTrader):
                trader.reset()
Beispiel #7
0
    def update_with_order_list(self, stock_market_data: StockMarketData, orders: List[Order]):
        """
        Update the portfolio by executing all given stock orders simultaneously.
        Executing simultaneously means:
            1) The order in which the stock orders are executed does not matter.
            2) Cash from selling stocks today is only available for buying stocks tomorrow.
        If a stock order couldn't be executed (e.g., not enough cash/stocks available), then that order is skipped.
        :param stock_market_data: Information about all stock prices
        :param orders: The list of all stock orders
        :return:
        """
        assert stock_market_data is not None
        assert orders is not None

        if len(orders) == 0:
            logger.debug("The order list is empty. No portfolio update this time")
            return

        available_cash = self.cash
        current_date = stock_market_data.get_most_recent_trade_day()
        logger.debug(f"Updating portfolio {self}: Available cash on {current_date} is {available_cash}")

        for order in orders:
            # get the infos about the order and the existing stock
            company = order.company
            current_price = stock_market_data.get_most_recent_price(company)
            amount = order.amount
            trade_volume = amount * current_price
            existing_amount = self.get_stock(company)

            if order.type is OrderType.BUY:
                logger.debug(f"Buying {amount} stocks of '{company}' at {current_price} (total {trade_volume})")
                if trade_volume <= available_cash:
                    self.stocks[company] = existing_amount + amount
                    self.cash -= trade_volume
                    available_cash -= trade_volume
                else:
                    logger.debug(f"Not enough cash ({available_cash}) for transaction with volume of {trade_volume}")
            elif order.type is OrderType.SELL:
                logger.debug(f"Selling {amount} stocks of '{company}' at {current_price} (total {trade_volume})")
                if existing_amount >= amount:
                    self.stocks[company] = existing_amount - amount
                    self.cash += trade_volume
                else:
                    logger.debug(f"Not enough stocks ({existing_amount}) for selling {amount} of them")
            else:
                assert False
            logger.debug(f"Resulting available cash after trade: {self.cash}")
Beispiel #8
0
def main_orig():
    """
    Code from the original main routine.
    Visualizes portfolio value over the testing period for different traders.
    """
    # Load stock market data for testing period
    stock_market_data = StockMarketData([Company.A, Company.B],
                                        [Period.TESTING])

    # create new stock exchange with initial portfolio cash for each traders
    stock_exchange = StockExchange(2000.0)

    # create the traders
    bah_trader = BuyAndHoldTrader('black', 'Buy and hold')
    tt_trader_obscure = TrustingTrader(ObscureExpert(Company.A),
                                       ObscureExpert(Company.B), 'green',
                                       'Trust experts')
    tt_trader2 = TrustingTrader2(ObscureExpert(Company.A),
                                 ObscureExpert(Company.B), 'limegreen',
                                 'Trust experts for sell only')
    dql_trader = deep_q_learning_trader.DeepQLearningTrader(
        ObscureExpert(Company.A),
        ObscureExpert(Company.B),
        True,
        False,
        'red',
        plot_name='Deep Q-learning trader')

    # run the stock exchange over the testing period, with 100 skipped trading days
    stock_exchange.run(stock_market_data,
                       [bah_trader, tt_trader_obscure, tt_trader2, dql_trader])

    # visualize the results
    stock_exchange.visualize_last_run()
Beispiel #9
0
    def make_order(self, company: Company, orderTyp: OrderType, percentage,
                   portfolio: Portfolio,
                   stock_market_data: StockMarketData) -> Order:
        """
         creates an Order
         Args:
            company: the company for the order
            orderTyp: the OrderTyp (as Vote instance)
            percentage: an integer indicating how much percent should be bought or sold
         Returns an order for one company of instance Order
        """
        if orderTyp == OrderType.BUY:
            stock_price = stock_market_data.get_most_recent_price(company)
            port = portfolio.cash * percentage
            amount_to_buy = int(port // stock_price)
            logger.debug(
                f"{self.get_name()}: Got best action to buy {company}: and bought {amount_to_buy}"
            )
            return Order(OrderType.BUY, company,
                         amount_to_buy) if amount_to_buy > 0 else None

        elif orderTyp == OrderType.SELL:
            amount_to_sell = portfolio.get_stock(company)
            amount_to_sell *= percentage
            logger.debug(
                f"{self.get_name()}: Got best action to sell {company}: and sold {amount_to_sell}"
            )
            return Order(OrderType.SELL, company,
                         amount_to_sell) if amount_to_sell > 0 else None

        else:
            assert False
    def trade(self, portfolio: Portfolio,
              stock_market_data: StockMarketData) -> List[Order]:
        """
        Generate action to be taken on the "stock market"
    
        Args:
          portfolio : current Portfolio of this traders
          stock_market_data : StockMarketData for evaluation

        Returns:
          A OrderList instance, may be empty never None
        """
        assert portfolio is not None
        assert stock_market_data is not None
        assert stock_market_data.get_companies() == [Company.A, Company.B]

        current_state = get_state(self, stock_market_data)

        if self.train_while_trading and self.last_state is not None:
            reward = get_reward(self, portfolio, stock_market_data)
            self.memory.append(
                (self.last_state, self.last_action, reward, current_state))
            train_neural_net(self)

        action_index = get_index_for_action_to_execute(self, current_state)

        self.last_state = current_state
        self.last_action = action_index
        self.last_portfolio_value = portfolio.get_value(stock_market_data)

        return get_order_list(self, portfolio, stock_market_data)
    def test_update_action_order_does_not_matter(self):
        stock_market_data = StockMarketData([Company.A, Company.B],
                                            [Period.TESTING])

        # Create two equal designed portfolios
        portfolio1 = Portfolio(0, {Company.A: 100})
        portfolio2 = Portfolio(0, {Company.A: 100})

        # Create two order lists with the same entries, however in different order
        order_list_1 = [
            Order(OrderType.BUY, Company.A, 50),
            Order(OrderType.SELL, Company.A, 100)
        ]
        order_list_2 = [
            Order(OrderType.SELL, Company.A, 100),
            Order(OrderType.BUY, Company.A, 50)
        ]

        # Execute the trade action lists on the two portfolios: Sell 100 stocks, skip buying because no cash available
        portfolio1.update_with_order_list(stock_market_data, order_list_1)
        portfolio2.update_with_order_list(stock_market_data, order_list_2)

        # The portfolios should still be equal after applying the actions
        self.assertEqual(portfolio1.cash, 10275.9895)
        self.assertEqual(portfolio1.cash, portfolio2.cash)
        self.assertEqual(portfolio1.stocks[Company.A], 0)
        self.assertEqual(portfolio1.stocks, portfolio2.stocks)
    def trade(self, portfolio: Portfolio, stock_market_data: StockMarketData) -> List[Order]:
        """
        Generate action to be taken on the "stock market"

        Args:
          portfolio : current Portfolio of this traders
          stock_market_data : StockMarketData for evaluation

        Returns:
          A OrderList instance, may be empty never None
        """
        order_list = []

        company_list = stock_market_data.get_companies()
        for company in company_list:
            if company == Company.A:
                stock_data_a = stock_market_data[Company.A]
                vote_a = self.__expert_a.vote(stock_data_a)
                self.__follow_expert_vote(Company.A, stock_data_a, vote_a, portfolio, order_list)
            elif company == Company.B:
                stock_data_b = stock_market_data[Company.B]
                vote_b = self.__expert_b.vote(stock_data_b)
                self.__follow_expert_vote(Company.B, stock_data_b, vote_b, portfolio, order_list)
            else:
                assert False
        return order_list
Beispiel #13
0
    def trade(self, portfolio: Portfolio,
              stock_market_data: StockMarketData) -> List[Order]:
        """
        Generate actions to be taken on the "stock market"

        Args:
          portfolio : current Portfolio of this traders
          stock_market_data : StockMarketData for evaluation

        Returns:
          A OrderList instance, may be empty never None
        """
        order_list = []

        company_list = stock_market_data.get_companies()
        experts = [self.__expert_a, self.__expert_b]
        votes = [
            expert.vote(stock_market_data[comp])
            for comp, expert in zip(company_list, experts)
        ]
        buy_weight_sum = sum(
            (1 for vote in votes if vote is Vote.BUY or vote is Vote.HOLD))
        for comp, vote in zip(company_list, votes):
            buy_weight = 1 / buy_weight_sum if vote is Vote.BUY or vote is Vote.HOLD else None
            self.__follow_expert_vote(comp, stock_market_data[comp], vote,
                                      buy_weight, portfolio, order_list)
        return order_list
Beispiel #14
0
    def test_run_two_days_incorrect_offset(self):
        stock_exchange = StockExchange()
        stock_market_data = StockMarketData([Company.A, Company.B], [Period.TESTING]).deepcopy_first_n_items(2)
        trader = BuyAndHoldTrader()

        # too small and too big
        self.assertRaises(AssertionError, stock_exchange.run, stock_market_data, [trader], -1)
        self.assertRaises(AssertionError, stock_exchange.run, stock_market_data, [trader], 2)
Beispiel #15
0
    def test_run_two_days_correct_offset(self):
        stock_exchange = StockExchange()
        stock_market_data = StockMarketData([Company.A, Company.B], [Period.TESTING]).deepcopy_first_n_items(2)
        trader = BuyAndHoldTrader()
        result = stock_exchange.run(stock_market_data, [trader], 1)

        # test final day
        final_day = stock_market_data.get_most_recent_trade_day()
        self.assertEqual(final_day, Date(2012, 1, 4))

        # test final portfolio
        final_portfolio = result[trader][final_day]
        self.assertIsNotNone(final_portfolio)
        self.assertEqual(final_portfolio.cash, 1000.0)
        self.assertEqual(final_portfolio.get_stock(Company.A), 0)
        self.assertEqual(final_portfolio.get_stock(Company.B), 0)
        self.assertEqual(final_portfolio.get_value(stock_market_data), 1000.0)
Beispiel #16
0
    def test_trader_no_stock(self):
        trader = BuyAndHoldTrader('test_color', 'test_name')

        portfolio = Portfolio(1000)
        stock_market_data = StockMarketData([], [Period.TESTING])
        order_list = trader.trade(portfolio, stock_market_data)
        self.assertIsNotNone(order_list)
        self.assertEqual(len(order_list), 0)
Beispiel #17
0
    def test_update_sufficient_cash_reserve(self):
        stock_market_data = StockMarketData([Company.A, Company.B], [Period.TESTING])
        portfolio = Portfolio(20000, {Company.A: 200})
        order_list = [Order(OrderType.BUY, Company.A, 100)]

        # Current cash reserve is sufficient for trade volume. Trade should happen
        portfolio.update_with_order_list(stock_market_data, order_list)
        self.assertEqual(portfolio.cash, 9724.0105)
        self.assertEqual(portfolio.stocks[Company.A], 300)
Beispiel #18
0
    def test_update_no_sufficient_cash_reserve(self):
        stock_market_data = StockMarketData([Company.A, Company.B], [Period.TESTING])
        portfolio = Portfolio(0, {Company.A: 200})
        order_list = [Order(OrderType.BUY, Company.A, 100)]

        # Trade volume is too high for current cash reserve. Nothing should happen
        portfolio.update_with_order_list(stock_market_data, order_list)
        self.assertEqual(portfolio.cash, 0)
        self.assertEqual(portfolio.stocks[Company.A], 200)
Beispiel #19
0
    def test_get_final_portfolio_value(self):
        stock_exchange = StockExchange()
        stock_market_data = StockMarketData([Company.A, Company.B], [Period.TESTING]).deepcopy_first_n_items(2)
        trader1 = BuyAndHoldTrader()
        trader2 = BuyAndHoldTrader()
        stock_exchange.run(stock_market_data, [trader1, trader2])

        # test final portfolio value
        self.assertEqual(stock_exchange.get_final_portfolio_value(trader1), 1005.0684910000001)
        self.assertEqual(stock_exchange.get_final_portfolio_value(trader2), 1005.0684910000001)
    def test_deepcopy_first_n_items(self):
        stock_market_data = StockMarketData([Company.A, Company.B],
                                            [Period.TRAINING, Period.TESTING])

        # test copying zero items
        copy = stock_market_data.deepcopy_first_n_items(0)
        self.assertIsNotNone(copy)
        self.assertNotEqual(stock_market_data, copy)
        self.assertEqual(copy.get_number_of_companies(), 2)
        self.assertEqual(copy.get_row_count(), 0)

        # test copying one item
        copy = stock_market_data.deepcopy_first_n_items(1)
        self.assertIsNotNone(copy)
        self.assertNotEqual(stock_market_data, copy)
        self.assertEqual(copy.get_number_of_companies(), 2)
        self.assertEqual(copy.get_most_recent_trade_day(), Date(1962, 1, 2))
        self.assertEqual(copy.get_most_recent_price(Company.A), 0.059620)
        self.assertEqual(copy.get_most_recent_price(Company.B), 2.192523)
Beispiel #21
0
    def test_update_do_not_drop_below_cash_0(self):
        stock_market_data = StockMarketData([Company.A, Company.B], [Period.TESTING])
        portfolio = Portfolio(110)

        # Create a order list whose individual actions are within the limit but in sum are over the limit
        # Most recent stock price of stock A is 102.759895
        order_list = [Order(OrderType.BUY, Company.A, 1), Order(OrderType.BUY, Company.A, 1)]
        portfolio.update_with_order_list(stock_market_data, order_list)
        self.assertEqual(portfolio.cash, 7.240105)
        self.assertEqual(portfolio.stocks[Company.A], 1)
Beispiel #22
0
    def get_value(self, stock_market_data: StockMarketData, date: Date = None) -> float:
        """
        Return the value of this portfolio: It is the contained ash plus the value of all contained stocks.
        If no date is given, the most recent trade day from stock market data is used.
        :param stock_market_data: Information about all stock prices
        :param date: The day we want the portfolio value for
        :return: The portfolio value
        """
        assert stock_market_data is not None

        result = self.cash
        for company in self.stocks.keys():
            if date is None:
                price = stock_market_data.get_most_recent_price(company)
            else:
                stock_data = stock_market_data.__getitem__(company)
                price = stock_data.get_price(date)
            result += self.stocks[company] * price
        return result
Beispiel #23
0
    def test_get_value_with_date(self):
        stock_market_data = StockMarketData([Company.A, Company.B], [Period.TESTING])
        date = Date(2012, 1, 3)

        portfolio = Portfolio(100.0)
        self.assertEqual(portfolio.get_value(stock_market_data, date), 100.0)
        portfolio = Portfolio(100.0, {Company.A: 10})
        self.assertEqual(portfolio.get_value(stock_market_data, date), 455.54107999999997)
        portfolio = Portfolio(100.0, {Company.A: 10, Company.B: 10})
        self.assertEqual(portfolio.get_value(stock_market_data, date), 2046.9924999999998)
Beispiel #24
0
    def test_get_value_without_date(self):
        stock_market_data = StockMarketData([Company.A, Company.B], [Period.TESTING])
        portfolio = Portfolio()
        self.assertEqual(portfolio.get_value(stock_market_data), 0)

        portfolio = Portfolio(100.0)
        self.assertEqual(portfolio.get_value(stock_market_data), 100.0)
        portfolio = Portfolio(100.0, {Company.A: 10})
        self.assertEqual(portfolio.get_value(stock_market_data), 1127.59895)
        portfolio = Portfolio(100.0, {Company.A: 10, Company.B: 10})
        self.assertEqual(portfolio.get_value(stock_market_data), 2416.5398400000004)
Beispiel #25
0
    def test_trade_one_stock(self):
        trader = BuyAndHoldTrader('test_color', 'test_name')

        portfolio = Portfolio(1000)
        stock_market_data = StockMarketData([Company.A], [Period.TESTING])
        order_list = trader.trade(portfolio, stock_market_data)
        self.assertIsNotNone(order_list)
        self.assertEqual(len(order_list), 1)
        self.assertEqual(order_list[0].type, OrderType.BUY)
        self.assertEqual(order_list[0].company, Company.A)
        self.assertEqual(order_list[0].amount, 9)
Beispiel #26
0
    def trade(self, portfolio: Portfolio,
              stock_market_data: StockMarketData) -> List[Order]:
        """
        Generate action to be taken on the "stock market"
    
        Args:
          portfolio : current Portfolio of this traders
          stock_market_data : StockMarketData for evaluation

        Returns:
          A OrderList instance, may be empty never None
        """

        assert portfolio is not None
        assert stock_market_data is not None
        assert stock_market_data.get_companies() == [Company.A, Company.B]

        order_list = []
        vote_a = self.expert_a.vote(stock_market_data[Company.A])
        vote_b = self.expert_b.vote(stock_market_data[Company.B])

        # convert votes to state
        state = np.array([self.vote2num[vote_a], self.vote2num[vote_b]])

        if self.train_while_trading:
            if len(self.memory) > self.min_size_of_memory_before_training:
                # helper function which executes experience replay
                self._replay()

        # act
        action = self._act(state, stock_market_data, portfolio, order_list)

        if self.last_portfolio_value is not None:
            # Reward function R1
            if self.last_portfolio_value <= portfolio.get_value(
                    stock_market_data):
                reward = 1
            else:
                reward = 0

            # Reward function R2
            #reward = (portfolio.get_value(
            #        stock_market_data) - self.last_portfolio_value) / self.last_portfolio_value

            # helper to fill up the queue for performance replay
            self._remember(self.last_state, action, reward, state)

        # save state and portfolio value
        self.last_portfolio_value = portfolio.get_value(stock_market_data)
        self.last_state = state

        return order_list
    def test_stock_market_data_one_company_one_period(self):
        stock_market_data = StockMarketData([Company.A], [Period.TRAINING])

        self.assertIsNotNone(stock_market_data)
        self.assertEqual(stock_market_data.get_number_of_companies(), 1)
        self.assertEqual(stock_market_data.get_row_count(), 12588)
        self.assertEqual(stock_market_data.get_most_recent_trade_day(),
                         Date(2011, 12, 30))
        self.assertEqual(stock_market_data.get_most_recent_price(Company.A),
                         34.802376)
        self.assertIsNone(stock_market_data.get_most_recent_price(Company.B))
    def test_stock_market_data_one_company_two_periods(self):
        stock_market_data = StockMarketData([Company.A],
                                            [Period.TRAINING, Period.TESTING])

        self.assertIsNotNone(stock_market_data)
        self.assertEqual(stock_market_data.get_number_of_companies(), 1)
        self.assertEqual(stock_market_data.get_row_count(), 13594)
        self.assertEqual(stock_market_data.get_most_recent_trade_day(),
                         Date(2015, 12, 31))
        self.assertEqual(stock_market_data.get_most_recent_price(Company.A),
                         102.759895)
        self.assertIsNone(stock_market_data.get_most_recent_price(Company.B))
Beispiel #29
0
    def trade(self, portfolio: Portfolio,
              stock_market_data: StockMarketData) -> List[Order]:
        """
        Generate action to be taken on the "stock market"
        Args:
          portfolio : current Portfolio of this traders
          stock_market_data : StockMarketData for evaluation

        Returns:
          A OrderList instance, may be empty never None
        """
        assert portfolio is not None
        assert stock_market_data is not None
        assert stock_market_data.get_companies() == [Company.A, Company.B]

        # calculate current state
        state_ = state_maker(self.expert_a, self.expert_b, stock_market_data,
                             portfolio)
        curr_state = state_.create_numerical_state(self.state_size)
        # calculate current portfolio value
        curr_portfolio_value = portfolio.get_value(stock_market_data)

        # train or testing mode
        if self.train_while_trading == True:
            # Store state as experience (memory) and train the neural network only if trade() was called before at least once
            if self.last_state is not None:
                reward = self.get_rewards(self.last_portfolio_value,
                                          curr_portfolio_value)
                self.remember(self.last_state, self.last_action_a, reward,
                              curr_state)
                if len(self.memory) > self.min_size_of_memory_before_training:
                    self.replay()
            # Create actions for current state and decrease epsilon for fewer random actions
            curr_action_a = self.get_best_action(curr_state)
            final_order = self.create_order_list(curr_action_a, portfolio,
                                                 stock_market_data)
            self.decrease_epsilon()
        else:
            # predict best action from neuronal net
            curr_action_a = self.model.predict(curr_state)
            curr_action_a = np.argmax(curr_action_a[0])
            final_order = self.create_order_list(curr_action_a, portfolio,
                                                 stock_market_data)

        # Save created state, actions and portfolio value for the next call of trade()  --> erledigt
        self.last_state = curr_state
        self.last_action_a = curr_action_a
        self.last_portfolio_value = curr_portfolio_value

        return final_order
Beispiel #30
0
    def test_trade_vote_down_stock_a(self):
        expert_a = PerfectExpert(Company.A)
        expert_b = PerfectExpert(Company.B)
        trader = TrustingTrader(expert_a, expert_b, 'test_color', 'test_name')

        portfolio = Portfolio(1000.0, {Company.A: 10, Company.B: 10})
        stock_market_data = StockMarketData([Company.A, Company.B], [Period.TESTING]).deepcopy_first_n_items(4)
        order_list = trader.trade(portfolio, stock_market_data)
        self.assertIsNotNone(order_list)
        self.assertEqual(len(order_list), 2)
        self.assertEqual(order_list[0].type, OrderType.SELL)
        self.assertEqual(order_list[0].company, Company.A)
        self.assertEqual(order_list[0].amount, 10.0)
        self.assertEqual(order_list[1].type, OrderType.SELL)
        self.assertEqual(order_list[1].company, Company.B)
        self.assertEqual(order_list[1].amount, 10.0)