You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
73 lines
2.5 KiB
Python
73 lines
2.5 KiB
Python
"""Unit tests for market feature calculations."""
|
|
|
|
from libs.oracle_client.models import PriceBar
|
|
|
|
BARS = [
|
|
PriceBar(date="2026-01-26", open=227.5, high=230.0, low=226.0, close=229.5, volume=48000000),
|
|
PriceBar(date="2026-01-27", open=229.0, high=232.0, low=228.0, close=231.0, volume=55000000),
|
|
PriceBar(date="2026-01-28", open=231.5, high=234.0, low=230.0, close=233.0, volume=60000000),
|
|
PriceBar(date="2026-01-29", open=240.0, high=245.0, low=238.0, close=243.0, volume=120000000),
|
|
]
|
|
|
|
|
|
def test_reaction_day_return():
|
|
from libs.features.market_features import reaction_day_return
|
|
r = reaction_day_return(BARS, "2026-01-29")
|
|
assert r is not None
|
|
expected = (243.0 - 233.0) / 233.0
|
|
assert abs(r - expected) < 1e-6
|
|
|
|
|
|
def test_reaction_day_return_missing_date():
|
|
from libs.features.market_features import reaction_day_return
|
|
assert reaction_day_return(BARS, "2026-12-01") is None
|
|
|
|
|
|
def test_volume_ratio_20d():
|
|
from libs.features.market_features import volume_ratio_20d
|
|
r = volume_ratio_20d(BARS, "2026-01-29")
|
|
assert r is not None
|
|
avg = (48000000 + 55000000 + 60000000) / 3
|
|
assert abs(r - 120000000 / avg) < 1e-3
|
|
|
|
|
|
def test_close_location():
|
|
from libs.features.market_features import close_location
|
|
bar = PriceBar(date="2026-01-29", open=240.0, high=245.0, low=238.0, close=243.0, volume=120000000)
|
|
cl = close_location(bar)
|
|
assert cl is not None
|
|
expected = (243.0 - 238.0) / (245.0 - 238.0)
|
|
assert abs(cl - expected) < 1e-6
|
|
|
|
|
|
def test_close_location_zero_range():
|
|
from libs.features.market_features import close_location
|
|
bar = PriceBar(date="2026-01-29", open=100.0, high=100.0, low=100.0, close=100.0, volume=1000)
|
|
assert close_location(bar) is None
|
|
|
|
|
|
def test_gap_size():
|
|
from libs.features.market_features import gap_size
|
|
g = gap_size(BARS, "2026-01-29")
|
|
assert g is not None
|
|
expected = (240.0 - 233.0) / 233.0
|
|
assert abs(g - expected) < 1e-6
|
|
|
|
|
|
def test_atr_14():
|
|
from libs.features.market_features import atr_14
|
|
# With fewer than 14 bars, should still return avg TR
|
|
r = atr_14(BARS)
|
|
assert r is not None
|
|
assert r > 0
|
|
|
|
|
|
def test_compute_market_features_dict():
|
|
from libs.features.market_features import compute_market_features
|
|
features = compute_market_features(BARS, "2026-01-29")
|
|
assert "reaction_day_return" in features
|
|
assert "volume_ratio_20d" in features
|
|
assert "gap_size" in features
|
|
assert "atr_14" in features
|
|
assert "close_location" in features
|