def run(self):
     ticker_min_order_dates = self.order_logic.get_all_order_tickers_min_date(
     )
     for ticker_date in ticker_min_order_dates:
         self.process_ticker_order_date(ticker_date)
     min_date = min(t.date for t in ticker_min_order_dates)
     for ticker in constants.BENCHMARK_TICKERS:
         self.process_ticker_order_date(TickerDate(ticker, min_date))
    def test_run(self):
        batch = AlphavantagePriceHistoryFetcher()
        ticker_date = TickerDate('AAPL', datetime.date(2017, 6, 19))

        with mock.patch.object(
            batch.order_logic,
            'get_all_order_tickers_min_date',
            return_value=[ticker_date]
        ), mock.patch.object(
            batch,
            'process_ticker_order_date'
        ) as patch_process:

            batch.run()
            benchmark_ticker_dates = [TickerDate(t, ticker_date.date) for t in constants.BENCHMARK_TICKERS]
            assert patch_process.call_args_list == [mock.call(ticker_date)] + \
                [mock.call(td) for td in benchmark_ticker_dates]
 def get_ticker_price_history_map(self, tickers, dates):
     ticker_dates = [
         TickerDate(x[0], x[1]) for x in itertools.product(tickers, dates)
     ]
     prices = self.get_ticker_dates_prices(ticker_dates)
     price_info = defaultdict(dict)
     for price in prices:
         price_info[price.ticker][price.date] = price.price
     return price_info
 def process_ticker_order_date(self, ticker_date):
     self.log.info("Processing ticker %s" % ticker_date.ticker)
     fetch_date = self.get_fetch_date(ticker_date)
     if self.should_fetch_data_for_date(fetch_date):
         self.log.info("Fetch history for ticker %s to %s" %
                       (ticker_date.ticker, fetch_date.isoformat()))
         history = self.fetch_ticker_history(
             TickerDate(ticker_date.ticker, fetch_date))
         self.price_logic.add_prices(history)
    def test_fetch_ticker_history(self):
        batch = AlphavantagePriceHistoryFetcher()
        ticker_date = TickerDate('YELP', datetime.date(2017, 6, 12))
        ticker_date_price = TickerDatePrice('YELP', datetime.date(2017, 6, 12), 31.2)
        with mock.patch(
            'batch.advantagealpha_price_history_fetcher.time'
        ), mock.patch(
            'batch.advantagealpha_price_history_fetcher.requests'
        ) as mock_requests, mock.patch.object(
            batch,
            '_parse_historical',
            return_value=[ticker_date_price]
        ) as mock_parse:
                mock_requests.get = mock.Mock()
                data = batch.fetch_ticker_history(ticker_date)

                assert mock_requests.get.called
                assert mock_parse.called
                assert data == [ticker_date_price]
    def test_process_ticker_order_date(self):
        batch = AlphavantagePriceHistoryFetcher()
        ticker_date = TickerDate('AAPL', datetime.date(2017, 6, 19))
        mock_history = mock.Mock()
        with mock.patch.object(
            batch,
            'get_fetch_date',
            return_value=ticker_date.date
        ), mock.patch.object(
            batch,
            'should_fetch_data_for_date',
            return_value=True
        ), mock.patch.object(
            batch,
            'fetch_ticker_history',
            return_value=mock_history
        ), mock.patch.object(
            batch.price_logic,
            'add_prices'
        ) as mock_price_logic:

            batch.process_ticker_order_date(ticker_date)
            assert mock_price_logic.call_args_list == [mock.call(mock_history)]
    def test_get_all_order_tickers_min_date(self):
        logic = OrderHistoryLogic()
        user_id_1 = 1
        user_id_2 = 2
        order1 = Order(
            user_id=user_id_1,
            order_type=order_history.BUY_ORDER_TYPE,
            date=datetime.date(2015, 8, 9),
            ticker='AAPL',
            num_shares=20,
            price=150.001,
        )
        order2 = Order(
            user_id=user_id_2,
            order_type=order_history.BUY_ORDER_TYPE,
            date=datetime.date(2017, 1, 1),
            ticker='AAPL',
            num_shares=20,
            price=152.333,
        )
        logic.add_orders([order1, order2])

        ticker_dates = logic.get_all_order_tickers_min_date()
        assert ticker_dates == [TickerDate(order1.ticker, order1.date)]
class TestAlphavantagePriceHistoryFetcher(object):

    def test_parse_historical_data(self):
        batch = AlphavantagePriceHistoryFetcher()
        content = '{ "Meta Data": {  "2. Symbol": "MOMO"},"Time Series (Daily)": {' + \
            '"2017-12-20": { "4. close": "1.0" }, ' + \
            '"2017-12-19": { "4. close": "2.0" }}}'
        content = content.encode()
        price_history = batch._parse_historical(content)
        assert price_history == [
            TickerDatePrice(ticker='MOMO', date=datetime.date(2017, 12, 19), price=2.0),
            TickerDatePrice(ticker='MOMO', date=datetime.date(2017, 12, 20), price=1.0),
        ]

    @pytest.mark.parametrize(
        'fetch_date,now,should_fetch', [
            # Have data for Thursday but not Friday and it's Sunday
            (datetime.date(2017, 6, 16), datetime.datetime(2017, 6, 18), True),
            # Have data for Friday and it's Sunday
            (datetime.date(2017, 6, 17), datetime.datetime(2017, 6, 18), False),
            # Have data for Friday and it's Monday before close
            (datetime.date(2017, 6, 17), datetime.datetime(2017, 6, 19, 15, tzinfo=pytz.timezone('US/Eastern')), False),
            # Have data for Friday and it's Monday after close
            (datetime.date(2017, 6, 17), datetime.datetime(2017, 6, 19, 17, tzinfo=pytz.timezone('US/Eastern')), True),
            # Have data for day before and it's before close
            (datetime.date(2017, 6, 13), datetime.datetime(2017, 6, 13, 15, tzinfo=pytz.timezone('US/Eastern')), False),
            # Have data for day before and it's after close
            (datetime.date(2017, 6, 13), datetime.datetime(2017, 6, 13, 17, tzinfo=pytz.timezone('US/Eastern')), True),

        ]
    )
    def test_should_fetch_data_for_date(self, fetch_date, now, should_fetch):
        batch = AlphavantagePriceHistoryFetcher()
        with mock.patch(
            'batch.advantagealpha_price_history_fetcher.datetime.datetime'
        ) as mock_datetime:
            mock_datetime.now.return_value = now
            assert batch.should_fetch_data_for_date(fetch_date) is should_fetch

    def test_fetch_ticker_history(self):
        batch = AlphavantagePriceHistoryFetcher()
        ticker_date = TickerDate('YELP', datetime.date(2017, 6, 12))
        ticker_date_price = TickerDatePrice('YELP', datetime.date(2017, 6, 12), 31.2)
        with mock.patch(
            'batch.advantagealpha_price_history_fetcher.time'
        ), mock.patch(
            'batch.advantagealpha_price_history_fetcher.requests'
        ) as mock_requests, mock.patch.object(
            batch,
            '_parse_historical',
            return_value=[ticker_date_price]
        ) as mock_parse:
                mock_requests.get = mock.Mock()
                data = batch.fetch_ticker_history(ticker_date)

                assert mock_requests.get.called
                assert mock_parse.called
                assert data == [ticker_date_price]

    @pytest.mark.parametrize(
        'ticker_date,min_date_history_exists,max_history_date,result', [
            (
                TickerDate('AAPL', datetime.date(2017, 6, 16)),
                False,
                None,
                datetime.date(2017, 6, 16)
            ),
            (
                TickerDate('AAPL', datetime.date(2017, 6, 16)),
                True,
                datetime.date(2017, 6, 26),
                datetime.date(2017, 6, 27)
            ),
        ]
    )
    def test_get_fetch_date(self, ticker_date, min_date_history_exists, max_history_date, result):
        batch = AlphavantagePriceHistoryFetcher()
        with mock.patch.object(
            batch.price_logic,
            'does_ticker_date_history_exists',
            return_value=min_date_history_exists
        ), mock.patch.object(
            batch.price_logic,
            'get_max_date_history_for_ticker',
            return_value=max_history_date
        ):
            assert batch.get_fetch_date(ticker_date) == result

    def test_run(self):
        batch = AlphavantagePriceHistoryFetcher()
        ticker_date = TickerDate('AAPL', datetime.date(2017, 6, 19))

        with mock.patch.object(
            batch.order_logic,
            'get_all_order_tickers_min_date',
            return_value=[ticker_date]
        ), mock.patch.object(
            batch,
            'process_ticker_order_date'
        ) as patch_process:

            batch.run()
            benchmark_ticker_dates = [TickerDate(t, ticker_date.date) for t in constants.BENCHMARK_TICKERS]
            assert patch_process.call_args_list == [mock.call(ticker_date)] + \
                [mock.call(td) for td in benchmark_ticker_dates]

    def test_process_ticker_order_date(self):
        batch = AlphavantagePriceHistoryFetcher()
        ticker_date = TickerDate('AAPL', datetime.date(2017, 6, 19))
        mock_history = mock.Mock()
        with mock.patch.object(
            batch,
            'get_fetch_date',
            return_value=ticker_date.date
        ), mock.patch.object(
            batch,
            'should_fetch_data_for_date',
            return_value=True
        ), mock.patch.object(
            batch,
            'fetch_ticker_history',
            return_value=mock_history
        ), mock.patch.object(
            batch.price_logic,
            'add_prices'
        ) as mock_price_logic:

            batch.process_ticker_order_date(ticker_date)
            assert mock_price_logic.call_args_list == [mock.call(mock_history)]