fix bruno collection

This commit is contained in:
saikiranvella
2026-06-06 21:49:31 -04:00
parent 96a752ecf7
commit 17bc985260
25 changed files with 4361 additions and 94 deletions
+279
View File
@@ -0,0 +1,279 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import { StockScorer } from '../server/domains/screener/scorers/StockScorer.js';
import { ScoringConfig } from '../server/domains/shared/scoring/ScoringConfig.js';
import type { StockMetrics } from '../server/domains/shared/types/models.model.js';
const DEFAULT_RULES = {
gates: ScoringConfig.base.gates.STOCK,
weights: ScoringConfig.base.weights.STOCK,
thresholds: ScoringConfig.base.thresholds.STOCK,
};
test('StockScorer', async (t) => {
await t.test('rejects stock with high debt-to-equity ratio', () => {
const metrics: StockMetrics = {
peRatio: 15,
pegRatio: 1.0,
debtToEquity: 2.5, // Exceeds 1.5 gate
quickRatio: 1.0,
returnOnEquity: 20,
operatingMargin: 15,
netProfitMargin: 10,
revenueGrowth: 5,
fcfYield: 3,
priceToBook: 1.5,
} as any;
const result = StockScorer.score(metrics, DEFAULT_RULES);
assert.equal(result.label, '🔴 REJECT');
assert.ok(result.scoreSummary.includes('D/E'));
});
await t.test('rejects stock with low quick ratio', () => {
const metrics: StockMetrics = {
peRatio: 15,
pegRatio: 1.0,
debtToEquity: 1.0,
quickRatio: 0.5, // Below 0.8 gate
returnOnEquity: 20,
operatingMargin: 15,
netProfitMargin: 10,
revenueGrowth: 5,
fcfYield: 3,
priceToBook: 1.5,
} as any;
const result = StockScorer.score(metrics, DEFAULT_RULES);
assert.equal(result.label, '🔴 REJECT');
assert.ok(result.scoreSummary.includes('Quick'));
});
await t.test('rejects stock with high P/E ratio', () => {
const metrics: StockMetrics = {
peRatio: 25, // Exceeds 15 gate
pegRatio: 1.0,
debtToEquity: 1.0,
quickRatio: 1.0,
returnOnEquity: 20,
operatingMargin: 15,
netProfitMargin: 10,
revenueGrowth: 5,
fcfYield: 3,
priceToBook: 1.5,
} as any;
const result = StockScorer.score(metrics, DEFAULT_RULES);
assert.equal(result.label, '🔴 REJECT');
assert.ok(result.scoreSummary.includes('P/E'));
});
await t.test('rejects stock with high PEG ratio', () => {
const metrics: StockMetrics = {
peRatio: 15,
pegRatio: 1.5, // Exceeds 1.0 gate
debtToEquity: 1.0,
quickRatio: 1.0,
returnOnEquity: 20,
operatingMargin: 15,
netProfitMargin: 10,
revenueGrowth: 5,
fcfYield: 3,
priceToBook: 1.5,
} as any;
const result = StockScorer.score(metrics, DEFAULT_RULES);
assert.equal(result.label, '🔴 REJECT');
assert.ok(result.scoreSummary.includes('PEG'));
});
await t.test('scores high-quality stock positively', () => {
const metrics: StockMetrics = {
peRatio: 12, // Below gate
pegRatio: 0.8, // Below gate
debtToEquity: 0.5,
quickRatio: 1.2,
returnOnEquity: 25, // High ROE
operatingMargin: 20,
netProfitMargin: 15,
revenueGrowth: 10,
fcfYield: 5,
priceToBook: 2.0,
} as any;
const result = StockScorer.score(metrics, DEFAULT_RULES);
assert.notEqual(result.label, '🔴 REJECT');
// Should have positive score
assert.ok(result.audit?.passedGates);
});
await t.test('handles null/undefined metrics gracefully', () => {
const metrics: StockMetrics = {
peRatio: 15,
pegRatio: 1.0,
debtToEquity: null,
quickRatio: 1.0,
returnOnEquity: 20,
operatingMargin: null,
netProfitMargin: 10,
revenueGrowth: 5,
fcfYield: 3,
priceToBook: 1.5,
} as any;
const result = StockScorer.score(metrics, DEFAULT_RULES);
// Should not crash, null values are skipped in gate checks
assert.ok(result);
});
await t.test('passes all quality gates for strong stock', () => {
const metrics: StockMetrics = {
peRatio: 10,
pegRatio: 0.9,
debtToEquity: 0.3,
quickRatio: 1.5,
returnOnEquity: 30,
operatingMargin: 25,
netProfitMargin: 18,
revenueGrowth: 8,
fcfYield: 6,
priceToBook: 3.0,
} as any;
const result = StockScorer.score(metrics, DEFAULT_RULES);
assert.ok(result.audit?.passedGates);
assert.notEqual(result.label, '🔴 REJECT');
});
await t.test('includes audit trail of gate checks', () => {
const metrics: StockMetrics = {
peRatio: 25,
pegRatio: 1.0,
debtToEquity: 1.0,
quickRatio: 1.0,
returnOnEquity: 20,
operatingMargin: 15,
netProfitMargin: 10,
revenueGrowth: 5,
fcfYield: 3,
priceToBook: 1.5,
} as any;
const result = StockScorer.score(metrics, DEFAULT_RULES);
assert.ok(result.audit);
if (!result.audit?.passedGates) {
assert.ok(Array.isArray(result.audit?.failures));
}
});
await t.test('scores ROE as primary quality factor', () => {
const metricsLowRoe: StockMetrics = {
peRatio: 10,
pegRatio: 0.9,
debtToEquity: 0.3,
quickRatio: 1.5,
returnOnEquity: 5, // Low ROE
operatingMargin: 25,
netProfitMargin: 18,
revenueGrowth: 8,
fcfYield: 6,
priceToBook: 3.0,
} as any;
const metricsHighRoe: StockMetrics = {
peRatio: 10,
pegRatio: 0.9,
debtToEquity: 0.3,
quickRatio: 1.5,
returnOnEquity: 40, // High ROE
operatingMargin: 25,
netProfitMargin: 18,
revenueGrowth: 8,
fcfYield: 6,
priceToBook: 3.0,
} as any;
const resultLow = StockScorer.score(metricsLowRoe, DEFAULT_RULES);
const resultHigh = StockScorer.score(metricsHighRoe, DEFAULT_RULES);
// Both should pass gates, but high ROE should score better
assert.ok(resultLow.audit?.passedGates);
assert.ok(resultHigh.audit?.passedGates);
});
await t.test('rejects stock with multiple gate failures', () => {
const metrics: StockMetrics = {
peRatio: 25, // High
pegRatio: 1.5, // High
debtToEquity: 2.5, // High
quickRatio: 0.5, // Low
returnOnEquity: 5,
operatingMargin: 5,
netProfitMargin: 2,
revenueGrowth: -5,
fcfYield: -1,
priceToBook: 0.5,
} as any;
const result = StockScorer.score(metrics, DEFAULT_RULES);
assert.equal(result.label, '🔴 REJECT');
// Should have multiple failures
if (!result.audit?.passedGates && result.audit?.failures) {
assert.ok(result.audit.failures.length > 1);
}
});
await t.test('handles edge case of zero metrics', () => {
const metrics: StockMetrics = {
peRatio: 0,
pegRatio: 0,
debtToEquity: 0,
quickRatio: 0,
returnOnEquity: 0,
operatingMargin: 0,
netProfitMargin: 0,
revenueGrowth: 0,
fcfYield: 0,
priceToBook: 0,
} as any;
const result = StockScorer.score(metrics, DEFAULT_RULES);
// Should handle gracefully (zero is falsy, treated as null)
assert.ok(result);
});
await t.test('scores based on configured thresholds', () => {
const metricsLowMargin: StockMetrics = {
peRatio: 10,
pegRatio: 0.9,
debtToEquity: 0.3,
quickRatio: 1.5,
returnOnEquity: 20,
operatingMargin: 5, // Below medium threshold
netProfitMargin: 18,
revenueGrowth: 8,
fcfYield: 6,
priceToBook: 3.0,
} as any;
const metricsHighMargin: StockMetrics = {
peRatio: 10,
pegRatio: 0.9,
debtToEquity: 0.3,
quickRatio: 1.5,
returnOnEquity: 20,
operatingMargin: 25, // Above high threshold
netProfitMargin: 18,
revenueGrowth: 8,
fcfYield: 6,
priceToBook: 3.0,
} as any;
const resultLow = StockScorer.score(metricsLowMargin, DEFAULT_RULES);
const resultHigh = StockScorer.score(metricsHighMargin, DEFAULT_RULES);
// Both should pass gates
assert.ok(resultLow.audit?.passedGates);
assert.ok(resultHigh.audit?.passedGates);
});
});