diff --git a/synth/validator/moving_average.py b/synth/validator/moving_average.py index 168d3e96..ff2ff290 100644 --- a/synth/validator/moving_average.py +++ b/synth/validator/moving_average.py @@ -121,7 +121,10 @@ def apply_per_asset_coefficients( df.loc[df["asset"] == asset, "prompt_score_v3"] *= coef sum_coefficients += coef * len(df.loc[df["asset"] == asset]) - df["prompt_score_v3"] /= sum_coefficients + if sum_coefficients == 0: + df["prompt_score_v3"] = 0.0 + else: + df["prompt_score_v3"] /= sum_coefficients return df["prompt_score_v3"] diff --git a/tests/test_asset_coefficients.py b/tests/test_asset_coefficients.py new file mode 100644 index 00000000..b56f03ba --- /dev/null +++ b/tests/test_asset_coefficients.py @@ -0,0 +1,43 @@ +import pandas as pd + +from synth.validator.moving_average import apply_per_asset_coefficients + + +def test_zero_coefficients_no_nan(): + """When all assets have coefficient 0 (unknown assets), scores should be 0, not NaN.""" + df = pd.DataFrame( + { + "asset": ["UNKNOWN_A", "UNKNOWN_B", "UNKNOWN_A"], + "prompt_score_v3": [0.5, 0.3, 0.7], + } + ) + result = apply_per_asset_coefficients(df) + assert not result.isna().any(), f"Got NaN: {result.tolist()}" + assert (result == 0.0).all() + + +def test_normal_coefficients_unchanged(): + """Normal assets with non-zero coefficients still work.""" + df = pd.DataFrame( + { + "asset": ["BTC", "ETH"], + "prompt_score_v3": [0.5, 0.3], + } + ) + result = apply_per_asset_coefficients(df) + assert not result.isna().any() + assert result.sum() > 0 + + +def test_mixed_zero_and_nonzero_coefficients(): + """Mix of zero-coef (unknown) and nonzero-coef assets.""" + df = pd.DataFrame( + { + "asset": ["BTC", "UNKNOWN_X"], + "prompt_score_v3": [0.5, 0.3], + } + ) + result = apply_per_asset_coefficients(df) + assert not result.isna().any() + # BTC has non-zero coef so total should be > 0 + assert result.sum() > 0