Support/Resistance Levels System Development
Automatic determination of support and resistance levels is a task that every experienced trader solves intuitively, but algorithmic implementation requires clear methodology. The system should find "significant" levels: those that price returns to repeatedly.
Methods for Determining Levels
1. Cluster Analysis of Pivot Points
Most common approach. Algorithm:
- Find all pivot highs and pivot lows for the period (rolling window)
- Group close levels into clusters (tolerance ±0.5% from price)
- Assess "strength" of each level: number of touches, volume at level, freshness
from scipy.cluster.hierarchy import linkage, fcluster
def cluster_levels(price_points, tolerance=0.005):
prices = np.array([p[1] for p in price_points]).reshape(-1, 1)
Z = linkage(prices, method='single')
labels = fcluster(Z, t=tolerance * np.mean(prices), criterion='distance')
clusters = {}
for i, label in enumerate(labels):
clusters.setdefault(label, []).append(price_points[i])
return {k: np.mean([p[1] for p in v]) for k, v in clusters.items()}
2. Volume Profile / POC
Levels with maximum trading volume — most significant zones. Point of Control (POC) — price level with largest volume for the period. This approach is described in detail in Volume Profile system.
3. Round Numbers and Psychological Levels
Round numbers (50000, 100000 for BTC; 3000, 4000 for ETH) act as levels purely psychologically. Algorithm additionally adds such levels with basic weight.
4. Fractal Levels
Bill Williams fractal: pivot high with two lower highs on each side. More strict definition of significant local maximum than simple rolling max.
Assessing Level Strength
Each level receives score based on several metrics:
| Metric | Description | Weight |
|---|---|---|
| Touch count | How many times price tested the level | High |
| Volume at level | Trading volume near the level | High |
| Recency | How recently the level was relevant | Medium |
| Bounce strength | How strongly price rebounded | Medium |
| Timeframe confluence | Level visible on multiple timeframes | High |
Level visible on both daily and 4h timeframe simultaneously receives significantly higher score.
Dynamic Levels
Static levels are supplemented with dynamic ones:
- Moving Averages (EMA 20, 50, 200) — dynamic S/R
- Bollinger Bands — upper/lower band as dynamic S/R
- VWAP and Anchored VWAP — dynamic levels based on volume
Visualization and Updates
Levels are drawn as horizontal lines or zones (rectangles) on price chart. Line thickness/color saturation proportional to level strength.
Zones instead of lines — level represented not as exact price, but as range (±ATR/4 from center price). This is more realistic: market "tests" the zone, not the point.
Automatic updates — when level breaks (price closes outside zone) it is marked as "broken" and status changes (support → resistance or vice versa — polarity change). New levels are added in real-time as pivot points accumulate.
Stack: Python for calculations (pandas, scipy, numpy), PostgreSQL for storing levels, WebSocket API for real-time frontend updates, React + TradingView Lightweight Charts for visualization. System scans specified list of instruments and updates levels on each candle close.







