pine-script

$npx mdskill add HKUDS/Vibe-Trading/pine-script

Transform Python backtests or natural language into Pine Script v6.

  • Converts Python signal_engine.py logic to TradingView Pine Script v6.
  • Generates Pine Script v6 code from natural language strategy descriptions.
  • Outputs strategy.pine files to artifacts/strategy.pine within the run directory.
  • Returns generated code in a code block with TradingView editor usage instructions.

SKILL.md

.github/skills/pine-scriptView on GitHub ↗
---
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

More from HKUDS/Vibe-Trading

SkillDescription
adr-hshareADR/H-share/A-share cross-listing premium analysis — track pricing gaps between US-listed ADRs, HK-listed H-shares, and A-shares for arbitrage signals, dual-listing valuation, and delisting risk assessment.
akshareAKShare financial data aggregator (18k+ stars). Free, no API key. Covers A-shares, US, HK, futures, macro, forex. Primary fallback for tushare and yfinance.
asset-allocationAsset allocation theory and optimizer usage — MPT / Black-Litterman / risk budgeting / all-weather strategy, including guides for 4 optimizers and rebalancing rules.
backtest-diagnoseDiagnose failed or underperforming backtests, locate the root cause, and fix the issue
behavioral-financeBehavioral finance applications: theories of overreaction and underreaction, behavioral explanations for momentum and reversal, investor sentiment cycles, cognitive-bias checklists, and debiasing quantitative strategies.
candlestickCandlestick pattern recognition engine, pure pandas vectorized implementation of 15 classic candlestick patterns (5 single-candle + 5 double-candle + 4 triple-candle + 1 trend confirmation), generating a composite signal from bullish/bearish pattern scores.
ccxtCCXT unified crypto exchange library (100+ exchanges). Free public market data. Fallback when OKX is unavailable.
chanlun基于缠论(缠中说禅)的形态识别引擎,使用czsc库自动检测K线分型、笔、中枢,并生成一买/一卖/二买/二卖/三买/三卖等买卖点信号。支持多周期分析和形态分类(3/5/7/9/11笔形态)。
commodity-analysisCommodity analysis (oil supply-demand balance / gold pricing / copper as an economic predictor / inventory cycles / futures premium-discount structure / seasonality), generating directional commodity signals.
convertible-bondA股可转债分析——转股/纯债/期权三维估值、下修/强赎/回售博弈、双低策略与转债轮动选债框架