def __init__(self, companies: List[Company] = None, periods: List[Period] = None):
        """
        TODO refactor comment
        Reads the "cross product" from `stocks` and `periods` from CSV files and creates a `StockMarketData` object from
        this. For each defined stock in `stocks` the corresponding value from `Company` is used as logical name. If
        there are `periods` provided those are each read.

        Args:
            stocks: The company names for which to read the stock data. *Important:* These values need to be stated in `CompanyEnum`
            periods: The periods to read. If not empty each period is appended to the filename like this: `[stock_name]_[period].csv`

        Returns:
            The created `StockMarketData` object

        Examples:
            * Preface: Provided stock names are supposed to be part to `CompanyEnum`. They are stated plaintext-ish here to show the point:
            * `(['stock_a', 'stock_b'], ['1962-2011', '2012-2017'])` reads:
                * 'stock_a_1962-2011.csv'
                * 'stock_a_2012-2015.csv'
                * 'stock_b_1962-2011.csv'
                * 'stock_b_2012-2015.csv'
              into a dict with keys `CompanyEnum.COMPANY_A` and `CompanyEnum.COMPANY_B` respectively
            * `(['stock_a'], ['1962-2011', '2012-2017'])` reads:
                * 'stock_a_1962-2011.csv'
                * 'stock_a_2012-2015.csv'
              into a dict with a key `CompanyEnum.COMPANY_A`
            * `(['stock_a', 'stock_b'], ['1962-2011'])` reads:
                * 'stock_a_1962-2011.csv'
                * 'stock_b_1962-2011.csv'
              into a dict with keys `CompanyEnum.COMPANY_A` and `CompanyEnum.COMPANY_B` respectively
            * `(['stock_a', 'stock_b'], [])` reads:
                * 'stock_a.csv'
                * 'stock_b.csv'
              into a dict with keys `CompanyEnum.COMPANY_A` and `CompanyEnum.COMPANY_B` respectively
        """
        data = dict()
        if companies is not None and periods is not None:
            # Read *all* available data
            for company in companies:
                filename = company.value
                if len(periods) is 0:
                    data[company] = StockData(self.__read_stock_market_data([[company, filename]])[company])
                else:
                    period_data = list()
                    for period in periods:
                        period_data.append(self.__read_stock_market_data([[company, ('%s_%s' % (filename, period.value))]]))

                    data[company] = StockData(
                        [item for period_dict in period_data if period_dict is not None for item in period_dict[company]])

        self.__market_data = data
Example #2
0
    def __follow_expert_vote(self, company: Company, stock_data: StockData,
                             vote: Vote, buy_weight: float,
                             portfolio: Portfolio, order_list: List[Order]):
        assert company is not None
        assert stock_data is not None
        assert vote is not None
        assert portfolio is not None
        assert order_list is not None

        if vote is Vote.BUY or vote is Vote.HOLD:
            assert buy_weight is not None and 0 < buy_weight <= 1.0
            stock_price = stock_data.get_last()[-1]
            amount_to_buy = int(buy_weight * portfolio.cash // stock_price)
            logger.debug(
                f"{self.get_name()}: Got vote to buy {company}: {amount_to_buy} shares a {stock_price}"
            )
            if amount_to_buy > 0:
                order_list.append(Order(OrderType.BUY, company, amount_to_buy))
        elif vote == Vote.SELL:
            # sell as many stocks as possible
            amount_to_sell = portfolio.get_stock(company)
            logger.debug(
                f"{self.get_name()}: Got vote to sell {company}: {amount_to_sell} shares available"
            )
            if amount_to_sell > 0:
                order_list.append(
                    Order(OrderType.SELL, company, amount_to_sell))
        else:
            # do nothing
            assert vote == Vote.HOLD
            logger.debug(f"{self.get_name()}: Got vote to hold {company}")
Example #3
0
    def vote(self, stock_data: StockData) -> Vote:
        """
        Vote based on the stock's historic prices.
        :param stock_data: StockData object capturing the past stock prices
        :return:
        """
        assert stock_data is not None

        try:
            (current_date, _) = stock_data.get_last()
            return self.__answers[self.__company][current_date]
        except (ValueError, IndexError):
            assert False
Example #4
0
    def __follow_action(self, company: Company, stock_data: StockData,
                        vote: Vote, portfolio: Portfolio,
                        order_list: List[Order]):
        """
        Protected helper method to calculate amount of stocks to be bought and sold.

        :param company: Company
        :param stock_data: StockData
        :param vote: Vote
        :param portfolio: Portfolio
        :param order_list: List[Order]
        :return: None (writes result to order_list)
        """

        assert company is not None
        assert stock_data is not None
        assert vote is not None
        assert portfolio is not None
        assert order_list is not None

        if vote == Vote.BUY:
            # buy as many stocks as possible
            stock_price = stock_data.get_last()[-1]
            amount_to_buy = int(portfolio.cash // stock_price)
            logger.debug(
                f"{self.get_name()}: Got vote to buy {company}: {amount_to_buy} shares a {stock_price}"
            )
            if amount_to_buy > 0:
                order_list.append(Order(OrderType.BUY, company, amount_to_buy))
        elif vote == Vote.SELL:
            # sell as many stocks as possible
            amount_to_sell = portfolio.get_stock(company)
            logger.debug(
                f"{self.get_name()}: Got vote to sell {company}: {amount_to_sell} shares available"
            )
            if amount_to_sell > 0:
                order_list.append(
                    Order(OrderType.SELL, company, amount_to_sell))
        else:
            # do nothing
            assert vote == Vote.HOLD
            logger.debug(f"{self.get_name()}: Got vote to hold {company}")
def get_test_data():
    return StockData([(Date(2017, 1, 1), 150.0), (Date(2017, 1, 2), 200.0)])
Example #6
0
    def choose_actions(self,
                       stock_data_a: StockData,
                       stock_data_b: StockData,
                       portfolio: Portfolio,
                       order_list: List[Order],
                       epsilon=None,
                       model_choice=None):
        assert epsilon is not None
        assert model_choice is not None

        action_a = None
        action_b = None

        if random.random() < self.epsilon:
            action_comb = random.randrange(10)
        else:
            action_comb = model_choice

        potential_buy_a = int(portfolio.cash // stock_data_a.get_last()[-1])
        potential_buy_b = int(portfolio.cash // stock_data_b.get_last()[-1])

        potential_sell_a = portfolio.get_stock(Company.A)
        potential_sell_b = portfolio.get_stock(Company.B)
        """10 action combinations:
        - buy  100% A, buy    0% B  # buy only A completely
        - buy  100% A, sell 100% B  # sell all B, buy all A
        - buy   50% A, buy   50% B  # buy both
        - buy    0% A, buy  100% B  # buy only B completely
        - sell 100% A, sell   0% B  # sell only A completely
        - sell 100% A, sell 100% B  # sell both completely
        - sell 100% A, buy  100% B  # sell all A, buy all B
        - sell  50% A, sell  50% B  # sell both half
        - sell   0% A, sell 100% B  # sell only B completely
        - hold                      # do nothing
        """
        logger.debug(f"{self.get_name()}: chooses action comb {action_comb}")
        if action_comb == 0:
            # buy  100% A, buy    0% B  # buy only A completely
            action_a = OrderType.BUY.value
            action_b = 0
            order_list.append(Order(OrderType.BUY, Company.A, potential_buy_a))
        elif action_comb == 1:
            # buy  100% A, sell 100% B  # sell all B, buy all A
            action_a = OrderType.BUY.value
            action_b = OrderType.SELL.value
            order_list.append(Order(OrderType.BUY, Company.A, potential_buy_a))
            order_list.append(
                Order(OrderType.SELL, Company.B, potential_sell_b))
        elif action_comb == 2:
            # buy   50% A, buy   50% B  # buy both
            action_a = OrderType.BUY.value
            action_b = OrderType.SELL.value
            order_list.append(
                Order(OrderType.BUY, Company.A, potential_buy_a // 2))
            remaining_cash = portfolio.cash - (potential_buy_a //
                                               2) * stock_data_a.get_last()[-1]
            potential_buy_b = int(remaining_cash //
                                  stock_data_b.get_last()[-1])
            order_list.append(Order(OrderType.SELL, Company.B,
                                    potential_buy_b))
        elif action_comb == 3:
            # buy    0% A, buy  100% B  # buy only B completely
            action_a = 0
            action_b = OrderType.BUY.value
            order_list.append(Order(OrderType.BUY, Company.B, potential_buy_b))
        elif action_comb == 4:
            # sell 100% A, sell   0% B  # sell only A completely
            action_a = OrderType.SELL.value
            action_b = 0
            order_list.append(
                Order(OrderType.SELL, Company.A, potential_sell_a))
        elif action_comb == 5:
            # sell 100% A, sell 100% B  # sell both completely
            action_a = OrderType.SELL.value
            action_b = OrderType.SELL.value
            order_list.append(
                Order(OrderType.SELL, Company.A, potential_sell_a))
            order_list.append(
                Order(OrderType.SELL, Company.B, potential_sell_b))
        elif action_comb == 6:
            # sell 100% A, buy  100% B  # sell all A, buy all B
            action_a = OrderType.SELL.value
            action_b = OrderType.BUY.value
            order_list.append(
                Order(OrderType.SELL, Company.A, potential_sell_a))
            order_list.append(Order(OrderType.BUY, Company.B, potential_buy_b))
        elif action_comb == 7:
            # sell  50% A, sell  50% B  # sell both half
            action_a = OrderType.SELL.value
            action_b = OrderType.SELL.value
            order_list.append(
                Order(OrderType.SELL, Company.A, potential_sell_a // 2))
            order_list.append(
                Order(OrderType.SELL, Company.B, potential_sell_b // 2))
        elif action_comb == 8:
            # sell   0% A, sell 100% B  # sell only B completely
            action_a = 0
            action_b = OrderType.SELL.value
            order_list.append(
                Order(OrderType.SELL, Company.B, potential_sell_b))
        elif action_comb == 9:
            # hold                      # do nothing
            action_a = 0
            action_b = 0
        return action_a, action_b, order_list