Initial import: grid-bot — grid trading bot for BTC-USDT on Cifra Markets
This commit is contained in:
@@ -0,0 +1,312 @@
|
||||
import dataclasses
|
||||
import typing
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from einops import EinopsError, asnumpy, pack, unpack
|
||||
from einops.tests import collect_test_backends
|
||||
|
||||
rng = np.random.default_rng()
|
||||
|
||||
|
||||
def pack_unpack(xs, pattern):
|
||||
x, ps = pack(xs, pattern)
|
||||
unpacked = unpack(xs, ps, pattern)
|
||||
assert len(unpacked) == len(xs)
|
||||
for a, b in zip(unpacked, xs):
|
||||
assert np.allclose(asnumpy(a), asnumpy(b))
|
||||
|
||||
|
||||
def unpack_and_pack(x, ps, pattern: str):
|
||||
unpacked = unpack(x, ps, pattern)
|
||||
packed, ps2 = pack(unpacked, pattern=pattern)
|
||||
|
||||
assert np.allclose(asnumpy(packed), asnumpy(x))
|
||||
return unpacked
|
||||
|
||||
|
||||
def unpack_and_pack_against_numpy(x, ps, pattern: str):
|
||||
capturer_backend = CaptureException()
|
||||
capturer_numpy = CaptureException()
|
||||
|
||||
with capturer_backend:
|
||||
unpacked = unpack(x, ps, pattern)
|
||||
packed, ps2 = pack(unpacked, pattern=pattern)
|
||||
|
||||
with capturer_numpy:
|
||||
x_np = asnumpy(x)
|
||||
unpacked_np = unpack(x_np, ps, pattern)
|
||||
packed_np, ps3 = pack(unpacked_np, pattern=pattern)
|
||||
|
||||
assert type(capturer_numpy.exception) == type(capturer_backend.exception) # noqa E721
|
||||
if capturer_numpy.exception is not None:
|
||||
# both failed
|
||||
return
|
||||
else:
|
||||
# neither failed, check results are identical
|
||||
assert np.allclose(asnumpy(packed), asnumpy(x))
|
||||
assert np.allclose(asnumpy(packed_np), asnumpy(x))
|
||||
assert len(unpacked) == len(unpacked_np)
|
||||
for a, b in zip(unpacked, unpacked_np):
|
||||
assert np.allclose(asnumpy(a), b)
|
||||
|
||||
|
||||
class CaptureException:
|
||||
def __enter__(self):
|
||||
self.exception = None
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
self.exception = exc_val
|
||||
return True
|
||||
|
||||
|
||||
def test_numpy_trivial(H=13, W=17):
|
||||
def rand(*shape):
|
||||
return rng.random(shape)
|
||||
|
||||
def check(a, b):
|
||||
assert a.dtype == b.dtype
|
||||
assert a.shape == b.shape
|
||||
assert np.all(a == b)
|
||||
|
||||
r, g, b = rand(3, H, W)
|
||||
embeddings = rand(H, W, 32)
|
||||
|
||||
check(
|
||||
np.stack([r, g, b], axis=2),
|
||||
pack([r, g, b], "h w *")[0],
|
||||
)
|
||||
check(
|
||||
np.stack([r, g, b], axis=1),
|
||||
pack([r, g, b], "h * w")[0],
|
||||
)
|
||||
check(
|
||||
np.stack([r, g, b], axis=0),
|
||||
pack([r, g, b], "* h w")[0],
|
||||
)
|
||||
|
||||
check(
|
||||
np.concatenate([r, g, b], axis=1),
|
||||
pack([r, g, b], "h *")[0],
|
||||
)
|
||||
check(
|
||||
np.concatenate([r, g, b], axis=0),
|
||||
pack([r, g, b], "* w")[0],
|
||||
)
|
||||
|
||||
i = np.index_exp[:, :, None]
|
||||
check(
|
||||
np.concatenate([r[i], g[i], b[i], embeddings], axis=2),
|
||||
pack([r, g, b, embeddings], "h w *")[0],
|
||||
)
|
||||
|
||||
with pytest.raises(EinopsError):
|
||||
pack([r, g, b, embeddings], "h w nonexisting_axis *")
|
||||
|
||||
pack([r, g, b], "some_name_for_H some_name_for_w1 *")
|
||||
|
||||
with pytest.raises(EinopsError):
|
||||
pack([r, g, b, embeddings], "h _w *") # no leading underscore
|
||||
with pytest.raises(EinopsError):
|
||||
pack([r, g, b, embeddings], "h_ w *") # no trailing underscore
|
||||
with pytest.raises(EinopsError):
|
||||
pack([r, g, b, embeddings], "1h_ w *")
|
||||
with pytest.raises(EinopsError):
|
||||
pack([r, g, b, embeddings], "1 w *")
|
||||
with pytest.raises(EinopsError):
|
||||
pack([r, g, b, embeddings], "h h *")
|
||||
# capital and non-capital are different
|
||||
pack([r, g, b, embeddings], "h H *")
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class UnpackTestCase:
|
||||
shape: typing.Tuple[int, ...]
|
||||
pattern: str
|
||||
|
||||
def dim(self):
|
||||
return self.pattern.split().index("*")
|
||||
|
||||
def selfcheck(self):
|
||||
assert self.shape[self.dim()] == 5
|
||||
|
||||
|
||||
cases = [
|
||||
# NB: in all cases unpacked axis is of length 5.
|
||||
# that's actively used in tests below
|
||||
UnpackTestCase((5,), "*"),
|
||||
UnpackTestCase((5, 7), "* seven"),
|
||||
UnpackTestCase((7, 5), "seven *"),
|
||||
UnpackTestCase((5, 3, 4), "* three four"),
|
||||
UnpackTestCase((4, 5, 3), "four * three"),
|
||||
UnpackTestCase((3, 4, 5), "three four *"),
|
||||
]
|
||||
|
||||
|
||||
def test_pack_unpack_with_numpy():
|
||||
case: UnpackTestCase
|
||||
|
||||
for case in cases:
|
||||
shape = case.shape
|
||||
pattern = case.pattern
|
||||
|
||||
x = rng.random(shape)
|
||||
# all correct, no minus 1
|
||||
unpack_and_pack(x, [[2], [1], [2]], pattern)
|
||||
# no -1, asking for wrong shapes
|
||||
with pytest.raises(EinopsError):
|
||||
unpack_and_pack(x, [[2], [1], [2]], pattern + " non_existent_axis")
|
||||
with pytest.raises(EinopsError):
|
||||
unpack_and_pack(x, [[2], [1], [1]], pattern)
|
||||
with pytest.raises(EinopsError):
|
||||
unpack_and_pack(x, [[4], [1], [1]], pattern)
|
||||
# all correct, with -1
|
||||
unpack_and_pack(x, [[2], [1], [-1]], pattern)
|
||||
unpack_and_pack(x, [[2], [-1], [2]], pattern)
|
||||
unpack_and_pack(x, [[-1], [1], [2]], pattern)
|
||||
_, _, last = unpack_and_pack(x, [[2], [3], [-1]], pattern)
|
||||
assert last.shape[case.dim()] == 0
|
||||
# asking for more elements than available
|
||||
with pytest.raises(EinopsError):
|
||||
unpack(x, [[2], [4], [-1]], pattern)
|
||||
# this one does not raise, because indexing x[2:1] just returns zero elements
|
||||
# with pytest.raises(EinopsError):
|
||||
# unpack(x, [[2], [-1], [4]], pattern)
|
||||
with pytest.raises(EinopsError):
|
||||
unpack(x, [[-1], [1], [5]], pattern)
|
||||
|
||||
# all correct, -1 nested
|
||||
rs = unpack_and_pack(x, [[1, 2], [1, 1], [-1, 1]], pattern)
|
||||
assert all(len(r.shape) == len(x.shape) + 1 for r in rs)
|
||||
rs = unpack_and_pack(x, [[1, 2], [1, -1], [1, 1]], pattern)
|
||||
assert all(len(r.shape) == len(x.shape) + 1 for r in rs)
|
||||
rs = unpack_and_pack(x, [[2, -1], [1, 2], [1, 1]], pattern)
|
||||
assert all(len(r.shape) == len(x.shape) + 1 for r in rs)
|
||||
|
||||
# asking for more elements, -1 nested
|
||||
with pytest.raises(EinopsError):
|
||||
unpack(x, [[-1, 2], [1], [5]], pattern)
|
||||
with pytest.raises(EinopsError):
|
||||
unpack(x, [[2, 2], [2], [5, -1]], pattern)
|
||||
|
||||
# asking for non-divisible number of elements
|
||||
with pytest.raises(EinopsError):
|
||||
unpack(x, [[2, 1], [1], [3, -1]], pattern)
|
||||
with pytest.raises(EinopsError):
|
||||
unpack(x, [[2, 1], [3, -1], [1]], pattern)
|
||||
with pytest.raises(EinopsError):
|
||||
unpack(x, [[3, -1], [2, 1], [1]], pattern)
|
||||
|
||||
# -1 takes zero
|
||||
unpack_and_pack(x, [[0], [5], [-1]], pattern)
|
||||
unpack_and_pack(x, [[0], [-1], [5]], pattern)
|
||||
unpack_and_pack(x, [[-1], [5], [0]], pattern)
|
||||
|
||||
# -1 takes zero, -1
|
||||
unpack_and_pack(x, [[2, -1], [1, 5]], pattern)
|
||||
|
||||
|
||||
def test_pack_unpack_against_numpy():
|
||||
for backend in collect_test_backends(symbolic=False, layers=False):
|
||||
print(f"test packing against numpy for {backend.framework_name}")
|
||||
check_zero_len = True
|
||||
|
||||
for case in cases:
|
||||
unpack_and_pack = unpack_and_pack_against_numpy
|
||||
shape = case.shape
|
||||
pattern = case.pattern
|
||||
|
||||
x = rng.random(shape)
|
||||
x = backend.from_numpy(x)
|
||||
# all correct, no minus 1
|
||||
unpack_and_pack(x, [[2], [1], [2]], pattern)
|
||||
# no -1, asking for wrong shapes
|
||||
with pytest.raises(EinopsError):
|
||||
unpack(x, [[2], [1], [1]], pattern)
|
||||
|
||||
with pytest.raises(EinopsError):
|
||||
unpack(x, [[4], [1], [1]], pattern)
|
||||
# all correct, with -1
|
||||
unpack_and_pack(x, [[2], [1], [-1]], pattern)
|
||||
unpack_and_pack(x, [[2], [-1], [2]], pattern)
|
||||
unpack_and_pack(x, [[-1], [1], [2]], pattern)
|
||||
|
||||
# asking for more elements than available
|
||||
with pytest.raises(EinopsError):
|
||||
unpack(x, [[2], [4], [-1]], pattern)
|
||||
# this one does not raise, because indexing x[2:1] just returns zero elements
|
||||
# with pytest.raises(EinopsError):
|
||||
# unpack(x, [[2], [-1], [4]], pattern)
|
||||
with pytest.raises(EinopsError):
|
||||
unpack(x, [[-1], [1], [5]], pattern)
|
||||
|
||||
# all correct, -1 nested
|
||||
unpack_and_pack(x, [[1, 2], [1, 1], [-1, 1]], pattern)
|
||||
unpack_and_pack(x, [[1, 2], [1, -1], [1, 1]], pattern)
|
||||
unpack_and_pack(x, [[2, -1], [1, 2], [1, 1]], pattern)
|
||||
|
||||
# asking for more elements, -1 nested
|
||||
with pytest.raises(EinopsError):
|
||||
unpack(x, [[-1, 2], [1], [5]], pattern)
|
||||
with pytest.raises(EinopsError):
|
||||
unpack(x, [[2, 2], [2], [5, -1]], pattern)
|
||||
|
||||
# asking for non-divisible number of elements
|
||||
with pytest.raises(EinopsError):
|
||||
unpack(x, [[2, 1], [1], [3, -1]], pattern)
|
||||
with pytest.raises(EinopsError):
|
||||
unpack(x, [[2, 1], [3, -1], [1]], pattern)
|
||||
with pytest.raises(EinopsError):
|
||||
unpack(x, [[3, -1], [2, 1], [1]], pattern)
|
||||
|
||||
if check_zero_len:
|
||||
# -1 takes zero
|
||||
unpack_and_pack(x, [[2], [3], [-1]], pattern)
|
||||
unpack_and_pack(x, [[0], [5], [-1]], pattern)
|
||||
unpack_and_pack(x, [[0], [-1], [5]], pattern)
|
||||
unpack_and_pack(x, [[-1], [5], [0]], pattern)
|
||||
|
||||
# -1 takes zero, -1
|
||||
unpack_and_pack(x, [[2, -1], [1, 5]], pattern)
|
||||
|
||||
|
||||
def test_pack_unpack_array_api():
|
||||
import numpy as xp
|
||||
|
||||
from einops import array_api as AA
|
||||
|
||||
if xp.__version__ < "2.0.0":
|
||||
pytest.skip()
|
||||
|
||||
for case in cases:
|
||||
shape = case.shape
|
||||
pattern = case.pattern
|
||||
x_np = rng.random(shape)
|
||||
x_xp = xp.from_dlpack(x_np)
|
||||
|
||||
for ps in [
|
||||
[[2], [1], [2]],
|
||||
[[1], [1], [-1]],
|
||||
[[1], [1], [-1, 3]],
|
||||
[[2, 1], [1, 1, 1], [-1]],
|
||||
]:
|
||||
x_np_split = unpack(x_np, ps, pattern)
|
||||
x_xp_split = AA.unpack(x_xp, ps, pattern)
|
||||
for a, b in zip(x_np_split, x_xp_split):
|
||||
assert np.allclose(a, AA.asnumpy(b + 0))
|
||||
|
||||
x_agg_np, ps1 = pack(x_np_split, pattern)
|
||||
x_agg_xp, ps2 = AA.pack(x_xp_split, pattern)
|
||||
assert ps1 == ps2
|
||||
assert np.allclose(x_agg_np, AA.asnumpy(x_agg_xp))
|
||||
|
||||
for ps in [
|
||||
[[2, 3]],
|
||||
[[1], [5]],
|
||||
[[1], [5], [-1]],
|
||||
[[1], [2, 3]],
|
||||
[[1], [5], [-1, 2]],
|
||||
]:
|
||||
with pytest.raises(EinopsError):
|
||||
unpack(x_np, ps, pattern)
|
||||
Reference in New Issue
Block a user