MCP Server live — AI agents can now query 105M+ SEC facts. Connect your agent →
ValueinValuein
quant
intermediate
10 min

Factor-Based Stock Screening

Build a multi-factor stock screen using cross-sectional percentile ranks. Filter by ROE, Piotroski F-score, FCF yield, and momentum signals.

Python SDKMCP ServerDuckDB

What Are Factor Scores?

Factor scores are cross-sectional percentile ranks computed across the full universe. A score of 1.0 means best in universe, 0.0 means worst. Valuein computes 10 factors: ROE, gross margin, operating margin, net profit margin, revenue growth YoY, FCF-to-assets, debt-to-equity, asset turnover, current ratio, and Piotroski F-score.

Screen via MCP (in Claude or Cursor)

Ask your AI agent to screen the universe directly using the screen_universe tool.

# In Claude or Cursor with MCP configured:
# "Show me the top 10 Technology companies by composite factor rank"

# The MCP tool call:
# screen_universe(sector="Technology", sort_by="composite_rank", limit=10)

Screen via Python SDK

Use DuckDB to query factor_scores.parquet directly for more flexibility.

from valuein_sdk import ValueinClient, ValueinError

try:
    with ValueinClient() as client:

        # Top 20 companies with strong profitability AND low debt
        results = client.query("""
          SELECT symbol, name, sector,
            composite_rank,
            roe_rank,
            gross_margin_rank,
            debt_to_equity_rank,
            piotroski_f_score_rank
          FROM factor_scores
          JOIN references USING (entity_id)
          WHERE roe_rank > 0.8          -- Top 20% ROE
            AND debt_to_equity_rank > 0.7 -- Low debt (high rank = low D/E)
            AND piotroski_f_score_rank > 0.7
          ORDER BY composite_rank DESC
          LIMIT 20
        """)
        print(results)

except ValueinError as e:
    print(f"Error: {e}")

Build a Composite Score

Combine multiple factors with custom weights instead of using the equal-weighted composite.

# Continuing from above — reuse the same client context
        custom_screen = client.query("""
          SELECT symbol, name, sector,
            -- Custom weighted composite: 40% profitability, 30% quality, 30% value
            (0.4 * roe_rank
             + 0.2 * gross_margin_rank
             + 0.3 * fcf_to_assets_rank
             + 0.1 * debt_to_equity_rank) AS custom_score
          FROM factor_scores
          JOIN references USING (entity_id)
          WHERE symbol IS NOT NULL
          ORDER BY custom_score DESC
          LIMIT 25
        """)
        print(custom_screen)

Up next

Point-in-Time Backtesting

Construct survivorship-bias-free factor portfolios using knowledge_at timestamps and PIT universe snapshots.

Read next