from datetime import datetime import numpy as np import pandas as pd import pytest from numba import njit import vectorbt as vbt from tests.utils import record_arrays_close from vectorbt.generic.enums import range_dt, drawdown_dt from vectorbt.portfolio.enums import order_dt, trade_dt, log_dt day_dt = np.timedelta64(86400000000000) example_dt = np.dtype([ ('id', np.int64), ('col', np.int64), ('idx', np.int64), ('some_field1', np.float64), ('some_field2', np.float64) ], align=True) records_arr = np.asarray([ (0, 0, 0, 10, 21), (1, 0, 1, 11, 20), (2, 0, 2, 12, 19), (3, 1, 0, 13, 18), (4, 1, 1, 14, 17), (5, 1, 2, 13, 18), (6, 2, 0, 12, 19), (7, 2, 1, 11, 20), (8, 2, 2, 10, 21) ], dtype=example_dt) records_nosort_arr = np.concatenate(( records_arr[0::3], records_arr[1::3], records_arr[2::3] )) group_by = pd.Index(['g1', 'g1', 'g2', 'g2']) wrapper = vbt.ArrayWrapper( index=['x', 'y', 'z'], columns=['a', 'b', 'c', 'd'], ndim=2, freq='1 days' ) wrapper_grouped = wrapper.replace(group_by=group_by) records = vbt.records.Records(wrapper, records_arr) records_grouped = vbt.records.Records(wrapper_grouped, records_arr) records_nosort = records.replace(records_arr=records_nosort_arr) records_nosort_grouped = vbt.records.Records(wrapper_grouped, records_nosort_arr) # ############# Global ############# # def setup_module(): vbt.settings.numba['check_func_suffix'] = True vbt.settings.caching.enabled = False vbt.settings.caching.whitelist = [] vbt.settings.caching.blacklist = [] def teardown_module(): vbt.settings.reset() # ############# col_mapper.py ############# # class TestColumnMapper: def test_col_arr(self): np.testing.assert_array_equal( records['a'].col_mapper.col_arr, np.array([0, 0, 0]) ) np.testing.assert_array_equal( records.col_mapper.col_arr, np.array([0, 0, 0, 1, 1, 1, 2, 2, 2]) ) def test_get_col_arr(self): np.testing.assert_array_equal( records.col_mapper.get_col_arr(), records.col_mapper.col_arr ) np.testing.assert_array_equal( records_grouped['g1'].col_mapper.get_col_arr(), np.array([0, 0, 0, 0, 0, 0]) ) np.testing.assert_array_equal( records_grouped.col_mapper.get_col_arr(), np.array([0, 0, 0, 0, 0, 0, 1, 1, 1]) ) def test_col_range(self): np.testing.assert_array_equal( records['a'].col_mapper.col_range, np.array([ [0, 3] ]) ) np.testing.assert_array_equal( records.col_mapper.col_range, np.array([ [0, 3], [3, 6], [6, 9], [-1, -1] ]) ) def test_get_col_range(self): np.testing.assert_array_equal( records.col_mapper.get_col_range(), np.array([ [0, 3], [3, 6], [6, 9], [-1, -1] ]) ) np.testing.assert_array_equal( records_grouped['g1'].col_mapper.get_col_range(), np.array([[0, 6]]) ) np.testing.assert_array_equal( records_grouped.col_mapper.get_col_range(), np.array([[0, 6], [6, 9]]) ) def test_col_map(self): np.testing.assert_array_equal( records['a'].col_mapper.col_map[0], np.array([0, 1, 2]) ) np.testing.assert_array_equal( records['a'].col_mapper.col_map[1], np.array([3]) ) np.testing.assert_array_equal( records.col_mapper.col_map[0], np.array([0, 1, 2, 3, 4, 5, 6, 7, 8]) ) np.testing.assert_array_equal( records.col_mapper.col_map[1], np.array([3, 3, 3, 0]) ) def test_get_col_map(self): np.testing.assert_array_equal( records.col_mapper.get_col_map()[0], records.col_mapper.col_map[0] ) np.testing.assert_array_equal( records.col_mapper.get_col_map()[1], records.col_mapper.col_map[1] ) np.testing.assert_array_equal( records_grouped['g1'].col_mapper.get_col_map()[0], np.array([0, 1, 2, 3, 4, 5]) ) np.testing.assert_array_equal( records_grouped['g1'].col_mapper.get_col_map()[1], np.array([6]) ) np.testing.assert_array_equal( records_grouped.col_mapper.get_col_map()[0], np.array([0, 1, 2, 3, 4, 5, 6, 7, 8]) ) np.testing.assert_array_equal( records_grouped.col_mapper.get_col_map()[1], np.array([6, 3]) ) def test_is_sorted(self): assert records.col_mapper.is_sorted() assert not records_nosort.col_mapper.is_sorted() # ############# mapped_array.py ############# # mapped_array = records.map_field('some_field1') mapped_array_grouped = records_grouped.map_field('some_field1') mapped_array_nosort = records_nosort.map_field('some_field1') mapped_array_nosort_grouped = records_nosort_grouped.map_field('some_field1') mapping = {x: 'test_' + str(x) for x in pd.unique(mapped_array.values)} mp_mapped_array = mapped_array.replace(mapping=mapping) mp_mapped_array_grouped = mapped_array_grouped.replace(mapping=mapping) class TestMappedArray: def test_config(self, tmp_path): assert vbt.MappedArray.loads(mapped_array.dumps()) == mapped_array mapped_array.save(tmp_path / 'mapped_array') assert vbt.MappedArray.load(tmp_path / 'mapped_array') == mapped_array def test_mapped_arr(self): np.testing.assert_array_equal( mapped_array['a'].values, np.array([10., 11., 12.]) ) np.testing.assert_array_equal( mapped_array.values, np.array([10., 11., 12., 13., 14., 13., 12., 11., 10.]) ) def test_id_arr(self): np.testing.assert_array_equal( mapped_array['a'].id_arr, np.array([0, 1, 2]) ) np.testing.assert_array_equal( mapped_array.id_arr, np.array([0, 1, 2, 3, 4, 5, 6, 7, 8]) ) def test_col_arr(self): np.testing.assert_array_equal( mapped_array['a'].col_arr, np.array([0, 0, 0]) ) np.testing.assert_array_equal( mapped_array.col_arr, np.array([0, 0, 0, 1, 1, 1, 2, 2, 2]) ) def test_idx_arr(self): np.testing.assert_array_equal( mapped_array['a'].idx_arr, np.array([0, 1, 2]) ) np.testing.assert_array_equal( mapped_array.idx_arr, np.array([0, 1, 2, 0, 1, 2, 0, 1, 2]) ) def test_is_sorted(self): assert mapped_array.is_sorted() assert mapped_array.is_sorted(incl_id=True) assert not mapped_array_nosort.is_sorted() assert not mapped_array_nosort.is_sorted(incl_id=True) def test_sort(self): assert mapped_array.sort().is_sorted() assert mapped_array.sort().is_sorted(incl_id=True) assert mapped_array.sort(incl_id=True).is_sorted(incl_id=True) assert mapped_array_nosort.sort().is_sorted() assert mapped_array_nosort.sort().is_sorted(incl_id=True) assert mapped_array_nosort.sort(incl_id=True).is_sorted(incl_id=True) def test_apply_mask(self): mask_a = mapped_array['a'].values >= mapped_array['a'].values.mean() np.testing.assert_array_equal( mapped_array['a'].apply_mask(mask_a).id_arr, np.array([1, 2]) ) mask = mapped_array.values >= mapped_array.values.mean() filtered = mapped_array.apply_mask(mask) np.testing.assert_array_equal( filtered.id_arr, np.array([2, 3, 4, 5, 6]) ) np.testing.assert_array_equal(filtered.col_arr, mapped_array.col_arr[mask]) np.testing.assert_array_equal(filtered.idx_arr, mapped_array.idx_arr[mask]) assert mapped_array_grouped.apply_mask(mask).wrapper == mapped_array_grouped.wrapper assert mapped_array_grouped.apply_mask(mask, group_by=False).wrapper.grouper.group_by is None def test_map_to_mask(self): @njit def every_2_nb(inout, idxs, col, mapped_arr): inout[idxs[::2]] = True np.testing.assert_array_equal( mapped_array.map_to_mask(every_2_nb), np.array([True, False, True, True, False, True, True, False, True]) ) def test_top_n_mask(self): np.testing.assert_array_equal( mapped_array.top_n_mask(1), np.array([False, False, True, False, True, False, True, False, False]) ) def test_bottom_n_mask(self): np.testing.assert_array_equal( mapped_array.bottom_n_mask(1), np.array([True, False, False, True, False, False, False, False, True]) ) def test_top_n(self): np.testing.assert_array_equal( mapped_array.top_n(1).id_arr, np.array([2, 4, 6]) ) def test_bottom_n(self): np.testing.assert_array_equal( mapped_array.bottom_n(1).id_arr, np.array([0, 3, 8]) ) def test_to_pd(self): target = pd.DataFrame( np.array([ [10., 13., 12., np.nan], [11., 14., 11., np.nan], [12., 13., 10., np.nan] ]), index=wrapper.index, columns=wrapper.columns ) pd.testing.assert_series_equal( mapped_array['a'].to_pd(), target['a'] ) pd.testing.assert_frame_equal( mapped_array.to_pd(), target ) pd.testing.assert_frame_equal( mapped_array.to_pd(fill_value=0.), target.fillna(0.) ) mapped_array2 = vbt.MappedArray( wrapper, records_arr['some_field1'].tolist() + [1], records_arr['col'].tolist() + [2], idx_arr=records_arr['idx'].tolist() + [2] ) with pytest.raises(Exception): _ = mapped_array2.to_pd() pd.testing.assert_series_equal( mapped_array['a'].to_pd(ignore_index=True), pd.Series(np.array([10., 11., 12.]), name='a') ) pd.testing.assert_frame_equal( mapped_array.to_pd(ignore_index=True), pd.DataFrame( np.array([ [10., 13., 12., np.nan], [11., 14., 11., np.nan], [12., 13., 10., np.nan] ]), columns=wrapper.columns ) ) pd.testing.assert_frame_equal( mapped_array.to_pd(fill_value=0, ignore_index=True), pd.DataFrame( np.array([ [10., 13., 12., 0.], [11., 14., 11., 0.], [12., 13., 10., 0.] ]), columns=wrapper.columns ) ) pd.testing.assert_frame_equal( mapped_array_grouped.to_pd(ignore_index=True), pd.DataFrame( np.array([ [10., 12.], [11., 11.], [12., 10.], [13., np.nan], [14., np.nan], [13., np.nan], ]), columns=pd.Index(['g1', 'g2'], dtype='object') ) ) def test_apply(self): @njit def cumsum_apply_nb(idxs, col, a): return np.cumsum(a) np.testing.assert_array_equal( mapped_array['a'].apply(cumsum_apply_nb).values, np.array([10., 21., 33.]) ) np.testing.assert_array_equal( mapped_array.apply(cumsum_apply_nb).values, np.array([10., 21., 33., 13., 27., 40., 12., 23., 33.]) ) np.testing.assert_array_equal( mapped_array_grouped.apply(cumsum_apply_nb, apply_per_group=False).values, np.array([10., 21., 33., 13., 27., 40., 12., 23., 33.]) ) np.testing.assert_array_equal( mapped_array_grouped.apply(cumsum_apply_nb, apply_per_group=True).values, np.array([10., 21., 33., 46., 60., 73., 12., 23., 33.]) ) assert mapped_array_grouped.apply(cumsum_apply_nb).wrapper == \ mapped_array.apply(cumsum_apply_nb, group_by=group_by).wrapper assert mapped_array.apply(cumsum_apply_nb, group_by=False).wrapper.grouper.group_by is None def test_reduce(self): @njit def mean_reduce_nb(col, a): return np.mean(a) assert mapped_array['a'].reduce(mean_reduce_nb) == 11. pd.testing.assert_series_equal( mapped_array.reduce(mean_reduce_nb), pd.Series(np.array([11., 13.333333333333334, 11., np.nan]), index=wrapper.columns).rename('reduce') ) pd.testing.assert_series_equal( mapped_array.reduce(mean_reduce_nb, fill_value=0.), pd.Series(np.array([11., 13.333333333333334, 11., 0.]), index=wrapper.columns).rename('reduce') ) pd.testing.assert_series_equal( mapped_array.reduce(mean_reduce_nb, wrap_kwargs=dict(to_timedelta=True)), pd.Series(np.array([11., 13.333333333333334, 11., np.nan]), index=wrapper.columns).rename('reduce') * day_dt ) pd.testing.assert_series_equal( mapped_array_grouped.reduce(mean_reduce_nb), pd.Series([12.166666666666666, 11.0], index=pd.Index(['g1', 'g2'], dtype='object')).rename('reduce') ) assert mapped_array_grouped['g1'].reduce(mean_reduce_nb) == 12.166666666666666 pd.testing.assert_series_equal( mapped_array_grouped[['g1']].reduce(mean_reduce_nb), pd.Series([12.166666666666666], index=pd.Index(['g1'], dtype='object')).rename('reduce') ) pd.testing.assert_series_equal( mapped_array.reduce(mean_reduce_nb), mapped_array_grouped.reduce(mean_reduce_nb, group_by=False) ) pd.testing.assert_series_equal( mapped_array.reduce(mean_reduce_nb, group_by=group_by), mapped_array_grouped.reduce(mean_reduce_nb) ) def test_reduce_to_idx(self): @njit def argmin_reduce_nb(col, a): return np.argmin(a) assert mapped_array['a'].reduce(argmin_reduce_nb, returns_idx=True) == 'x' pd.testing.assert_series_equal( mapped_array.reduce(argmin_reduce_nb, returns_idx=True), pd.Series(np.array(['x', 'x', 'z', np.nan], dtype=object), index=wrapper.columns).rename('reduce') ) pd.testing.assert_series_equal( mapped_array.reduce(argmin_reduce_nb, returns_idx=True, to_index=False), pd.Series(np.array([0, 0, 2, -1], dtype=int), index=wrapper.columns).rename('reduce') ) pd.testing.assert_series_equal( mapped_array_grouped.reduce(argmin_reduce_nb, returns_idx=True, to_index=False), pd.Series(np.array([0, 2], dtype=int), index=pd.Index(['g1', 'g2'], dtype='object')).rename('reduce') ) def test_reduce_to_array(self): @njit def min_max_reduce_nb(col, a): return np.array([np.min(a), np.max(a)]) pd.testing.assert_series_equal( mapped_array['a'].reduce(min_max_reduce_nb, returns_array=True, wrap_kwargs=dict(name_or_index=['min', 'max'])), pd.Series([10., 12.], index=pd.Index(['min', 'max'], dtype='object'), name='a') ) pd.testing.assert_frame_equal( mapped_array.reduce(min_max_reduce_nb, returns_array=True, wrap_kwargs=dict(name_or_index=['min', 'max'])), pd.DataFrame( np.array([ [10., 13., 10., np.nan], [12., 14., 12., np.nan] ]), index=pd.Index(['min', 'max'], dtype='object'), columns=wrapper.columns ) ) pd.testing.assert_frame_equal( mapped_array.reduce(min_max_reduce_nb, returns_array=True, fill_value=0.), pd.DataFrame( np.array([ [10., 13., 10., 0.], [12., 14., 12., 0.] ]), columns=wrapper.columns ) ) pd.testing.assert_frame_equal( mapped_array.reduce(min_max_reduce_nb, returns_array=True, wrap_kwargs=dict(to_timedelta=True)), pd.DataFrame( np.array([ [10., 13., 10., np.nan], [12., 14., 12., np.nan] ]), columns=wrapper.columns ) * day_dt ) pd.testing.assert_frame_equal( mapped_array_grouped.reduce(min_max_reduce_nb, returns_array=True), pd.DataFrame( np.array([ [10., 10.], [14., 12.] ]), columns=pd.Index(['g1', 'g2'], dtype='object') ) ) pd.testing.assert_frame_equal( mapped_array.reduce(min_max_reduce_nb, returns_array=True), mapped_array_grouped.reduce(min_max_reduce_nb, returns_array=True, group_by=False) ) pd.testing.assert_frame_equal( mapped_array.reduce(min_max_reduce_nb, returns_array=True, group_by=group_by), mapped_array_grouped.reduce(min_max_reduce_nb, returns_array=True) ) pd.testing.assert_series_equal( mapped_array_grouped['g1'].reduce(min_max_reduce_nb, returns_array=True), pd.Series([10., 14.], name='g1') ) pd.testing.assert_frame_equal( mapped_array_grouped[['g1']].reduce(min_max_reduce_nb, returns_array=True), pd.DataFrame([[10.], [14.]], columns=pd.Index(['g1'], dtype='object')) ) def test_reduce_to_idx_array(self): @njit def idxmin_idxmax_reduce_nb(col, a): return np.array([np.argmin(a), np.argmax(a)]) pd.testing.assert_series_equal( mapped_array['a'].reduce( idxmin_idxmax_reduce_nb, returns_array=True, returns_idx=True, wrap_kwargs=dict(name_or_index=['min', 'max']) ), pd.Series( np.array(['x', 'z'], dtype=object), index=pd.Index(['min', 'max'], dtype='object'), name='a' ) ) pd.testing.assert_frame_equal( mapped_array.reduce( idxmin_idxmax_reduce_nb, returns_array=True, returns_idx=True, wrap_kwargs=dict(name_or_index=['min', 'max']) ), pd.DataFrame( { 'a': ['x', 'z'], 'b': ['x', 'y'], 'c': ['z', 'x'], 'd': [np.nan, np.nan] }, index=pd.Index(['min', 'max'], dtype='object') ) ) pd.testing.assert_frame_equal( mapped_array.reduce( idxmin_idxmax_reduce_nb, returns_array=True, returns_idx=True, to_index=False ), pd.DataFrame( np.array([ [0, 0, 2, -1], [2, 1, 0, -1] ]), columns=wrapper.columns ) ) pd.testing.assert_frame_equal( mapped_array_grouped.reduce( idxmin_idxmax_reduce_nb, returns_array=True, returns_idx=True, to_index=False ), pd.DataFrame( np.array([ [0, 2], [1, 0] ]), columns=pd.Index(['g1', 'g2'], dtype='object') ) ) def test_nth(self): assert mapped_array['a'].nth(0) == 10. pd.testing.assert_series_equal( mapped_array.nth(0), pd.Series(np.array([10., 13., 12., np.nan]), index=wrapper.columns).rename('nth') ) assert mapped_array['a'].nth(-1) == 12. pd.testing.assert_series_equal( mapped_array.nth(-1), pd.Series(np.array([12., 13., 10., np.nan]), index=wrapper.columns).rename('nth') ) with pytest.raises(Exception): _ = mapped_array.nth(10) pd.testing.assert_series_equal( mapped_array_grouped.nth(0), pd.Series(np.array([10., 12.]), index=pd.Index(['g1', 'g2'], dtype='object')).rename('nth') ) def test_nth_index(self): assert mapped_array['a'].nth(0) == 10. pd.testing.assert_series_equal( mapped_array.nth_index(0), pd.Series( np.array(['x', 'x', 'x', np.nan], dtype='object'), index=wrapper.columns ).rename('nth_index') ) assert mapped_array['a'].nth(-1) == 12. pd.testing.assert_series_equal( mapped_array.nth_index(-1), pd.Series( np.array(['z', 'z', 'z', np.nan], dtype='object'), index=wrapper.columns ).rename('nth_index') ) with pytest.raises(Exception): _ = mapped_array.nth_index(10) pd.testing.assert_series_equal( mapped_array_grouped.nth_index(0), pd.Series( np.array(['x', 'x'], dtype='object'), index=pd.Index(['g1', 'g2'], dtype='object') ).rename('nth_index') ) def test_min(self): assert mapped_array['a'].min() == mapped_array['a'].to_pd().min() pd.testing.assert_series_equal( mapped_array.min(), mapped_array.to_pd().min().rename('min') ) pd.testing.assert_series_equal( mapped_array_grouped.min(), pd.Series([10., 10.], index=pd.Index(['g1', 'g2'], dtype='object')).rename('min') ) def test_max(self): assert mapped_array['a'].max() == mapped_array['a'].to_pd().max() pd.testing.assert_series_equal( mapped_array.max(), mapped_array.to_pd().max().rename('max') ) pd.testing.assert_series_equal( mapped_array_grouped.max(), pd.Series([14., 12.], index=pd.Index(['g1', 'g2'], dtype='object')).rename('max') ) def test_mean(self): assert mapped_array['a'].mean() == mapped_array['a'].to_pd().mean() pd.testing.assert_series_equal( mapped_array.mean(), mapped_array.to_pd().mean().rename('mean') ) pd.testing.assert_series_equal( mapped_array_grouped.mean(), pd.Series([12.166667, 11.], index=pd.Index(['g1', 'g2'], dtype='object')).rename('mean') ) def test_median(self): assert mapped_array['a'].median() == mapped_array['a'].to_pd().median() pd.testing.assert_series_equal( mapped_array.median(), mapped_array.to_pd().median().rename('median') ) pd.testing.assert_series_equal( mapped_array_grouped.median(), pd.Series([12.5, 11.], index=pd.Index(['g1', 'g2'], dtype='object')).rename('median') ) def test_std(self): assert mapped_array['a'].std() == mapped_array['a'].to_pd().std() pd.testing.assert_series_equal( mapped_array.std(), mapped_array.to_pd().std().rename('std') ) pd.testing.assert_series_equal( mapped_array.std(ddof=0), mapped_array.to_pd().std(ddof=0).rename('std') ) pd.testing.assert_series_equal( mapped_array_grouped.std(), pd.Series([1.4719601443879746, 1.0], index=pd.Index(['g1', 'g2'], dtype='object')).rename('std') ) def test_sum(self): assert mapped_array['a'].sum() == mapped_array['a'].to_pd().sum() pd.testing.assert_series_equal( mapped_array.sum(), mapped_array.to_pd().sum().rename('sum') ) pd.testing.assert_series_equal( mapped_array_grouped.sum(), pd.Series([73.0, 33.0], index=pd.Index(['g1', 'g2'], dtype='object')).rename('sum') ) def test_count(self): assert mapped_array['a'].count() == mapped_array['a'].to_pd().count() pd.testing.assert_series_equal( mapped_array.count(), mapped_array.to_pd().count().rename('count') ) pd.testing.assert_series_equal( mapped_array_grouped.count(), pd.Series([6, 3], index=pd.Index(['g1', 'g2'], dtype='object')).rename('count') ) def test_idxmin(self): assert mapped_array['a'].idxmin() == mapped_array['a'].to_pd().idxmin() pd.testing.assert_series_equal( mapped_array.idxmin(), mapped_array.to_pd().idxmin().rename('idxmin') ) pd.testing.assert_series_equal( mapped_array_grouped.idxmin(), pd.Series( np.array(['x', 'z'], dtype=object), index=pd.Index(['g1', 'g2'], dtype='object') ).rename('idxmin') ) def test_idxmax(self): assert mapped_array['a'].idxmax() == mapped_array['a'].to_pd().idxmax() pd.testing.assert_series_equal( mapped_array.idxmax(), mapped_array.to_pd().idxmax().rename('idxmax') ) pd.testing.assert_series_equal( mapped_array_grouped.idxmax(), pd.Series( np.array(['y', 'x'], dtype=object), index=pd.Index(['g1', 'g2'], dtype='object') ).rename('idxmax') ) def test_describe(self): pd.testing.assert_series_equal( mapped_array['a'].describe(), mapped_array['a'].to_pd().describe() ) pd.testing.assert_frame_equal( mapped_array.describe(percentiles=None), mapped_array.to_pd().describe(percentiles=None) ) pd.testing.assert_frame_equal( mapped_array.describe(percentiles=[]), mapped_array.to_pd().describe(percentiles=[]) ) pd.testing.assert_frame_equal( mapped_array.describe(percentiles=np.arange(0, 1, 0.1)), mapped_array.to_pd().describe(percentiles=np.arange(0, 1, 0.1)) ) pd.testing.assert_frame_equal( mapped_array_grouped.describe(), pd.DataFrame( np.array([ [6., 3.], [12.16666667, 11.], [1.47196014, 1.], [10., 10.], [11.25, 10.5], [12.5, 11.], [13., 11.5], [14., 12.] ]), columns=pd.Index(['g1', 'g2'], dtype='object'), index=mapped_array.describe().index ) ) def test_value_counts(self): pd.testing.assert_series_equal( mapped_array['a'].value_counts(), pd.Series( np.array([1, 1, 1]), index=pd.Index([10.0, 11.0, 12.0], dtype='float64'), name='a' ) ) pd.testing.assert_series_equal( mapped_array['a'].value_counts(mapping=mapping), pd.Series( np.array([1, 1, 1]), index=pd.Index(['test_10.0', 'test_11.0', 'test_12.0'], dtype='object'), name='a' ) ) pd.testing.assert_frame_equal( mapped_array.value_counts(), pd.DataFrame( np.array([ [1, 0, 1, 0], [1, 0, 1, 0], [1, 0, 1, 0], [0, 2, 0, 0], [0, 1, 0, 0] ]), index=pd.Index([10.0, 11.0, 12.0, 13.0, 14.0], dtype='float64'), columns=wrapper.columns ) ) pd.testing.assert_frame_equal( mapped_array_grouped.value_counts(), pd.DataFrame( np.array([ [1, 1], [1, 1], [1, 1], [2, 0], [1, 0] ]), index=pd.Index([10.0, 11.0, 12.0, 13.0, 14.0], dtype='float64'), columns=pd.Index(['g1', 'g2'], dtype='object') ) ) mapped_array2 = mapped_array.replace(mapped_arr=[4, 4, 3, 2, np.nan, 4, 3, 2, 1]) pd.testing.assert_frame_equal( mapped_array2.value_counts(sort_uniques=False), pd.DataFrame( np.array([ [2, 1, 0, 0], [1, 0, 1, 0], [0, 1, 1, 0], [0, 0, 1, 0], [0, 1, 0, 0] ]), index=pd.Index([4.0, 3.0, 2.0, 1.0, None], dtype='float64'), columns=wrapper.columns ) ) pd.testing.assert_frame_equal( mapped_array2.value_counts(sort_uniques=True), pd.DataFrame( np.array([ [0, 0, 1, 0], [0, 1, 1, 0], [1, 0, 1, 0], [2, 1, 0, 0], [0, 1, 0, 0] ]), index=pd.Index([1.0, 2.0, 3.0, 4.0, None], dtype='float64'), columns=wrapper.columns ) ) pd.testing.assert_frame_equal( mapped_array2.value_counts(sort=True), pd.DataFrame( np.array([ [2, 1, 0, 0], [0, 1, 1, 0], [1, 0, 1, 0], [0, 0, 1, 0], [0, 1, 0, 0] ]), index=pd.Index([4.0, 2.0, 3.0, 1.0, np.nan], dtype='float64'), columns=wrapper.columns ) ) pd.testing.assert_frame_equal( mapped_array2.value_counts(sort=True, ascending=True), pd.DataFrame( np.array([ [0, 0, 1, 0], [0, 1, 0, 0], [0, 1, 1, 0], [1, 0, 1, 0], [2, 1, 0, 0] ]), index=pd.Index([1.0, np.nan, 2.0, 3.0, 4.0], dtype='float64'), columns=wrapper.columns ) ) pd.testing.assert_frame_equal( mapped_array2.value_counts(sort=True, normalize=True), pd.DataFrame( np.array([ [0.2222222222222222, 0.1111111111111111, 0.0, 0.0], [0.0, 0.1111111111111111, 0.1111111111111111, 0.0], [0.1111111111111111, 0.0, 0.1111111111111111, 0.0], [0.0, 0.0, 0.1111111111111111, 0.0], [0.0, 0.1111111111111111, 0.0, 0.0] ]), index=pd.Index([4.0, 2.0, 3.0, 1.0, np.nan], dtype='float64'), columns=wrapper.columns ) ) pd.testing.assert_frame_equal( mapped_array2.value_counts(sort=True, normalize=True, dropna=True), pd.DataFrame( np.array([ [0.25, 0.125, 0.0, 0.0], [0.0, 0.125, 0.125, 0.0], [0.125, 0.0, 0.125, 0.0], [0.0, 0.0, 0.125, 0.0] ]), index=pd.Index([4.0, 2.0, 3.0, 1.0], dtype='float64'), columns=wrapper.columns ) ) @pytest.mark.parametrize( "test_nosort", [False, True], ) def test_indexing(self, test_nosort): if test_nosort: ma = mapped_array_nosort ma_grouped = mapped_array_nosort_grouped else: ma = mapped_array ma_grouped = mapped_array_grouped np.testing.assert_array_equal( ma['a'].id_arr, np.array([0, 1, 2]) ) np.testing.assert_array_equal( ma['a'].col_arr, np.array([0, 0, 0]) ) pd.testing.assert_index_equal( ma['a'].wrapper.columns, pd.Index(['a'], dtype='object') ) np.testing.assert_array_equal( ma['b'].id_arr, np.array([3, 4, 5]) ) np.testing.assert_array_equal( ma['b'].col_arr, np.array([0, 0, 0]) ) pd.testing.assert_index_equal( ma['b'].wrapper.columns, pd.Index(['b'], dtype='object') ) np.testing.assert_array_equal( ma[['a', 'a']].id_arr, np.array([0, 1, 2, 0, 1, 2]) ) np.testing.assert_array_equal( ma[['a', 'a']].col_arr, np.array([0, 0, 0, 1, 1, 1]) ) pd.testing.assert_index_equal( ma[['a', 'a']].wrapper.columns, pd.Index(['a', 'a'], dtype='object') ) np.testing.assert_array_equal( ma[['a', 'b']].id_arr, np.array([0, 1, 2, 3, 4, 5]) ) np.testing.assert_array_equal( ma[['a', 'b']].col_arr, np.array([0, 0, 0, 1, 1, 1]) ) pd.testing.assert_index_equal( ma[['a', 'b']].wrapper.columns, pd.Index(['a', 'b'], dtype='object') ) with pytest.raises(Exception): _ = ma.iloc[::2, :] # changing time not supported pd.testing.assert_index_equal( ma_grouped['g1'].wrapper.columns, pd.Index(['a', 'b'], dtype='object') ) assert ma_grouped['g1'].wrapper.ndim == 2 assert ma_grouped['g1'].wrapper.grouped_ndim == 1 pd.testing.assert_index_equal( ma_grouped['g1'].wrapper.grouper.group_by, pd.Index(['g1', 'g1'], dtype='object') ) pd.testing.assert_index_equal( ma_grouped['g2'].wrapper.columns, pd.Index(['c', 'd'], dtype='object') ) assert ma_grouped['g2'].wrapper.ndim == 2 assert ma_grouped['g2'].wrapper.grouped_ndim == 1 pd.testing.assert_index_equal( ma_grouped['g2'].wrapper.grouper.group_by, pd.Index(['g2', 'g2'], dtype='object') ) pd.testing.assert_index_equal( ma_grouped[['g1']].wrapper.columns, pd.Index(['a', 'b'], dtype='object') ) assert ma_grouped[['g1']].wrapper.ndim == 2 assert ma_grouped[['g1']].wrapper.grouped_ndim == 2 pd.testing.assert_index_equal( ma_grouped[['g1']].wrapper.grouper.group_by, pd.Index(['g1', 'g1'], dtype='object') ) pd.testing.assert_index_equal( ma_grouped[['g1', 'g2']].wrapper.columns, pd.Index(['a', 'b', 'c', 'd'], dtype='object') ) assert ma_grouped[['g1', 'g2']].wrapper.ndim == 2 assert ma_grouped[['g1', 'g2']].wrapper.grouped_ndim == 2 pd.testing.assert_index_equal( ma_grouped[['g1', 'g2']].wrapper.grouper.group_by, pd.Index(['g1', 'g1', 'g2', 'g2'], dtype='object') ) def test_magic(self): a = vbt.MappedArray( wrapper, records_arr['some_field1'], records_arr['col'], id_arr=records_arr['id'], idx_arr=records_arr['idx'] ) a_inv = vbt.MappedArray( wrapper, records_arr['some_field1'][::-1], records_arr['col'][::-1], id_arr=records_arr['id'][::-1], idx_arr=records_arr['idx'][::-1] ) b = records_arr['some_field2'] a_bool = vbt.MappedArray( wrapper, records_arr['some_field1'] > np.mean(records_arr['some_field1']), records_arr['col'], id_arr=records_arr['id'], idx_arr=records_arr['idx'] ) b_bool = records_arr['some_field2'] > np.mean(records_arr['some_field2']) assert a ** a == a ** 2 with pytest.raises(Exception): _ = a * a_inv # binary ops # comparison ops np.testing.assert_array_equal((a == b).values, a.values == b) np.testing.assert_array_equal((a != b).values, a.values != b) np.testing.assert_array_equal((a < b).values, a.values < b) np.testing.assert_array_equal((a > b).values, a.values > b) np.testing.assert_array_equal((a <= b).values, a.values <= b) np.testing.assert_array_equal((a >= b).values, a.values >= b) # arithmetic ops np.testing.assert_array_equal((a + b).values, a.values + b) np.testing.assert_array_equal((a - b).values, a.values - b) np.testing.assert_array_equal((a * b).values, a.values * b) np.testing.assert_array_equal((a ** b).values, a.values ** b) np.testing.assert_array_equal((a % b).values, a.values % b) np.testing.assert_array_equal((a // b).values, a.values // b) np.testing.assert_array_equal((a / b).values, a.values / b) # __r*__ is only called if the left object does not have an __*__ method np.testing.assert_array_equal((10 + a).values, 10 + a.values) np.testing.assert_array_equal((10 - a).values, 10 - a.values) np.testing.assert_array_equal((10 * a).values, 10 * a.values) np.testing.assert_array_equal((10 ** a).values, 10 ** a.values) np.testing.assert_array_equal((10 % a).values, 10 % a.values) np.testing.assert_array_equal((10 // a).values, 10 // a.values) np.testing.assert_array_equal((10 / a).values, 10 / a.values) # mask ops np.testing.assert_array_equal((a_bool & b_bool).values, a_bool.values & b_bool) np.testing.assert_array_equal((a_bool | b_bool).values, a_bool.values | b_bool) np.testing.assert_array_equal((a_bool ^ b_bool).values, a_bool.values ^ b_bool) np.testing.assert_array_equal((True & a_bool).values, True & a_bool.values) np.testing.assert_array_equal((True | a_bool).values, True | a_bool.values) np.testing.assert_array_equal((True ^ a_bool).values, True ^ a_bool.values) # unary ops np.testing.assert_array_equal((-a).values, -a.values) np.testing.assert_array_equal((+a).values, +a.values) np.testing.assert_array_equal((abs(-a)).values, abs((-a.values))) def test_stats(self): stats_index = pd.Index([ 'Start', 'End', 'Period', 'Count', 'Mean', 'Std', 'Min', 'Median', 'Max', 'Min Index', 'Max Index' ], dtype='object') pd.testing.assert_series_equal( mapped_array.stats(), pd.Series([ 'x', 'z', pd.Timedelta('3 days 00:00:00'), 2.25, 11.777777777777779, 0.859116756396542, 11.0, 11.666666666666666, 12.666666666666666 ], index=stats_index[:-2], name='agg_func_mean' ) ) pd.testing.assert_series_equal( mapped_array.stats(column='a'), pd.Series([ 'x', 'z', pd.Timedelta('3 days 00:00:00'), 3, 11.0, 1.0, 10.0, 11.0, 12.0, 'x', 'z' ], index=stats_index, name='a' ) ) pd.testing.assert_series_equal( mapped_array.stats(column='g1', group_by=group_by), pd.Series([ 'x', 'z', pd.Timedelta('3 days 00:00:00'), 6, 12.166666666666666, 1.4719601443879746, 10.0, 12.5, 14.0, 'x', 'y' ], index=stats_index, name='g1' ) ) pd.testing.assert_series_equal( mapped_array['c'].stats(), mapped_array.stats(column='c') ) pd.testing.assert_series_equal( mapped_array['c'].stats(), mapped_array.stats(column='c', group_by=False) ) pd.testing.assert_series_equal( mapped_array_grouped['g2'].stats(), mapped_array_grouped.stats(column='g2') ) pd.testing.assert_series_equal( mapped_array_grouped['g2'].stats(), mapped_array.stats(column='g2', group_by=group_by) ) stats_df = mapped_array.stats(agg_func=None) assert stats_df.shape == (4, 11) pd.testing.assert_index_equal(stats_df.index, mapped_array.wrapper.columns) pd.testing.assert_index_equal(stats_df.columns, stats_index) def test_stats_mapping(self): stats_index = pd.Index([ 'Start', 'End', 'Period', 'Count', 'Value Counts: test_10.0', 'Value Counts: test_11.0', 'Value Counts: test_12.0', 'Value Counts: test_13.0', 'Value Counts: test_14.0' ], dtype='object') pd.testing.assert_series_equal( mp_mapped_array.stats(), pd.Series([ 'x', 'z', pd.Timedelta('3 days 00:00:00'), 2.25, 0.5, 0.5, 0.5, 0.5, 0.25 ], index=stats_index, name='agg_func_mean' ) ) pd.testing.assert_series_equal( mp_mapped_array.stats(column='a'), pd.Series([ 'x', 'z', pd.Timedelta('3 days 00:00:00'), 3, 1, 1, 1, 0, 0 ], index=stats_index, name='a' ) ) pd.testing.assert_series_equal( mp_mapped_array.stats(column='g1', group_by=group_by), pd.Series([ 'x', 'z', pd.Timedelta('3 days 00:00:00'), 6, 1, 1, 1, 2, 1 ], index=stats_index, name='g1' ) ) pd.testing.assert_series_equal( mp_mapped_array.stats(), mapped_array.stats(settings=dict(mapping=mapping)) ) pd.testing.assert_series_equal( mp_mapped_array['c'].stats(settings=dict(incl_all_keys=True)), mp_mapped_array.stats(column='c') ) pd.testing.assert_series_equal( mp_mapped_array['c'].stats(settings=dict(incl_all_keys=True)), mp_mapped_array.stats(column='c', group_by=False) ) pd.testing.assert_series_equal( mp_mapped_array_grouped['g2'].stats(settings=dict(incl_all_keys=True)), mp_mapped_array_grouped.stats(column='g2') ) pd.testing.assert_series_equal( mp_mapped_array_grouped['g2'].stats(settings=dict(incl_all_keys=True)), mp_mapped_array.stats(column='g2', group_by=group_by) ) stats_df = mp_mapped_array.stats(agg_func=None) assert stats_df.shape == (4, 9) pd.testing.assert_index_equal(stats_df.index, mp_mapped_array.wrapper.columns) pd.testing.assert_index_equal(stats_df.columns, stats_index) # ############# base.py ############# # class TestRecords: def test_config(self, tmp_path): assert vbt.Records.loads(records['a'].dumps()) == records['a'] assert vbt.Records.loads(records.dumps()) == records records.save(tmp_path / 'records') assert vbt.Records.load(tmp_path / 'records') == records def test_records(self): pd.testing.assert_frame_equal( records.records, pd.DataFrame.from_records(records_arr) ) def test_recarray(self): np.testing.assert_array_equal(records['a'].recarray.some_field1, records['a'].values['some_field1']) np.testing.assert_array_equal(records.recarray.some_field1, records.values['some_field1']) def test_records_readable(self): pd.testing.assert_frame_equal( records.records_readable, pd.DataFrame([ [0, 'a', 'x', 10.0, 21.0], [1, 'a', 'y', 11.0, 20.0], [2, 'a', 'z', 12.0, 19.0], [3, 'b', 'x', 13.0, 18.0], [4, 'b', 'y', 14.0, 17.0], [5, 'b', 'z', 13.0, 18.0], [6, 'c', 'x', 12.0, 19.0], [7, 'c', 'y', 11.0, 20.0], [8, 'c', 'z', 10.0, 21.0] ], columns=pd.Index(['Id', 'Column', 'Timestamp', 'some_field1', 'some_field2'], dtype='object')) ) def test_is_sorted(self): assert records.is_sorted() assert records.is_sorted(incl_id=True) assert not records_nosort.is_sorted() assert not records_nosort.is_sorted(incl_id=True) def test_sort(self): assert records.sort().is_sorted() assert records.sort().is_sorted(incl_id=True) assert records.sort(incl_id=True).is_sorted(incl_id=True) assert records_nosort.sort().is_sorted() assert records_nosort.sort().is_sorted(incl_id=True) assert records_nosort.sort(incl_id=True).is_sorted(incl_id=True) def test_apply_mask(self): mask_a = records['a'].values['some_field1'] >= records['a'].values['some_field1'].mean() record_arrays_close( records['a'].apply_mask(mask_a).values, np.array([ (1, 0, 1, 11., 20.), (2, 0, 2, 12., 19.) ], dtype=example_dt) ) mask = records.values['some_field1'] >= records.values['some_field1'].mean() filtered = records.apply_mask(mask) record_arrays_close( filtered.values, np.array([ (2, 0, 2, 12., 19.), (3, 1, 0, 13., 18.), (4, 1, 1, 14., 17.), (5, 1, 2, 13., 18.), (6, 2, 0, 12., 19.) ], dtype=example_dt) ) assert records_grouped.apply_mask(mask).wrapper == records_grouped.wrapper def test_map_field(self): np.testing.assert_array_equal( records['a'].map_field('some_field1').values, np.array([10., 11., 12.]) ) np.testing.assert_array_equal( records.map_field('some_field1').values, np.array([10., 11., 12., 13., 14., 13., 12., 11., 10.]) ) assert records_grouped.map_field('some_field1').wrapper == \ records.map_field('some_field1', group_by=group_by).wrapper assert records_grouped.map_field('some_field1', group_by=False).wrapper.grouper.group_by is None def test_map(self): @njit def map_func_nb(record): return record['some_field1'] + record['some_field2'] np.testing.assert_array_equal( records['a'].map(map_func_nb).values, np.array([31., 31., 31.]) ) np.testing.assert_array_equal( records.map(map_func_nb).values, np.array([31., 31., 31., 31., 31., 31., 31., 31., 31.]) ) assert records_grouped.map(map_func_nb).wrapper == \ records.map(map_func_nb, group_by=group_by).wrapper assert records_grouped.map(map_func_nb, group_by=False).wrapper.grouper.group_by is None def test_map_array(self): arr = records_arr['some_field1'] + records_arr['some_field2'] np.testing.assert_array_equal( records['a'].map_array(arr[:3]).values, np.array([31., 31., 31.]) ) np.testing.assert_array_equal( records.map_array(arr).values, np.array([31., 31., 31., 31., 31., 31., 31., 31., 31.]) ) assert records_grouped.map_array(arr).wrapper == \ records.map_array(arr, group_by=group_by).wrapper assert records_grouped.map_array(arr, group_by=False).wrapper.grouper.group_by is None def test_apply(self): @njit def cumsum_apply_nb(records): return np.cumsum(records['some_field1']) np.testing.assert_array_equal( records['a'].apply(cumsum_apply_nb).values, np.array([10., 21., 33.]) ) np.testing.assert_array_equal( records.apply(cumsum_apply_nb).values, np.array([10., 21., 33., 13., 27., 40., 12., 23., 33.]) ) np.testing.assert_array_equal( records_grouped.apply(cumsum_apply_nb, apply_per_group=False).values, np.array([10., 21., 33., 13., 27., 40., 12., 23., 33.]) ) np.testing.assert_array_equal( records_grouped.apply(cumsum_apply_nb, apply_per_group=True).values, np.array([10., 21., 33., 46., 60., 73., 12., 23., 33.]) ) assert records_grouped.apply(cumsum_apply_nb).wrapper == \ records.apply(cumsum_apply_nb, group_by=group_by).wrapper assert records_grouped.apply(cumsum_apply_nb, group_by=False).wrapper.grouper.group_by is None def test_count(self): assert records['a'].count() == 3 pd.testing.assert_series_equal( records.count(), pd.Series( np.array([3, 3, 3, 0]), index=wrapper.columns ).rename('count') ) assert records_grouped['g1'].count() == 6 pd.testing.assert_series_equal( records_grouped.count(), pd.Series( np.array([6, 3]), index=pd.Index(['g1', 'g2'], dtype='object') ).rename('count') ) @pytest.mark.parametrize( "test_nosort", [False, True], ) def test_indexing(self, test_nosort): if test_nosort: r = records_nosort r_grouped = records_nosort_grouped else: r = records r_grouped = records_grouped record_arrays_close( r['a'].values, np.array([ (0, 0, 0, 10., 21.), (1, 0, 1, 11., 20.), (2, 0, 2, 12., 19.) ], dtype=example_dt) ) pd.testing.assert_index_equal( r['a'].wrapper.columns, pd.Index(['a'], dtype='object') ) pd.testing.assert_index_equal( r['b'].wrapper.columns, pd.Index(['b'], dtype='object') ) record_arrays_close( r[['a', 'a']].values, np.array([ (0, 0, 0, 10., 21.), (1, 0, 1, 11., 20.), (2, 0, 2, 12., 19.), (0, 1, 0, 10., 21.), (1, 1, 1, 11., 20.), (2, 1, 2, 12., 19.) ], dtype=example_dt) ) pd.testing.assert_index_equal( r[['a', 'a']].wrapper.columns, pd.Index(['a', 'a'], dtype='object') ) record_arrays_close( r[['a', 'b']].values, np.array([ (0, 0, 0, 10., 21.), (1, 0, 1, 11., 20.), (2, 0, 2, 12., 19.), (3, 1, 0, 13., 18.), (4, 1, 1, 14., 17.), (5, 1, 2, 13., 18.) ], dtype=example_dt) ) pd.testing.assert_index_equal( r[['a', 'b']].wrapper.columns, pd.Index(['a', 'b'], dtype='object') ) with pytest.raises(Exception): _ = r.iloc[::2, :] # changing time not supported pd.testing.assert_index_equal( r_grouped['g1'].wrapper.columns, pd.Index(['a', 'b'], dtype='object') ) assert r_grouped['g1'].wrapper.ndim == 2 assert r_grouped['g1'].wrapper.grouped_ndim == 1 pd.testing.assert_index_equal( r_grouped['g1'].wrapper.grouper.group_by, pd.Index(['g1', 'g1'], dtype='object') ) pd.testing.assert_index_equal( r_grouped['g2'].wrapper.columns, pd.Index(['c', 'd'], dtype='object') ) assert r_grouped['g2'].wrapper.ndim == 2 assert r_grouped['g2'].wrapper.grouped_ndim == 1 pd.testing.assert_index_equal( r_grouped['g2'].wrapper.grouper.group_by, pd.Index(['g2', 'g2'], dtype='object') ) pd.testing.assert_index_equal( r_grouped[['g1']].wrapper.columns, pd.Index(['a', 'b'], dtype='object') ) assert r_grouped[['g1']].wrapper.ndim == 2 assert r_grouped[['g1']].wrapper.grouped_ndim == 2 pd.testing.assert_index_equal( r_grouped[['g1']].wrapper.grouper.group_by, pd.Index(['g1', 'g1'], dtype='object') ) pd.testing.assert_index_equal( r_grouped[['g1', 'g2']].wrapper.columns, pd.Index(['a', 'b', 'c', 'd'], dtype='object') ) assert r_grouped[['g1', 'g2']].wrapper.ndim == 2 assert r_grouped[['g1', 'g2']].wrapper.grouped_ndim == 2 pd.testing.assert_index_equal( r_grouped[['g1', 'g2']].wrapper.grouper.group_by, pd.Index(['g1', 'g1', 'g2', 'g2'], dtype='object') ) def test_filtering(self): filtered_records = vbt.Records(wrapper, records_arr[[0, -1]]) record_arrays_close( filtered_records.values, np.array([(0, 0, 0, 10., 21.), (8, 2, 2, 10., 21.)], dtype=example_dt) ) # a record_arrays_close( filtered_records['a'].values, np.array([(0, 0, 0, 10., 21.)], dtype=example_dt) ) np.testing.assert_array_equal( filtered_records['a'].map_field('some_field1').id_arr, np.array([0]) ) assert filtered_records['a'].map_field('some_field1').min() == 10. assert filtered_records['a'].count() == 1. # b record_arrays_close( filtered_records['b'].values, np.array([], dtype=example_dt) ) np.testing.assert_array_equal( filtered_records['b'].map_field('some_field1').id_arr, np.array([]) ) assert np.isnan(filtered_records['b'].map_field('some_field1').min()) assert filtered_records['b'].count() == 0. # c record_arrays_close( filtered_records['c'].values, np.array([(8, 0, 2, 10., 21.)], dtype=example_dt) ) np.testing.assert_array_equal( filtered_records['c'].map_field('some_field1').id_arr, np.array([8]) ) assert filtered_records['c'].map_field('some_field1').min() == 10. assert filtered_records['c'].count() == 1. # d record_arrays_close( filtered_records['d'].values, np.array([], dtype=example_dt) ) np.testing.assert_array_equal( filtered_records['d'].map_field('some_field1').id_arr, np.array([]) ) assert np.isnan(filtered_records['d'].map_field('some_field1').min()) assert filtered_records['d'].count() == 0. def test_stats(self): stats_index = pd.Index([ 'Start', 'End', 'Period', 'Count' ], dtype='object') pd.testing.assert_series_equal( records.stats(), pd.Series([ 'x', 'z', pd.Timedelta('3 days 00:00:00'), 2.25 ], index=stats_index, name='agg_func_mean' ) ) pd.testing.assert_series_equal( records.stats(column='a'), pd.Series([ 'x', 'z', pd.Timedelta('3 days 00:00:00'), 3 ], index=stats_index, name='a' ) ) pd.testing.assert_series_equal( records.stats(column='g1', group_by=group_by), pd.Series([ 'x', 'z', pd.Timedelta('3 days 00:00:00'), 6 ], index=stats_index, name='g1' ) ) pd.testing.assert_series_equal( records['c'].stats(), records.stats(column='c') ) pd.testing.assert_series_equal( records['c'].stats(), records.stats(column='c', group_by=False) ) pd.testing.assert_series_equal( records_grouped['g2'].stats(), records_grouped.stats(column='g2') ) pd.testing.assert_series_equal( records_grouped['g2'].stats(), records.stats(column='g2', group_by=group_by) ) stats_df = records.stats(agg_func=None) assert stats_df.shape == (4, 4) pd.testing.assert_index_equal(stats_df.index, records.wrapper.columns) pd.testing.assert_index_equal(stats_df.columns, stats_index) # ############# ranges.py ############# # ts = pd.DataFrame({ 'a': [1, -1, 3, -1, 5, -1], 'b': [-1, -1, -1, 4, 5, 6], 'c': [1, 2, 3, -1, -1, -1], 'd': [-1, -1, -1, -1, -1, -1] }, index=[ datetime(2020, 1, 1), datetime(2020, 1, 2), datetime(2020, 1, 3), datetime(2020, 1, 4), datetime(2020, 1, 5), datetime(2020, 1, 6) ]) ranges = vbt.Ranges.from_ts(ts, wrapper_kwargs=dict(freq='1 days')) ranges_grouped = vbt.Ranges.from_ts(ts, wrapper_kwargs=dict(freq='1 days', group_by=group_by)) class TestRanges: def test_mapped_fields(self): for name in range_dt.names: np.testing.assert_array_equal( getattr(ranges, name).values, ranges.values[name] ) def test_from_ts(self): record_arrays_close( ranges.values, np.array([ (0, 0, 0, 1, 1), (1, 0, 2, 3, 1), (2, 0, 4, 5, 1), (3, 1, 3, 5, 0), (4, 2, 0, 3, 1) ], dtype=range_dt) ) assert ranges.wrapper.freq == day_dt pd.testing.assert_index_equal( ranges_grouped.wrapper.grouper.group_by, group_by ) def test_records_readable(self): records_readable = ranges.records_readable np.testing.assert_array_equal( records_readable['Range Id'].values, np.array([ 0, 1, 2, 3, 4 ]) ) np.testing.assert_array_equal( records_readable['Column'].values, np.array([ 'a', 'a', 'a', 'b', 'c' ]) ) np.testing.assert_array_equal( records_readable['Start Timestamp'].values, np.array([ '2020-01-01T00:00:00.000000000', '2020-01-03T00:00:00.000000000', '2020-01-05T00:00:00.000000000', '2020-01-04T00:00:00.000000000', '2020-01-01T00:00:00.000000000' ], dtype='datetime64[ns]') ) np.testing.assert_array_equal( records_readable['End Timestamp'].values, np.array([ '2020-01-02T00:00:00.000000000', '2020-01-04T00:00:00.000000000', '2020-01-06T00:00:00.000000000', '2020-01-06T00:00:00.000000000', '2020-01-04T00:00:00.000000000' ], dtype='datetime64[ns]') ) np.testing.assert_array_equal( records_readable['Status'].values, np.array([ 'Closed', 'Closed', 'Closed', 'Open', 'Closed' ]) ) def test_to_mask(self): pd.testing.assert_series_equal( ranges['a'].to_mask(), ts['a'] != -1 ) pd.testing.assert_frame_equal( ranges.to_mask(), ts != -1 ) pd.testing.assert_frame_equal( ranges_grouped.to_mask(), pd.DataFrame( [ [True, True], [False, True], [True, True], [True, False], [True, False], [True, False] ], index=ts.index, columns=pd.Index(['g1', 'g2'], dtype='object') ) ) def test_duration(self): np.testing.assert_array_equal( ranges['a'].duration.values, np.array([1, 1, 1]) ) np.testing.assert_array_equal( ranges.duration.values, np.array([1, 1, 1, 3, 3]) ) def test_avg_duration(self): assert ranges['a'].avg_duration() == pd.Timedelta('1 days 00:00:00') pd.testing.assert_series_equal( ranges.avg_duration(), pd.Series( np.array([86400000000000, 259200000000000, 259200000000000, 'NaT'], dtype='timedelta64[ns]'), index=wrapper.columns ).rename('avg_duration') ) pd.testing.assert_series_equal( ranges_grouped.avg_duration(), pd.Series( np.array([129600000000000, 259200000000000], dtype='timedelta64[ns]'), index=pd.Index(['g1', 'g2'], dtype='object') ).rename('avg_duration') ) def test_max_duration(self): assert ranges['a'].max_duration() == pd.Timedelta('1 days 00:00:00') pd.testing.assert_series_equal( ranges.max_duration(), pd.Series( np.array([86400000000000, 259200000000000, 259200000000000, 'NaT'], dtype='timedelta64[ns]'), index=wrapper.columns ).rename('max_duration') ) pd.testing.assert_series_equal( ranges_grouped.max_duration(), pd.Series( np.array([259200000000000, 259200000000000], dtype='timedelta64[ns]'), index=pd.Index(['g1', 'g2'], dtype='object') ).rename('max_duration') ) def test_coverage(self): assert ranges['a'].coverage() == 0.5 pd.testing.assert_series_equal( ranges.coverage(), pd.Series( np.array([0.5, 0.5, 0.5, np.nan]), index=ts2.columns ).rename('coverage') ) pd.testing.assert_series_equal( ranges.coverage(), ranges.replace(records_arr=np.repeat(ranges.values, 2)).coverage() ) pd.testing.assert_series_equal( ranges.replace(records_arr=np.repeat(ranges.values, 2)).coverage(overlapping=True), pd.Series( np.array([1.0, 1.0, 1.0, np.nan]), index=ts2.columns ).rename('coverage') ) pd.testing.assert_series_equal( ranges.coverage(normalize=False), pd.Series( np.array([3.0, 3.0, 3.0, np.nan]), index=ts2.columns ).rename('coverage') ) pd.testing.assert_series_equal( ranges.replace(records_arr=np.repeat(ranges.values, 2)).coverage(overlapping=True, normalize=False), pd.Series( np.array([3.0, 3.0, 3.0, np.nan]), index=ts2.columns ).rename('coverage') ) pd.testing.assert_series_equal( ranges_grouped.coverage(), pd.Series( np.array([0.4166666666666667, 0.25]), index=pd.Index(['g1', 'g2'], dtype='object') ).rename('coverage') ) pd.testing.assert_series_equal( ranges_grouped.coverage(), ranges_grouped.replace(records_arr=np.repeat(ranges_grouped.values, 2)).coverage() ) def test_stats(self): stats_index = pd.Index([ 'Start', 'End', 'Period', 'Coverage', 'Overlap Coverage', 'Total Records', 'Duration: Min', 'Duration: Median', 'Duration: Max', 'Duration: Mean', 'Duration: Std' ], dtype='object') pd.testing.assert_series_equal( ranges.stats(), pd.Series([ pd.Timestamp('2020-01-01 00:00:00'), pd.Timestamp('2020-01-06 00:00:00'), pd.Timedelta('6 days 00:00:00'), pd.Timedelta('3 days 00:00:00'), pd.Timedelta('0 days 00:00:00'), 1.25, pd.Timedelta('2 days 08:00:00'), pd.Timedelta('2 days 08:00:00'), pd.Timedelta('2 days 08:00:00'), pd.Timedelta('2 days 08:00:00'), pd.Timedelta('0 days 00:00:00') ], index=stats_index, name='agg_func_mean' ) ) pd.testing.assert_series_equal( ranges.stats(column='a'), pd.Series([ pd.Timestamp('2020-01-01 00:00:00'), pd.Timestamp('2020-01-06 00:00:00'), pd.Timedelta('6 days 00:00:00'), pd.Timedelta('3 days 00:00:00'), pd.Timedelta('0 days 00:00:00'), 3, pd.Timedelta('1 days 00:00:00'), pd.Timedelta('1 days 00:00:00'), pd.Timedelta('1 days 00:00:00'), pd.Timedelta('1 days 00:00:00'), pd.Timedelta('0 days 00:00:00') ], index=stats_index, name='a' ) ) pd.testing.assert_series_equal( ranges.stats(column='g1', group_by=group_by), pd.Series([ pd.Timestamp('2020-01-01 00:00:00'), pd.Timestamp('2020-01-06 00:00:00'), pd.Timedelta('6 days 00:00:00'), pd.Timedelta('5 days 00:00:00'), pd.Timedelta('1 days 00:00:00'), 4, pd.Timedelta('1 days 00:00:00'), pd.Timedelta('1 days 00:00:00'), pd.Timedelta('3 days 00:00:00'), pd.Timedelta('1 days 12:00:00'), pd.Timedelta('1 days 00:00:00') ], index=stats_index, name='g1' ) ) pd.testing.assert_series_equal( ranges['c'].stats(), ranges.stats(column='c') ) pd.testing.assert_series_equal( ranges['c'].stats(), ranges.stats(column='c', group_by=False) ) pd.testing.assert_series_equal( ranges_grouped['g2'].stats(), ranges_grouped.stats(column='g2') ) pd.testing.assert_series_equal( ranges_grouped['g2'].stats(), ranges.stats(column='g2', group_by=group_by) ) stats_df = ranges.stats(agg_func=None) assert stats_df.shape == (4, 11) pd.testing.assert_index_equal(stats_df.index, ranges.wrapper.columns) pd.testing.assert_index_equal(stats_df.columns, stats_index) # ############# drawdowns.py ############# # ts2 = pd.DataFrame({ 'a': [2, 1, 3, 1, 4, 1], 'b': [1, 2, 1, 3, 1, 4], 'c': [1, 2, 3, 2, 1, 2], 'd': [1, 2, 3, 4, 5, 6] }, index=[ datetime(2020, 1, 1), datetime(2020, 1, 2), datetime(2020, 1, 3), datetime(2020, 1, 4), datetime(2020, 1, 5), datetime(2020, 1, 6) ]) drawdowns = vbt.Drawdowns.from_ts(ts2, wrapper_kwargs=dict(freq='1 days')) drawdowns_grouped = vbt.Drawdowns.from_ts(ts2, wrapper_kwargs=dict(freq='1 days', group_by=group_by)) class TestDrawdowns: def test_mapped_fields(self): for name in drawdown_dt.names: np.testing.assert_array_equal( getattr(drawdowns, name).values, drawdowns.values[name] ) def test_ts(self): pd.testing.assert_frame_equal( drawdowns.ts, ts2 ) pd.testing.assert_series_equal( drawdowns['a'].ts, ts2['a'] ) pd.testing.assert_frame_equal( drawdowns_grouped['g1'].ts, ts2[['a', 'b']] ) assert drawdowns.replace(ts=None)['a'].ts is None def test_from_ts(self): record_arrays_close( drawdowns.values, np.array([ (0, 0, 0, 1, 1, 2, 2.0, 1.0, 3.0, 1), (1, 0, 2, 3, 3, 4, 3.0, 1.0, 4.0, 1), (2, 0, 4, 5, 5, 5, 4.0, 1.0, 1.0, 0), (3, 1, 1, 2, 2, 3, 2.0, 1.0, 3.0, 1), (4, 1, 3, 4, 4, 5, 3.0, 1.0, 4.0, 1), (5, 2, 2, 3, 4, 5, 3.0, 1.0, 2.0, 0) ], dtype=drawdown_dt) ) assert drawdowns.wrapper.freq == day_dt pd.testing.assert_index_equal( drawdowns_grouped.wrapper.grouper.group_by, group_by ) def test_records_readable(self): records_readable = drawdowns.records_readable np.testing.assert_array_equal( records_readable['Drawdown Id'].values, np.array([ 0, 1, 2, 3, 4, 5 ]) ) np.testing.assert_array_equal( records_readable['Column'].values, np.array([ 'a', 'a', 'a', 'b', 'b', 'c' ]) ) np.testing.assert_array_equal( records_readable['Peak Timestamp'].values, np.array([ '2020-01-01T00:00:00.000000000', '2020-01-03T00:00:00.000000000', '2020-01-05T00:00:00.000000000', '2020-01-02T00:00:00.000000000', '2020-01-04T00:00:00.000000000', '2020-01-03T00:00:00.000000000' ], dtype='datetime64[ns]') ) np.testing.assert_array_equal( records_readable['Start Timestamp'].values, np.array([ '2020-01-02T00:00:00.000000000', '2020-01-04T00:00:00.000000000', '2020-01-06T00:00:00.000000000', '2020-01-03T00:00:00.000000000', '2020-01-05T00:00:00.000000000', '2020-01-04T00:00:00.000000000' ], dtype='datetime64[ns]') ) np.testing.assert_array_equal( records_readable['Valley Timestamp'].values, np.array([ '2020-01-02T00:00:00.000000000', '2020-01-04T00:00:00.000000000', '2020-01-06T00:00:00.000000000', '2020-01-03T00:00:00.000000000', '2020-01-05T00:00:00.000000000', '2020-01-05T00:00:00.000000000' ], dtype='datetime64[ns]') ) np.testing.assert_array_equal( records_readable['End Timestamp'].values, np.array([ '2020-01-03T00:00:00.000000000', '2020-01-05T00:00:00.000000000', '2020-01-06T00:00:00.000000000', '2020-01-04T00:00:00.000000000', '2020-01-06T00:00:00.000000000', '2020-01-06T00:00:00.000000000' ], dtype='datetime64[ns]') ) np.testing.assert_array_equal( records_readable['Peak Value'].values, np.array([ 2., 3., 4., 2., 3., 3. ]) ) np.testing.assert_array_equal( records_readable['Valley Value'].values, np.array([ 1., 1., 1., 1., 1., 1. ]) ) np.testing.assert_array_equal( records_readable['End Value'].values, np.array([ 3., 4., 1., 3., 4., 2. ]) ) np.testing.assert_array_equal( records_readable['Status'].values, np.array([ 'Recovered', 'Recovered', 'Active', 'Recovered', 'Recovered', 'Active' ]) ) def test_drawdown(self): np.testing.assert_array_almost_equal( drawdowns['a'].drawdown.values, np.array([-0.5, -0.66666667, -0.75]) ) np.testing.assert_array_almost_equal( drawdowns.drawdown.values, np.array([-0.5, -0.66666667, -0.75, -0.5, -0.66666667, -0.66666667]) ) pd.testing.assert_frame_equal( drawdowns.drawdown.to_pd(), pd.DataFrame( np.array([ [np.nan, np.nan, np.nan, np.nan], [np.nan, np.nan, np.nan, np.nan], [-0.5, np.nan, np.nan, np.nan], [np.nan, -0.5, np.nan, np.nan], [-0.66666669, np.nan, np.nan, np.nan], [-0.75, -0.66666669, -0.66666669, np.nan] ]), index=ts2.index, columns=ts2.columns ) ) def test_avg_drawdown(self): assert drawdowns['a'].avg_drawdown() == -0.6388888888888888 pd.testing.assert_series_equal( drawdowns.avg_drawdown(), pd.Series( np.array([-0.63888889, -0.58333333, -0.66666667, np.nan]), index=wrapper.columns ).rename('avg_drawdown') ) pd.testing.assert_series_equal( drawdowns_grouped.avg_drawdown(), pd.Series( np.array([-0.6166666666666666, -0.6666666666666666]), index=pd.Index(['g1', 'g2'], dtype='object') ).rename('avg_drawdown') ) def test_max_drawdown(self): assert drawdowns['a'].max_drawdown() == -0.75 pd.testing.assert_series_equal( drawdowns.max_drawdown(), pd.Series( np.array([-0.75, -0.66666667, -0.66666667, np.nan]), index=wrapper.columns ).rename('max_drawdown') ) pd.testing.assert_series_equal( drawdowns_grouped.max_drawdown(), pd.Series( np.array([-0.75, -0.6666666666666666]), index=pd.Index(['g1', 'g2'], dtype='object') ).rename('max_drawdown') ) def test_recovery_return(self): np.testing.assert_array_almost_equal( drawdowns['a'].recovery_return.values, np.array([2., 3., 0.]) ) np.testing.assert_array_almost_equal( drawdowns.recovery_return.values, np.array([2., 3., 0., 2., 3., 1.]) ) pd.testing.assert_frame_equal( drawdowns.recovery_return.to_pd(), pd.DataFrame( np.array([ [np.nan, np.nan, np.nan, np.nan], [np.nan, np.nan, np.nan, np.nan], [2.0, np.nan, np.nan, np.nan], [np.nan, 2.0, np.nan, np.nan], [3.0, np.nan, np.nan, np.nan], [0.0, 3.0, 1.0, np.nan] ]), index=ts2.index, columns=ts2.columns ) ) def test_avg_recovery_return(self): assert drawdowns['a'].avg_recovery_return() == 1.6666666666666667 pd.testing.assert_series_equal( drawdowns.avg_recovery_return(), pd.Series( np.array([1.6666666666666667, 2.5, 1.0, np.nan]), index=wrapper.columns ).rename('avg_recovery_return') ) pd.testing.assert_series_equal( drawdowns_grouped.avg_recovery_return(), pd.Series( np.array([2.0, 1.0]), index=pd.Index(['g1', 'g2'], dtype='object') ).rename('avg_recovery_return') ) def test_max_recovery_return(self): assert drawdowns['a'].max_recovery_return() == 3.0 pd.testing.assert_series_equal( drawdowns.max_recovery_return(), pd.Series( np.array([3.0, 3.0, 1.0, np.nan]), index=wrapper.columns ).rename('max_recovery_return') ) pd.testing.assert_series_equal( drawdowns_grouped.max_recovery_return(), pd.Series( np.array([3.0, 1.0]), index=pd.Index(['g1', 'g2'], dtype='object') ).rename('max_recovery_return') ) def test_duration(self): np.testing.assert_array_almost_equal( drawdowns['a'].duration.values, np.array([1, 1, 1]) ) np.testing.assert_array_almost_equal( drawdowns.duration.values, np.array([1, 1, 1, 1, 1, 3]) ) def test_avg_duration(self): assert drawdowns['a'].avg_duration() == pd.Timedelta('1 days 00:00:00') pd.testing.assert_series_equal( drawdowns.avg_duration(), pd.Series( np.array([86400000000000, 86400000000000, 259200000000000, 'NaT'], dtype='timedelta64[ns]'), index=wrapper.columns ).rename('avg_duration') ) pd.testing.assert_series_equal( drawdowns_grouped.avg_duration(), pd.Series( np.array([86400000000000, 259200000000000], dtype='timedelta64[ns]'), index=pd.Index(['g1', 'g2'], dtype='object') ).rename('avg_duration') ) def test_max_duration(self): assert drawdowns['a'].max_duration() == pd.Timedelta('1 days 00:00:00') pd.testing.assert_series_equal( drawdowns.max_duration(), pd.Series( np.array([86400000000000, 86400000000000, 259200000000000, 'NaT'], dtype='timedelta64[ns]'), index=wrapper.columns ).rename('max_duration') ) pd.testing.assert_series_equal( drawdowns_grouped.max_duration(), pd.Series( np.array([86400000000000, 259200000000000], dtype='timedelta64[ns]'), index=pd.Index(['g1', 'g2'], dtype='object') ).rename('max_duration') ) def test_coverage(self): assert drawdowns['a'].coverage() == 0.5 pd.testing.assert_series_equal( drawdowns.coverage(), pd.Series( np.array([0.5, 0.3333333333333333, 0.5, np.nan]), index=ts2.columns ).rename('coverage') ) pd.testing.assert_series_equal( drawdowns_grouped.coverage(), pd.Series( np.array([0.4166666666666667, 0.25]), index=pd.Index(['g1', 'g2'], dtype='object') ).rename('coverage') ) def test_decline_duration(self): np.testing.assert_array_almost_equal( drawdowns['a'].decline_duration.values, np.array([1., 1., 1.]) ) np.testing.assert_array_almost_equal( drawdowns.decline_duration.values, np.array([1., 1., 1., 1., 1., 2.]) ) def test_recovery_duration(self): np.testing.assert_array_almost_equal( drawdowns['a'].recovery_duration.values, np.array([1, 1, 0]) ) np.testing.assert_array_almost_equal( drawdowns.recovery_duration.values, np.array([1, 1, 0, 1, 1, 1]) ) def test_recovery_duration_ratio(self): np.testing.assert_array_almost_equal( drawdowns['a'].recovery_duration_ratio.values, np.array([1., 1., 0.]) ) np.testing.assert_array_almost_equal( drawdowns.recovery_duration_ratio.values, np.array([1., 1., 0., 1., 1., 0.5]) ) def test_active_records(self): assert isinstance(drawdowns.active, vbt.Drawdowns) assert drawdowns.active.wrapper == drawdowns.wrapper record_arrays_close( drawdowns['a'].active.values, np.array([ (2, 0, 4, 5, 5, 5, 4., 1., 1., 0) ], dtype=drawdown_dt) ) record_arrays_close( drawdowns['a'].active.values, drawdowns.active['a'].values ) record_arrays_close( drawdowns.active.values, np.array([ (2, 0, 4, 5, 5, 5, 4.0, 1.0, 1.0, 0), (5, 2, 2, 3, 4, 5, 3.0, 1.0, 2.0, 0) ], dtype=drawdown_dt) ) def test_recovered_records(self): assert isinstance(drawdowns.recovered, vbt.Drawdowns) assert drawdowns.recovered.wrapper == drawdowns.wrapper record_arrays_close( drawdowns['a'].recovered.values, np.array([ (0, 0, 0, 1, 1, 2, 2.0, 1.0, 3.0, 1), (1, 0, 2, 3, 3, 4, 3.0, 1.0, 4.0, 1) ], dtype=drawdown_dt) ) record_arrays_close( drawdowns['a'].recovered.values, drawdowns.recovered['a'].values ) record_arrays_close( drawdowns.recovered.values, np.array([ (0, 0, 0, 1, 1, 2, 2.0, 1.0, 3.0, 1), (1, 0, 2, 3, 3, 4, 3.0, 1.0, 4.0, 1), (3, 1, 1, 2, 2, 3, 2.0, 1.0, 3.0, 1), (4, 1, 3, 4, 4, 5, 3.0, 1.0, 4.0, 1) ], dtype=drawdown_dt) ) def test_active_drawdown(self): assert drawdowns['a'].active_drawdown() == -0.75 pd.testing.assert_series_equal( drawdowns.active_drawdown(), pd.Series( np.array([-0.75, np.nan, -0.3333333333333333, np.nan]), index=wrapper.columns ).rename('active_drawdown') ) with pytest.raises(Exception): drawdowns_grouped.active_drawdown() def test_active_duration(self): assert drawdowns['a'].active_duration() == np.timedelta64(86400000000000) pd.testing.assert_series_equal( drawdowns.active_duration(), pd.Series( np.array([86400000000000, 'NaT', 259200000000000, 'NaT'], dtype='timedelta64[ns]'), index=wrapper.columns ).rename('active_duration') ) with pytest.raises(Exception): drawdowns_grouped.active_duration() def test_active_recovery(self): assert drawdowns['a'].active_recovery() == 0. pd.testing.assert_series_equal( drawdowns.active_recovery(), pd.Series( np.array([0., np.nan, 0.5, np.nan]), index=wrapper.columns ).rename('active_recovery') ) with pytest.raises(Exception): drawdowns_grouped.active_recovery() def test_active_recovery_return(self): assert drawdowns['a'].active_recovery_return() == 0. pd.testing.assert_series_equal( drawdowns.active_recovery_return(), pd.Series( np.array([0., np.nan, 1., np.nan]), index=wrapper.columns ).rename('active_recovery_return') ) with pytest.raises(Exception): drawdowns_grouped.active_recovery_return() def test_active_recovery_duration(self): assert drawdowns['a'].active_recovery_duration() == pd.Timedelta('0 days 00:00:00') pd.testing.assert_series_equal( drawdowns.active_recovery_duration(), pd.Series( np.array([0, 'NaT', 86400000000000, 'NaT'], dtype='timedelta64[ns]'), index=wrapper.columns ).rename('active_recovery_duration') ) with pytest.raises(Exception): drawdowns_grouped.active_recovery_duration() def test_stats(self): stats_index = pd.Index([ 'Start', 'End', 'Period', 'Coverage [%]', 'Total Records', 'Total Recovered Drawdowns', 'Total Active Drawdowns', 'Active Drawdown [%]', 'Active Duration', 'Active Recovery [%]', 'Active Recovery Return [%]', 'Active Recovery Duration', 'Max Drawdown [%]', 'Avg Drawdown [%]', 'Max Drawdown Duration', 'Avg Drawdown Duration', 'Max Recovery Return [%]', 'Avg Recovery Return [%]', 'Max Recovery Duration', 'Avg Recovery Duration', 'Avg Recovery Duration Ratio' ], dtype='object') pd.testing.assert_series_equal( drawdowns.stats(), pd.Series([ pd.Timestamp('2020-01-01 00:00:00'), pd.Timestamp('2020-01-06 00:00:00'), pd.Timedelta('6 days 00:00:00'), 44.444444444444436, 1.5, 1.0, 0.5, 54.166666666666664, pd.Timedelta('2 days 00:00:00'), 25.0, 50.0, pd.Timedelta('0 days 12:00:00'), 66.66666666666666, 58.33333333333333, pd.Timedelta('1 days 00:00:00'), pd.Timedelta('1 days 00:00:00'), 300.0, 250.0, pd.Timedelta('1 days 00:00:00'), pd.Timedelta('1 days 00:00:00'), 1.0 ], index=stats_index, name='agg_func_mean' ) ) pd.testing.assert_series_equal( drawdowns.stats(settings=dict(incl_active=True)), pd.Series([ pd.Timestamp('2020-01-01 00:00:00'), pd.Timestamp('2020-01-06 00:00:00'), pd.Timedelta('6 days 00:00:00'), 44.444444444444436, 1.5, 1.0, 0.5, 54.166666666666664, pd.Timedelta('2 days 00:00:00'), 25.0, 50.0, pd.Timedelta('0 days 12:00:00'), 69.44444444444444, 62.962962962962955, pd.Timedelta('1 days 16:00:00'), pd.Timedelta('1 days 16:00:00'), 300.0, 250.0, pd.Timedelta('1 days 00:00:00'), pd.Timedelta('1 days 00:00:00'), 1.0 ], index=stats_index, name='agg_func_mean' ) ) pd.testing.assert_series_equal( drawdowns.stats(column='a'), pd.Series([ pd.Timestamp('2020-01-01 00:00:00'), pd.Timestamp('2020-01-06 00:00:00'), pd.Timedelta('6 days 00:00:00'), 50.0, 3, 2, 1, 75.0, pd.Timedelta('1 days 00:00:00'), 0.0, 0.0, pd.Timedelta('0 days 00:00:00'), 66.66666666666666, 58.33333333333333, pd.Timedelta('1 days 00:00:00'), pd.Timedelta('1 days 00:00:00'), 300.0, 250.0, pd.Timedelta('1 days 00:00:00'), pd.Timedelta('1 days 00:00:00'), 1.0 ], index=stats_index, name='a' ) ) pd.testing.assert_series_equal( drawdowns.stats(column='g1', group_by=group_by), pd.Series([ pd.Timestamp('2020-01-01 00:00:00'), pd.Timestamp('2020-01-06 00:00:00'), pd.Timedelta('6 days 00:00:00'), 41.66666666666667, 5, 4, 1, 66.66666666666666, 58.33333333333333, pd.Timedelta('1 days 00:00:00'), pd.Timedelta('1 days 00:00:00'), 300.0, 250.0, pd.Timedelta('1 days 00:00:00'), pd.Timedelta('1 days 00:00:00'), 1.0 ], index=pd.Index([ 'Start', 'End', 'Period', 'Coverage [%]', 'Total Records', 'Total Recovered Drawdowns', 'Total Active Drawdowns', 'Max Drawdown [%]', 'Avg Drawdown [%]', 'Max Drawdown Duration', 'Avg Drawdown Duration', 'Max Recovery Return [%]', 'Avg Recovery Return [%]', 'Max Recovery Duration', 'Avg Recovery Duration', 'Avg Recovery Duration Ratio' ], dtype='object'), name='g1' ) ) pd.testing.assert_series_equal( drawdowns['c'].stats(), drawdowns.stats(column='c') ) pd.testing.assert_series_equal( drawdowns['c'].stats(), drawdowns.stats(column='c', group_by=False) ) pd.testing.assert_series_equal( drawdowns_grouped['g2'].stats(), drawdowns_grouped.stats(column='g2') ) pd.testing.assert_series_equal( drawdowns_grouped['g2'].stats(), drawdowns.stats(column='g2', group_by=group_by) ) stats_df = drawdowns.stats(agg_func=None) assert stats_df.shape == (4, 21) pd.testing.assert_index_equal(stats_df.index, drawdowns.wrapper.columns) pd.testing.assert_index_equal(stats_df.columns, stats_index) # ############# orders.py ############# # close = pd.Series([1, 2, 3, 4, 5, 6, 7, 8], index=[ datetime(2020, 1, 1), datetime(2020, 1, 2), datetime(2020, 1, 3), datetime(2020, 1, 4), datetime(2020, 1, 5), datetime(2020, 1, 6), datetime(2020, 1, 7), datetime(2020, 1, 8) ]).vbt.tile(4, keys=['a', 'b', 'c', 'd']) size = np.full(close.shape, np.nan, dtype=np.float64) size[:, 0] = [1, 0.1, -1, -0.1, np.nan, 1, -1, 2] size[:, 1] = [-1, -0.1, 1, 0.1, np.nan, -1, 1, -2] size[:, 2] = [1, 0.1, -1, -0.1, np.nan, 1, -2, 2] orders = vbt.Portfolio.from_orders(close, size, fees=0.01, freq='1 days').orders orders_grouped = orders.regroup(group_by) class TestOrders: def test_mapped_fields(self): for name in order_dt.names: np.testing.assert_array_equal( getattr(orders, name).values, orders.values[name] ) def test_close(self): pd.testing.assert_frame_equal( orders.close, close ) pd.testing.assert_series_equal( orders['a'].close, close['a'] ) pd.testing.assert_frame_equal( orders_grouped['g1'].close, close[['a', 'b']] ) assert orders.replace(close=None)['a'].close is None def test_records_readable(self): records_readable = orders.records_readable np.testing.assert_array_equal( records_readable['Order Id'].values, np.array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 ]) ) np.testing.assert_array_equal( records_readable['Timestamp'].values, np.array([ '2020-01-01T00:00:00.000000000', '2020-01-02T00:00:00.000000000', '2020-01-03T00:00:00.000000000', '2020-01-04T00:00:00.000000000', '2020-01-06T00:00:00.000000000', '2020-01-07T00:00:00.000000000', '2020-01-08T00:00:00.000000000', '2020-01-01T00:00:00.000000000', '2020-01-02T00:00:00.000000000', '2020-01-03T00:00:00.000000000', '2020-01-04T00:00:00.000000000', '2020-01-06T00:00:00.000000000', '2020-01-07T00:00:00.000000000', '2020-01-08T00:00:00.000000000', '2020-01-01T00:00:00.000000000', '2020-01-02T00:00:00.000000000', '2020-01-03T00:00:00.000000000', '2020-01-04T00:00:00.000000000', '2020-01-06T00:00:00.000000000', '2020-01-07T00:00:00.000000000', '2020-01-08T00:00:00.000000000' ], dtype='datetime64[ns]') ) np.testing.assert_array_equal( records_readable['Column'].values, np.array([ 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'c', 'c', 'c', 'c' ]) ) np.testing.assert_array_equal( records_readable['Size'].values, np.array([ 1.0, 0.1, 1.0, 0.1, 1.0, 1.0, 2.0, 1.0, 0.1, 1.0, 0.1, 1.0, 1.0, 2.0, 1.0, 0.1, 1.0, 0.1, 1.0, 2.0, 2.0 ]) ) np.testing.assert_array_equal( records_readable['Price'].values, np.array([ 1.0, 2.0, 3.0, 4.0, 6.0, 7.0, 8.0, 1.0, 2.0, 3.0, 4.0, 6.0, 7.0, 8.0, 1.0, 2.0, 3.0, 4.0, 6.0, 7.0, 8.0 ]) ) np.testing.assert_array_equal( records_readable['Fees'].values, np.array([ 0.01, 0.002, 0.03, 0.004, 0.06, 0.07, 0.16, 0.01, 0.002, 0.03, 0.004, 0.06, 0.07, 0.16, 0.01, 0.002, 0.03, 0.004, 0.06, 0.14, 0.16 ]) ) np.testing.assert_array_equal( records_readable['Side'].values, np.array([ 'Buy', 'Buy', 'Sell', 'Sell', 'Buy', 'Sell', 'Buy', 'Sell', 'Sell', 'Buy', 'Buy', 'Sell', 'Buy', 'Sell', 'Buy', 'Buy', 'Sell', 'Sell', 'Buy', 'Sell', 'Buy' ]) ) def test_buy_records(self): assert isinstance(orders.buy, vbt.Orders) assert orders.buy.wrapper == orders.wrapper record_arrays_close( orders['a'].buy.values, np.array([ (0, 0, 0, 1., 1., 0.01, 0), (1, 0, 1, 0.1, 2., 0.002, 0), (4, 0, 5, 1., 6., 0.06, 0), (6, 0, 7, 2., 8., 0.16, 0) ], dtype=order_dt) ) record_arrays_close( orders['a'].buy.values, orders.buy['a'].values ) record_arrays_close( orders.buy.values, np.array([ (0, 0, 0, 1., 1., 0.01, 0), (1, 0, 1, 0.1, 2., 0.002, 0), (4, 0, 5, 1., 6., 0.06, 0), (6, 0, 7, 2., 8., 0.16, 0), (9, 1, 2, 1., 3., 0.03, 0), (10, 1, 3, 0.1, 4., 0.004, 0), (12, 1, 6, 1., 7., 0.07, 0), (14, 2, 0, 1., 1., 0.01, 0), (15, 2, 1, 0.1, 2., 0.002, 0), (18, 2, 5, 1., 6., 0.06, 0), (20, 2, 7, 2., 8., 0.16, 0) ], dtype=order_dt) ) def test_sell_records(self): assert isinstance(orders.sell, vbt.Orders) assert orders.sell.wrapper == orders.wrapper record_arrays_close( orders['a'].sell.values, np.array([ (2, 0, 2, 1., 3., 0.03, 1), (3, 0, 3, 0.1, 4., 0.004, 1), (5, 0, 6, 1., 7., 0.07, 1) ], dtype=order_dt) ) record_arrays_close( orders['a'].sell.values, orders.sell['a'].values ) record_arrays_close( orders.sell.values, np.array([ (2, 0, 2, 1., 3., 0.03, 1), (3, 0, 3, 0.1, 4., 0.004, 1), (5, 0, 6, 1., 7., 0.07, 1), (7, 1, 0, 1., 1., 0.01, 1), (8, 1, 1, 0.1, 2., 0.002, 1), (11, 1, 5, 1., 6., 0.06, 1), (13, 1, 7, 2., 8., 0.16, 1), (16, 2, 2, 1., 3., 0.03, 1), (17, 2, 3, 0.1, 4., 0.004, 1), (19, 2, 6, 2., 7., 0.14, 1) ], dtype=order_dt) ) def test_stats(self): stats_index = pd.Index([ 'Start', 'End', 'Period', 'Total Records', 'Total Buy Orders', 'Total Sell Orders', 'Min Size', 'Max Size', 'Avg Size', 'Avg Buy Size', 'Avg Sell Size', 'Avg Buy Price', 'Avg Sell Price', 'Total Fees', 'Min Fees', 'Max Fees', 'Avg Fees', 'Avg Buy Fees', 'Avg Sell Fees' ], dtype='object') pd.testing.assert_series_equal( orders.stats(), pd.Series([ pd.Timestamp('2020-01-01 00:00:00'), pd.Timestamp('2020-01-08 00:00:00'), pd.Timedelta('8 days 00:00:00'), 5.25, 2.75, 2.5, 0.10000000000000002, 2.0, 0.9333333333333335, 0.9166666666666666, 0.9194444444444446, 4.388888888888889, 4.527777777777779, 0.26949999999999996, 0.002, 0.16, 0.051333333333333335, 0.050222222222222224, 0.050222222222222224 ], index=stats_index, name='agg_func_mean' ) ) pd.testing.assert_series_equal( orders.stats(column='a'), pd.Series([ pd.Timestamp('2020-01-01 00:00:00'), pd.Timestamp('2020-01-08 00:00:00'), pd.Timedelta('8 days 00:00:00'), 7, 4, 3, 0.1, 2.0, 0.8857142857142858, 1.025, 0.7000000000000001, 4.25, 4.666666666666667, 0.33599999999999997, 0.002, 0.16, 0.047999999999999994, 0.057999999999999996, 0.03466666666666667 ], index=stats_index, name='a' ) ) pd.testing.assert_series_equal( orders.stats(column='g1', group_by=group_by), pd.Series([ pd.Timestamp('2020-01-01 00:00:00'), pd.Timestamp('2020-01-08 00:00:00'), pd.Timedelta('8 days 00:00:00'), 14, 7, 7, 0.1, 2.0, 0.8857142857142858, 0.8857142857142856, 0.8857142857142858, 4.428571428571429, 4.428571428571429, 0.672, 0.002, 0.16, 0.048, 0.048, 0.047999999999999994 ], index=stats_index, name='g1' ) ) pd.testing.assert_series_equal( orders['c'].stats(), orders.stats(column='c') ) pd.testing.assert_series_equal( orders['c'].stats(), orders.stats(column='c', group_by=False) ) pd.testing.assert_series_equal( orders_grouped['g2'].stats(), orders_grouped.stats(column='g2') ) pd.testing.assert_series_equal( orders_grouped['g2'].stats(), orders.stats(column='g2', group_by=group_by) ) stats_df = orders.stats(agg_func=None) assert stats_df.shape == (4, 19) pd.testing.assert_index_equal(stats_df.index, orders.wrapper.columns) pd.testing.assert_index_equal(stats_df.columns, stats_index) # ############# trades.py ############# # exit_trades = vbt.ExitTrades.from_orders(orders) exit_trades_grouped = vbt.ExitTrades.from_orders(orders_grouped) class TestExitTrades: def test_mapped_fields(self): for name in trade_dt.names: if name == 'return': np.testing.assert_array_equal( getattr(exit_trades, 'returns').values, exit_trades.values[name] ) else: np.testing.assert_array_equal( getattr(exit_trades, name).values, exit_trades.values[name] ) def test_close(self): pd.testing.assert_frame_equal( exit_trades.close, close ) pd.testing.assert_series_equal( exit_trades['a'].close, close['a'] ) pd.testing.assert_frame_equal( exit_trades_grouped['g1'].close, close[['a', 'b']] ) assert exit_trades.replace(close=None)['a'].close is None def test_records_arr(self): record_arrays_close( exit_trades.values, np.array([ (0, 0, 1., 0, 1.09090909, 0.01090909, 2, 3., 0.03, 1.86818182, 1.7125, 0, 1, 0), (1, 0, 0.1, 0, 1.09090909, 0.00109091, 3, 4., 0.004, 0.28581818, 2.62, 0, 1, 0), (2, 0, 1., 5, 6., 0.06, 6, 7., 0.07, 0.87, 0.145, 0, 1, 1), (3, 0, 2., 7, 8., 0.16, 7, 8., 0., -0.16, -0.01, 0, 0, 2), (4, 1, 1., 0, 1.09090909, 0.01090909, 2, 3., 0.03, -1.95, -1.7875, 1, 1, 3), (5, 1, 0.1, 0, 1.09090909, 0.00109091, 3, 4., 0.004, -0.296, -2.71333333, 1, 1, 3), (6, 1, 1., 5, 6., 0.06, 6, 7., 0.07, -1.13, -0.18833333, 1, 1, 4), (7, 1, 2., 7, 8., 0.16, 7, 8., 0., -0.16, -0.01, 1, 0, 5), (8, 2, 1., 0, 1.09090909, 0.01090909, 2, 3., 0.03, 1.86818182, 1.7125, 0, 1, 6), (9, 2, 0.1, 0, 1.09090909, 0.00109091, 3, 4., 0.004, 0.28581818, 2.62, 0, 1, 6), (10, 2, 1., 5, 6., 0.06, 6, 7., 0.07, 0.87, 0.145, 0, 1, 7), (11, 2, 1., 6, 7., 0.07, 7, 8., 0.08, -1.15, -0.16428571, 1, 1, 8), (12, 2, 1., 7, 8., 0.08, 7, 8., 0., -0.08, -0.01, 0, 0, 9) ], dtype=trade_dt) ) reversed_col_orders = orders.replace(records_arr=np.concatenate(( orders.values[orders.values['col'] == 2], orders.values[orders.values['col'] == 1], orders.values[orders.values['col'] == 0] ))) record_arrays_close( vbt.ExitTrades.from_orders(reversed_col_orders).values, exit_trades.values ) def test_records_readable(self): records_readable = exit_trades.records_readable np.testing.assert_array_equal( records_readable['Exit Trade Id'].values, np.array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]) ) np.testing.assert_array_equal( records_readable['Column'].values, np.array([ 'a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'c', 'c' ]) ) np.testing.assert_array_equal( records_readable['Size'].values, np.array([ 1.0, 0.10000000000000009, 1.0, 2.0, 1.0, 0.10000000000000009, 1.0, 2.0, 1.0, 0.10000000000000009, 1.0, 1.0, 1.0 ]) ) np.testing.assert_array_equal( records_readable['Entry Timestamp'].values, np.array([ '2020-01-01T00:00:00.000000000', '2020-01-01T00:00:00.000000000', '2020-01-06T00:00:00.000000000', '2020-01-08T00:00:00.000000000', '2020-01-01T00:00:00.000000000', '2020-01-01T00:00:00.000000000', '2020-01-06T00:00:00.000000000', '2020-01-08T00:00:00.000000000', '2020-01-01T00:00:00.000000000', '2020-01-01T00:00:00.000000000', '2020-01-06T00:00:00.000000000', '2020-01-07T00:00:00.000000000', '2020-01-08T00:00:00.000000000' ], dtype='datetime64[ns]') ) np.testing.assert_array_equal( records_readable['Avg Entry Price'].values, np.array([ 1.0909090909090908, 1.0909090909090908, 6.0, 8.0, 1.0909090909090908, 1.0909090909090908, 6.0, 8.0, 1.0909090909090908, 1.0909090909090908, 6.0, 7.0, 8.0 ]) ) np.testing.assert_array_equal( records_readable['Entry Fees'].values, np.array([ 0.010909090909090908, 0.0010909090909090918, 0.06, 0.16, 0.010909090909090908, 0.0010909090909090918, 0.06, 0.16, 0.010909090909090908, 0.0010909090909090918, 0.06, 0.07, 0.08 ]) ) np.testing.assert_array_equal( records_readable['Exit Timestamp'].values, np.array([ '2020-01-03T00:00:00.000000000', '2020-01-04T00:00:00.000000000', '2020-01-07T00:00:00.000000000', '2020-01-08T00:00:00.000000000', '2020-01-03T00:00:00.000000000', '2020-01-04T00:00:00.000000000', '2020-01-07T00:00:00.000000000', '2020-01-08T00:00:00.000000000', '2020-01-03T00:00:00.000000000', '2020-01-04T00:00:00.000000000', '2020-01-07T00:00:00.000000000', '2020-01-08T00:00:00.000000000', '2020-01-08T00:00:00.000000000' ], dtype='datetime64[ns]') ) np.testing.assert_array_equal( records_readable['Avg Exit Price'].values, np.array([ 3.0, 4.0, 7.0, 8.0, 3.0, 4.0, 7.0, 8.0, 3.0, 4.0, 7.0, 8.0, 8.0 ]) ) np.testing.assert_array_equal( records_readable['Exit Fees'].values, np.array([ 0.03, 0.004, 0.07, 0.0, 0.03, 0.004, 0.07, 0.0, 0.03, 0.004, 0.07, 0.08, 0.0 ]) ) np.testing.assert_array_equal( records_readable['PnL'].values, np.array([ 1.8681818181818182, 0.2858181818181821, 0.8699999999999999, -0.16, -1.9500000000000002, -0.29600000000000026, -1.1300000000000001, -0.16, 1.8681818181818182, 0.2858181818181821, 0.8699999999999999, -1.1500000000000001, -0.08 ]) ) np.testing.assert_array_equal( records_readable['Return'].values, np.array([ 1.7125000000000001, 2.62, 0.145, -0.01, -1.7875000000000003, -2.7133333333333334, -0.18833333333333335, -0.01, 1.7125000000000001, 2.62, 0.145, -0.1642857142857143, -0.01 ]) ) np.testing.assert_array_equal( records_readable['Direction'].values, np.array([ 'Long', 'Long', 'Long', 'Long', 'Short', 'Short', 'Short', 'Short', 'Long', 'Long', 'Long', 'Short', 'Long' ]) ) np.testing.assert_array_equal( records_readable['Status'].values, np.array([ 'Closed', 'Closed', 'Closed', 'Open', 'Closed', 'Closed', 'Closed', 'Open', 'Closed', 'Closed', 'Closed', 'Closed', 'Open' ]) ) np.testing.assert_array_equal( records_readable['Position Id'].values, np.array([ 0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9 ]) ) def test_duration(self): np.testing.assert_array_almost_equal( exit_trades['a'].duration.values, np.array([2, 3, 1, 1]) ) np.testing.assert_array_almost_equal( exit_trades.duration.values, np.array([2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1, 1, 1]) ) def test_winning_records(self): assert isinstance(exit_trades.winning, vbt.ExitTrades) assert exit_trades.winning.wrapper == exit_trades.wrapper record_arrays_close( exit_trades['a'].winning.values, np.array([ (0, 0, 1., 0, 1.09090909, 0.01090909, 2, 3., 0.03, 1.86818182, 1.7125, 0, 1, 0), (1, 0, 0.1, 0, 1.09090909, 0.00109091, 3, 4., 0.004, 0.28581818, 2.62, 0, 1, 0), (2, 0, 1., 5, 6., 0.06, 6, 7., 0.07, 0.87, 0.145, 0, 1, 1) ], dtype=trade_dt) ) record_arrays_close( exit_trades['a'].winning.values, exit_trades.winning['a'].values ) record_arrays_close( exit_trades.winning.values, np.array([ (0, 0, 1., 0, 1.09090909, 0.01090909, 2, 3., 0.03, 1.86818182, 1.7125, 0, 1, 0), (1, 0, 0.1, 0, 1.09090909, 0.00109091, 3, 4., 0.004, 0.28581818, 2.62, 0, 1, 0), (2, 0, 1., 5, 6., 0.06, 6, 7., 0.07, 0.87, 0.145, 0, 1, 1), (8, 2, 1., 0, 1.09090909, 0.01090909, 2, 3., 0.03, 1.86818182, 1.7125, 0, 1, 6), (9, 2, 0.1, 0, 1.09090909, 0.00109091, 3, 4., 0.004, 0.28581818, 2.62, 0, 1, 6), (10, 2, 1., 5, 6., 0.06, 6, 7., 0.07, 0.87, 0.145, 0, 1, 7) ], dtype=trade_dt) ) def test_losing_records(self): assert isinstance(exit_trades.losing, vbt.ExitTrades) assert exit_trades.losing.wrapper == exit_trades.wrapper record_arrays_close( exit_trades['a'].losing.values, np.array([ (3, 0, 2., 7, 8., 0.16, 7, 8., 0., -0.16, -0.01, 0, 0, 2) ], dtype=trade_dt) ) record_arrays_close( exit_trades['a'].losing.values, exit_trades.losing['a'].values ) record_arrays_close( exit_trades.losing.values, np.array([ (3, 0, 2., 7, 8., 0.16, 7, 8., 0., -0.16, -0.01, 0, 0, 2), (4, 1, 1., 0, 1.09090909, 0.01090909, 2, 3., 0.03, -1.95, -1.7875, 1, 1, 3), (5, 1, 0.1, 0, 1.09090909, 0.00109091, 3, 4., 0.004, -0.296, -2.71333333, 1, 1, 3), (6, 1, 1., 5, 6., 0.06, 6, 7., 0.07, -1.13, -0.18833333, 1, 1, 4), (7, 1, 2., 7, 8., 0.16, 7, 8., 0., -0.16, -0.01, 1, 0, 5), (11, 2, 1., 6, 7., 0.07, 7, 8., 0.08, -1.15, -0.16428571, 1, 1, 8), (12, 2, 1., 7, 8., 0.08, 7, 8., 0., -0.08, -0.01, 0, 0, 9) ], dtype=trade_dt) ) def test_win_rate(self): assert exit_trades['a'].win_rate() == 0.75 pd.testing.assert_series_equal( exit_trades.win_rate(), pd.Series( np.array([0.75, 0., 0.6, np.nan]), index=close.columns ).rename('win_rate') ) pd.testing.assert_series_equal( exit_trades_grouped.win_rate(), pd.Series( np.array([0.375, 0.6]), index=pd.Index(['g1', 'g2'], dtype='object') ).rename('win_rate') ) def test_winning_streak(self): np.testing.assert_array_almost_equal( exit_trades['a'].winning_streak.values, np.array([1, 2, 3, 0]) ) np.testing.assert_array_almost_equal( exit_trades.winning_streak.values, np.array([1, 2, 3, 0, 0, 0, 0, 0, 1, 2, 3, 0, 0]) ) def test_losing_streak(self): np.testing.assert_array_almost_equal( exit_trades['a'].losing_streak.values, np.array([0, 0, 0, 1]) ) np.testing.assert_array_almost_equal( exit_trades.losing_streak.values, np.array([0, 0, 0, 1, 1, 2, 3, 4, 0, 0, 0, 1, 2]) ) def test_profit_factor(self): assert exit_trades['a'].profit_factor() == 18.9 pd.testing.assert_series_equal( exit_trades.profit_factor(), pd.Series( np.array([18.9, 0., 2.45853659, np.nan]), index=ts2.columns ).rename('profit_factor') ) pd.testing.assert_series_equal( exit_trades_grouped.profit_factor(), pd.Series( np.array([0.81818182, 2.45853659]), index=pd.Index(['g1', 'g2'], dtype='object') ).rename('profit_factor') ) def test_expectancy(self): assert exit_trades['a'].expectancy() == 0.716 pd.testing.assert_series_equal( exit_trades.expectancy(), pd.Series( np.array([0.716, -0.884, 0.3588, np.nan]), index=ts2.columns ).rename('expectancy') ) pd.testing.assert_series_equal( exit_trades_grouped.expectancy(), pd.Series( np.array([-0.084, 0.3588]), index=pd.Index(['g1', 'g2'], dtype='object') ).rename('expectancy') ) def test_sqn(self): assert exit_trades['a'].sqn() == 1.634155521947584 pd.testing.assert_series_equal( exit_trades.sqn(), pd.Series( np.array([1.63415552, -2.13007307, 0.71660403, np.nan]), index=ts2.columns ).rename('sqn') ) pd.testing.assert_series_equal( exit_trades_grouped.sqn(), pd.Series( np.array([-0.20404671, 0.71660403]), index=pd.Index(['g1', 'g2'], dtype='object') ).rename('sqn') ) def test_long_records(self): assert isinstance(exit_trades.long, vbt.ExitTrades) assert exit_trades.long.wrapper == exit_trades.wrapper record_arrays_close( exit_trades['a'].long.values, np.array([ (0, 0, 1., 0, 1.09090909, 0.01090909, 2, 3., 0.03, 1.86818182, 1.7125, 0, 1, 0), (1, 0, 0.1, 0, 1.09090909, 0.00109091, 3, 4., 0.004, 0.28581818, 2.62, 0, 1, 0), (2, 0, 1., 5, 6., 0.06, 6, 7., 0.07, 0.87, 0.145, 0, 1, 1), (3, 0, 2., 7, 8., 0.16, 7, 8., 0., -0.16, -0.01, 0, 0, 2) ], dtype=trade_dt) ) record_arrays_close( exit_trades['a'].long.values, exit_trades.long['a'].values ) record_arrays_close( exit_trades.long.values, np.array([ (0, 0, 1., 0, 1.09090909, 0.01090909, 2, 3., 0.03, 1.86818182, 1.7125, 0, 1, 0), (1, 0, 0.1, 0, 1.09090909, 0.00109091, 3, 4., 0.004, 0.28581818, 2.62, 0, 1, 0), (2, 0, 1., 5, 6., 0.06, 6, 7., 0.07, 0.87, 0.145, 0, 1, 1), (3, 0, 2., 7, 8., 0.16, 7, 8., 0., -0.16, -0.01, 0, 0, 2), (8, 2, 1., 0, 1.09090909, 0.01090909, 2, 3., 0.03, 1.86818182, 1.7125, 0, 1, 6), (9, 2, 0.1, 0, 1.09090909, 0.00109091, 3, 4., 0.004, 0.28581818, 2.62, 0, 1, 6), (10, 2, 1., 5, 6., 0.06, 6, 7., 0.07, 0.87, 0.145, 0, 1, 7), (12, 2, 1., 7, 8., 0.08, 7, 8., 0., -0.08, -0.01, 0, 0, 9) ], dtype=trade_dt) ) def test_short_records(self): assert isinstance(exit_trades.short, vbt.ExitTrades) assert exit_trades.short.wrapper == exit_trades.wrapper record_arrays_close( exit_trades['a'].short.values, np.array([], dtype=trade_dt) ) record_arrays_close( exit_trades['a'].short.values, exit_trades.short['a'].values ) record_arrays_close( exit_trades.short.values, np.array([ (4, 1, 1., 0, 1.09090909, 0.01090909, 2, 3., 0.03, -1.95, -1.7875, 1, 1, 3), (5, 1, 0.1, 0, 1.09090909, 0.00109091, 3, 4., 0.004, -0.296, -2.71333333, 1, 1, 3), (6, 1, 1., 5, 6., 0.06, 6, 7., 0.07, -1.13, -0.18833333, 1, 1, 4), (7, 1, 2., 7, 8., 0.16, 7, 8., 0., -0.16, -0.01, 1, 0, 5), (11, 2, 1., 6, 7., 0.07, 7, 8., 0.08, -1.15, -0.16428571, 1, 1, 8) ], dtype=trade_dt) ) def test_open_records(self): assert isinstance(exit_trades.open, vbt.ExitTrades) assert exit_trades.open.wrapper == exit_trades.wrapper record_arrays_close( exit_trades['a'].open.values, np.array([ (3, 0, 2., 7, 8., 0.16, 7, 8., 0., -0.16, -0.01, 0, 0, 2) ], dtype=trade_dt) ) record_arrays_close( exit_trades['a'].open.values, exit_trades.open['a'].values ) record_arrays_close( exit_trades.open.values, np.array([ (3, 0, 2., 7, 8., 0.16, 7, 8., 0., -0.16, -0.01, 0, 0, 2), (7, 1, 2., 7, 8., 0.16, 7, 8., 0., -0.16, -0.01, 1, 0, 5), (12, 2, 1., 7, 8., 0.08, 7, 8., 0., -0.08, -0.01, 0, 0, 9) ], dtype=trade_dt) ) def test_closed_records(self): assert isinstance(exit_trades.closed, vbt.ExitTrades) assert exit_trades.closed.wrapper == exit_trades.wrapper record_arrays_close( exit_trades['a'].closed.values, np.array([ (0, 0, 1., 0, 1.09090909, 0.01090909, 2, 3., 0.03, 1.86818182, 1.7125, 0, 1, 0), (1, 0, 0.1, 0, 1.09090909, 0.00109091, 3, 4., 0.004, 0.28581818, 2.62, 0, 1, 0), (2, 0, 1., 5, 6., 0.06, 6, 7., 0.07, 0.87, 0.145, 0, 1, 1) ], dtype=trade_dt) ) record_arrays_close( exit_trades['a'].closed.values, exit_trades.closed['a'].values ) record_arrays_close( exit_trades.closed.values, np.array([ (0, 0, 1., 0, 1.09090909, 0.01090909, 2, 3., 0.03, 1.86818182, 1.7125, 0, 1, 0), (1, 0, 0.1, 0, 1.09090909, 0.00109091, 3, 4., 0.004, 0.28581818, 2.62, 0, 1, 0), (2, 0, 1., 5, 6., 0.06, 6, 7., 0.07, 0.87, 0.145, 0, 1, 1), (4, 1, 1., 0, 1.09090909, 0.01090909, 2, 3., 0.03, -1.95, -1.7875, 1, 1, 3), (5, 1, 0.1, 0, 1.09090909, 0.00109091, 3, 4., 0.004, -0.296, -2.71333333, 1, 1, 3), (6, 1, 1., 5, 6., 0.06, 6, 7., 0.07, -1.13, -0.18833333, 1, 1, 4), (8, 2, 1., 0, 1.09090909, 0.01090909, 2, 3., 0.03, 1.86818182, 1.7125, 0, 1, 6), (9, 2, 0.1, 0, 1.09090909, 0.00109091, 3, 4., 0.004, 0.28581818, 2.62, 0, 1, 6), (10, 2, 1., 5, 6., 0.06, 6, 7., 0.07, 0.87, 0.145, 0, 1, 7), (11, 2, 1., 6, 7., 0.07, 7, 8., 0.08, -1.15, -0.16428571, 1, 1, 8) ], dtype=trade_dt) ) def test_stats(self): stats_index = pd.Index([ 'Start', 'End', 'Period', 'First Trade Start', 'Last Trade End', 'Coverage', 'Overlap Coverage', 'Total Records', 'Total Long Trades', 'Total Short Trades', 'Total Closed Trades', 'Total Open Trades', 'Open Trade PnL', 'Win Rate [%]', 'Max Win Streak', 'Max Loss Streak', 'Best Trade [%]', 'Worst Trade [%]', 'Avg Winning Trade [%]', 'Avg Losing Trade [%]', 'Avg Winning Trade Duration', 'Avg Losing Trade Duration', 'Profit Factor', 'Expectancy', 'SQN' ], dtype='object') pd.testing.assert_series_equal( exit_trades.stats(), pd.Series([ pd.Timestamp('2020-01-01 00:00:00'), pd.Timestamp('2020-01-08 00:00:00'), pd.Timedelta('8 days 00:00:00'), pd.Timestamp('2020-01-01 00:00:00'), pd.Timestamp('2020-01-08 00:00:00'), pd.Timedelta('5 days 08:00:00'), pd.Timedelta('2 days 00:00:00'), 3.25, 2.0, 1.25, 2.5, 0.75, -0.1, 58.333333333333336, 2.0, 1.3333333333333333, 168.38888888888889, -91.08730158730158, 149.25, -86.3670634920635, pd.Timedelta('2 days 00:00:00'), pd.Timedelta('1 days 12:00:00'), np.inf, 0.11705555555555548, 0.18931590012681135 ], index=stats_index, name='agg_func_mean' ) ) pd.testing.assert_series_equal( exit_trades.stats(settings=dict(incl_open=True)), pd.Series([ pd.Timestamp('2020-01-01 00:00:00'), pd.Timestamp('2020-01-08 00:00:00'), pd.Timedelta('8 days 00:00:00'), pd.Timestamp('2020-01-01 00:00:00'), pd.Timestamp('2020-01-08 00:00:00'), pd.Timedelta('5 days 08:00:00'), pd.Timedelta('2 days 00:00:00'), 3.25, 2.0, 1.25, 2.5, 0.75, -0.1, 58.333333333333336, 2.0, 2.3333333333333335, 174.33333333333334, -96.25396825396825, 149.25, -42.39781746031746, pd.Timedelta('2 days 00:00:00'), pd.Timedelta('1 days 06:00:00'), 7.11951219512195, 0.06359999999999993, 0.07356215977397455 ], index=stats_index, name='agg_func_mean' ) ) pd.testing.assert_series_equal( exit_trades.stats(column='a'), pd.Series([ pd.Timestamp('2020-01-01 00:00:00'), pd.Timestamp('2020-01-08 00:00:00'), pd.Timedelta('8 days 00:00:00'), pd.Timestamp('2020-01-01 00:00:00'), pd.Timestamp('2020-01-08 00:00:00'), pd.Timedelta('5 days 00:00:00'), pd.Timedelta('2 days 00:00:00'), 4, 4, 0, 3, 1, -0.16, 100.0, 3, 0, 262.0, 14.499999999999998, 149.25, np.nan, pd.Timedelta('2 days 00:00:00'), pd.NaT, np.inf, 1.008, 2.181955050824476 ], index=stats_index, name='a' ) ) pd.testing.assert_series_equal( exit_trades.stats(column='g1', group_by=group_by), pd.Series([ pd.Timestamp('2020-01-01 00:00:00'), pd.Timestamp('2020-01-08 00:00:00'), pd.Timedelta('8 days 00:00:00'), pd.Timestamp('2020-01-01 00:00:00'), pd.Timestamp('2020-01-08 00:00:00'), pd.Timedelta('5 days 00:00:00'), pd.Timedelta('5 days 00:00:00'), 8, 4, 4, 6, 2, -0.32, 50.0, 3, 3, 262.0, -271.3333333333333, 149.25, -156.30555555555557, pd.Timedelta('2 days 00:00:00'), pd.Timedelta('2 days 00:00:00'), 0.895734597156398, -0.058666666666666756, -0.10439051512510047 ], index=stats_index, name='g1' ) ) pd.testing.assert_index_equal( exit_trades.stats(tags='trades').index, pd.Index([ 'First Trade Start', 'Last Trade End', 'Total Long Trades', 'Total Short Trades', 'Total Closed Trades', 'Total Open Trades', 'Open Trade PnL', 'Win Rate [%]', 'Max Win Streak', 'Max Loss Streak', 'Best Trade [%]', 'Worst Trade [%]', 'Avg Winning Trade [%]', 'Avg Losing Trade [%]', 'Avg Winning Trade Duration', 'Avg Losing Trade Duration', 'Profit Factor', 'Expectancy', 'SQN' ], dtype='object') ) pd.testing.assert_series_equal( exit_trades['c'].stats(), exit_trades.stats(column='c') ) pd.testing.assert_series_equal( exit_trades['c'].stats(), exit_trades.stats(column='c', group_by=False) ) pd.testing.assert_series_equal( exit_trades_grouped['g2'].stats(), exit_trades_grouped.stats(column='g2') ) pd.testing.assert_series_equal( exit_trades_grouped['g2'].stats(), exit_trades.stats(column='g2', group_by=group_by) ) stats_df = exit_trades.stats(agg_func=None) assert stats_df.shape == (4, 25) pd.testing.assert_index_equal(stats_df.index, exit_trades.wrapper.columns) pd.testing.assert_index_equal(stats_df.columns, stats_index) entry_trades = vbt.EntryTrades.from_orders(orders) entry_trades_grouped = vbt.EntryTrades.from_orders(orders_grouped) class TestEntryTrades: def test_records_arr(self): record_arrays_close( entry_trades.values, np.array([ (0, 0, 1.0, 0, 1.0, 0.01, 3, 3.0909090909090904, 0.03090909090909091, 2.05, 2.05, 0, 1, 0), (1, 0, 0.1, 1, 2.0, 0.002, 3, 3.0909090909090904, 0.003090909090909091, 0.10399999999999998, 0.5199999999999999, 0, 1, 0), (2, 0, 1.0, 5, 6.0, 0.06, 6, 7.0, 0.07, 0.8699999999999999, 0.145, 0, 1, 1), (3, 0, 2.0, 7, 8.0, 0.16, 7, 8.0, 0.0, -0.16, -0.01, 0, 0, 2), (4, 1, 1.0, 0, 1.0, 0.01, 3, 3.0909090909090904, 0.03090909090909091, -2.131818181818181, -2.131818181818181, 1, 1, 3), (5, 1, 0.1, 1, 2.0, 0.002, 3, 3.0909090909090904, 0.003090909090909091, -0.11418181818181816, -0.5709090909090908, 1, 1, 3), (6, 1, 1.0, 5, 6.0, 0.06, 6, 7.0, 0.07, -1.1300000000000001, -0.18833333333333335, 1, 1, 4), (7, 1, 2.0, 7, 8.0, 0.16, 7, 8.0, 0.0, -0.16, -0.01, 1, 0, 5), (8, 2, 1.0, 0, 1.0, 0.01, 3, 3.0909090909090904, 0.03090909090909091, 2.05, 2.05, 0, 1, 6), (9, 2, 0.1, 1, 2.0, 0.002, 3, 3.0909090909090904, 0.003090909090909091, 0.10399999999999998, 0.5199999999999999, 0, 1, 6), (10, 2, 1.0, 5, 6.0, 0.06, 6, 7.0, 0.07, 0.8699999999999999, 0.145, 0, 1, 7), (11, 2, 1.0, 6, 7.0, 0.07, 7, 8.0, 0.08, -1.1500000000000001, -0.1642857142857143, 1, 1, 8), (12, 2, 1.0, 7, 8.0, 0.08, 7, 8.0, 0.0, -0.08, -0.01, 0, 0, 9) ], dtype=trade_dt) ) reversed_col_orders = orders.replace(records_arr=np.concatenate(( orders.values[orders.values['col'] == 2], orders.values[orders.values['col'] == 1], orders.values[orders.values['col'] == 0] ))) record_arrays_close( vbt.EntryTrades.from_orders(reversed_col_orders).values, entry_trades.values ) def test_records_readable(self): records_readable = entry_trades.records_readable np.testing.assert_array_equal( records_readable['Entry Trade Id'].values, np.array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]) ) np.testing.assert_array_equal( records_readable['Position Id'].values, np.array([ 0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9 ]) ) positions = vbt.Positions.from_trades(exit_trades) positions_grouped = vbt.Positions.from_trades(exit_trades_grouped) class TestPositions: def test_records_arr(self): record_arrays_close( positions.values, np.array([ (0, 0, 1.1, 0, 1.09090909, 0.012, 3, 3.09090909, 0.034, 2.154, 1.795, 0, 1, 0), (1, 0, 1., 5, 6., 0.06, 6, 7., 0.07, 0.87, 0.145, 0, 1, 1), (2, 0, 2., 7, 8., 0.16, 7, 8., 0., -0.16, -0.01, 0, 0, 2), (3, 1, 1.1, 0, 1.09090909, 0.012, 3, 3.09090909, 0.034, -2.246, -1.87166667, 1, 1, 3), (4, 1, 1., 5, 6., 0.06, 6, 7., 0.07, -1.13, -0.18833333, 1, 1, 4), (5, 1, 2., 7, 8., 0.16, 7, 8., 0., -0.16, -0.01, 1, 0, 5), (6, 2, 1.1, 0, 1.09090909, 0.012, 3, 3.09090909, 0.034, 2.154, 1.795, 0, 1, 6), (7, 2, 1., 5, 6., 0.06, 6, 7., 0.07, 0.87, 0.145, 0, 1, 7), (8, 2, 1., 6, 7., 0.07, 7, 8., 0.08, -1.15, -0.16428571, 1, 1, 8), (9, 2, 1., 7, 8., 0.08, 7, 8., 0., -0.08, -0.01, 0, 0, 9) ], dtype=trade_dt) ) reversed_col_trades = exit_trades.replace(records_arr=np.concatenate(( exit_trades.values[exit_trades.values['col'] == 2], exit_trades.values[exit_trades.values['col'] == 1], exit_trades.values[exit_trades.values['col'] == 0] ))) record_arrays_close( vbt.Positions.from_trades(reversed_col_trades).values, positions.values ) def test_records_readable(self): records_readable = positions.records_readable np.testing.assert_array_equal( records_readable['Position Id'].values, np.array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]) ) assert 'Parent Id' not in records_readable.columns # ############# logs.py ############# # logs = vbt.Portfolio.from_orders(close, size, fees=0.01, log=True, freq='1 days').logs logs_grouped = logs.regroup(group_by) class TestLogs: def test_mapped_fields(self): for name in log_dt.names: np.testing.assert_array_equal( getattr(logs, name).values, logs.values[name] ) def test_records_readable(self): records_readable = logs.records_readable np.testing.assert_array_equal( records_readable['Log Id'].values, np.array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 ]) ) np.testing.assert_array_equal( records_readable['Timestamp'].values, np.array([ '2020-01-01T00:00:00.000000000', '2020-01-02T00:00:00.000000000', '2020-01-03T00:00:00.000000000', '2020-01-04T00:00:00.000000000', '2020-01-05T00:00:00.000000000', '2020-01-06T00:00:00.000000000', '2020-01-07T00:00:00.000000000', '2020-01-08T00:00:00.000000000', '2020-01-01T00:00:00.000000000', '2020-01-02T00:00:00.000000000', '2020-01-03T00:00:00.000000000', '2020-01-04T00:00:00.000000000', '2020-01-05T00:00:00.000000000', '2020-01-06T00:00:00.000000000', '2020-01-07T00:00:00.000000000', '2020-01-08T00:00:00.000000000', '2020-01-01T00:00:00.000000000', '2020-01-02T00:00:00.000000000', '2020-01-03T00:00:00.000000000', '2020-01-04T00:00:00.000000000', '2020-01-05T00:00:00.000000000', '2020-01-06T00:00:00.000000000', '2020-01-07T00:00:00.000000000', '2020-01-08T00:00:00.000000000', '2020-01-01T00:00:00.000000000', '2020-01-02T00:00:00.000000000', '2020-01-03T00:00:00.000000000', '2020-01-04T00:00:00.000000000', '2020-01-05T00:00:00.000000000', '2020-01-06T00:00:00.000000000', '2020-01-07T00:00:00.000000000', '2020-01-08T00:00:00.000000000' ], dtype='datetime64[ns]') ) np.testing.assert_array_equal( records_readable['Column'].values, np.array([ 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd' ]) ) np.testing.assert_array_equal( records_readable['Group'].values, np.array([ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 ]) ) np.testing.assert_array_equal( records_readable['Cash'].values, np.array([ 100.0, 98.99, 98.788, 101.758, 102.154, 102.154, 96.094, 103.024, 100.0, 100.99, 101.18799999999999, 98.15799999999999, 97.75399999999999, 97.75399999999999, 103.69399999999999, 96.624, 100.0, 98.99, 98.788, 101.758, 102.154, 102.154, 96.094, 109.954, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0 ]) ) np.testing.assert_array_equal( records_readable['Position'].values, np.array([ 0.0, 1.0, 1.1, 0.10000000000000009, 0.0, 0.0, 1.0, 0.0, 0.0, -1.0, -1.1, -0.10000000000000009, 0.0, 0.0, -1.0, 0.0, 0.0, 1.0, 1.1, 0.10000000000000009, 0.0, 0.0, 1.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ]) ) np.testing.assert_array_equal( records_readable['Debt'].values, np.array([ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.2, 0.10909090909090913, 0.0, 0.0, 6.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 7.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ]) ) np.testing.assert_array_equal( records_readable['Free Cash'].values, np.array([ 100.0, 98.99, 98.788, 101.758, 102.154, 102.154, 96.094, 103.024, 100.0, 98.99, 98.788, 97.93981818181818, 97.754, 97.754, 91.694, 96.624, 100.0, 98.99, 98.788, 101.758, 102.154, 102.154, 96.094, 95.954, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0 ]) ) np.testing.assert_array_equal( records_readable['Val Price'].values, np.array([ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ]) ) np.testing.assert_array_equal( records_readable['Value'].values, np.array([ 100.0, 100.99, 102.088, 102.158, 102.154, 102.154, 103.094, 103.024, 100.0, 98.99, 97.88799999999999, 97.75799999999998, 97.75399999999999, 97.75399999999999, 96.69399999999999, 96.624, 100.0, 100.99, 102.088, 102.158, 102.154, 102.154, 103.094, 101.954, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0 ]) ) np.testing.assert_array_equal( records_readable['Request Size'].values, np.array([ 1.0, 0.1, -1.0, -0.1, np.nan, 1.0, -1.0, 2.0, -1.0, -0.1, 1.0, 0.1, np.nan, -1.0, 1.0, -2.0, 1.0, 0.1, -1.0, -0.1, np.nan, 1.0, -2.0, 2.0, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan ]) ) np.testing.assert_array_equal( records_readable['Request Price'].values, np.array([ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ]) ) np.testing.assert_array_equal( records_readable['Request Size Type'].values, np.array([ 'Amount', 'Amount', 'Amount', 'Amount', 'Amount', 'Amount', 'Amount', 'Amount', 'Amount', 'Amount', 'Amount', 'Amount', 'Amount', 'Amount', 'Amount', 'Amount', 'Amount', 'Amount', 'Amount', 'Amount', 'Amount', 'Amount', 'Amount', 'Amount', 'Amount', 'Amount', 'Amount', 'Amount', 'Amount', 'Amount', 'Amount', 'Amount' ]) ) np.testing.assert_array_equal( records_readable['Request Direction'].values, np.array([ 'Both', 'Both', 'Both', 'Both', 'Both', 'Both', 'Both', 'Both', 'Both', 'Both', 'Both', 'Both', 'Both', 'Both', 'Both', 'Both', 'Both', 'Both', 'Both', 'Both', 'Both', 'Both', 'Both', 'Both', 'Both', 'Both', 'Both', 'Both', 'Both', 'Both', 'Both', 'Both' ]) ) np.testing.assert_array_equal( records_readable['Request Fees'].values, np.array([ 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ]) ) np.testing.assert_array_equal( records_readable['Request Fixed Fees'].values, np.array([ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ]) ) np.testing.assert_array_equal( records_readable['Request Slippage'].values, np.array([ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ]) ) np.testing.assert_array_equal( records_readable['Request Min Size'].values, np.array([ 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08 ]) ) np.testing.assert_array_equal( records_readable['Request Max Size'].values, np.array([ np.inf, np.inf, np.inf, np.inf, np.inf, np.inf, np.inf, np.inf, np.inf, np.inf, np.inf, np.inf, np.inf, np.inf, np.inf, np.inf, np.inf, np.inf, np.inf, np.inf, np.inf, np.inf, np.inf, np.inf, np.inf, np.inf, np.inf, np.inf, np.inf, np.inf, np.inf, np.inf ]) ) np.testing.assert_array_equal( records_readable['Request Size Granularity'].values, np.array([ np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan ]) ) np.testing.assert_array_equal( records_readable['Request Rejection Prob'].values, np.array([ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ]) ) np.testing.assert_array_equal( records_readable['Request Lock Cash'].values, np.array([ False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False ]) ) np.testing.assert_array_equal( records_readable['Request Allow Partial'].values, np.array([ True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True ]) ) np.testing.assert_array_equal( records_readable['Request Raise Rejection'].values, np.array([ False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False ]) ) np.testing.assert_array_equal( records_readable['Request Log'].values, np.array([ True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True ]) ) np.testing.assert_array_equal( records_readable['New Cash'].values, np.array([ 98.99, 98.788, 101.758, 102.154, 102.154, 96.094, 103.024, 86.864, 100.99, 101.18799999999999, 98.15799999999999, 97.75399999999999, 97.75399999999999, 103.69399999999999, 96.624, 112.464, 98.99, 98.788, 101.758, 102.154, 102.154, 96.094, 109.954, 93.794, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0 ]) ) np.testing.assert_array_equal( records_readable['New Position'].values, np.array([ 1.0, 1.1, 0.10000000000000009, 0.0, 0.0, 1.0, 0.0, 2.0, -1.0, -1.1, -0.10000000000000009, 0.0, 0.0, -1.0, 0.0, -2.0, 1.0, 1.1, 0.10000000000000009, 0.0, 0.0, 1.0, -1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ]) ) np.testing.assert_array_equal( records_readable['New Debt'].values, np.array([ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.2, 0.10909090909090913, 0.0, 0.0, 6.0, 0.0, 16.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 7.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ]) ) np.testing.assert_array_equal( records_readable['New Free Cash'].values, np.array([ 98.99, 98.788, 101.758, 102.154, 102.154, 96.094, 103.024, 86.864, 98.99, 98.788, 97.93981818181818, 97.754, 97.754, 91.694, 96.624, 80.464, 98.99, 98.788, 101.758, 102.154, 102.154, 96.094, 95.954, 93.794, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0 ]) ) np.testing.assert_array_equal( records_readable['New Val Price'].values, np.array([ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ]) ) np.testing.assert_array_equal( records_readable['New Value'].values, np.array([ 100.0, 100.99, 102.088, 102.158, 102.154, 102.154, 103.094, 103.024, 100.0, 98.99, 97.88799999999999, 97.75799999999998, 97.75399999999999, 97.75399999999999, 96.69399999999999, 96.624, 100.0, 100.99, 102.088, 102.158, 102.154, 102.154, 103.094, 101.954, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0 ]) ) np.testing.assert_array_equal( records_readable['Result Size'].values, np.array([ 1.0, 0.1, 1.0, 0.1, np.nan, 1.0, 1.0, 2.0, 1.0, 0.1, 1.0, 0.1, np.nan, 1.0, 1.0, 2.0, 1.0, 0.1, 1.0, 0.1, np.nan, 1.0, 2.0, 2.0, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan ]) ) np.testing.assert_array_equal( records_readable['Result Price'].values, np.array([ 1.0, 2.0, 3.0, 4.0, np.nan, 6.0, 7.0, 8.0, 1.0, 2.0, 3.0, 4.0, np.nan, 6.0, 7.0, 8.0, 1.0, 2.0, 3.0, 4.0, np.nan, 6.0, 7.0, 8.0, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan ]) ) np.testing.assert_array_equal( records_readable['Result Fees'].values, np.array([ 0.01, 0.002, 0.03, 0.004, np.nan, 0.06, 0.07, 0.16, 0.01, 0.002, 0.03, 0.004, np.nan, 0.06, 0.07, 0.16, 0.01, 0.002, 0.03, 0.004, np.nan, 0.06, 0.14, 0.16, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan ]) ) np.testing.assert_array_equal( records_readable['Result Side'].values, np.array([ 'Buy', 'Buy', 'Sell', 'Sell', None, 'Buy', 'Sell', 'Buy', 'Sell', 'Sell', 'Buy', 'Buy', None, 'Sell', 'Buy', 'Sell', 'Buy', 'Buy', 'Sell', 'Sell', None, 'Buy', 'Sell', 'Buy', None, None, None, None, None, None, None, None ]) ) np.testing.assert_array_equal( records_readable['Result Status'].values, np.array([ 'Filled', 'Filled', 'Filled', 'Filled', 'Ignored', 'Filled', 'Filled', 'Filled', 'Filled', 'Filled', 'Filled', 'Filled', 'Ignored', 'Filled', 'Filled', 'Filled', 'Filled', 'Filled', 'Filled', 'Filled', 'Ignored', 'Filled', 'Filled', 'Filled', 'Ignored', 'Ignored', 'Ignored', 'Ignored', 'Ignored', 'Ignored', 'Ignored', 'Ignored' ]) ) np.testing.assert_array_equal( records_readable['Result Status Info'].values, np.array([ None, None, None, None, 'SizeNaN', None, None, None, None, None, None, None, 'SizeNaN', None, None, None, None, None, None, None, 'SizeNaN', None, None, None, 'SizeNaN', 'SizeNaN', 'SizeNaN', 'SizeNaN', 'SizeNaN', 'SizeNaN', 'SizeNaN', 'SizeNaN' ]) ) np.testing.assert_array_equal( records_readable['Order Id'].values, np.array([ 0, 1, 2, 3, -1, 4, 5, 6, 7, 8, 9, 10, -1, 11, 12, 13, 14, 15, 16, 17, -1, 18, 19, 20, -1, -1, -1, -1, -1, -1, -1, -1 ]) ) def test_stats(self): stats_index = pd.Index([ 'Start', 'End', 'Period', 'Total Records', 'Status Counts: None', 'Status Counts: Filled', 'Status Counts: Ignored', 'Status Counts: Rejected', 'Status Info Counts: None', 'Status Info Counts: SizeNaN' ], dtype='object') pd.testing.assert_series_equal( logs.stats(), pd.Series([ pd.Timestamp('2020-01-01 00:00:00'), pd.Timestamp('2020-01-08 00:00:00'), pd.Timedelta('8 days 00:00:00'), 8.0, 0.0, 5.25, 2.75, 0.0, 5.25, 2.75 ], index=stats_index, name='agg_func_mean' ) ) pd.testing.assert_series_equal( logs.stats(column='a'), pd.Series([ pd.Timestamp('2020-01-01 00:00:00'), pd.Timestamp('2020-01-08 00:00:00'), pd.Timedelta('8 days 00:00:00'), 8, 0, 7, 1, 0, 7, 1 ], index=stats_index, name='a' ) ) pd.testing.assert_series_equal( logs.stats(column='g1', group_by=group_by), pd.Series([ pd.Timestamp('2020-01-01 00:00:00'), pd.Timestamp('2020-01-08 00:00:00'), pd.Timedelta('8 days 00:00:00'), 16, 0, 14, 2, 0, 14, 2 ], index=stats_index, name='g1' ) ) pd.testing.assert_series_equal( logs['c'].stats(), logs.stats(column='c') ) pd.testing.assert_series_equal( logs['c'].stats(), logs.stats(column='c', group_by=False) ) pd.testing.assert_series_equal( logs_grouped['g2'].stats(), logs_grouped.stats(column='g2') ) pd.testing.assert_series_equal( logs_grouped['g2'].stats(), logs.stats(column='g2', group_by=group_by) ) stats_df = logs.stats(agg_func=None) assert stats_df.shape == (4, 10) pd.testing.assert_index_equal(stats_df.index, logs.wrapper.columns) pd.testing.assert_index_equal(stats_df.columns, stats_index) def test_count(self): assert logs['a'].count() == 8 pd.testing.assert_series_equal( logs.count(), pd.Series( np.array([8, 8, 8, 8]), index=pd.Index(['a', 'b', 'c', 'd'], dtype='object') ).rename('count') ) pd.testing.assert_series_equal( logs_grouped.count(), pd.Series( np.array([16, 16]), index=pd.Index(['g1', 'g2'], dtype='object') ).rename('count') )