Skip to content

Commit

Permalink
Using fixtures (#96)
Browse files Browse the repository at this point in the history
* new release 0.6.0 (#92)

* better description of development process (#70)

* Update README.rst (#71)

* feat: bump version to latest release +1 (#69)

* Wavgfix (#62)

* initial commit

* small fix

* stash for the weekend

* Fixed wavg to handle surplus values.

* Re-instated 'Europe/Berlin' as default for tz in standardize. For now.

* small fix in docs

* docs and better unit handling

* Kind available at project root

* fixed init tests (?)

* new release

* fixed for pyton 3.9 too

* additional tests (#74)

* Portfolyo Release 0.5.10 (#75)

* Slice (#78)

* added slice property & tests

* changed toml

* fixed tz issue and added tz test for slicing

* added test-cases with tz

---------

Co-authored-by: Alina Voilova <[email protected]>
Co-authored-by: rwijtvliet <[email protected]>

* Standardise sod (#82)

* refactoring and additional assertion on start-of-day

* fixed test and assertion

* fixed?

* fixed some

* not working

* fixed some things

* tests for slice

* final test for slice for 15T

* docs

* try to fix docs

* another try to fix

* poetry shell

* fixing 2.0

* fixing 2.1

* fixing 3.0

* fixing 4.0

* fixing 5.0

* fixing 6.0

* fixng 7.0

* fixng 8.0

* fixing 11

* fixing 12

* fixing 13

* fixng 14

* fixing 15

* fixing 16

* fixing 17

* deleted python 3.0 from tests

* deleted hmtl folder

* changed toml

* updated lock file

---------

Co-authored-by: rwijtvliet <[email protected]>
Co-authored-by: Alina Voilova <[email protected]>

* Concat (#83)

* added slice property & tests

* changed toml

* created branch concat

* first commit

* works for flat pflines, nested not yet

* draft of concat function done, need more testing though

* created error_case tests for concat

* wrote test_func for concat_pflines, improved the code for concat

* added test cases for concat pfstates, requires approval(!)

* changed test_function

* change general to take iterable as argument

---------

Co-authored-by: Alina Voilova <[email protected]>

* Toplevelfunctions (#84)

* initial commit

* gitignore

* Intersect (#79)

* added slice property & tests

* changed toml

* created branch for intersect_flex function

* new test function

* added tests for intersect_flex frames

* all test are passing

* test ignore all for intersect frame

* fixed documentation

* deleted req docs

* added DST testcase

* not working help

* Added back missing file

* added valuerror for sod with less than daily freq

* deleted unnecessary files

* tests for indexable

* tests for indexable with 2 obj

* added oneliner in docs and test for 3 obj. case

---------

Co-authored-by: Alina Voilova <[email protected]>
Co-authored-by: rwijtvliet <[email protected]>

* Plot children (#87)

* changed to poetry

* fixed pint problem (groups in unitdef.txt) and pint-pandas dependency problem by fixing pandas to 2.0

* ci pipeline

* ci pipeline

* ci with poetry

* solve dependency problems between pandas and pint-pandas

* workaround pint-pandas bug

* typo

* seaborn pinned version to 0.8

* fixed to_excel function, updated version of pint

* fixed arithmatic on pflines without overlap

* small changes
small changes

* more consistent functions to get random pfline

* deleted comment

* change the python version for push request to 3.11

* test

* Removed unused dependency

* updated toml

* added exception if no clipboard available

* updated toml

* fixed pfline_excelclipboad.py

* changed lock file for pre-commit

* install poetry libraries in pre-commit step

* use black on all files in pre-commit

* updated flake8 version in pre-commit.yaml

* exclude .venv folder from flake8

* changed setup.cfg to ignore flake8 error messages

* initial commit

* first try at plotting children

* bar plot with children

* created plot_children(),fixed bug with darken

* area plots for children stacked on top of each other. for daily it plots only parent

* changed the logic of all plot_timeseries_as functions, now based on frequency

* created a function to test plotting pfline

* created slice attr, wrote tests for it

* more flexible intersec function with ignore freq, tz, start_of_day + tests

* small changes to intersect

* intersect_flex function is finished, more testing with frames needed

* finished intersect_flex, more testing with frames needed

* added children bool to plot pfstate

* added hash function for colors for children

* deleted unnecessary test

* changed hash function, and width of hline

* deleted unnecessary test

* plot with children

* changed plot_pfstate to work with new logic

* tests for plot function

* added function to set limits to plot pfstate

* fixed strict variable for test cases

* Deleted unnecessary files

* changed yaml file to exclude python 3.10 with mac 14

---------

Co-authored-by: rwijtvliet <[email protected]>
Co-authored-by: Alina Voilova <[email protected]>

* Structure (#90)

* changed to poetry

* fixed pint problem (groups in unitdef.txt) and pint-pandas dependency problem by fixing pandas to 2.0

* ci pipeline

* ci pipeline

* ci with poetry

* solve dependency problems between pandas and pint-pandas

* workaround pint-pandas bug

* typo

* seaborn pinned version to 0.8

* fixed to_excel function, updated version of pint

* fixed arithmatic on pflines without overlap

* small changes
small changes

* more consistent functions to get random pfline

* deleted comment

* change the python version for push request to 3.11

* test

* Removed unused dependency

* updated toml

* added exception if no clipboard available

* updated toml

* fixed pfline_excelclipboad.py

* changed lock file for pre-commit

* install poetry libraries in pre-commit step

* use black on all files in pre-commit

* updated flake8 version in pre-commit.yaml

* exclude .venv folder from flake8

* changed setup.cfg to ignore flake8 error messages

* initial commit

* first try at plotting children

* bar plot with children

* created plot_children(),fixed bug with darken

* area plots for children stacked on top of each other. for daily it plots only parent

* changed the logic of all plot_timeseries_as functions, now based on frequency

* created a function to test plotting pfline

* created slice attr, wrote tests for it

* more flexible intersec function with ignore freq, tz, start_of_day + tests

* small changes to intersect

* intersect_flex function is finished, more testing with frames needed

* finished intersect_flex, more testing with frames needed

* added children bool to plot pfstate

* added hash function for colors for children

* deleted unnecessary test

* changed hash function, and width of hline

* deleted unnecessary test

* plot with children

* changed plot_pfstate to work with new logic

* tests for plot function

* refactoring

* more powerful peak/offpeak functions

* removed longer_or_shorter from frequency tools; Use the up_or_down function instead

* tests for peakfn and peakconvert

* fixed test

* removed all Union and replaced with |


---------

Co-authored-by: rwijtvliet <[email protected]>
Co-authored-by: Alina Voilova <[email protected]>

* Portfolyo Release 0.6.0

* Portfolyo Release 0.6.0 (#91)

* 0.6.0 (#93)

* 0.6.0 (#94)

---------

Co-authored-by: Stefan Keidel <[email protected]>
Co-authored-by: Alina Voilova <[email protected]>
Co-authored-by: Alina Voilova <[email protected]>

* tests using fixtures

* cov report

---------

Co-authored-by: Stefan Keidel <[email protected]>
Co-authored-by: Alina Voilova <[email protected]>
Co-authored-by: Alina Voilova <[email protected]>
  • Loading branch information
4 people authored May 28, 2024
1 parent 0f49c1f commit 9364444
Show file tree
Hide file tree
Showing 3 changed files with 233 additions and 1 deletion.
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ max-line-length = 120
ignore = E501, W503, E202, E226

[tool:pytest]
#addopts = --cov=.
addopts = --cov=.
markers =
only_on_pr: marks tests as slow (select with -m only_on_pr and deselect with -m "not only_on_pr")
pythonpath = ./tests
Expand Down
105 changes: 105 additions & 0 deletions tests/tools/test_hedge1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
"""Testing hedge functions using hard-coded hedge values."""

import numpy as np
import pandas as pd
import pytest

from portfolyo import testing, tools


@pytest.mark.parametrize("how", ["vol", "val"])
@pytest.mark.parametrize(
"w_vals,start,w_expected",
[
([1, 2, 3], "2020-01-01", 2),
(range(12), "2020-01-01", 5.5),
([*[10] * (23 + 8), *[15] * 5], "2020-03-29", 10.69444),
([*[10] * (25 + 8), *[15] * 5], "2020-10-25", 10.65789),
],
)
def test_onehedge_uniformpricesandduration(w_vals, start, w_expected, how):
"""Test hedge with uniform prices and durations."""
i = pd.date_range(start, freq="H", periods=len(w_vals), tz="Europe/Berlin")
df = pd.DataFrame({"w": w_vals, "p": 100.0}, i)
df["duration"] = tools.duration.index(i)

result = tools.hedge.one_hedge(df, how=how)
expected = pd.Series({"w": w_expected, "p": 100.0})
testing.assert_series_equal(result, expected)


@pytest.mark.parametrize("how", ["vol", "val"])
@pytest.mark.parametrize(
"w_vals,start,w_expected,tz",
[
([1, 2], "2020-01-01", 1.483333333, None), # 29 days in Feb
([1, 2], "2021-01-01", 1.474576271, None), # 28 days in Feb
(range(12), "2020-01-01", 5.51366120, None), # no DST
(range(12), "2020-01-01", 5.514458106, "Europe/Berlin"), # DST
],
)
def test_onehedge_uniformprices(w_vals, start, w_expected, how, tz):
"""Test hedge with uniform prices but distinct durations."""
i = pd.date_range(start, freq="MS", periods=len(w_vals), tz=tz)
df = pd.DataFrame({"w": w_vals, "p": 100.0}, i)
df["duration"] = tools.duration.index(i)

result = tools.hedge.one_hedge(df, how=how)
expected = pd.Series({"w": w_expected, "p": 100.0})
testing.assert_series_equal(result, expected)


@pytest.mark.parametrize("how", ["vol", "val"])
@pytest.mark.parametrize(
"w_vals,p_vals,start,p_expected,w_expected_vol,w_expected_val,tz",
[
(
[1, 2],
[100, 200],
"2020-01-01",
148.333333333,
1.4833333,
1.651685393,
None,
), # 29 days in Feb
(
[1, 2],
[100, 200],
"2021-01-01",
147.4576271,
1.474576271,
1.643678161,
None,
), # 28 days in Feb
(
np.arange(12),
np.arange(12) * 100,
"2020-01-01",
551.366120,
5.51366120,
7.673934589,
None,
), # no DST
(
np.arange(12),
np.arange(12) * 100,
"2020-01-01",
551.4458106,
5.514458106,
7.674415244,
"Europe/Berlin",
), # DST
],
)
def test_onehedge(
w_vals, p_vals, start, w_expected_val, w_expected_vol, p_expected, how, tz
):
"""Test value hedge."""
i = pd.date_range(start, freq="MS", periods=len(w_vals), tz=tz)
df = pd.DataFrame({"w": w_vals, "p": p_vals}, i)
df["duration"] = tools.duration.index(i)

result = tools.hedge.one_hedge(df, how=how)
w_expected = w_expected_val if how == "val" else w_expected_vol
expected = pd.Series({"w": w_expected, "p": p_expected})
testing.assert_series_equal(result, expected)
127 changes: 127 additions & 0 deletions tests/tools/test_hedge2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
"""Testing hedge functions using pre-calculated hedge values from excel."""

from pathlib import Path

import pandas as pd
import pytest

from portfolyo import testing, tools

PATH = Path(__file__).parent / "test_hedge_data.xlsx"


def sheetname(freq, tz):
return f'{freq}_{"None" if tz is None else tz.replace("/", "")}'


@pytest.fixture(
scope="session",
params=[pytest.param(True, id="withunits"), pytest.param(False, id="withoutunits")],
)
def has_units(request):
return request.param


@pytest.fixture(scope="session", params=["H", "D"])
def freq(request):
return request.param


@pytest.fixture(scope="session", params=[None, "Europe/Berlin"])
def tz(request):
return request.param


@pytest.fixture(scope="session", params=["vol", "val"])
def how(request):
return request.param


@pytest.fixture(
scope="session",
params=[
pytest.param(None, id="base"),
pytest.param(tools.product.germanpower_peakfn, id="peakoffpeakgerman"),
],
)
def peak_fn(request):
return request.param


@pytest.fixture(scope="session", params=["MS", "QS", "AS"])
def aggfreq(request):
return request.param


@pytest.fixture
def dfin(freq: str, tz: str) -> pd.DataFrame:
df = pd.read_excel(
PATH, sheetname(freq, tz), header=6, index_col=0, usecols="A,B:C"
)
if tz:
df = df.tz_localize(tz, ambiguous="infer")
df.index.freq = pd.infer_freq(df.index)
return df


@pytest.fixture
def dfexp(freq: str, tz: str) -> pd.DataFrame:
df = pd.read_excel(
PATH, f"{sheetname(freq, tz)}_out", header=[3, 4, 5, 6], index_col=0
)
if tz:
df = df.tz_localize(tz, ambiguous="infer")
df.index.freq = pd.infer_freq(df.index)
return df


@pytest.fixture
def win(dfin: pd.DataFrame, has_units: bool) -> pd.Series:
s = dfin["w"]
return s if not has_units else s.astype("pint[MW]")


@pytest.fixture
def pin(dfin: pd.DataFrame, has_units: bool) -> pd.Series:
s = dfin["p"]
return s if not has_units else s.astype("pint[Eur/MWh]")


@pytest.fixture
def wexp(
dfexp: pd.DataFrame,
has_units: bool,
aggfreq: str,
peak_fn: tools.peakfn.PeakFunction,
how: str,
) -> pd.Series:
if dfexp.index.freq == "D" and peak_fn is not None:
pytest.skip("Don't decompose in peak and offpeak if daily values")
s = dfexp[aggfreq][peak_fn is not None][how]["w"]
return s if not has_units else s.astype("pint[MW]")


@pytest.fixture
def pexp(
dfexp: pd.DataFrame,
has_units: bool,
aggfreq: str,
peak_fn: tools.peakfn.PeakFunction,
) -> pd.Series:
s = dfexp[aggfreq][peak_fn is not None].iloc[:, 0] # price is first column
return s if not has_units else s.astype("pint[Eur/MWh]")


def test_hedge_fromexcel(
win: pd.Series,
pin: pd.Series,
wexp: pd.Series,
pexp: pd.Series,
how: str,
aggfreq: str,
peak_fn: tools.peakfn.PeakFunction,
):
"""Test if hedge results are correctly calculated, by comparing against previously calculated results."""
wresult, presult = tools.hedge.hedge(win, pin, how, peak_fn, aggfreq)
testing.assert_series_equal(wresult, wexp, check_names=False)
testing.assert_series_equal(presult, pexp, check_names=False)

0 comments on commit 9364444

Please sign in to comment.