Example #1
0
    def __trade_for_company(self, company_enum: CompanyEnum,
                            company_data: StockData, predictor: IPredictor,
                            portfolio: Portfolio,
                            result_order_list: OrderList):

        last_value = company_data.get_last()[-1]

        # This determines the trade action to apply
        order = self.__determine_action(company_data, predictor, last_value)

        if order == OrderType.BUY:
            if portfolio.cash > last_value:
                # We can buy something
                amount_of_units_to_buy = int(portfolio.cash // last_value)
                result_order_list.buy(company_enum, amount_of_units_to_buy)

                # Update Cash in portfolio
                portfolio.cash = portfolio.cash - (amount_of_units_to_buy *
                                                   last_value)

        elif order == OrderType.SELL:
            # Check if something can be selled
            shares_in_portfolio = self.__find_shares_of_company(
                company_enum, portfolio.shares)
            if shares_in_portfolio is not None:
                # Sell everything
                result_order_list.sell(company_enum,
                                       shares_in_portfolio.amount)
Example #2
0
    def doTrade(self, portfolio: Portfolio, current_portfolio_value: float,
                stock_market_data: StockMarketData) -> OrderList:
        """
        Generate action to be taken on the "stock market"
    
        Args:
          portfolio : current Portfolio of this trader
          current_portfolio_value : value of Portfolio at given Momemnt
          stock_market_data : StockMarketData for evaluation

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

        y_a = stock_market_data.get_most_recent_price(CompanyEnum.COMPANY_A)
        y_b = stock_market_data.get_most_recent_price(CompanyEnum.COMPANY_B)

        p_a = self.stock_a_predictor.doPredict(
            stock_market_data[CompanyEnum.COMPANY_A])
        p_b = self.stock_b_predictor.doPredict(
            stock_market_data[CompanyEnum.COMPANY_B])

        r_a = (p_a - y_a) / y_a * 100
        r_b = (p_b - y_b) / y_b * 100

        result = OrderList()

        if (r_a < 0 and portfolio.get_amount(CompanyEnum.COMPANY_A) > 0):
            result.sell(CompanyEnum.COMPANY_A,
                        portfolio.get_amount(CompanyEnum.COMPANY_A))

        if (r_b < 0 and portfolio.get_amount(CompanyEnum.COMPANY_B) > 0):
            result.sell(CompanyEnum.COMPANY_B,
                        portfolio.get_amount(CompanyEnum.COMPANY_B))

        if (r_a <= 0 and r_b <= 0):
            return result

        company = CompanyEnum.COMPANY_A

        if (r_b > r_a):
            company = CompanyEnum.COMPANY_B

        buy_amount = math.floor(
            portfolio.cash / stock_market_data.get_most_recent_price(company))

        if (portfolio.cash > 0 and buy_amount > 0):
            result.buy(company, buy_amount)

        print("Portfolio: " + str(
            portfolio.total_value(
                stock_market_data.get_most_recent_trade_day(),
                stock_market_data)))

        # TODO: implement trading logic

        return result
    def doTrade(self, portfolio: Portfolio, current_portfolio_value: float,
                stock_market_data: StockMarketData) -> OrderList:
        """
        Generate action to be taken on the "stock market"
    
        Args:
          portfolio : current Portfolio of this trader
          current_portfolio_value : value of Portfolio at given Momemnt
          stock_market_data : StockMarketData for evaluation

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

        result = OrderList()

        predictions = {
            CompanyEnum.COMPANY_A: self.stock_a_predictor.doPredict(stock_market_data[CompanyEnum.COMPANY_A]),
            CompanyEnum.COMPANY_B: self.stock_b_predictor.doPredict(stock_market_data[CompanyEnum.COMPANY_B])
        }

        zuwachs = {}

        # sell companies which get worse
        for company in CompanyEnum:
            prediction = predictions[company]
            anzahl = portfolio.get_amount(company)
            current = stock_market_data.get_most_recent_price(company)

            zuwachs[company] = prediction / current

            # sell if getting worse
            if anzahl > 0:
                if current > prediction:
                    result.sell(company, anzahl)

        best = sorted(zuwachs, key=zuwachs.__getitem__)[::-1]

        currentCash = portfolio.cash

        for b in best:
            prediction = predictions[b]
            current = stock_market_data.get_most_recent_price(b)
            wachstum = (prediction / current)
            vola = self.isVolatile(stock_market_data[b].get_values())

            if wachstum > 1:
                if vola or wachstum > 1.001:
                    count = math.floor(currentCash / current)
                    result.buy(b, count)
                    currentCash -= count * current
                else:
                    result.sell(b, portfolio.get_amount(b))

        return result
    def doTrade(self, portfolio: Portfolio, current_portfolio_value: float,
                stock_market_data: StockMarketData) -> OrderList:
        """
        Generate action to be taken on the "stock market"
    
        Args:
          portfolio : current Portfolio of this trader
          current_portfolio_value : value of Portfolio at given Momemnt
          stock_market_data : StockMarketData for evaluation

        Returns:
          A OrderList instance, may be empty never None
        """
        result = OrderList()

        predictions = {
            CompanyEnum.COMPANY_A: self.stock_a_predictor.doPredict(stock_market_data[CompanyEnum.COMPANY_A]),
            CompanyEnum.COMPANY_B: self.stock_b_predictor.doPredict(stock_market_data[CompanyEnum.COMPANY_B])
        }

        zuwachs = {}

        # sell companies which get worse
        for company in CompanyEnum:
            prediction = predictions[company]
            anzahl = portfolio.get_amount(company)
            current = stock_market_data.get_most_recent_price(company)

            zuwachs[company] = prediction / current

            # sell if getting worse
            if anzahl > 0:
                if current > prediction:
                    result.sell(company, anzahl)

        bestCompany = None
        bestZuwachs = 1
        for company in CompanyEnum:
            if zuwachs[company] > bestZuwachs:
                bestZuwachs = zuwachs[company]
                bestCompany = company

        if bestCompany:
            current = stock_market_data.get_most_recent_price(company)
            count = math.floor(portfolio.cash / current)
            result.buy(bestCompany, count)



        # TODO: implement trading logic

        return result
    def doTrade(self, portfolio: Portfolio, current_portfolio_value: float,
                stock_market_data: StockMarketData) -> OrderList:
        """
        Generate action to be taken on the "stock market"
    
        Args:
          portfolio : current Portfolio of this trader
          current_portfolio_value : value of Portfolio at given Momemnt
          stock_market_data : StockMarketData for evaluation

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

        order_list = OrderList()

        pred_a_value = self.stock_a_predictor.doPredict(
            stock_market_data[CompanyEnum.COMPANY_A])
        pred_b_value = self.stock_b_predictor.doPredict(
            stock_market_data[CompanyEnum.COMPANY_B])

        stock_a = portfolio.get_amount(CompanyEnum.COMPANY_A)
        stock_a_value = stock_market_data.get_most_recent_price(
            CompanyEnum.COMPANY_A)
        stock_b = portfolio.get_amount(CompanyEnum.COMPANY_B)
        stock_b_value = stock_market_data.get_most_recent_price(
            CompanyEnum.COMPANY_B)

        increase_a = pred_a_value - stock_a_value
        increase_b = pred_b_value - stock_b_value

        new_cash = 0.0

        if stock_a > 0 and increase_a < 0.0:
            order_list.sell(CompanyEnum.COMPANY_A, stock_a)

        if stock_b > 0 and increase_b < 0.0:
            order_list.sell(CompanyEnum.COMPANY_B, stock_b)

        if increase_a > increase_b and increase_a > 0.0:
            count_a = portfolio.cash / stock_a_value
            if count_a > 0:
                order_list.buy(CompanyEnum.COMPANY_A, int(count_a))
        elif increase_b > increase_a and increase_b > 0.0:
            count_b = portfolio.cash / stock_b_value
            if count_b > 0:
                order_list.buy(CompanyEnum.COMPANY_B, int(count_b))

        # TODO: implement trading logic

        return order_list
    def test_update__action_order_does_not_matter(self):
        """
        Tests: Portfolio#update

        Flavour: It shouldn't matter which order the orders are in, the result should always look the same. In
         this case the portfolio's cash reserve is too low to execute a BUY action. However, it shouldn't matter if we
         execute a SELL action first, because the updated cash reserve after a SELL action shouldn't affect the
         available cash reserve for a subsequent BUY action

        Creates a portfolio, a stock market data object and a arbitrary `OrderList` and executes these orders on the
        portfolio. Checks if those are applied correctly
        """
        cash_reserve = 10.0

        data = StockData([(date(2017, 1, 1), 150.0)])
        stock_market_data = StockMarketData({CompanyEnum.COMPANY_A: data})

        # Create two equal designed portfolios
        portfolio1 = Portfolio(cash_reserve,
                               [SharesOfCompany(CompanyEnum.COMPANY_A, 200)])
        portfolio2 = Portfolio(cash_reserve,
                               [SharesOfCompany(CompanyEnum.COMPANY_A, 200)])

        assert portfolio1 == portfolio2

        # Create two order lists with the same entries, however in different order
        order_list_1 = OrderList()
        order_list_1.buy(CompanyEnum.COMPANY_A, 100)
        order_list_1.sell(CompanyEnum.COMPANY_A, 100)

        order_list_2 = OrderList()
        order_list_2.sell(CompanyEnum.COMPANY_A, 100)
        order_list_2.buy(CompanyEnum.COMPANY_A, 100)

        # Execute the trade action lists on the two portfolios
        updated_portfolio_order1 = portfolio1.update(stock_market_data,
                                                     order_list_1)
        updated_portfolio_order2 = portfolio2.update(stock_market_data,
                                                     order_list_2)

        # The portfolios should still be equal after applying the actions
        assert updated_portfolio_order1 == updated_portfolio_order2
Example #7
0
    def create_order_list(self, action_a: float, action_b: float,
                          portfolio: Portfolio, stock_market_data: StockMarketData) -> OrderList:
        """
        Take two floats between -1.0 and +1.0 (one for stock A and one for stock B) and convert them into corresponding
        orders.

        Args:
            action_a: float between -1.0 and 1.0, representing buy(positive) / sell(negative) for Company A
            action_b: float between -1.0 and 1.0, representing buy(positive) / sell(negative) for Company B
            portfolio: current portfolio of this trader
            stock_market_data: current stock market data

        Returns:
            List of corresponding orders
        """
        assert -1.0 <= action_a <= +1.0 and -1.0 <= action_b <= +1.0
        assert portfolio is not None and stock_market_data is not None
        order_list = OrderList()

        # Create orders for stock A
        owned_amount_a = portfolio.get_amount(CompanyEnum.COMPANY_A)
        if action_a > 0.0:
            current_price = stock_market_data.get_most_recent_price(CompanyEnum.COMPANY_A)
            amount_to_buy = int(action_a * (portfolio.cash // current_price))
            order_list.buy(CompanyEnum.COMPANY_A, amount_to_buy)
        if action_a < 0.0 and owned_amount_a > 0:
            amount_to_sell = int(abs(action_a) * owned_amount_a)
            order_list.sell(CompanyEnum.COMPANY_A, amount_to_sell)

        # Create orders for stock B
        owned_amount_b = portfolio.get_amount(CompanyEnum.COMPANY_B)
        if action_b > 0.0:
            current_price = stock_market_data.get_most_recent_price(CompanyEnum.COMPANY_B)
            amount_to_buy = int(action_b * (portfolio.cash // current_price))
            order_list.buy(CompanyEnum.COMPANY_B, amount_to_buy)
        if action_b < 0.0 and owned_amount_b > 0:
            amount_to_sell = int(abs(action_b) * owned_amount_b)
            order_list.sell(CompanyEnum.COMPANY_B, amount_to_sell)
        return order_list
    def doTrade(self, portfolio: Portfolio, current_portfolio_value: float,
                stock_market_data: StockMarketData) -> OrderList:
        """
        Generate action to be taken on the "stock market"
    
        Args:
          portfolio : current Portfolio of this trader
          current_portfolio_value : value of Portfolio at given moment
          stock_market_data : StockMarketData for evaluation

        Returns:
          A OrderList instance, may be empty never None
        """
        # TODO: Build and store current state object
        s_a_current = stock_market_data.get_most_recent_price(CompanyEnum.COMPANY_A)
        s_b_current = stock_market_data.get_most_recent_price(CompanyEnum.COMPANY_B)

        pct_a = round((s_a_current * portfolio.get_amount(CompanyEnum.COMPANY_A))/portfolio.total_value(stock_market_data.get_most_recent_trade_day(), stock_market_data), 2)
        pct_b = round((s_b_current * portfolio.get_amount(CompanyEnum.COMPANY_B))/portfolio.total_value(stock_market_data.get_most_recent_trade_day(), stock_market_data), 2)
        pct_cash = 1 - pct_a - pct_b;


        s_a_next = self.stock_a_predictor.doPredict(stock_market_data[CompanyEnum.COMPANY_A]);
        s_b_next = self.stock_b_predictor.doPredict(stock_market_data[CompanyEnum.COMPANY_B]);

        pct_a_diff = round((s_a_next - s_a_current) / s_a_current, 2);
        pct_b_diff = round((s_b_next - s_b_current) / s_b_current, 2);

        portfolio_value = portfolio.total_value(stock_market_data.get_most_recent_trade_day(), stock_market_data);
        portfolio_diff = round((self.portfolio_value_prev - portfolio_value) / self.portfolio_value_prev, 2);




        #r = -1;
        #if (portfolio_diff < 0):
        #    r = 1;
        #elif (portfolio_diff == 0):
        #    r = 0;

        if (portfolio_diff < 0):
            self.y_prev[0][self.idx_prev] = 1;
        elif (portfolio_diff >= 0):
            self.y_prev[0][self.idx_prev] = -1;




        # TODO: Store experience and train the neural network only if doTrade was called before at least once
        if (self.loop_value > 0):
            self.model.fit(np.array([[self.pct_a_prev, self.pct_b_prev, self.pct_cash_prev, self.diff_a_prev, self.diff_b_prev]]), self.y_prev, epochs=1, batch_size=1)

        # TODO: Create actions for current state and decrease epsilon for fewer random actions

        res = self.model.predict(np.array([[pct_a, pct_b, pct_cash, pct_a_diff, pct_b_diff]])) # [0, 0, 1, 0]
        idx = np.argmax(res);

        ret = OrderList()


        if (idx == 0):
            ret.buy(CompanyEnum.COMPANY_A, math.floor(portfolio.cash / stock_market_data.get_most_recent_price(CompanyEnum.COMPANY_A)))
        elif (idx == 1):
            ret.buy(CompanyEnum.COMPANY_B, math.floor(portfolio.cash / stock_market_data.get_most_recent_price(CompanyEnum.COMPANY_B)))
        elif (idx == 2):
            ret.sell(CompanyEnum.COMPANY_A, portfolio.get_amount(CompanyEnum.COMPANY_A))     
        else:
            ret.sell(CompanyEnum.COMPANY_B, portfolio.get_amount(CompanyEnum.COMPANY_B))



        # TODO: Save created state, actions and portfolio value for the next call of doTrade
        self.portfolio_value_prev = portfolio_value;
        self.pct_a_prev = pct_a;
        self.pct_b_prev = pct_b;
        self.pct_cash_prev = pct_cash;
        self.diff_a_prev = pct_a_diff;
        self.diff_b_prev = pct_a_diff;
        self.idx_prev = idx;
        self.y_prev = res;

        self.loop_value = self.loop_value + 1;

        return ret
    def doTrade(self, portfolio: Portfolio, current_portfolio_value: float,
                stock_market_data: StockMarketData) -> OrderList:
        """
        Generate action to be taken on the "stock market"
    
        Args:
          portfolio : current Portfolio of this trader
          current_portfolio_value : value of Portfolio at given moment
          stock_market_data : StockMarketData for evaluation

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

        # TODO: Store experience and train the neural network only if doTrade was called before at least once

        # TODO: Create actions for current state and decrease epsilon for fewer random actions

        # TODO: Save created state, actions and portfolio value for the next call of doTrade

        deltaA = self.stock_a_predictor.doPredict(
            stock_market_data[CompanyEnum.COMPANY_A]) / stock_market_data.get_most_recent_price(CompanyEnum.COMPANY_A)
        deltaB = self.stock_b_predictor.doPredict(
            stock_market_data[CompanyEnum.COMPANY_B]) / stock_market_data.get_most_recent_price(CompanyEnum.COMPANY_B)

        INPUT = numpy.asarray([[
            (deltaA - 1.0) / 0.04,
            (deltaB - 1.0) / 0.04,
        ]])
        qualities = self.model.predict(INPUT)[0]

        qmax = max(qualities[0], qualities[1], qualities[2])

        currentValue = portfolio.total_value(stock_market_data.get_most_recent_trade_day(), stock_market_data)

        if self.lastValue and self.train_while_trading:
            lastReward = min(1, max(-1, (currentValue / self.lastValue - 1) / 0.04))
            shouldBeQ = lastReward + GAMMA * qmax

            self.lastOutput[self.lastAmax] = shouldBeQ

            xtrain = [self.lastInput[0]]
            ytrain = [self.lastOutput]
            for m in self.memory:
                xtrain.append(m[0][0])
                qs = self.model.predict(m[0])[0]
                qs[m[1]] = m[2] + GAMMA * qs[m[1]]
                ytrain.append(qs)

            self.model.fit(numpy.asarray(xtrain), numpy.asarray(ytrain))

            self.memory.append([self.lastInput, self.lastAmax, lastReward])
            if len(self.memory) > MEMOMRY_SIZE:
                self.memory.pop(0)

        self.lastValue = currentValue
        self.lastInput = INPUT
        self.lastOutput = qualities

        result = OrderList()

        actions = ["BUY_A__SELL_B", "BUY_A", "BUY_B__SELL_A", "BUY_B", "SELL_ALL"]

        nextAction = None
        if random.random() < self.epsilon and self.train_while_trading:
            nextAction = actions[random.randint(0, self.action_size - 1)]
        else:
            i = 0 if qualities[0] > qualities[1] else 1
            i = 2 if qualities[2] > qualities[i] else i
            i = 3 if qualities[3] > qualities[i] else i
            i = 4 if qualities[4] > qualities[i] else i
            nextAction = actions[i]

        self.epsilon = max(self.epsilon_decay * self.epsilon, self.epsilon_min)

        if nextAction == "BUY_A__SELL_B":
            result.sell(CompanyEnum.COMPANY_B, portfolio.get_amount(CompanyEnum.COMPANY_B))
            count = math.floor(portfolio.cash / stock_market_data.get_most_recent_price(CompanyEnum.COMPANY_A))
            result.buy(CompanyEnum.COMPANY_A, count)
            self.lastAmax = 0
        elif nextAction == "BUY_A":
            count = math.floor(portfolio.cash / stock_market_data.get_most_recent_price(CompanyEnum.COMPANY_A))
            result.buy(CompanyEnum.COMPANY_A, count)
            self.lastAmax = 1
        elif nextAction == "BUY_B__SELL_A":
            result.sell(CompanyEnum.COMPANY_A, portfolio.get_amount(CompanyEnum.COMPANY_A))
            count = math.floor(portfolio.cash / stock_market_data.get_most_recent_price(CompanyEnum.COMPANY_B))
            result.buy(CompanyEnum.COMPANY_B, count)
            self.lastAmax = 2
        elif nextAction == "BUY_B":
            count = math.floor(portfolio.cash / stock_market_data.get_most_recent_price(CompanyEnum.COMPANY_B))
            result.buy(CompanyEnum.COMPANY_B, count)
            self.lastAmax = 3
        elif nextAction == "SELL_ALL":
            result.sell(CompanyEnum.COMPANY_A, portfolio.get_amount(CompanyEnum.COMPANY_A))
            result.sell(CompanyEnum.COMPANY_B, portfolio.get_amount(CompanyEnum.COMPANY_B))
            self.lastAmax = 4

        return result
Example #10
0
    def doTrade(self, portfolio: Portfolio, current_portfolio_value: float,
                stock_market_data: StockMarketData) -> OrderList:
        """
        Generate action to be taken on the "stock market"
    
        Args:
          portfolio : current Portfolio of this trader
          current_portfolio_value : value of Portfolio at given moment
          stock_market_data : StockMarketData for evaluation

        Returns:
          A OrderList instance, may be empty never None
        """
        # TODO: Build and store current state object

        ## cash %, portfolio a value %, portfolio b %, pred a, pred b

        account_value = portfolio.cash + current_portfolio_value
        a_value = portfolio.get_amount(CompanyEnum.COMPANY_A) * stock_market_data.get_most_recent_price(CompanyEnum.COMPANY_A)
        b_value = portfolio.get_amount(CompanyEnum.COMPANY_B) * stock_market_data.get_most_recent_price(CompanyEnum.COMPANY_B)

        a_value_percent = a_value / account_value
        b_value_percent = b_value / account_value
        cash_percent = portfolio.cash / account_value

        pred_a_value = self.stock_a_predictor.doPredict(stock_market_data[CompanyEnum.COMPANY_A])
        pred_b_value = self.stock_b_predictor.doPredict(stock_market_data[CompanyEnum.COMPANY_B])

        stock_a_value = stock_market_data.get_most_recent_price(CompanyEnum.COMPANY_A)
        stock_b_value = stock_market_data.get_most_recent_price(CompanyEnum.COMPANY_B)

        increase_a = (pred_a_value - stock_a_value) / stock_a_value
        increase_b = (pred_b_value - stock_b_value) / stock_b_value

        current_status = [[cash_percent, a_value_percent, b_value_percent, increase_a, increase_b]]

        np_current_status = np.array(current_status)

        # TODO: Store experience and train the neural network only if doTrade was called before at least once

        ## calc rewards = was cash + portfolio - (old cash + old portfolio), map auf 1 0 -1, now simple:
        if self.stored_action >= 0:

            if current_portfolio_value > self.stored_portfolio_value:
                reward = 1.0
            elif current_portfolio_value < self.stored_portfolio_value:
                reward = -1.0
            else:
                reward = 0

            reward_array = [0, 0, 0]

            reward_array[self.stored_action] = reward

            np_reward_array = np.array([reward_array])

            ## train again

            # print(np_reward_array)


            if self.train_while_trading:
                self.model.fit(self.np_previous_status, np_reward_array, epochs=1, batch_size=1, verbose=0)

        # TODO: Create actions for current state and decrease epsilon for fewer random actions

        action = -1

        random_value = uniform(0.0, 1.0)
        if random_value > self.epsilon:
            action = randint(0, 2)
        else:
            pred = self.model.predict(np_current_status)
            prediction = pred[0]

            if len(prediction) != 3:
                print("komische prediction")

            action = 2
            max = prediction[action]

            for i in range(3):
                if prediction[i] > max:
                    action = i


        self.count[action] = self.count[action] + 1
        # print("actions")
        # print(self.count)

        self.epsilon = self.epsilon * self.epsilon_decay
        if self.epsilon < self.epsilon_min:
            self.epsilon = self.epsilon_min

        order_list = OrderList()

        if action < 0 or action > 2:
            print("komische action")
            print(action)
        else:

            stock_a = portfolio.get_amount(CompanyEnum.COMPANY_A)
            stock_b = portfolio.get_amount(CompanyEnum.COMPANY_B)

            if action == 0:
                # sell a
                if stock_a > 0:
                    order_list.sell(CompanyEnum.COMPANY_A, stock_a)
                # buy b
                count_b = portfolio.cash / stock_b_value
                if count_b > 0:
                    order_list.buy(CompanyEnum.COMPANY_B, int(count_b))
            if action == 1:
                # sell b
                if stock_b > 0:
                    order_list.sell(CompanyEnum.COMPANY_B, stock_b)
                # boy a
                count_a = portfolio.cash / stock_a_value
                if count_a > 0:
                    order_list.buy(CompanyEnum.COMPANY_A, int(count_a))

        # TODO: Save created state, actions and portfolio value for the next call of

        self.stored_action = action
        self.stored_portfolio_value = current_portfolio_value
        self.np_previous_status = np_current_status

        ## save current state as laststate, current portfolio and cash

        return order_list