gerrymanoim / exchange_calendars

Calendars for various securities exchanges.
Apache License 2.0
422 stars 132 forks source link

tests fail on 32-bit architecture: Cannot cast array data from dtype('int64') to dtype('int32') #410

Open EdwardBetts opened 1 month ago

EdwardBetts commented 1 month ago

When running the tests on a 32-bit architecture I get this error:

TypeError: Cannot cast array data from dtype('int64') to dtype('int32') according to the rule 'safe'

Here's the full output

============================= test session starts ==============================
platform linux -- Python 3.12.4, pytest-8.2.2, pluggy-1.5.0 -- /usr/bin/python3.12
cachedir: .pytest_cache
hypothesis profile 'default' -> database=DirectoryBasedExampleDatabase(PosixPath('/tmp/autopkgtest-lxc.cjwmuxri/downtmp/autopkgtest_tmp/.hypothesis/examples'))
rootdir: /tmp/autopkgtest-lxc.cjwmuxri/downtmp/autopkgtest_tmp
plugins: hypothesis-6.105.1
collecting ... collected 8189 items

tests/test_aixk_calendar.py::TestAIXKCalendar::test_testbase_integrity PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_base_integrity PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_calculated_against_csv PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_start_end PASSED     [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_invalid_input PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_bound_min PASSED     [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_bound_max PASSED     [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_sanity_check_session_lengths PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_adhoc_holidays_specification PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_daylight_savings PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_sessions PASSED      [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_opens_closes_break_starts_ends PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minutes_properties[both] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minutes[both] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_calendar_bounds_properties[both] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_session_minute_methods[both] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_session_minutes[both] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_is_trading_minute[both] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_is_break_minute[both] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_is_open_on_minute[both] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_is_open_at_time[both] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_prev_next_minute[both] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_session[both-next] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_trading_minute[both-next] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_session[left-next] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_trading_minute[left-next] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minutes_properties[left] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minutes[left] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_calendar_bounds_properties[left] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_session_minute_methods[left] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_session_minutes[left] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_is_trading_minute[left] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_is_break_minute[left] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_is_open_on_minute[left] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_is_open_at_time[left] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_prev_next_minute[left] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_session[left-previous] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_trading_minute[left-previous] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_session[both-previous] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_trading_minute[both-previous] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_session[right-previous] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_trading_minute[right-previous] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_session[right-next] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_trading_minute[right-next] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minutes_properties[right] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minutes[right] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_calendar_bounds_properties[right] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_session_minute_methods[right] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_session_minutes[right] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_is_trading_minute[right] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_is_break_minute[right] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_is_open_on_minute[right] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_is_open_at_time[right] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_prev_next_minute[right] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_session[right-none] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_trading_minute[right-none] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_session[left-none] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_trading_minute[left-none] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_session[both-none] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_trading_minute[both-none] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_session[neither-none] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_trading_minute[neither-none] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_session[neither-previous] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_trading_minute[neither-previous] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_session[neither-next] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_trading_minute[neither-next] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minutes_properties[neither] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minutes[neither] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_calendar_bounds_properties[neither] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_session_minute_methods[neither] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_session_minutes[neither] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_is_trading_minute[neither] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_is_break_minute[neither] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_is_open_on_minute[neither] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_is_open_at_time[neither] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_prev_next_minute[neither] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_past_session[neither] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_future_session[neither] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_offset[neither] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_offset_by_sessions[neither] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minutes_in_range[neither] PASSED [  0%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minutes_window[neither] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minutes_distance[neither] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minutes_to_sessions[neither] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_sessions_minutes[neither] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_sessions_minutes_count[neither] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_past_session[right] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_future_session[right] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_offset[right] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_offset_by_sessions[right] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minutes_in_range[right] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minutes_window[right] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minutes_distance[right] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minutes_to_sessions[right] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_sessions_minutes[right] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_sessions_minutes_count[right] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_past_session[left] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_future_session[left] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_offset[left] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_offset_by_sessions[left] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minutes_in_range[left] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minutes_window[left] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minutes_distance[left] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minutes_to_sessions[left] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_sessions_minutes[left] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_sessions_minutes_count[left] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_past_session[both] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_to_future_session[both] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_offset[both] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minute_offset_by_sessions[both] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minutes_in_range[both] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minutes_window[both] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minutes_distance[both] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_minutes_to_sessions[both] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_sessions_minutes[both] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_sessions_minutes_count[both] PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_has_break PASSED     [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_regular_holidays_sample PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_adhoc_holidays_sample PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_non_holidays_sample PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_late_opens_sample PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_early_closes_sample PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_early_closes_sample_time PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_early_closes_weekdays PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_early_closes_weekdays_time PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_non_early_closes_sample PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_non_early_closes_sample_time PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_late_opens PASSED    [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_early_closes PASSED  [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_session_open_close_break_start_end PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_session_has_break PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_next_prev_session PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_session_offset PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_is_session PASSED    [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_date_to_session PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_prev_next_open_close PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_sessions_in_range PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_sessions_has_break PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_sessions_window PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_sessions_distance PASSED [  1%]
tests/test_aixk_calendar.py::TestAIXKCalendar::test_trading_index FAILED [  1%]

=================================== FAILURES ===================================
_____________________ TestAIXKCalendar.test_trading_index ______________________

self = <tests.test_aixk_calendar.TestAIXKCalendar object at 0xf252f468>
calendars = {'both': <exchange_calendars.exchange_calendar_aixk.AIXKExchangeCalendar object at 0xf2686900>, 'left': <exchange_cale... object at 0xf1c92fa8>, 'right': <exchange_calendars.exchange_calendar_aixk.AIXKExchangeCalendar object at 0xf25fba98>}
answers = {'both': <Answers: calendar AIXK, side both>, 'left': <Answers: calendar AIXK, side left>, 'neither': <Answers: calendar AIXK, side neither>, 'right': <Answers: calendar AIXK, side right>}

    def test_trading_index(self, calendars, answers):
        """Test trading index with options as default values.

        Tests multitude of concrete cases covering product of all
        session blocks and various periods.

        Assumes default value (False) for each of `force_close`,
        `force_break_close` and `curtail_overlaps`. See test class
        `test_calendar_helpers.TestTradingIndex` for more comprehensive
        testing (including fuzz tests and parsing tests).
        """
        cal, ans = calendars["left"], answers["left"]

        def unite(dtis: list[pd.DatetimeIndex]) -> pd.DatetimeIndex:
            return dtis[0].append(dtis[1:])  # append to not sort or remove duplicates

        for _, sessions in ans.session_block_generator():
            for mins in [5, 17, 60, 123, 333, 1033]:
                period = pd.Timedelta(mins, "min")
                dtis = []
                for session in sessions:
                    indexes = ans.get_session_minutes(session)
                    for i, index in enumerate(indexes):
                        # Create closed 'both' trading index for each session/subsession
                        if i == 0 and len(indexes) == 2:
                            ends = ans.break_starts
                        else:
                            ends = ans.closes
                        # index for a 'left' calendar, add end so evaluated as if 'both'
                        index = index.append(pd.DatetimeIndex([ends[session]], tz=UTC))

                        index = index[::mins]  # only want every period
                        if not index[-1] == ends[session]:
                            # if period doesn't coincide with end, add right side of
                            # last interval which lies beyond end.
                            last_indice = index[-1] + period
                            index = index.append(
                                pd.DatetimeIndex([last_indice], tz=UTC)
                            )
                        dtis.append(index)

                both_index = unite(dtis)
                left_index = unite([dti[:-1] for dti in dtis])
                right_index = unite([dti[1:] for dti in dtis])
                neither_index = unite([dti[1:-1] for dti in dtis])

                overlaps = (right_index[:-1] > left_index[1:]).any()
                if overlaps:
                    both_overlaps = overlaps
                else:
                    both_overlaps = False
                    for dti, next_dti in zip(dtis, dtis[1:]):
                        if dti[-1] == next_dti[0]:
                            both_overlaps = True
                            break

                def get_index(closed: str, intervals: bool):
                    start, end = sessions[0], sessions[-1]
                    return cal.trading_index(
                        start, end, period, intervals, closed, parse=False
                    )

                def tst_indices_index(
                    expected: pd.DatetimeIndex, closed: str, overlaps: bool
                ):
                    if not overlaps:
                        rtrn = get_index(closed, False)
                        pd.testing.assert_index_equal(expected, rtrn)
                    else:
                        with pytest.raises(errors.IndicesOverlapError):
                            get_index(closed, False)

>               tst_indices_index(both_index, "both", both_overlaps)

tests/test_exchange_calendar.py:3906: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
tests/test_exchange_calendar.py:3900: in tst_indices_index
    rtrn = get_index(closed, False)
tests/test_exchange_calendar.py:3892: in get_index
    return cal.trading_index(
/usr/lib/python3/dist-packages/exchange_calendars/exchange_calendar.py:2708: in trading_index
    return _trading_index.trading_index()
/usr/lib/python3/dist-packages/exchange_calendars/calendar_helpers.py:677: in trading_index
    index = self._trading_index()
/usr/lib/python3/dist-packages/exchange_calendars/calendar_helpers.py:651: in _trading_index
    index = self._create_index_for_sessions(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <exchange_calendars.calendar_helpers._TradingIndex object at 0xf1da8168>
start_nanos = array([1556168400000000000, 1556254800000000000, 1556514000000000000],
      dtype=int64)
end_nanos = array([1556190000000000000, 1556276400000000000, 1556535600000000000],
      dtype=int64)
force_close = False

    def _create_index_for_sessions(
        self,
        start_nanos: np.ndarray,
        end_nanos: np.ndarray,
        force_close: bool,
    ) -> np.ndarray:
        """Create nano array of indices for sessions of given bounds."""
        if start_nanos.size == 0:
            return start_nanos

        # evaluate number of indices for each session
        num_intervals = (end_nanos - start_nanos) / self.interval_nanos
        num_indices = np.ceil(num_intervals).astype("int64")

        if force_close:
            if self.closed_right:
                on_freq = (num_intervals == num_indices).all()
                if not on_freq:
                    num_indices -= 1  # add the close later
            else:
                on_freq = True

        if self.closed == "both":
            num_indices += 1
        elif self.closed == "neither":
            num_indices -= 1

        # by session, evaluate a range of int such that indices of a session
        # could be evaluted from [ session_open + (freq * i) for i in range ]
        start = 0 if self.closed_left else 1
        func = np.vectorize(lambda stop: np.arange(start, stop), otypes=[np.ndarray])
        stop = num_indices if self.closed_left else num_indices + 1
        ranges = np.concatenate(func(stop), axis=0, dtype=np.int64)

        # evaluate index as nano array
>       base = start_nanos.repeat(num_indices)
E       TypeError: Cannot cast array data from dtype('int64') to dtype('int32') according to the rule 'safe'

/usr/lib/python3/dist-packages/exchange_calendars/calendar_helpers.py:602: TypeError
=========================== short test summary info ============================
FAILED tests/test_aixk_calendar.py::TestAIXKCalendar::test_trading_index - Ty...
!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!!
======================== 1 failed, 140 passed in 13.32s ========================

See:

gerrymanoim commented 3 weeks ago

Thanks for the report!

Let me see if there's an easy way we can be compatible with 32-bit and what our CI options are.