@backtest-kit/sidekick 0.1.2 β†’ 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +120 -13
  2. package/content/config/source/timeframe_15m.pine +114 -0
  3. package/content/config/source/timeframe_4h.pine +57 -0
  4. package/content/config/symbol.config.cjs +460 -0
  5. package/content/docker/ollama/docker-compose.yaml +34 -0
  6. package/content/docker/ollama/watch.sh +2 -0
  7. package/content/scripts/cache/cache_candles.mjs +47 -0
  8. package/content/scripts/cache/cache_model.mjs +42 -0
  9. package/content/scripts/cache/validate_candles.mjs +46 -0
  10. package/content/scripts/run_timeframe_15m.mjs +77 -0
  11. package/content/scripts/run_timeframe_4h.mjs +68 -0
  12. package/package.json +2 -2
  13. package/scripts/init.mjs +40 -9
  14. package/src/classes/BacktestLowerStopOnBreakevenAction.mjs +18 -0
  15. package/src/classes/BacktestPartialProfitTakingAction.mjs +5 -0
  16. package/src/classes/BacktestPositionMonitorAction.mjs +4 -0
  17. package/src/config/setup.mjs +27 -1
  18. package/src/enum/ActionName.mjs +1 -1
  19. package/src/enum/FrameName.mjs +1 -0
  20. package/src/enum/RiskName.mjs +1 -1
  21. package/src/logic/action/backtest_lower_stop_on_breakeven.action.mjs +9 -0
  22. package/src/logic/exchange/binance.exchange.mjs +12 -2
  23. package/src/logic/frame/feb_2024.frame.mjs +10 -0
  24. package/src/logic/index.mjs +3 -2
  25. package/src/logic/risk/sl_distance.risk.mjs +32 -0
  26. package/src/logic/risk/tp_distance.risk.mjs +5 -3
  27. package/src/logic/strategy/main.strategy.mjs +29 -12
  28. package/src/main/bootstrap.mjs +1 -1
  29. package/src/math/timeframe_15m.math.mjs +68 -0
  30. package/src/math/timeframe_4h.math.mjs +53 -0
  31. package/template/CLAUDE.mustache +421 -0
  32. package/template/README.mustache +232 -24
  33. package/template/env.mustache +1 -17
  34. package/template/jsconfig.json.mustache +1 -0
  35. package/template/package.mustache +5 -4
  36. package/src/classes/BacktestTightenStopOnBreakevenAction.mjs +0 -13
  37. package/src/func/market.func.mjs +0 -46
  38. package/src/logic/action/backtest_tighten_stop_on_breakeven.action.mjs +0 -9
  39. package/src/logic/risk/rr_ratio.risk.mjs +0 -39
  40. /package/{types/backtest-kit.d.ts β†’ template/types.mustache} +0 -0
package/README.md CHANGED
@@ -1,25 +1,26 @@
1
1
  # 🧿 @backtest-kit/sidekick
2
2
 
3
- > The easiest way to create a new Backtest Kit trading bot project. Like create-react-app, but for algorithmic trading.
3
+ > The easiest way to create a new Backtest Kit trading bot project. Scaffolds a multi-timeframe crypto trading strategy with Pine Script indicators via [PineTS](https://github.com/QuantForgeOrg/PineTS) runtime, 4H trend filter + 15m signal generator, partial profit taking, breakeven trailing stops, and risk validation.
4
4
 
5
- ![bots](https://raw.githubusercontent.com/tripolskypetr/backtest-kit/HEAD/assets/bots.png)
5
+ ![screenshot](https://raw.githubusercontent.com/tripolskypetr/backtest-kit/HEAD/assets/screenshots/screenshot8.png)
6
6
 
7
7
  [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/tripolskypetr/backtest-kit)
8
8
  [![npm](https://img.shields.io/npm/v/@backtest-kit/sidekick.svg?style=flat-square)](https://npmjs.org/package/@backtest-kit/sidekick)
9
9
  [![License](https://img.shields.io/npm/l/@backtest-kit/sidekick.svg)](https://github.com/tripolskypetr/backtest-kit/blob/master/LICENSE)
10
10
 
11
- Create production-ready trading bots in seconds with pre-configured templates, LLM integration, and technical analysis.
12
-
13
11
  πŸ“š **[Backtest Kit Docs](https://backtest-kit.github.io/documents/example_02_first_backtest.html)** | 🌟 **[GitHub](https://github.com/tripolskypetr/backtest-kit)**
14
12
 
15
13
  ## ✨ Features
16
14
 
17
15
  - πŸš€ **Zero Config**: Get started with one command - no setup required
18
- - πŸ“¦ **Complete Template**: Includes backtest strategy, risk management, and LLM integration
19
- - πŸ€– **AI-Powered**: Pre-configured with DeepSeek, Claude, and GPT-5 fallback chain
20
- - πŸ“Š **Technical Analysis**: Built-in 50+ indicators via @backtest-kit/signals
21
- - πŸ”‘ **Environment Setup**: Auto-generated .env with all API key placeholders
22
- - πŸ“ **Best Practices**: Production-ready code structure with examples
16
+ - πŸ“Š **Multi-timeframe analysis** β€” 4H daily trend filter (RSI + MACD + ADX) combined with 15m entry signals (EMA crossover + volume spike + momentum)
17
+ - πŸ“œ **Pine Script indicators** β€” strategies written in TradingView Pine Script v5, executed locally via `@backtest-kit/pinets`
18
+ - πŸ›‘οΈ **Risk management** β€” SL/TP distance validation, Kelly-optimized partial profit taking (33/33/34%), breakeven trailing stop
19
+ - πŸ”„ **Position lifecycle** β€” full monitoring with scheduled/opened/closed/cancelled event logging
20
+ - πŸ”Œ **Binance integration** β€” OHLCV candles, order book depth, tick-precise price/quantity formatting via CCXT
21
+ - πŸ• **Historical frames** β€” predefined backtest periods covering bull runs, sharp drops, and sideways markets
22
+ - 🎨 **Web UI dashboard** β€” interactive charting via `@backtest-kit/ui`
23
+ - πŸ’Ύ **Persistent storage** β€” crash-safe state with atomic persistence for both backtest and live modes
23
24
 
24
25
  ## πŸš€ Quick Start
25
26
 
@@ -32,12 +33,104 @@ npm start
32
33
  ```
33
34
 
34
35
  That's it! You now have a working trading bot with:
35
- - Complete backtest setup
36
- - LLM-powered strategy
37
- - Multi-timeframe technical analysis
38
- - Risk management validation
36
+ - Multi-timeframe Pine Script strategy (4H trend + 15m signals)
37
+ - Risk management validation (SL/TP distance checks)
38
+ - Partial profit taking and breakeven trailing stops
39
+ - Cache utilities and debug scripts
40
+ - CLAUDE.md for AI-assisted strategy iteration
39
41
  - Environment configuration
40
42
 
43
+ ## πŸ—οΈ Generated Project Structure
44
+
45
+ ```
46
+ my-trading-bot/
47
+ β”œβ”€β”€ src/
48
+ β”‚ β”œβ”€β”€ index.mjs # Entry point β€” loads config, logic, bootstrap
49
+ β”‚ β”œβ”€β”€ main/bootstrap.mjs # Mode dispatcher (backtest / paper / live)
50
+ β”‚ β”œβ”€β”€ config/
51
+ β”‚ β”‚ β”œβ”€β”€ setup.mjs # Logger, storage, notifications, UI server
52
+ β”‚ β”‚ β”œβ”€β”€ validate.mjs # Schema validation for all enums
53
+ β”‚ β”‚ β”œβ”€β”€ params.mjs # Environment variables (Ollama API key)
54
+ β”‚ β”‚ └── ccxt.mjs # Binance exchange singleton via CCXT
55
+ β”‚ β”œβ”€β”€ logic/
56
+ β”‚ β”‚ β”œβ”€β”€ strategy/main.strategy.mjs # Main strategy β€” multi-TF signal logic
57
+ β”‚ β”‚ β”œβ”€β”€ exchange/binance.exchange.mjs # Exchange schema β€” candles, order book, formatting
58
+ β”‚ β”‚ β”œβ”€β”€ frame/*.frame.mjs # Backtest time frames (Feb 2024, Oct–Dec 2025)
59
+ β”‚ β”‚ β”œβ”€β”€ risk/sl_distance.risk.mjs # Stop-loss distance validation (β‰₯0.2%)
60
+ β”‚ β”‚ β”œβ”€β”€ risk/tp_distance.risk.mjs # Take-profit distance validation (β‰₯0.2%)
61
+ β”‚ β”‚ └── action/
62
+ β”‚ β”‚ β”œβ”€β”€ backtest_partial_profit_taking.action.mjs
63
+ β”‚ β”‚ β”œβ”€β”€ backtest_lower_stop_on_breakeven.action.mjs
64
+ β”‚ β”‚ └── backtest_position_monitor.action.mjs
65
+ β”‚ β”œβ”€β”€ classes/
66
+ β”‚ β”‚ β”œβ”€β”€ BacktestPartialProfitTakingAction.mjs # Scale out at 3 TP levels
67
+ β”‚ β”‚ β”œβ”€β”€ BacktestLowerStopOnBreakevenAction.mjs # Trailing stop on breakeven
68
+ β”‚ β”‚ └── BacktestPositionMonitorAction.mjs # Position event logger
69
+ β”‚ β”œβ”€β”€ math/
70
+ β”‚ β”‚ β”œβ”€β”€ timeframe_4h.math.mjs # 4H trend data β€” RSI, MACD, ADX, DI+/DI-
71
+ β”‚ β”‚ └── timeframe_15m.math.mjs # 15m signal data β€” EMA, ATR, volume, momentum
72
+ β”‚ β”œβ”€β”€ enum/ # String constants for type-safe schema refs
73
+ β”‚ └── utils/getArgs.mjs # CLI argument parser with defaults
74
+ β”œβ”€β”€ config/source/
75
+ β”‚ β”œβ”€β”€ timeframe_4h.pine # Pine Script v5 β€” Daily Trend Filter (RSI/MACD/ADX)
76
+ β”‚ └── timeframe_15m.pine # Pine Script v5 β€” Signal Strategy (EMA/ATR/Volume)
77
+ β”œβ”€β”€ scripts/
78
+ β”‚ β”œβ”€β”€ run_timeframe_15m.mjs # Standalone 15m Pine Script runner
79
+ β”‚ β”œβ”€β”€ run_timeframe_4h.mjs # Standalone 4H Pine Script runner
80
+ β”‚ └── cache/
81
+ β”‚ β”œβ”€β”€ cache_candles.mjs # Pre-download OHLCV candles (1m/15m/4h)
82
+ β”‚ β”œβ”€β”€ validate_candles.mjs # Verify cached candle data integrity
83
+ β”‚ └── cache_model.mjs # Pull Ollama LLM model with progress bar
84
+ β”œβ”€β”€ docker/ollama/
85
+ β”‚ β”œβ”€β”€ docker-compose.yaml # Ollama GPU container setup
86
+ β”‚ └── watch.sh # nvidia-smi monitor
87
+ β”œβ”€β”€ CLAUDE.md # AI strategy development guide
88
+ β”œβ”€β”€ .env # Environment variables
89
+ └── package.json # Dependencies
90
+ ```
91
+
92
+ ## πŸ’‘ Strategy Overview
93
+
94
+ ### 🎯 4H Trend Filter (`timeframe_4h.pine`)
95
+
96
+ Determines the market regime using three indicators:
97
+
98
+ | Regime | Condition |
99
+ |--------|-----------|
100
+ | **AllowLong** | ADX > 25, MACD histogram > 0, DI+ > DI-, RSI > 50 |
101
+ | **AllowShort** | ADX > 25, MACD histogram < 0, DI- > DI+, RSI < 50 |
102
+ | **AllowBoth** | Strong trend but no clear bull/bear regime |
103
+ | **NoTrades** | ADX ≀ 25 (weak trend) |
104
+
105
+ ### ⚑ 15m Signal Generator (`timeframe_15m.pine`)
106
+
107
+ Generates entry signals with EMA crossover confirmed by volume and momentum:
108
+
109
+ - **Long**: EMA(5) crosses above EMA(13), RSI 40–65, price above EMA(50), volume spike (>1.5x MA), positive momentum
110
+ - **Short**: EMA(5) crosses below EMA(13), RSI 35–60, price below EMA(50), volume spike, negative momentum
111
+ - **SL/TP**: Static 2%/3% from entry price
112
+ - **Signal expiry**: 5 bars
113
+
114
+ ### πŸ›‘οΈ Risk Filters
115
+
116
+ - Reject signals where SL distance < 0.2% (slippage protection)
117
+ - Reject signals where TP distance < 0.2% (slippage protection)
118
+ - Trend alignment: long signals rejected in bear regime, short signals rejected in bull regime
119
+
120
+ ### πŸ’Ή Position Management
121
+
122
+ - **Partial profit taking**: Scale out at 3 levels β€” 33% at TP3, 33% at TP2, 34% at TP1
123
+ - **Breakeven trailing stop**: When breakeven is reached, lower trailing stop by 3 points
124
+
125
+ ## πŸ• Backtest Frames
126
+
127
+ | Frame | Period | Market Note |
128
+ |-------|--------|-------------|
129
+ | `February2024` | Feb 1–29, 2024 | Bull run |
130
+ | `October2025` | Oct 1–31, 2025 | Sharp drop Oct 9–11 |
131
+ | `November2025` | Nov 1–30, 2025 | Sideways with downtrend |
132
+ | `December2025` | Dec 1–31, 2025 | Sideways, no clear direction |
133
+
41
134
  ## πŸ’‘ CLI Options
42
135
 
43
136
  ```bash
@@ -48,6 +141,20 @@ npx -y @backtest-kit/sidekick my-bot
48
141
  npx -y @backtest-kit/sidekick .
49
142
  ```
50
143
 
144
+ ## πŸ“‹ Dependencies
145
+
146
+ | Package | Purpose |
147
+ |---------|---------|
148
+ | [backtest-kit](https://libraries.io/npm/backtest-kit) | Core backtesting/trading framework |
149
+ | [@backtest-kit/pinets](https://github.com/QuantForgeOrg/PineTS) | Pine Script v5 runtime for Node.js |
150
+ | [@backtest-kit/ui](https://libraries.io/npm/backtest-kit) | Interactive charting dashboard |
151
+ | [@backtest-kit/ollama](https://libraries.io/npm/backtest-kit) | LLM inference integration |
152
+ | [ccxt](https://github.com/ccxt/ccxt) | Binance exchange connectivity |
153
+ | [functools-kit](https://www.npmjs.com/package/functools-kit) | `singleshot`, `randomString` utilities |
154
+ | [pinolog](https://www.npmjs.com/package/pinolog) | File-based structured logging |
155
+ | [openai](https://www.npmjs.com/package/openai) | OpenAI API client |
156
+ | [ollama](https://www.npmjs.com/package/ollama) | Ollama local LLM client |
157
+
51
158
  ## πŸ”— Links
52
159
 
53
160
  - [Backtest Kit Documentation](https://backtest-kit.github.io/documents/example_02_first_backtest.html)
@@ -0,0 +1,114 @@
1
+ //@version=5
2
+ indicator("Signal Strategy 15m v1", overlay=true)
3
+
4
+ plotcandle(open, high, low, close,
5
+ color=close > open ? color.new(color.green, 70) : color.new(color.red, 70),
6
+ wickcolor=color.new(color.gray, 70),
7
+ bordercolor=color.new(color.gray, 70))
8
+
9
+
10
+ // === INPUTS ===
11
+ rsi_len = input.int(7, "RSI Length", minval=2)
12
+ ema_fast_len = input.int(5, "EMA Fast", minval=1)
13
+ ema_slow_len = input.int(13, "EMA Slow", minval=1)
14
+ ema_trend_len = input.int(50, "EMA Trend", minval=1)
15
+ atr_len = input.int(14, "ATR Length", minval=1)
16
+ vol_ma_len = input.int(20, "Volume MA Length", minval=1)
17
+
18
+ sl_mult = input.float(1.5, "SL ATR Multiplier", minval=0.5, step=0.1)
19
+ tp_mult = input.float(2.5, "TP ATR Multiplier", minval=0.5, step=0.1)
20
+ signal_valid_bars = input.int(5, "Signal Valid Bars", minval=1)
21
+
22
+ // === INDICATORS ===
23
+ rsi = ta.rsi(close, rsi_len)
24
+ ema_fast = ta.ema(close, ema_fast_len)
25
+ ema_slow = ta.ema(close, ema_slow_len)
26
+ ema_trend = ta.ema(close, ema_trend_len)
27
+ atr = ta.atr(atr_len)
28
+
29
+ // Volume filter - Π²Ρ‹ΡˆΠ΅ срСднСго
30
+ vol_ma = ta.sma(volume, vol_ma_len)
31
+ vol_spike = volume > vol_ma * 1.5
32
+
33
+ // Momentum confirmation
34
+ mom = ta.mom(close, 3)
35
+ mom_up = mom > 0
36
+ mom_down = mom < 0
37
+
38
+ // === TREND FILTER ===
39
+ trend_up = close > ema_trend and ema_fast > ema_trend
40
+ trend_down = close < ema_trend and ema_fast < ema_trend
41
+
42
+ // === ENTRY CONDITIONS ===
43
+ // Long: пСрСсСчСниС + RSI Π½Π΅ ΠΏΠ΅Ρ€Π΅ΠΊΡƒΠΏΠ»Π΅Π½ + Ρ‚Ρ€Π΅Π½Π΄ Π²Π²Π΅Ρ€Ρ… + ΠΎΠ±ΡŠΡ‘ΠΌ + momentum
44
+ long_cond = ta.crossover(ema_fast, ema_slow) and rsi > 40 and rsi < 65 and trend_up and vol_spike and mom_up
45
+
46
+ // Short: пСрСсСчСниС + RSI Π½Π΅ ΠΏΠ΅Ρ€Π΅ΠΏΡ€ΠΎΠ΄Π°Π½ + Ρ‚Ρ€Π΅Π½Π΄ Π²Π½ΠΈΠ· + ΠΎΠ±ΡŠΡ‘ΠΌ + momentum
47
+ short_cond = ta.crossunder(ema_fast, ema_slow) and rsi < 60 and rsi > 35 and trend_down and vol_spike and mom_down
48
+
49
+ // === SIGNAL MANAGEMENT ===
50
+ var int bars_since_signal = 0
51
+ var int last_signal = 0
52
+ var float entry_price = na
53
+ var float signal_atr = na
54
+
55
+ if long_cond
56
+ last_signal := 1
57
+ bars_since_signal := 0
58
+ entry_price := close
59
+ signal_atr := atr
60
+ else if short_cond
61
+ last_signal := -1
62
+ bars_since_signal := 0
63
+ entry_price := close
64
+ signal_atr := atr
65
+ else
66
+ bars_since_signal += 1
67
+
68
+ // Signal expires faster on 15m
69
+ active_signal = bars_since_signal <= signal_valid_bars ? last_signal : 0
70
+
71
+ // === DYNAMIC SL/TP based on ATR ===
72
+ // sl = last_signal == 1 ? entry_price - signal_atr * sl_mult : last_signal == -1 ? entry_price + signal_atr * sl_mult : na
73
+ // tp = last_signal == 1 ? entry_price + signal_atr * tp_mult : last_signal == -1 ? entry_price - signal_atr * tp_mult : na
74
+
75
+ // === STATIC SL/TP for watch strategy ==
76
+ sl = last_signal == -1 ? close * 1.02 : close * 0.98
77
+ tp = last_signal == -1 ? close * 0.97 : close * 1.03
78
+
79
+ // === VISUALIZATION ===
80
+ line_color = active_signal == 1 ? color.green : active_signal == -1 ? color.red : color.gray
81
+
82
+ plot(ema_fast, "EMA Fast", color=color.new(color.blue, 50), linewidth=1)
83
+ plot(ema_slow, "EMA Slow", color=color.new(color.orange, 50), linewidth=1)
84
+ plot(ema_trend, "EMA Trend", color=color.new(color.white, 70), linewidth=2)
85
+
86
+ plotshape(long_cond, "Long", shape.triangleup, location.belowbar, color.green, size=size.small)
87
+ plotshape(short_cond, "Short", shape.triangledown, location.abovebar, color.red, size=size.small)
88
+
89
+ plot(close, "Active Signal", color=line_color, linewidth=6)
90
+
91
+ // === OUTPUTS FOR BOT ===
92
+ plot(close, "Close", display=display.data_window)
93
+ plot(active_signal, "Signal", display=display.data_window)
94
+ plot(sl, "StopLoss", display=display.data_window)
95
+ plot(tp, "TakeProfit", display=display.data_window)
96
+ plot(1440, "EstimatedTime", display=display.data_window) // 24 hour for 15m TF
97
+
98
+ // === DEBUG: INDICATOR DUMP ===
99
+ plot(rsi, "d_RSI", display=display.data_window)
100
+ plot(ema_fast, "d_EmaFast", display=display.data_window)
101
+ plot(ema_slow, "d_EmaSlow", display=display.data_window)
102
+ plot(ema_trend, "d_EmaTrend", display=display.data_window)
103
+ plot(atr, "d_ATR", display=display.data_window)
104
+ plot(volume, "d_Volume", display=display.data_window)
105
+ plot(vol_ma, "d_VolMA", display=display.data_window)
106
+ plot(vol_spike ? 1 : 0, "d_VolSpike", display=display.data_window)
107
+ plot(mom, "d_Mom", display=display.data_window)
108
+ plot(mom_up ? 1 : 0, "d_MomUp", display=display.data_window)
109
+ plot(mom_down ? 1 : 0, "d_MomDown", display=display.data_window)
110
+ plot(trend_up ? 1 : 0, "d_TrendUp", display=display.data_window)
111
+ plot(trend_down ? 1 : 0, "d_TrendDown", display=display.data_window)
112
+ plot(long_cond ? 1 : 0, "d_LongCond", display=display.data_window)
113
+ plot(short_cond ? 1 : 0, "d_ShortCond", display=display.data_window)
114
+ plot(bars_since_signal, "d_BarsSinceSignal", display=display.data_window)
@@ -0,0 +1,57 @@
1
+ //@version=5
2
+ indicator("Daily Trend Filter", overlay=true)
3
+
4
+ plotcandle(open, high, low, close,
5
+ color=close > open ? color.new(color.green, 70) : color.new(color.red, 70),
6
+ wickcolor=color.new(color.gray, 70),
7
+ bordercolor=color.new(color.gray, 70))
8
+
9
+ // === INPUTS ===
10
+ rsi_len = input.int(14, "RSI Length", minval=2)
11
+ macd_fast = input.int(12, "MACD Fast", minval=1)
12
+ macd_slow = input.int(26, "MACD Slow", minval=1)
13
+ macd_signal = input.int(9, "MACD Signal", minval=1)
14
+ adx_len = input.int(14, "ADX Length", minval=1)
15
+ adx_threshold = input.int(25, "ADX Threshold", minval=10)
16
+
17
+ rsi_bull_threshold = input.int(50, "RSI Bull Threshold", minval=50, maxval=70)
18
+ rsi_bear_threshold = input.int(50, "RSI Bear Threshold", minval=30, maxval=50)
19
+
20
+ // === INDICATORS ===
21
+ rsi = ta.rsi(close, rsi_len)
22
+ [macd_line, signal_line, macd_hist] = ta.macd(close, macd_fast, macd_slow, macd_signal)
23
+ [di_plus, di_minus, adx] = ta.dmi(adx_len, adx_len)
24
+
25
+ // === TREND FILTER LOGIC ===
26
+ strong_trend = adx > adx_threshold
27
+
28
+ bull_regime = strong_trend and macd_hist > 0 and di_plus > di_minus and rsi > rsi_bull_threshold
29
+
30
+ bear_regime = strong_trend and macd_hist < 0 and di_minus > di_plus and rsi < rsi_bear_threshold
31
+
32
+ both_allowed = strong_trend and not bull_regime and not bear_regime
33
+ no_trades = not strong_trend
34
+
35
+ // === VISUALIZATION ===
36
+ line_color = bull_regime ? color.green :
37
+ bear_regime ? color.red :
38
+ both_allowed ? color.gray :
39
+ color.orange
40
+
41
+ plot(close, "Active Signal", color=line_color, linewidth=6)
42
+
43
+ // === OUTPUTS FOR BOT ===
44
+ plot(bull_regime ? 1 : 0, "AllowLong", display=display.data_window)
45
+ plot(bear_regime ? 1 : 0, "AllowShort", display=display.data_window)
46
+ plot(both_allowed ? 1 : 0, "AllowBoth", display=display.data_window)
47
+ plot(no_trades ? 1 : 0, "NoTrades", display=display.data_window)
48
+ plot(rsi, "RSI", display=display.data_window)
49
+ plot(adx, "ADX", display=display.data_window)
50
+
51
+ // === DEBUG: INDICATOR DUMP ===
52
+ plot(macd_line, "d_MACDLine", display=display.data_window)
53
+ plot(signal_line, "d_SignalLine", display=display.data_window)
54
+ plot(macd_hist, "d_MACDHist", display=display.data_window)
55
+ plot(di_plus, "d_DIPlus", display=display.data_window)
56
+ plot(di_minus, "d_DIMinus", display=display.data_window)
57
+ plot(strong_trend ? 1 : 0, "d_StrongTrend", display=display.data_window)