fix(suggestion): profit buckets require combined_score > 0 (owner rule)

Owner: a stock with a NEGATIVE overall (combined) score must not be recommended
in the profit buckets, even with positive momentum + theme. BGRIM/TTB had
combined -0.029/-0.066 yet still landed in bucket 1.

- allocate_capital profit_pool now gates on combined_score > 0 (in addition to
  momentum>0 + theme>0), still ranking by momentum within that pool.
- Verified: bucket 1 now picks PTTGC (+0.209, mom +1.85) instead of BGRIM/TTB;
  BANPU in bucket 2; ADVANC/SCB/LH in bucket 3 by yield. Full suite 377 green.
This commit is contained in:
Kunthawat Greethong
2026-08-31 19:00:14 +07:00
parent 5b8a10c730
commit 54776d5647
3 changed files with 31 additions and 5 deletions

View File

@@ -142,6 +142,18 @@ class MomentumSelectionTest(unittest.TestCase):
self.assertEqual(b2, ["UP"]) # DOWN (falling price) excluded
self.assertNotIn("DOWN", b2)
def test_negative_combined_excluded_from_profit_buckets(self):
# Owner rule: a stock whose OVERALL (combined) score is negative must not
# be recommended in the profit buckets, even with positive momentum/theme.
cands = [
self._cand("NEG_A", 10.0, -0.05, True, 2.0, +2.0, 0.6), # momentum up, theme +, but combined negative
self._cand("POS_B", 10.0, 0.20, True, 2.0, +1.5, 0.6), # combined positive
]
res = allocate_capital(1_000_000, cands)
b1 = [o.symbol for o in res.orders if o.bucket == 1]
self.assertNotIn("NEG_A", b1) # combined negative -> excluded
self.assertIn("POS_B", b1)
class PriceSnapshotTest(unittest.TestCase):
"""Regression: load_price_snapshot must pick the snapshot retrieved MOST