--- name: pine-script description: Convert Python backtest strategies to TradingView Pine Script v6, or generate Pine Script from natural language descriptions. category: tool --- ## Overview This skill enables two workflows: 1. **Export**: convert an existing `signal_engine.py` (from a completed backtest run) into a TradingView Pine Script v6 strategy 2. **Generate**: write Pine Script v6 directly from a natural-language strategy description Output file: `artifacts/strategy.pine` (inside the run directory, or a new run directory). ## Workflow: Export from Backtest 1. `load_skill("pine-script")` — read this conversion guide 2. `read_file("config.json")` — understand instruments, dates, parameters 3. `read_file("code/signal_engine.py")` — understand the Python strategy logic 4. **Translate** the strategy to Pine Script v6 using the mapping table below 5. `write_file("artifacts/strategy.pine")` — save the output 6. Return the Pine Script in a code block with usage instructions ## Workflow: Generate from Description 1. `load_skill("pine-script")` — read this guide 2. Write Pine Script v6 directly based on the user's description 3. `write_file("artifacts/strategy.pine")` — save the output 4. Return the code with usage instructions ## Pine Script v6 Strategy Template ```pinescript // This strategy was generated by Vibe-Trading // Paste into TradingView Pine Editor → Add to Chart //@version=6 strategy("Strategy Name", overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=100, commission_type=strategy.commission.percent, commission_value=0.1, initial_capital=1000000) // ============================================================================ // INPUTS // ============================================================================ // [Group inputs logically with input.int(), input.float(), input.string()] // ============================================================================ // CALCULATIONS // ============================================================================ // [Core indicator calculations] // ============================================================================ // CONDITIONS // ============================================================================ longCondition = false shortCondition = false exitLongCondition = false exitShortCondition = false // ============================================================================ // STRATEGY EXECUTION // ============================================================================ if longCondition strategy.entry("Long", strategy.long) if shortCondition strategy.entry("Short", strategy.short) if exitLongCondition strategy.close("Long") if exitShortCondition strategy.close("Short") // ============================================================================ // PLOTS // ============================================================================ // [Visual overlays: moving averages, bands, signals] // ============================================================================ // ALERTS // ============================================================================ alertcondition(longCondition, title="Long Signal", message="Long entry signal triggered") alertcondition(shortCondition, title="Short Signal", message="Short entry signal triggered") ``` ## Python → Pine Script Mapping Table ### Technical Indicators | Python (pandas/numpy) | Pine Script v6 | |------------------------|----------------| | `df['close'].rolling(n).mean()` | `ta.sma(close, n)` | | `df['close'].ewm(span=n).mean()` | `ta.ema(close, n)` | | `ta.RSI(df['close'], n)` or manual RSI | `ta.rsi(close, n)` | | `ta.MACD(df['close'])` | `[macdLine, signalLine, hist] = ta.macd(close, 12, 26, 9)` | | `df['close'].rolling(n).std()` | `ta.stdev(close, n)` | | `df['high'].rolling(n).max()` | `ta.highest(high, n)` | | `df['low'].rolling(n).min()` | `ta.lowest(low, n)` | | `df['close'].pct_change()` | `(close - close[1]) / close[1]` | | `df['volume'].rolling(n).mean()` | `ta.sma(volume, n)` | | `df['close'] > df['close'].shift(1)` | `close > close[1]` | | Bollinger Bands (manual) | `[mid, upper, lower] = ta.bb(close, length, mult)` | | ATR (manual or ta-lib) | `ta.atr(length)` | | ADX | `ta.adx(high, low, close, length)` (returns adx value) | | Stochastic | `ta.stoch(close, high, low, length, smoothK, smoothD)` | | CCI | `ta.cci(close, length)` (Pine v6: `ta.cci(close, length)`) | | Williams %R | `ta.wpr(length)` | | MFI | `ta.mfi(hlc3, volume, length)` — Pine v6: `ta.mfi(close, length)` | | OBV | `ta.obv` | | VWAP | `ta.vwap` | ### Data References | Python | Pine Script v6 | |--------|----------------| | `df['open']` | `open` | | `df['high']` | `high` | | `df['low']` | `low` | | `df['close']` | `close` | | `df['volume']` | `volume` | | `df.index` (datetime) | `time` | | `df['close'].shift(n)` | `close[n]` | ### Signal Logic | Python Pattern | Pine Script v6 | |---------------|----------------| | `(fast > slow) & (fast.shift(1) <= slow.shift(1))` | `ta.crossover(fast, slow)` | | `(fast < slow) & (fast.shift(1) >= slow.shift(1))` | `ta.crossunder(fast, slow)` | | `signal.where(condition, 0)` | `condition ? value : 0` | | `np.where(cond, val_true, val_false)` | `cond ? val_true : val_false` | | `signal.clip(-1, 1)` | `math.max(-1, math.min(1, signal))` | | `signal.fillna(0)` | `nz(signal, 0)` | | `pd.isna(value)` | `na(value)` | ### Position Sizing | Python Pattern | Pine Script v6 | |---------------|----------------| | Equal weight 1/N | `strategy.percent_of_equity` with `default_qty_value = 100/N` | | Full position on signal=1.0 | `default_qty_type=strategy.percent_of_equity, default_qty_value=100` | | Half position on signal=0.5 | Use `strategy.entry(..., qty=strategy.equity * 0.5 / close)` | | Stop-loss | `strategy.exit("Exit", stop=entryPrice * (1 - stopPct))` | | Take-profit | `strategy.exit("Exit", limit=entryPrice * (1 + tpPct))` | ## Pine Script v6 Syntax Rules ### Critical Rules (common errors) 1. **Version declaration must be first line**: `//@version=6` 2. **Ternary operators MUST stay on one line** or use intermediate variables: ```pinescript // WRONG — causes "end of line without line continuation" text = condition ? "value1" : "value2" // CORRECT text = condition ? "value1" : "value2" ``` 3. **Line continuation**: continuation lines must be indented MORE than the starting line 4. **No plot() in local scope** (if/for/function): ```pinescript // WRONG if condition plot(value) // CORRECT plot(condition ? value : na) ``` 5. **var vs regular variables**: use `var` for persistent state across bars, regular assignment recalculates each bar 6. **varip**: persistent even on real-time bar updates (intrabar persistence) ### Script Types | Type | Declaration | Use Case | |------|-------------|----------| | `strategy` | `strategy("Name", ...)` | Backtestable with entry/exit orders | | `indicator` | `indicator("Name", ...)` | Visual indicators, no backtesting | | `library` | `library("Name")` | Reusable functions | **Default output: `strategy`** (matches Vibe-Trading's backtest-first philosophy). ### Avoid Repainting - Use `barstate.isconfirmed` for signals on confirmed bars only - Use `request.security()` with `lookahead=barmerge.lookahead_off` (default in v6) - Do NOT use `security()` on lower timeframes without understanding implications ### Platform Limits - Max 500 bars lookback for `[]` operator - Max 500 plot calls - Max 64 `strategy.entry/exit` calls per bar - Max 40 `request.security()` calls ## TradingView Symbol Format When generating Pine Script, map Vibe-Trading codes to TradingView symbols: | Vibe-Trading Format | TradingView Format | Exchange | |---------------------|-------------------|----------| | `000001.SZ` | `SZSE:000001` | Shenzhen | | `600519.SH` | `SSE:600519` | Shanghai | | `AAPL.US` | `NASDAQ:AAPL` | US (auto-detect) | | `700.HK` | `HKEX:0700` | Hong Kong | | `BTC-USDT` | `OKX:BTCUSDT.P` or `BINANCE:BTCUSDT` | Crypto | **Note**: Pine Script strategies are chart-independent — the user applies them to whichever symbol they want on TradingView. Include a comment noting the original instrument. ## Usage Instructions (include in response) After generating the Pine Script, always include: ``` How to use in TradingView: 1. Open TradingView → Pine Editor (bottom panel) 2. Click "Open" → "New blank indicator" 3. Delete all existing code 4. Paste the Pine Script above 5. Click "Add to Chart" 6. The strategy will appear on your chart with entry/exit markers 7. Open "Strategy Tester" tab to see backtest results ``` ## Quality Checklist Before outputting the Pine Script: - [ ] `//@version=6` is the first line - [ ] `strategy()` declaration includes commission and initial_capital matching config.json - [ ] All indicator calculations use Pine built-in `ta.*` functions (not manual reimplementation) - [ ] Entry/exit conditions match the Python signal logic semantically - [ ] No `plot()` inside local scopes (if/for/function) - [ ] Ternary operators are on single lines - [ ] Inputs use `input.int()` / `input.float()` so users can tune parameters in TradingView UI - [ ] Alert conditions are included for key signals - [ ] Comment header notes the original Vibe-Trading run_id and instrument