bitcoin-heuristics 0.1.0

Pattern detection heuristics for Bitcoin on-chain analytics — consolidations, distributions, CoinJoin, fee spikes, dormant supply reactivation and more
Documentation
pub fn encode_btc_price(price_usd: Option<f64>) -> u8 {
    let price_usd = match price_usd {
        Some(p) => p,
        None => return 0,
    };
    if price_usd < 1.0 {
        return 0;
    }

    if price_usd <= 100.0 {
        return 1 + ((price_usd / 20.0) as u8).min(4);
    }

    if price_usd <= 1000.0 {
        return 6 + (((price_usd - 100.0) / 180.0) as u8).min(4);
    }

    if price_usd <= 10000.0 {
        return 11 + (((price_usd - 1000.0) / 600.0) as u8).min(14);
    }

    if price_usd <= 50000.0 {
        return 26 + (((price_usd - 10000.0) / 2666.0) as u8).min(14);
    }

    if price_usd <= 150000.0 {
        return 41 + (((price_usd - 50000.0) / 6666.0) as u8).min(14);
    }

    if price_usd <= 500000.0 {
        return 56 + (((price_usd - 150000.0) / 50000.0) as u8).min(6);
    }

    63
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_none_returns_zero() {
        assert_eq!(encode_btc_price(None), 0);
    }

    #[test]
    fn test_below_one_dollar_returns_zero() {
        assert_eq!(encode_btc_price(Some(0.5)), 0);
    }

    #[test]
    fn test_100k_usd_in_high_range() {
        let tier = encode_btc_price(Some(100_000.0));
        assert!(tier >= 41, "100k should be in the 41–55 range, got {tier}");
    }

    #[test]
    fn test_encoding_is_monotone() {
        let prices = [
            1.0, 100.0, 1_000.0, 10_000.0, 50_000.0, 100_000.0, 500_000.0,
        ];
        let tiers: Vec<u8> = prices.iter().map(|&p| encode_btc_price(Some(p))).collect();
        for i in 1..tiers.len() {
            assert!(
                tiers[i] >= tiers[i - 1],
                "tier[{}]={} should be >= tier[{}]={} (prices: {} vs {})",
                i,
                tiers[i],
                i - 1,
                tiers[i - 1],
                prices[i],
                prices[i - 1]
            );
        }
    }

    #[test]
    fn test_max_tier_at_very_high_price() {
        assert_eq!(encode_btc_price(Some(1_000_000.0)), 63);
    }
}