Skip to main content

kestrel_chartkit/engine/
liquidity_path.rs

1#[cfg(feature = "serde")]
2use serde::{Deserialize, Serialize};
3
4/// Quantitative version of "da ist nichts im Weg" (plan Anhang G.3). `lvn_width_atr` and
5/// `distance_to_hvn_atr` are expected to already be ATR-normalized by the caller;
6/// `volume_density` is the traded-volume share at the current price bucket (0.0..1.0, lower
7/// = thinner / more "free space").
8///
9/// Deliberately distinct from real-time order-book liquidity — this measures **historical
10/// volume void / LVN**, not **current order-book liquidity** (plan Anhang G.3: "keine
11/// Liquidität im Weg" clarification). The latter needs order-book data this crate does not
12/// have.
13#[derive(Debug, Clone, Copy, PartialEq)]
14#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
15pub struct FreeSpaceScore {
16    /// 0.0..100.0, higher = more free space ahead.
17    pub score: f64,
18    pub lvn_width_atr: f64,
19    pub distance_to_hvn_atr: f64,
20    pub volume_density: f64,
21}
22
23pub fn build_free_space_score(
24    lvn_width_atr: f64,
25    distance_to_hvn_atr: f64,
26    volume_density: f64,
27) -> FreeSpaceScore {
28    let density_component = (1.0 - volume_density.clamp(0.0, 1.0)) * 40.0;
29    let width_component = lvn_width_atr.clamp(0.0, 3.0) / 3.0 * 30.0;
30    let distance_component = distance_to_hvn_atr.clamp(0.0, 3.0) / 3.0 * 30.0;
31    let score = (density_component + width_component + distance_component).clamp(0.0, 100.0);
32    FreeSpaceScore {
33        score,
34        lvn_width_atr,
35        distance_to_hvn_atr,
36        volume_density,
37    }
38}
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43
44    #[test]
45    fn thin_wide_far_book_scores_high() {
46        let out = build_free_space_score(3.0, 3.0, 0.0);
47        assert!((out.score - 100.0).abs() < 1e-9);
48    }
49
50    #[test]
51    fn dense_narrow_close_book_scores_low() {
52        let out = build_free_space_score(0.0, 0.0, 1.0);
53        assert!(out.score.abs() < 1e-9);
54    }
55}