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
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
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()
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}")
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()
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
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
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)
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)
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)
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)
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)
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)
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)
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
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)
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)
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)
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))
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
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)