mirror of
https://github.com/0xrsydn/idx-cli.git
synced 2026-11-07 09:45:36 +00:00
fix(core): symmetric bandar thresholds; bandar needs all investors
- Basis points truncate toward zero instead of flooring, so a reading of -4.9952% stays neutral like its mirror image and -14.9952% stays distribution; tests cover both signs at both thresholds through bandar_tier. Goldens move by the rounding (BBCA top 5: -2426 -> -2425). - With one investor side selected the summary has no total to weigh brokers against, so bandar and analyze_bandar reject it (INVALIDINPUT) instead of reading every tier as missing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V3syn2fN2LNo5pvTSqc6eh
This commit is contained in:
parent
970da26a0e
commit
4c2f0acff3
13 changed files with 73 additions and 18 deletions
|
|
@ -135,10 +135,12 @@ pub fn check_top(top: u8) -> Result<u8, IdxError> {
|
|||
}
|
||||
}
|
||||
|
||||
/// `part` in basis points of `whole`; `None` without a positive whole.
|
||||
/// `part` in basis points of `whole`, truncated toward zero so a negative
|
||||
/// reading never reaches a threshold its magnitude has not; `None` without
|
||||
/// a positive whole.
|
||||
fn bps(part: i64, whole: Option<i64>) -> Option<i64> {
|
||||
let whole = whole.filter(|whole| *whole > 0)?;
|
||||
i64::try_from((i128::from(part) * 10_000).div_euclid(i128::from(whole))).ok()
|
||||
i64::try_from(i128::from(part) * 10_000 / i128::from(whole)).ok()
|
||||
}
|
||||
|
||||
/// Sum of `field` over `flows`; `None` when any flow lacks it.
|
||||
|
|
@ -326,6 +328,37 @@ mod tests {
|
|||
assert_eq!(report.method, METHOD);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bandar_tier_thresholds_are_symmetric_for_sign() {
|
||||
let reading = |buy: i64, sell: i64| {
|
||||
let s = summary(
|
||||
vec![flow("AA", Some(buy), 100)],
|
||||
vec![flow("BB", Some(sell), 100)],
|
||||
2_100_000_000,
|
||||
);
|
||||
let tier = bandar_tier(&s, 1);
|
||||
(tier.imbalance_bps, tier.signal)
|
||||
};
|
||||
// -4.9952% and -14.9952% stay short of the thresholds, like their
|
||||
// mirror images.
|
||||
assert_eq!(
|
||||
reading(504_300_000, 609_200_000),
|
||||
(Some(-499), Some(BandarSignal::Neutral))
|
||||
);
|
||||
assert_eq!(
|
||||
reading(609_200_000, 504_300_000),
|
||||
(Some(499), Some(BandarSignal::Neutral))
|
||||
);
|
||||
assert_eq!(
|
||||
reading(504_300_000, 819_200_000),
|
||||
(Some(-1499), Some(BandarSignal::Distribution))
|
||||
);
|
||||
assert_eq!(
|
||||
reading(819_200_000, 504_300_000),
|
||||
(Some(1499), Some(BandarSignal::Accumulation))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_analyze_bandar_never_counts_a_missing_figure_as_zero() {
|
||||
let s = summary(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue