feat: bollinger bands support in rule-based DSL + chart overlay
Add BollingerUpper and BollingerLower as composable FuncName variants, enabling Bollinger Bands in any expression context (compare, cross_over, cross_under, apply_func). The multiplier field carries num_std_dev (default 2.0). Chart auto-detects bollinger_upper/lower func nodes and the legacy bollinger condition, rendering three lines (middle solid, upper/lower dashed). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -95,7 +95,8 @@ All expressions have a "kind" discriminator.
|
||||
"field": "open"|"high"|"low"|"close"|"volume", // which candle field (ignored for atr/adx/supertrend)
|
||||
"period": <int>,
|
||||
"offset": <int> // omit or 0 = current bar; 1 = window shifted one bar back
|
||||
// "multiplier": "<decimal>" — only for supertrend (ATR multiplier, typically "3.0")
|
||||
// "multiplier": "<decimal>" — for supertrend: ATR multiplier (typically "3.0")
|
||||
// — for bollinger_upper/bollinger_lower: num_std_dev (typically "2.0")
|
||||
}
|
||||
|
||||
### Bars since a condition last fired
|
||||
@@ -215,11 +216,14 @@ The API rejects backtest creation if any referenced timeframe lacks coverage.
|
||||
| rsi | RSI via Wilder's smoothing, result in [0,100] | yes |
|
||||
| std_dev | population standard deviation | yes |
|
||||
| sum | rolling sum | yes |
|
||||
| atr | Average True Range (Wilder simple avg, not smoothed) | NO (uses H/L/C) |
|
||||
| supertrend | Supertrend line (band-flip, ATR-based) | NO (uses H/L/C) |
|
||||
| adx | Average Directional Index, Wilder smoothing [0,100] | NO (uses H/L/C) |
|
||||
| atr | Average True Range (Wilder simple avg, not smoothed) | NO (uses H/L/C) |
|
||||
| supertrend | Supertrend line (band-flip, ATR-based) | NO (uses H/L/C) |
|
||||
| adx | Average Directional Index, Wilder smoothing [0,100] | NO (uses H/L/C) |
|
||||
| bollinger_upper | Upper Bollinger Band: SMA + multiplier×StdDev (multiplier default 2.0) | yes |
|
||||
| bollinger_lower | Lower Bollinger Band: SMA − multiplier×StdDev (multiplier default 2.0) | yes |
|
||||
|
||||
atr, supertrend, adx, and rsi are NOT valid inside "apply_func" (return None silently).
|
||||
bollinger_upper and bollinger_lower ARE valid inside "apply_func" but use a fixed num_std_dev of 2.0 in that context.
|
||||
|
||||
## Warm-up / minimum bar counts required before a condition can fire
|
||||
|
||||
@@ -228,6 +232,7 @@ atr, supertrend, adx, and rsi are NOT valid inside "apply_func" (return None sil
|
||||
| sma / ema / wma / sum(N) | N bars |
|
||||
| rsi(N) | N+1 bars |
|
||||
| std_dev(N) | N bars |
|
||||
| bollinger_upper/lower(N) | N bars |
|
||||
| highest/lowest(N) | N bars |
|
||||
| atr(N) | N+1 bars |
|
||||
| adx(N) | 2*N+1 bars |
|
||||
@@ -284,6 +289,32 @@ Use a candle_interval and backtesting window long enough to cover warm-up.
|
||||
{ "kind": "position", "state": "flat" }
|
||||
]}
|
||||
|
||||
### Bollinger Bands: close crosses above upper band (breakout entry)
|
||||
"when": { "kind": "cross_over",
|
||||
"left": { "kind": "field", "field": "close" },
|
||||
"right": { "kind": "func", "name": "bollinger_upper", "field": "close", "period": 20, "multiplier": "2.0" }
|
||||
}
|
||||
|
||||
### Bollinger Bands: close crosses below lower band (mean-reversion entry)
|
||||
"when": { "kind": "cross_under",
|
||||
"left": { "kind": "field", "field": "close" },
|
||||
"right": { "kind": "func", "name": "bollinger_lower", "field": "close", "period": 20, "multiplier": "2.0" }
|
||||
}
|
||||
|
||||
### Bollinger Bands: price inside the bands (range filter)
|
||||
"when": { "kind": "all_of", "conditions": [
|
||||
{ "kind": "compare",
|
||||
"left": { "kind": "field", "field": "close" },
|
||||
"op": "<",
|
||||
"right": { "kind": "func", "name": "bollinger_upper", "field": "close", "period": 20, "multiplier": "2.0" }
|
||||
},
|
||||
{ "kind": "compare",
|
||||
"left": { "kind": "field", "field": "close" },
|
||||
"op": ">",
|
||||
"right": { "kind": "func", "name": "bollinger_lower", "field": "close", "period": 20, "multiplier": "2.0" }
|
||||
}
|
||||
]}
|
||||
|
||||
### VWAP entry (close crosses above VWAP over last 20 bars)
|
||||
"when": { "kind": "cross_over",
|
||||
"left": { "kind": "field", "field": "close" },
|
||||
|
||||
Reference in New Issue
Block a user