← Назад
// scorer.js - Density Trust Scoring v2 (x-multiplier based) function analyzeBehavior(bin, markPrice, natr, avg5mVol) { const now = Date.now(); const lifetimeMs = now - bin.oldestSeen; const lifetimeMins = lifetimeMs / 60000; const distancePct = Math.abs(bin.anchorPrice - markPrice) / markPrice * 100; // x-multiplier: how many times bigger is the wall vs avg 5min volume const xMult = avg5mVol > 0 ? bin.notional / avg5mVol : 0; let trustScore = 0; const tags = []; // === Base score from x-multiplier === // x4 = 20pts, x8 = 40pts, x15 = 60pts, x30+ = 80pts trustScore = Math.min(80, xMult * 5); // === Distance bonus/penalty === // Closer walls are more meaningful if (distancePct <= 0.5) { trustScore += 15; // Very close — imminent tags.push('CLOSE'); } else if (distancePct <= 1.0) { trustScore += 10; } else if (distancePct > 3.0) { trustScore -= 15; tags.push('FAR'); } if (distancePct > 5.0) { trustScore -= 20; tags.push('SPOOF-FAR'); } // === Lifetime bonus === if (lifetimeMins >= 15) { trustScore += 15; tags.push('CONCRETE'); } else if (lifetimeMins >= 5) { trustScore += 8; tags.push('HOLDING'); } else if (lifetimeMins < 0.5 && distancePct > 2.0) { trustScore -= 10; tags.push('NEW-FAR'); } // === Robot aggressor === if (bin.isMovingTowardPrice) { trustScore += 20; tags.push('ROBOT-AGGRESSOR'); } // === NATR alignment === if (natr > 0) { const isNearNatr1 = Math.abs(distancePct - natr) < 0.3; const isNearNatr2 = Math.abs(distancePct - natr * 2) < 0.3; if (isNearNatr1 || isNearNatr2) { trustScore += 10; tags.push('TECH-NATR'); } } // === Severity label === let severity = 'L'; // Low if (xMult >= 15) { severity = 'S'; // Strong } else if (xMult >= 8) { severity = 'M'; // Medium } // Cap 0-100 trustScore = Math.max(0, Math.min(100, Math.round(trustScore))); return { trustScore, tags, lifetimeMins, distancePct, xMult, severity }; } module.exports = { analyzeBehavior };