Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 76 additions & 1 deletion tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
from trading_ig.utils import conv_datetime
import warnings

import pytest

from trading_ig.utils import conv_datetime, conv_resol

try:
import pandas # noqa

pandas_installed = True
except ImportError:
pandas_installed = False

"""
Unit tests for utils module
Expand All @@ -17,3 +28,67 @@ def test_conv_datetime_format_2(self):
def test_conv_datetime_format_3(self):
result = conv_datetime("2020/03/01", 3)
assert result == "2020/03/01 00:00:00"

@pytest.mark.skipif(not pandas_installed, reason="Requires pandas")
@pytest.mark.parametrize(
"resolution,expected",
[
("1s", "SECOND"),
("1Min", "MINUTE"),
("2Min", "MINUTE_2"),
("3Min", "MINUTE_3"),
("5Min", "MINUTE_5"),
("10Min", "MINUTE_10"),
("15Min", "MINUTE_15"),
("30Min", "MINUTE_30"),
("1h", "HOUR"),
("2h", "HOUR_2"),
("3h", "HOUR_3"),
("4h", "HOUR_4"),
("D", "DAY"),
("W", "WEEK"),
("ME", "MONTH"),
],
)
def test_conv_resol(self, resolution, expected):
assert conv_resol(resolution) == expected

@pytest.mark.skipif(not pandas_installed, reason="Requires pandas")
@pytest.mark.parametrize(
"resolution,expected",
[
("1H", "HOUR"),
("2H", "HOUR_2"),
("3H", "HOUR_3"),
("4H", "HOUR_4"),
("M", "MONTH"),
],
)
def test_conv_resol_legacy_alias(self, resolution, expected):
"""The 'H' and 'M' aliases were removed in pandas 3.0, but they are the
spellings this library has always documented, so they must keep working"""
assert conv_resol(resolution) == expected

@pytest.mark.skipif(not pandas_installed, reason="Requires pandas")
def test_conv_resol_legacy_alias_does_not_warn(self):
"""Legacy aliases are normalised before pandas sees them, so they don't
trigger the pandas 2 deprecation warning"""
with warnings.catch_warnings():
warnings.simplefilter("error", FutureWarning)
assert conv_resol("1H") == "HOUR"

@pytest.mark.skipif(not pandas_installed, reason="Requires pandas")
@pytest.mark.parametrize("resolution", ["2D", "2W", "12h"])
def test_conv_resol_unsupported(self, resolution):
"""A valid pandas offset that IG has no resolution for is returned
unchanged"""
assert conv_resol(resolution) == resolution

@pytest.mark.skipif(not pandas_installed, reason="Requires pandas")
@pytest.mark.parametrize("resolution", ["banana", "", "X"])
def test_conv_resol_invalid(self, resolution):
"""Anything pandas can't parse at all raises, rather than being passed
on to the API. Used e.g. in
test_historical_prices_v3_num_points_bad_resolution"""
with pytest.raises(ValueError):
conv_resol(resolution)
10 changes: 6 additions & 4 deletions trading_ig/rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -1791,8 +1791,9 @@ def fetch_historical_prices_by_epic(
:param epic: (str) The epic key for which historical prices are being
requested
:param resolution: (str, optional) timescale resolution. Expected values
are 1Min, 2Min, 3Min, 5Min, 10Min, 15Min, 30Min, 1H, 2H, 3H, 4H, D,
W, M. Default is 1Min
are 1Min, 2Min, 3Min, 5Min, 10Min, 15Min, 30Min, 1h, 2h, 3h, 4h, D,
W, ME. Default is 1Min. The pre-pandas 3 spellings 1H, 2H, 3H, 4H
and M are also accepted
:param start_date: (datetime, optional) date range start, format
yyyy-MM-dd'T'HH:mm:ss
:param end_date: (datetime, optional) date range end, format
Expand Down Expand Up @@ -1884,8 +1885,9 @@ def fetch_historical_prices_by_epic_and_date_range(
and date range. Supports both versions 1 and 2
:param epic: IG epic
:type epic: str
:param resolution: timescale for returned data. Expected values 'M', 'D',
'1H' etc
:param resolution: timescale for returned data. Expected values 'ME',
'D', '1h' etc. The pre-pandas 3 spellings 'M' and '1H' are also
accepted
:type resolution: str
:param start_date: start date for returned data. For v1, format
'2020:09:01-00:00:00', for v2 use '2020-09-01 00:00:00'
Expand Down
11 changes: 10 additions & 1 deletion trading_ig/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,16 @@ def conv_resol(resolution):
to_offset("W"): "WEEK",
to_offset("ME"): "MONTH",
}
offset = to_offset(resolution)
# pandas 3.0 removes the 'H' and 'M' frequency aliases, in favour of
# 'h' and 'ME' so normalise them before calling to_offset
alias = resolution
if isinstance(alias, str):
if alias.endswith("H"):
alias = alias[:-1] + "h"
elif alias in ("M", "1M"):
alias = "ME"

offset = to_offset(alias)
if offset in d:
return d[offset]
else:
Expand Down