Quality Small Cap Strategy (US Market)
Small-cap stocks can deliver outsized returns when selected with fundamental quality filters. This strategy combines market capitalization, cash flow, profitability, growth, and valuation criteria to screen for small-cap companies with strong fundamentals in the US market.
Strategy Logic
A stock must satisfy all five conditions simultaneously to be included in the portfolio:
- Market Cap < $2 Billion -- Target small-cap stocks, which tend to have more room for excess returns compared to large caps.
- Free Cash Flow > 0 -- The company generates real cash, not just accounting profits.
- ROE > 0 -- The company is profitable with positive Return on Equity.
- Revenue Growth > 0 -- Top-line revenue is growing year-over-year, indicating business momentum.
- Price-to-Sales < 5 -- Valuation is not excessive, avoiding stocks priced at extreme multiples of their revenue.
Free cash flow is computed as operating cash flow plus investing cash flow, smoothed with a 4-quarter rolling average to reduce seasonal fluctuations. Price-to-sales is calculated using trailing four-quarter revenue and daily market capitalization.
Code
from finlab import data
from finlab.backtest import sim
from finlab.market import USMarket
data.set_market('us')
close = data.get('price:adj_close')
close = close[close.index.dayofweek < 5] # remove weekends
# Market capitalization
marketcap = data.get('us_key_metrics:marketCap')
# Free cash flow (operating + investing cash flows), smoothed over 4 quarters
operating_cf = data.get('us_cash_flow:operatingCashFlow')
investing_cf = data.get('us_cash_flow:capitalExpenditure')
free_cash_flow = (operating_cf + investing_cf).rolling(4).mean()
# ROE from financial statements
net_income = data.get('us_income_statement:netIncome')
equity = data.get('us_balance_sheet:totalStockholdersEquity')
roe = net_income / equity
# Revenue growth (YoY)
revenue = data.get('us_income_statement:revenue')
revenue_growth = revenue / revenue.shift(4) - 1
# Price-to-Sales ratio
trailing_revenue = revenue.rolling(4).sum()
ps_ratio = marketcap / trailing_revenue
# All five conditions must be met
condition1 = marketcap < 2e9
condition2 = free_cash_flow > 0
condition3 = roe > 0
condition4 = revenue_growth > 0
condition5 = ps_ratio < 5
position = condition1 & condition2 & condition3 & condition4 & condition5
report = sim(position, resample='M', market=USMarket(), fee_ratio=0.001, tax_ratio=0)
report.display()
Key Parameters
marketcap < 2e9: Filters for companies with market capitalization under $2 billion. The $2B threshold is a common definition for US small-cap stocks.free_cash_flow > 0: Ensures the company produces positive free cash flow. The 4-quarter rolling mean smooths out lumpy capital expenditure cycles.roe > 0: A basic profitability check. Companies with negative ROE are often distressed or in early-stage growth without earnings.revenue_growth > 0: Year-over-year revenue growth, computed by comparing the current quarter's revenue to the same quarter one year ago (shift of 4 quarters).ps_ratio < 5: Price-to-sales below 5 keeps the portfolio away from highly speculative, overvalued names.resample='M': Monthly rebalancing allows the portfolio to incorporate new quarterly financial data promptly.
Expected Behavior
- The number of qualifying stocks varies dynamically with market conditions. In bull markets, more companies meet all five criteria; in bear markets, fewer qualify, which naturally reduces exposure.
- Equal-weighting all qualifying stocks provides broad diversification across the small-cap quality universe.
- Small-cap stocks are inherently more volatile than large caps, but the quality filters (positive FCF, positive ROE, revenue growth, reasonable valuation) help avoid value traps and speculative names.
- This strategy is well-suited for investors seeking long-term capital appreciation from small-cap stocks with the discipline of fundamental quality screens.