Skip to content

What (One-liner)

BLCV batch scan: run the four-dimension BLCV analysis (V/B/C/L) over a set of tickers, synthesise with weights, sort descending, assign rank numbers, and emit the top_pick with the full ranking. The core tool for equity-pool shortlisting.

How to use

Drag blcv_equity_scan_v1 onto the Canvas, fill the required symbols list plus optional weights and optional peers_map (peers per ticker). Output is {count, top_pick, results[], logic_lineage}.

Typical usage:

scan_full(["META", "AAPL", "GOOG", "MSFT", "AMZN"])
→ count=5, top_pick="NVDA" (e.g.), ranked 1-5 by blcv_score desc

Core formulas

Essentially a map + sort over score_single:

for sym in symbols:
    result = score_single(sym, weights, peers_map.get(sym))  # 4 dim + compose
    results.append(result)

ranking = sorted(results, key=blcv_score, reverse=True)    # stable sort
for i, r in enumerate(ranking):
    r.rank = i + 1

top_pick = ranking[0].symbol if ranking else None

Underlying score_single formula (see the blcv_score_v1 card):

blcv_raw = (wB×B + wL×L + wC×C + wV×V) / Σw
if industry ∈ avoided: blcv_raw ×= 0.6
blcv_score = round(clamp(blcv_raw, 0, 100), 2)

Assumptions & applicability

Assumptions: yfinance available + the four dimension analyzers' assumptions + DEFAULT_WEIGHTS + hardcoded thresholds.

Fits: US-equity shortlists, peer baskets, factor-investing ranking, quarterly reviews.

Does not fit: 100+ symbols (slow), non-US names, multi-factor attribution, time-series BLCV.

Input / Output contract

{symbols: list[str], weights?: dict, peers_map?: dict[sym, list[sym]]}{count: int, top_pick: str | null, results: list[{symbol, rank, blcv_score, signal, dimension_scores, margin_of_safety, details, ...}], logic_lineage: list[str]}.

A per-symbol exception becomes {symbol, error, blcv_score: 0} at the ranking tail.

Known limitations

  1. Sequential, no concurrency — N symbols = N yfinance calls
  2. Failed symbols appear at the ranking tail with blcv_score=0 (not excluded) — callers must check the error field
  3. DEFAULT_WEIGHTS / industry penalty ×0.6 / signal thresholds are all hardcoded
  4. Stable sort keeps input order on ties → potentially confusing in UI
  5. No caching (two scans of the same symbol fetch twice)
  6. peers_map is optional → without it the C dimension's peer_comparison is null

References

Graham-Dodd (1934) batch-screening methodology + Fama-French (1992) factor-ranking framework + Asness et al. (2013) multi-factor evidence. Full citations in the frontmatter.

Golden Test

tests/golden/fixtures/tier2/blcv_equity_scan/ — a yfinance-snapshot integration regression (single-symbol wrapper path), 1e-6 tolerance, 6 tests:

  • matches_snapshot — deep comparison of the full output
  • determinism — 5 reruns byte-identical
  • rank_assignment — multi-symbol (shared snapshot → equal scores), ranks=[1,2,3] with stable sort
  • empty_symbols — N=0 → count=0, top_pick=null, results=[]
  • logic_lineage_format — ["BLCV full scan", "symbols=AAPL,MSFT"]
  • result_preserves_rank_field — every result carries an integer rank

The four underlying dimensions have independent goldens (tier1/blcv_financials, tier1/blcv_business, tier2/blcv_compete, tier2/blcv_leadership) — this test focuses on the wrapper mechanics.

Changelog

  • 1.0.0 (2026-04-20) — First Active (Tier 2 batch 4, batch wrapper)

Verifiable intelligence for the decisions that demand scrutiny.