Master

Factor investing

Factors are traits that have, on average, earned a little extra return over history, value, momentum, size. They're not sure bets; they're small edges that show up across many years and many markets. Combining several is how people build something more robust than a single good idea.

What you will see

Combined score: 0.00

About 2 min of reading

Quick check

Before this new lesson, one small question about the lesson you just finished. Recall it, do not look it up.

Try It

Factors are traits like value, momentum, and size that have earned small extra returns over history. I standardize each to a z-score so they are comparable, combine them into one rank, and buy the top scorers while watching for factors that fade.

1

I standardize value, momentum, and size to z-scores so they share a common scale before being combined into a single ranking.

import math value = [0.5, -1.0, 2.0] momentum = [20.0, -5.0, 300.0] size = [500, 100, 1000] def zscore(values): n = len(values) mean = sum(values) / n var = sum((v - mean) ** 2 for v in values) / n std = math.sqrt(var) return [(v - mean) / std for v in values] print("Factor investing") print("Value z-score: %.2f" % zscore(value)[0]) print("Momentum z-score: %.2f" % zscore(momentum)[0]) print("Size z-score: %.2f" % zscore(size)[0])

Before you run it, say out loud what it will print. Then open the answer.

What it prints
Factor investing Value z-score: 0.00 Momentum z-score: -0.61 Size z-score: -0.09
A z-score keeps the biggest raw number from winning just by accident. Standardize everything to a shared scale before ranking.
2

I add the scores together into one composite rank and print the combined value so the top of the list can be bought without second-guessing every day.

value = [0.5, -1.0, 2.0] momentum = [20.0, -5.0, 300.0] def zscore(values): n = len(values) mean = sum(values) / n var = sum((v - mean) ** 2 for v in values) / n std = 1.0 return [(v - mean) / std for v in values] combined = [zscore(value)[i] + zscore(momentum)[i] for i in range(3)] print("Combined score: %.2f" % sum(combined))

Before you run it, say out loud what it will print. Then open the answer.

What it prints
Combined score: 0.00
The clever part is making the list. The boring, necessary part is having the discipline to follow it without second-guessing every day.

Data Flow

Stocks are scored on several factors, combined into one ranking, and traded systematically while watching for factors that fade.
1 Pick factors
↓
2 Score each stock
↓
3 Combine into one ranking
↓
4 Trade the top scored
Line by line

Read the first example one line at a time. A line that prints shows what appears on screen; the rest set things up quietly.

import math sets nothing on screen
value = [0.5, -1.0, 2.0] sets nothing on screen
momentum = [20.0, -5.0, 300.0] sets nothing on screen
size = [500, 100, 1000] sets nothing on screen
def zscore(values): sets nothing on screen
n = len(values) sets nothing on screen
mean = sum(values) / n sets nothing on screen
var = sum((v - mean) ** 2 for v in values) / n sets nothing on screen
std = math.sqrt(var) sets nothing on screen
return [(v - mean) / std for v in values] sets nothing on screen
print("Factor investing") Factor investing
print("Value z-score: %.2f" % zscore(value)[0]) Value z-score: 0.00
print("Momentum z-score: %.2f" % zscore(momentum)[0]) Momentum z-score: -0.61
print("Size z-score: %.2f" % zscore(size)[0]) Size z-score: -0.09
Why this works
Building a factor score

Rank every stock on each factor, then combine the ranks into a single score. Buy the top scorers and hold them systematically. It's how a pile of small, half-baked ideas becomes one disciplined rule you can actually follow.

Factors can disappear

A factor that paid for years can stop paying the moment too many people harvest it. The market eats easy edges, and master-level quant work includes watching for the ones fading and finding replacements before everyone else notices.

Examples

What tends to pay a premium

Value stocks (cheap): +premium
Small companies:        +premium
Strong recent price:    +premium (momentum)

Each factor is a small tilt, not a jackpot. Stacking several of them gives a portfolio that survives when any one of them is out of favor. Betting on one idea is a gamble. Betting on many at once is closer to insurance.

Making factors comparable

z = (value_ratio - value_ratio.mean()) / value_ratio.std()

Factors live on different scales, a z-score can't be compared to a price-to-earnings ratio directly. Standardizing each to a z-score puts them on the same footing so value and momentum contribute fairly, and the biggest raw number doesn't just win by accident.

Combining the scores into one list

Value z-score:   1.2
Momentum z:      0.8
Size z:         -0.5
Combined score:  1.5

A single composite rank mixes several edges into one ranking. Buy the top of the list and hold it without second-guessing every day. The boring part is the discipline; the clever part is making the list in the first place.

Words this lesson uses

Each one is defined here on this site. Open the entry for the full definition and the other words it points at.

← Simple models and predictions
Previous Lesson
Simple models and predictions
Next Lesson
Going live with a system
Going live with a system →