25 lines
1.1 KiB
Python
25 lines
1.1 KiB
Python
"""latest_target_weights: the current per-symbol target weight vector (dollar-neutral, gross=1)."""
|
|
from __future__ import annotations
|
|
|
|
import numpy as np
|
|
|
|
from fxhnt.application.crypto_momentum_research import latest_target_weights
|
|
|
|
|
|
def test_dollar_neutral_gross_one() -> None:
|
|
# 12 symbols, rising trends with different slopes -> distinct momentum ranks
|
|
rng = np.random.default_rng(0)
|
|
n = 12
|
|
close = np.cumprod(1.0 + np.linspace(0.0002, 0.004, n) + rng.normal(0, 1e-4, (200, n)), axis=0)
|
|
syms = [f"C{i}" for i in range(n)]
|
|
w = latest_target_weights(close, syms, lookback=30, min_names=10)
|
|
vals = np.array(list(w.values()))
|
|
assert abs(vals.sum()) < 1e-9 # dollar-neutral
|
|
assert abs(np.abs(vals).sum() - 1.0) < 1e-9 # gross = 1
|
|
assert (vals > 0).any() and (vals < 0).any() # both long and short
|
|
|
|
|
|
def test_too_few_names_returns_empty() -> None:
|
|
close = np.cumprod(1.0 + np.full((100, 3), 0.001), axis=0)
|
|
assert latest_target_weights(close, ["A", "B", "C"], lookback=30, min_names=10) == {}
|