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.

72 lines
2.3 KiB
Python

from __future__ import annotations
from libs.intraday.features import (
compute_average_range,
compute_average_true_range,
compute_entropy_approx,
compute_gap_zscore,
enrich_daily_bars,
)
def _daily_bar(day: str, open_: float, high: float, low: float, close: float, volume: float = 1_000_000.0) -> dict:
return {
"date": day,
"open": open_,
"high": high,
"low": low,
"close": close,
"volume": volume,
}
def test_entropy_approx_is_bounded() -> None:
bars = []
close = 100.0
for idx in range(30):
close *= 1.0 + (0.01 if idx % 2 == 0 else -0.008)
bars.append(_daily_bar(f"2024-01-{idx+1:02d}", close * 0.99, close * 1.01, close * 0.98, close))
entropy = compute_entropy_approx(bars, lookback=20)
assert entropy is not None
assert 0.0 <= entropy <= 1.0
def test_enrich_daily_bars_populates_new_research_features() -> None:
ticker = "AAA"
bars = []
close = 100.0
for idx in range(70):
date_str = f"2024-03-{idx+1:02d}" if idx < 31 else f"2024-04-{idx-30:02d}"
gap = 0.002 if idx % 3 == 0 else -0.001
open_ = close * (1.0 + gap)
high = open_ * 1.02
low = open_ * 0.99
close = open_ * (1.0 + (0.004 if idx % 2 == 0 else -0.003))
bars.append(_daily_bar(date_str, open_, high, low, close))
trading_day = bars[-1]["date"]
enriched = enrich_daily_bars({ticker: bars}, [trading_day])
features = enriched[ticker][trading_day]
assert features["entropy_20d"] is not None
assert 0.0 <= features["entropy_20d"] <= 1.0
assert features["atr_ratio_10_60"] is not None
assert features["range_compression_10_60"] is not None
assert features["gap_zscore_20d"] is not None
def test_gap_zscore_and_range_helpers_return_values() -> None:
bars = []
close = 50.0
for idx in range(65):
open_ = close * (1.0 + 0.002)
high = open_ * 1.03
low = open_ * 0.98
close = open_ * 1.001
bars.append(_daily_bar(f"2024-05-{idx+1:02d}", open_, high, low, close))
assert compute_average_true_range(bars, 10) is not None
assert compute_average_range(bars, 10) is not None
assert compute_gap_zscore(bars[:-1], today_open=bars[-1]["open"], lookback=20) is not None