
Turning support and resistance importance into a number
Quantifying the support and resistance lines that human traders "feel" works. It finally provides a robust edge for my trend-following systems.
Quantifying the support and resistance lines that human traders “feel” works. It finally provides a robust edge for my trend-following systems. A reader once suggested that discretionary trading isn’t just gut instinct, but a logical response to price levels that can be quantified. The theory was that if you use low-complexity, interpretable indicators, you can capture that same edge statistically without the overfitting risks common in machine learning. I decided to build a “Level Engine” to put this to the test.
The Level Engine
I developed a new module, btengine/levels.py, to act as a mechanical eye for support and resistance. It calculates a “level score” based on how many times price touches a line, the strength of the rejection, and the momentum of the break. To keep things honest, I enforced a strict “no-lookahead” policy using trailing windows; this means the system only knows what happened in the past.
I then integrated this into my existing trend-following logic, adding a min_level_score filter. This ensures the algorithm only enters trades when it detects a “proven” level of interest.
Performance and Robustness
The results were the first time I have seen a pullback strategy pass my forward-testing robustness criteria (defined as being profitable in 5 out of 6 years).
| Filter Threshold | Return (4-6 years) | Years Profitable |
|---|---|---|
| None (Baseline) | +25.9% | 4/6 |
| Score ≥ 10 | +45.3% | 4/6 |
| Score ≥ 25 | +27.2% | 5/6 |
| Score ≥ 50 | +1.9% | 3/6 |
| The “sweet spot” for this filter is a score between 10 and 25. Beyond that, the system becomes too selective and trade frequency drops significantly. More importantly, when I ran a “parameter gauntlet” to test 15 different variations of the logic, 14 of them remained profitable in forward testing. Most achieved success in 5 out of 6 years. This pattern of robustness mirrors my previous success with Donchian channel strategies, suggesting this isn’t just a lucky curve-fit. |
Quality and Integration
The new logic significantly improved the quality of the strategy compared to the base breakout system.
- Profit Factor: 1.63 (vs. 1.27 for the base breakout)
- Sharpe Ratio: 1.16 (vs. 1.01)
- Drawdown: -7.8% (vs. -13.3%) In other words, the system is now generating smoother, more consistent equity curves. While it hasn’t completely decoupled from the base trend strategy (correlation remains at 0.52), the higher Sharpe ratio makes it a much better candidate for steady, long-term operation. Finally, I ran the “stress tests” to see how the system handles real-world volatility. The M1 intraday worst-case loss was 4.18%, and zero days triggered a failure. In the Monte Carlo simulations, it passed the first step with a 77% success rate. While the peak drawdown of 14% is manageable, the risk levels will need to be dialed back slightly to ensure it stays within prop-firm safety limits. The Level Engine is now a permanent part of my research foundation. The hypothesis holds: quantifying human-like line recognition is a reliable way to add edge to a mechanical system.
How this connects
This verification builds on earlier ones (what failed before and what I tried this time, comparisons between approaches).
- The gold strategy that won on every setting, then dropped 7.2%…
- A trading course coded whole scored PF 1.05, but its horizontal…
Code to reproduce
You can reproduce this with the following scripts (see repo).
btengine/levels.py