Skip to content

Commit

Permalink
all test are passing
Browse files Browse the repository at this point in the history
  • Loading branch information
Alina Voilova committed Feb 12, 2024
1 parent f065a59 commit a3f68eb
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 10 deletions.
22 changes: 22 additions & 0 deletions docs/core/pfline.rst
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,28 @@ Another slicing method is implemented with the ``.slice[]`` property. The improv
# --- hide: stop ---


Concatenation
=============

Portfolio lines can be concatenated with the ``portfolio.concat()`` function. This only works if the input portfolio lines have contain compatible information (the same frequency, timezone, start-of-day, kind, etc) and, crucially, their indices are gapless and without overlap. To remove any overlap, use the ``.slice[]`` property.

.. exec_code::

# --- hide: start ---
import portfolyo as pf, pandas as pd
index = pd.date_range('2024', freq='AS', periods=3)
input_df = pd.DataFrame({'w':[200, 220, 300], 'p': [100, 150, 200]}, index)
pfl = pf.PfLine(input_df)
# --- hide: stop ---
# continuation of previous code example
index2 = pd.date_range('2025', freq='AS', periods=3) # 2 years' overlap with pfl
pfl2 = pf.PfLine(pd.DataFrame({'w':[22, 30, 40], 'p': [15, 20, 21]}, index))
# first two datapoints (until/excl 2026) from pfl, last two datapoints (from/incl 2026) from pfl2
pf.concat([pfl.slice[:'2026'], pfl2.slice['2026':]])
# --- hide: start ---
print(pf.concat([pfl.slice[:'2026'], pfl2.slice['2026':]]))
# --- hide: stop ---


Volume-only, price-only or revenue-only
=======================================
Expand Down
4 changes: 2 additions & 2 deletions portfolyo/tools/intersect.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,10 +221,10 @@ def frames(
The indices must have equal frequency, timezone, start-of-day. Otherwise, an error
is raised. If there is no overlap, empty frames are returned.
"""
new_idx = indices_flex(
new_idxs = indices_flex(
*[fr.index for fr in frames],
ignore_freq=ignore_freq,
ignore_tz=ignore_tz,
ignore_start_of_day=ignore_start_of_day,
)
return [fr.loc[idx] for idx, fr in zip(new_idx, frames)]
return [fr.loc[idx] for idx, fr in zip(new_idxs, frames)]
39 changes: 31 additions & 8 deletions tests/tools/test_intersect.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ def test_intersect_nooverlap(indexorframe: str, tz: str, freq: str, starttime: s
get_idx("2020-01-01", starttime, tz, freq, "2022-01-01"),
get_idx("2023-01-01", starttime, tz, freq, "2025-01-01"),
]
do_test_intersect(indexorframe, idxs, None, "", tz, freq)
do_test_intersect(indexorframe, idxs, None, "", tz, freq, check_freq=False)


def do_test_intersect(
Expand All @@ -164,12 +164,21 @@ def do_test_intersect(
expected_starttime: str = None,
expected_tz: str = None,
expected_freq: str = None,
**kwargs,
):
if indexorframe == "idx":
do_test_fn = do_test_intersect_index
do_test_intersect_index(
idxs, expected_startdate, expected_starttime, expected_tz, expected_freq
)
else:
do_test_fn = do_test_intersect_frame
do_test_fn(idxs, expected_startdate, expected_starttime, expected_tz, expected_freq)
do_test_intersect_frame(
idxs,
expected_startdate,
expected_starttime,
expected_tz,
expected_freq,
**kwargs,
)


def do_test_intersect_index(
Expand Down Expand Up @@ -200,24 +209,38 @@ def do_test_intersect_frame(
expected_starttime: str = None,
expected_tz: str = None,
expected_freq: str = None,
ignore_freq: bool = False,
ignore_start_of_day: bool = False,
ignore_tz: bool = False,
**kwargs,
):
frames = get_frames(idxs)

# Error case.
if type(expected_startdate) is type and issubclass(expected_startdate, Exception):
with pytest.raises(expected_startdate):
tools.intersect.frames(*frames)
tools.intersect.frames(
*frames,
ignore_start_of_day=ignore_start_of_day,
ignore_tz=ignore_tz,
ignore_freq=ignore_freq,
)
return

# Normal case.
result_frames = tools.intersect.frames(*frames)
result_frames = tools.intersect.frames(
*frames,
ignore_freq=ignore_freq,
ignore_start_of_day=ignore_start_of_day,
ignore_tz=ignore_tz,
)
expected_index = get_idx(
expected_startdate, expected_starttime, expected_tz, expected_freq
)
expected_frames = get_frames(idxs, expected_index)

for result, expected in zip(result_frames, expected_frames):
if isinstance(result, pd.Series):
testing.assert_series_equal(result, expected)
testing.assert_series_equal(result, expected, **kwargs)
else:
testing.assert_frame_equal(result, expected)
testing.assert_frame_equal(result, expected, **kwargs)

0 comments on commit a3f68eb

Please sign in to comment.