Skip to content

fix(api): use N(d2) for probability of profit, not N(d1) (#8)#27

Open
bradsmithmba wants to merge 1 commit into
cloudtrainerwork:masterfrom
bradsmithmba:fix/pop-nd2
Open

fix(api): use N(d2) for probability of profit, not N(d1) (#8)#27
bradsmithmba wants to merge 1 commit into
cloudtrainerwork:masterfrom
bradsmithmba:fix/pop-nd2

Conversation

@bradsmithmba

Copy link
Copy Markdown

Summary

_calculate_probability_above() in src/api/enhanced_strategy_recommender.py returned norm.cdf(d1) as the probability that the underlying finishes above a target price. The correct risk-neutral probability P[S_T > K] is N(d2), not N(d1). N(d1) is the call delta — always larger than N(d2) — so every probability-of-profit figure in the system was overstated.

Closes #8.

Blast radius

This method is the single source of POP in the recommender. _calculate_probability_below() and _calculate_probability_between() both delegate to it, and strategy POP/prob_profit fields are computed from it, so the bias propagated everywhere POP is shown or used for ranking.

Fix

d2 = d1 - volatility * np.sqrt(t)
return norm.cdf(d2)

Verification

For S=100, K=105, vol=0.25, 30 days, r=0.05:

old N(d1) = 0.2784   (overstated)
new N(d2) = 0.2549   (correct risk-neutral P[S_T > K])
removed overstatement = 2.35 pts

No existing test asserts the previous (incorrect) value, so nothing else changes.

🤖 Generated with Claude Code

_calculate_probability_above() returned norm.cdf(d1) as the probability
that the underlying finishes above a target. The risk-neutral probability
P[S_T > K] is N(d2), not N(d1); N(d1) is the call delta and is always
larger, so every probability-of-profit figure was overstated.

Every POP value in the system flows through this method (directly and via
_calculate_probability_below / _between), so the bias was system-wide.

Compute d2 = d1 - sigma*sqrt(t) and return N(d2). For S=100, K=105,
vol=0.25, 30d, r=0.05 this corrects 0.2784 -> 0.2549 (a 2.35 pt
overstatement removed).

Closes cloudtrainerwork#8

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Probability of Profit uses N(d1) instead of N(d2) — overstates POP system-wide

1 participant