pine-scriptpine-script-v6

Pine Script v6: Syntax error at function definition 'input "("' - How to declare functions correctly?


I am trying to combine two Pine Script indicators (LuxAlgo Reversal Signals and VuManChu B Divergences) into a single script. I have recently migrated the script to Pine Script v6.

I am consistently encountering a "Syntax error at input "(" " error when defining functions. This specific error appears on lines where functions like f_top_fractal are declared.

Problem Summary: Despite various attempts to correctly declare functions in Pine Script v6, I keep getting a "Syntax error at input "(" " error. I suspect there might be a subtle rule regarding function declaration syntax in v6 that I'm missing, especially with array indexing in arguments or the exact structure required by the parser.

Error Message:

네, 알겠습니다. Stack Overflow 질문의 "Body" (본문) 섹션에 들어갈 내용을 깔끔하게 정리해서 한 번에 드릴게요.

아래 내용을 그대로 복사해서 Stack Overflow 질문 페이지의 "Body" (본문) 섹션에 붙여넣으시면 됩니다. <> Code 버튼을 눌러서 코드 블록 안에 넣는 것을 잊지 마세요.

I am trying to combine two Pine Script indicators (LuxAlgo Reversal Signals and VuManChu B Divergences) into a single script. I have recently migrated the script to Pine Script v6.

I am consistently encountering a "Syntax error at input "(" " error when defining functions. This specific error appears on lines where functions like f_top_fractal are declared.

Problem Summary: Despite various attempts to correctly declare functions in Pine Script v6, I keep getting a "Syntax error at input "(" " error. I suspect there might be a subtle rule regarding function declaration syntax in v6 that I'm missing, especially with array indexing in arguments or the exact structure required by the parser.

Error Message: Syntax error at input "("

(Please note: The exact line number in the error message changes as I try different fixes, but the error type remains the same and points to function declaration lines, such as function f_top_fractal(src).)

What I have tried so far (Troubleshooting Steps):

Despite these efforts, the syntax error persists. Could someone please review my full script and provide guidance on the correct way to declare functions in Pine Script v6 to resolve this "Syntax error at input "(" " error?

My Goal: My objective is to compile this script successfully and add it to my TradingView chart.

Full Script:

//@version=6
// This work is licensed under a Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) [https://creativecommons.org/licenses/by-nc-sa/4.0/](https://creativecommons.org/licenses/by-nc-sa/4.0/)
// © LuxAlgo
indicator("Integrated Long Buy Signal", "Intg. Long", true, max_labels_count = 500)

//-----------------------------------------------------------------------------}
// User Defined Types (FROM LUXALGO)
//-----------------------------------------------------------------------------{

type bar
    float o
    float h
    float l
    float c
    int   i

type trb
    int   bSC
    float bSH
    float bSL

    int   sSC
    float sSH
    float sSL

type tre
    int   bCC
    float bC8 = 0.0
    float bCHt
    float bCH
    float bCL
    float bCLt
    float bCD

    int   sCC
    float sC8 = 0.0
    float sCHt
    float sCH
    float sCL
    float sCLt
    float sCT

//-----------------------------------------------------------------------------}
// **원래의 LuxAlgo/VuManChu 설정들 (여기서 모든 input 변수들을 선언)**

// WaveTrend Settings (from VuManChu)
wtChannelLen = input.int(9, title = 'WT Channel Length', group = 'WaveTrend Settings')
wtAverageLen = input.int(12, title = 'WT Average Length', group = 'WaveTrend Settings')
wtMALen = input.int(3, title = 'WT MA Length', group = 'WaveTrend Settings')
wtMASource = input.source(hlc3, title = 'WT MA Source', group = 'WaveTrend Settings')
osLevel = input.int(-53, title = 'WT Oversold Level 1', group = 'WaveTrend Settings')
obLevel = input.int(53, title = 'WT Overbought Level 1', group = 'WaveTrend Settings')
osLevel3 = input.int(-75, title = 'WT Oversold Level 3', group = 'WaveTrend Settings')
wtDivOBLevel = input.int(45, 'WT Bearish Divergence min', group = 'WaveTrend Settings')
wtDivOSLevel = input.int(-65, 'WT Bullish Divergence min', group = 'WaveTrend Settings')
wtDivOBLevel_add = input.int(15, 'WT 2nd Bearish Divergence', group = 'WaveTrend Settings')
wtDivOSLevel_add = input.int(-40, 'WT 2nd Bullish Divergence 15 min', group = 'WaveTrend Settings')
showHiddenDiv_nl = input.bool(true, 'Not apply OB/OS Limits on Hidden Divergences', group = 'WaveTrend Settings')

// RSI MFI Settings (from VuManChu)
rsiMFIperiod = input.int(60, 'MFI Period', group = 'MFI Settings')
rsiMFIMultiplier = input.float(150, 'MFI Area multiplier', group = 'MFI Settings')
rsiMFIPosY = input.float(2.5, 'MFI Area Y Pos', group = 'MFI Settings')

// RSI Settings (from VuManChu)
rsiSRC = input.source(close, 'RSI Source', group = 'RSI Settings')
rsiLen = input.int(14, 'RSI Length', group = 'RSI Settings')
rsiDivOBLevel = input.int(60, 'RSI Bearish Divergence min', group = 'RSI Settings')
rsiDivOSLevel = input.int(30, 'RSI Bullish Divergence min', group = 'RSI Settings')

// Stoch Settings (from VuManChu)
stochUseLog = input.bool(true, 'Use Log?', group = 'Stoch Settings')
stochAvg = input.bool(false, 'Use Average of both K & D', group = 'Stoch Settings')
stochSRC = input.source(close, 'Stochastic RSI Source', group = 'Stoch Settings')
stochLen = input.int(14, 'Stochastic RSI Length', group = 'Stoch Settings')
stochRsiLen = input.int(14, 'RSI Length ', group = 'Stoch Settings')
stochKSmooth = input.int(3, 'Stochastic RSI K Smooth', group = 'Stoch Settings')
stochDSmooth = input.int(3, 'Stochastic RSI D Smooth', group = 'Stoch Settings')

// Sommi Settings (from VuManChu)
sommiVwapTF = input.string('720', 'Sommi F. Wave timeframe', group = 'Sommi Settings')
sommiVwapBullLevel = input.int(0, 'F. Wave Bull Level (more than)', group = 'Sommi Settings')
soomiFlagWTBullLevel = input.int(0, 'WT Bull Level (less than)', group = 'Sommi Settings')
soomiRSIMFIBullLevel = input.int(0, 'Money flow Bull Level (more than)', group = 'Sommi Settings')
sommiDiamondShow = input.bool(false, title = 'Show Sommi diamond', group = 'Sommi Settings')
sommiHTCRes = input.string('60', 'HTF Candle Res. 1', group = 'Sommi Settings')
sommiHTCRes2 = input.string('240', 'HTF Candle Res. 2', group = 'Sommi Settings')
soomiDiamondWTBullLevel = input.int(0, 'WT Bull Level (Less than)', group = 'Sommi Settings')

// LuxAlgo Trade Setups (tso)
tso = input.string('Exhaustion', 'Phase Specific Trade Setup Options', options = ['Momentum', 'Exhaustion', 'Qualified', 'None'], group = "LuxAlgo Trade Setups")

// ==============================================================================
// VuManChu B Divergences - FUNCTIONS (if bar_index >= 50 블록 밖으로 이동)
// ==============================================================================

// **수정: 모든 함수 정의를 전역 스코프(if bar_index >= 50 블록 밖)로 이동**
// **수정: 함수 이름과 괄호 사이 공백 제거, 들여쓰기 및 return 명시 재확인**

function f_top_fractal(src)
    return src[4] < src[2] and src[3] < src[2] and src[2] > src[1] and src[2] > src[0]
function f_bot_fractal(src)
    return src[4] > src[2] and src[3] > src[2] and src[2] < src[1] and src[2] < src[0]
function f_fractalize(src)
    return f_top_fractal(src) ? 1 : f_bot_fractal(src) ? -1 : 0

function f_findDivs(src, topLimit, botLimit, useLimits)
    fractalTop_cond = f_fractalize(src) > 0 and (useLimits ? src[2] >= topLimit : true)
    fractalBot_cond = f_fractalize(src) < 0 and (useLimits ? src[2] <= botLimit : true)

    fractalTop_val = fractalTop_cond ? src[2] : na
    fractalBot_val = fractalBot_cond ? src[2] : na

    highPrev = ta.valuewhen(fractalTop_cond, fractalTop_val, 0)[2]
    highPrice = ta.valuewhen(fractalTop_cond, high[2], 0)[2]
    lowPrev = ta.valuewhen(fractalBot_cond, fractalBot_val, 0)[2]
    lowPrice = ta.valuewhen(fractalBot_cond, low[2], 0)[2]

    bearSignal = fractalTop_cond and high[2] > highPrice and src[2] < highPrev
    bullSignal = fractalBot_cond and low[2] < lowPrice and src[2] > lowPrev
    bearDivHidden = fractalTop_cond and high[2] < highPrice and src[2] > highPrev
    bullDivHidden = fractalBot_cond and low[2] > lowPrice and src[2] < lowPrev
    
    return [fractalTop_cond, fractalBot_cond, lowPrev, bearSignal, bullSignal, bearDivHidden, bullDivHidden]

function f_rsimfi(_period, _multiplier, _tf)
    return request.security(syminfo.tickerid, _tf, ta.sma(((close - open) / (high - low)) * _multiplier, _period) - rsiMFIPosY)

function f_wavetrend(src, chlen, avg, malen, tf)
    tfsrc = request.security(syminfo.tickerid, tf, src)
    esa = ta.ema(tfsrc, chlen)
    de = ta.ema(math.abs(tfsrc - esa), chlen)
    ci = (tfsrc - esa) / (0.015 * de)
    wt1 = request.security(syminfo.tickerid, tf, ta.ema(ci, avg))
    wt2 = request.security(syminfo.tickerid, tf, ta.sma(wt1, malen))
    wtVwap = wt1 - wt2
    wtOversold = wt2 <= osLevel
    wtOverbought = wt2 >= obLevel
    wtCross = ta.cross(wt1, wt2)
    wtCrossUp = wt2 - wt1 <= 0
    wtCrossDown = wt2 - wt1 >= 0
    return [wt1, wt2, wtOversold, wtOverbought, wtCross, wtCrossUp, wtCrossDown, wtVwap]

function f_stochrsi(_src, _stochlen, _rsilen, _smoothk, _smoothd, _log, _avg)
    src = _log ? math.log(_src) : _src
    rsi = ta.rsi(src, _rsilen)
    kk = ta.sma(ta.stoch(rsi, rsi, rsi, _stochlen), _smoothk)
    d1 = ta.sma(kk, _smoothd)
    avg_1 = (kk + d1) / 2
    k = _avg ? avg_1 : kk
    return [k, d1]

function f_getTFCandle(_tf)
    [htf_open, htf_high, htf_low, htf_close] = request.security(syminfo.tickerid, _tf, [open, high, low, close], barmerge.gaps_off, barmerge.lookahead_on)

    var float _open_ha = na
    var float _close_ha = na
    var float _high_ha = na
    var float _low_ha = na

    if bar_index == 0
        _open_ha  := htf_open
        _close_ha := htf_close
        _high_ha  := htf_high
        _low_ha   := htf_low
    else
        _open_ha  := math.avg(_open_ha[1], _close_ha[1])
        _close_ha := math.avg(htf_open, htf_high, htf_low, htf_close)
        _high_ha  := math.max(htf_high, math.max(_open_ha, _close_ha))
        _low_ha   := math.min(htf_low, math.min(_open_ha, _close_ha))

    newBar = ta.change(htf_open)
    candleBodyDir = _close_ha > _open_ha
    
    return [ _open_ha, _close_ha, _high_ha, _low_ha, candleBodyDir, newBar]

function f_findSommiFlag(tf, wt1, wt2, rsiMFI_arg, wtCross, wtCrossUp)
    [hwt1, hwt2, hwtOversold, hwtOverbought, hwtCross, hwtCrossUp, hwtCrossDown, hwtVwap] = f_wavetrend(wtMASource, wtChannelLen, wtAverageLen, wtMALen, tf)
    
    bullPattern = rsiMFI_arg > soomiRSIMFIBullLevel and
                  wt2 < soomiFlagWTBullLevel and
                  wtCross and
                  wtCrossUp and
                  hwtVwap > sommiVwapBullLevel
    
    return [bullPattern, hwtVwap]
    
function f_findSommiDiamond(tf, tf2, wt2, wtCross, wtCrossUp)
    [_open, _close, _high, _low, candleBodyDir, newBar] = f_getTFCandle(tf)
    [_open2, _close2, _high2, _low2, candleBodyDir2, newBar2] = f_getTFCandle(tf2)

    bullPattern = wt2 <= soomiDiamondWTBullLevel and
                  wtCross and
                  wtCrossUp and
                  candleBodyDir and
                  candleBodyDir2
    return [bullPattern]
    
// ==============================================================================
// LuxAlgo - Reversal Signals - Adapted for integration (다시 메인 블록으로)
// ==============================================================================

// LuxAlgo General Calculations (minimal required)
var b = bar.new(o=open, h=high, l=low, c=close, i=bar_index)
var S = trb.new()
var C = tre.new()

// **수정: 런타임 오류 방지 - 충분한 바가 로드되었는지 확인**
if bar_index >= 50
    con = b.c < (b[4]).c

    if con
        S.bSC := (S[0]).bSC == 9 ? 1 : (S[0]).bSC + 1
        S.sSC := 0
    else
        S.sSC := (S[0]).sSC == 9 ? 1 : (S[0]).sSC + 1
        S.bSC := 0

    pbS = (b.l <= (b[3]).l and b.l <= (b[2]).l) or ((b[1]).l <= (b[3]).l and (b[1]).l <= (b[2]).l)
    bC8 = (S[1]).bSC == 8 and (S[0]).sSC == 1
    sR  = ta.highest(high, 9)
    bSR = 0.0
    bSR := (S[0]).bSC == 9 or bC8 ? sR : b.c > bSR[1] ? 0 : bSR[1]

    if (S[0]).bSC == 1
        S.bSL := b.l

    if (S[0]).bSC > 0
        S.bSL := math.min(b.l, (S[0]).bSL)
        if b.l == (S[0]).bSL
            S.bSH := b.h

    psS = (b.h >= (b[3]).h and b.h >= (b[2]).h) or ((b[1]).h >= (b[3]).h and (b[1]).h >= (b[2]).h)
    sC8 = (S[1]).sSC == 8 and (S[0]).bSC == 1
    sS  = ta.lowest(low, 9)
    sSS = 0.0
    sSS := (S[0]).sSC == 9 or sC8 ? sS : b.c < sSS[1] ? 0 : sSS[1]

    if (S[0]).sSC == 1
        S.sSH := b.h

    if (S[0]).sSC > 0
        S.sSH := math.max(b.h, (S[0]).sSH)
        if b.h == (S[0]).sSH
            S.sSL := b.l

    // LuxAlgo Trend Exhaustion Phase (minimal required for bPFc)
    bCC = b.c <= (b[2]).l
    b13 = b.c <= (b[2]).l and b.l >= (C[0]).bC8

    var sbC = false
    sbC := if (S[0]).bSC == 9 and (C[0]).bCC == 0 and (pbS or (pbS[1]))
        true
    else
        if (S[0]).sSC == 9 or (C[0]).bCC == 13 or b.c > bSR
            false
        else
            sbC[1]

    C.bCC := sbC ? (S[0]).bSC == 9 ? bCC ? 1 : 0 : bCC ? (C[0]).bCC + 1 : (C[0]).bCC : 0
    C.bCC := (C[0]).bCC == 13 and b13 ? (C[0]).bCC - 1 : (C[0]).bCC

    if (C[0]).bCC == 8 and (C[0]).bCC != (C[1]).bCC
        C.bC8 := b.c

    if (C[0]).bCC == 1
        C.bCLt := b.l
        C.bCHt := b.h
        
    if sbC
        C.bCHt := math.max(b.h, (C[0]).bCHt)
        C.bCLt := math.min(b.l, (C[0]).bCLt)
        
        if b.h == (C[0]).bCHt
            C.bCL := b.l

        if b.l == (C[0]).bCLt
            C.bCH := b.h

    sCD = 2 * (C[0]).sCHt - (C[0]).sCL
    sCD := (C[0]).sCC == 13 ? 2 * (C[0]).sCHt - (C[0]).sCL : b.c > sCD[1] or ((C[0]).sCT == 0 and (C[0]).bCC == 13) ? 0. : sCD[1]

    sCT = 2 * (C[0]).sCLt - (C[0]).sCH
    sCT := (C[0]).sCC == 13 ? sCT : b.c < sCT[1] or ((sCD[0]) == 0 and (C[0]).bCC == 13) ? 0. : sCT[1]
    C.sCT := sCT

    // LuxAlgo Trade Setups (tso)
    bBl9 = ta.valuewhen((S[0]).bSC == 9 , (b[0]).i, 0)
    bBp9 = ta.valuewhen((S[0]).bSC == 9 , (b[0]).i, 1)
    bB13 = ta.valuewhen((C[0]).bCC == 13, (b[0]).i, 0)

    sBl9 = ta.valuewhen((S[0]).sSC == 9 , (b[0]).i, 0)
    sBp9 = ta.valuewhen((S[0]).sSC == 9 , (b[0]).i, 1)
    sB13 = ta.valuewhen((C[0]).sCC == 13, (b[0]).i, 0)

    trdS = tso != 'None'

    bQC  = (bBl9 > bB13) and (bB13 > bBp9) and (bBp9 > sBl9)
    bPFO = tso == 'Momentum' ? (S[0]).bSC == 9 or bC8 : tso == 'Exhaustion' ? (C[5]).bCC == 13 : (S[0]).bSC == 9 and bQC

    var sbPF = false
    var bPFc_val = false

    sbPF := if bPFO
        true
    else
        if bPFc_val
            false
        else
            sbPF[1]

    bPFc_val := sbPF and b.c > (b[4]).c and (b[1]).c < (b[5]).c


    // ==============================================================================
    // CALCULATE INDICATORS (if bar_index >= 50 블록 안으로 이동)
    // ==============================================================================

    rsiMFI = f_rsimfi(rsiMFIperiod, rsiMFIMultiplier, timeframe.period)

    // Calculates WaveTrend
    [wt1, wt2, wtOversold, wtOverbought, wtCross, wtCrossUp, wtCrossDown, wtVwap] = f_wavetrend(wtMASource, wtChannelLen, wtAverageLen, wtMALen, timeframe.period)
        
    // Stochastic RSI
    [stochK, stochD] = f_stochrsi(stochSRC, stochLen, stochRsiLen, stochKSmooth, stochDSmooth, stochUseLog, stochAvg)

    // Sommi flag
    [sommiBullish, hvwap] = f_findSommiFlag(sommiVwapTF, wt1, wt2, rsiMFI, wtCross, wtCrossUp)

    //Sommi diamond
    [sommiBullishDiamond] = f_findSommiDiamond(sommiHTCRes, sommiHTCRes2, wt2, wtCross, wtCrossUp)

    // WT Divergences
    wtDivOBLevel = input.int(45, 'WT Bearish Divergence min', group = 'WaveTrend Settings')
    wtDivOSLevel = input.int(-65, 'WT Bullish Divergence min', group = 'WaveTrend Settings')
    wtDivOBLevel_add = input.int(15, 'WT 2nd Bearish Divergence', group = 'WaveTrend Settings')
    wtDivOSLevel_add = input.int(-40, 'WT 2nd Bullish Divergence 15 min', group = 'WaveTrend Settings')
    showHiddenDiv_nl = input.bool(true, 'Not apply OB/OS Limits on Hidden Divergences', group = 'WaveTrend Settings')


    [wtFractalTop, wtFractalBot, wtLow_prev, wtBearDiv, wtBullDiv, wtBearDivHidden, wtBullDivHidden] = f_findDivs(wt2, wtDivOBLevel, wtDivOSLevel, true)
    [wtFractalTop_add, wtFractalBot_add, wtLow_prev_add, wtBearDiv_add, wtBullDiv_add, wtBearDivHidden_add, wtBullDivHidden_add] = f_findDivs(wt2, wtDivOBLevel_add, wtDivOSLevel_add, true)
    [wtFractalTop_nl, wtFractalBot_nl, wtLow_prev_nl, wtBearDiv_nl, wtBullDiv_nl, wtBearDivHidden_nl, wtBullDivHidden_nl] = f_findDivs(wt2, 0, 0, false)

    wtBullDivHidden_ = showHiddenDiv_nl ? wtBullDivHidden_nl : wtBullDivHidden

    // RSI Divergences
    rsiSRC = input.source(close, 'RSI Source', group = 'RSI Settings')
    rsiLen = input.int(14, 'RSI Length', group = 'RSI Settings')
    rsi = ta.rsi(rsiSRC, rsiLen)
    rsiDivOBLevel = input.int(60, 'RSI Bearish Divergence min', group = 'RSI Settings')
    rsiDivOSLevel = input.int(30, 'RSI Bullish Divergence min', group = 'RSI Settings')

    [rsiFractalTop, rsiFractalBot, rsiLow_prev, rsiBearDiv, rsiBullDiv, rsiBearDivHidden, rsiBullDivHidden] = f_findDivs(rsi, rsiDivOBLevel, rsiDivOSLevel, true)
    [rsiFractalTop_nl, rsiFractalBot_nl, rsiLow_prev_nl, rsiBearDiv_nl, rsiBullDiv_nl, rsiBearDivHidden_nl, rsiBullDivHidden_nl] = f_findDivs(rsi, 0, 0, false)

    rsiBullDivHidden_ = showHiddenDiv_nl ? rsiBullDivHidden_nl : rsiBullDivHidden
        
    // Stoch Divergences
    [stochFractalTop, stochFractalBot, stochLow_prev, stochBearDiv, stochBullDiv, stochBearDivHidden, stochBullDivHidden] = f_findDivs(stochK, 0, 0, false)

    // Small Circles WT Cross
    buySignal = wtCross and wtCrossUp and wtOversold
        
    buySignalDiv = (wtBullDiv) or
                   (wtBullDiv_add) or
                   (stochBullDiv) or
                   (rsiBullDiv)
        
    // Gold Buy
    lastRsi = ta.valuewhen(wtFractalBot, rsi[2], 0)[2]
    wtGoldBuy = ((wtBullDiv) or (rsiBullDiv)) and (wtLow_prev <= osLevel3) and (wt2 > osLevel3) and (wtLow_prev - wt2 <= -5) and (lastRsi < 30)
              
    // } CALCULATE INDICATORS

    // ==============================================================================
    // INTEGRATED LONG BUY SIGNAL
    // ==============================================================================

    // Combined Long Signal Logic
    bool combinedLongSignal = bPFc_val and (buySignal or buySignalDiv or wtGoldBuy or sommiBullish or sommiBullishDiamond)

    // Plotting the combined signal
    plotshape(combinedLongSignal,
              title='Integrated Long Buy Signal',
              location=location.belowbar,
              color=color.new(color.blue, 0),
              style=shape.triangleup,
              size=size.normal)

    // Alert for the combined signal
    alertcondition(combinedLongSignal,
                  'Integrated Long Buy Signal!',
                  'LuxAlgo Price Flip + VuManChu Bullish Signals')

Solution

  • Your first attempt should be to read the documentation.

    Syntax is:

    <identifier>(<list of arguments>) =>
        <variable declaration>
        ...
        <variable declaration or expression>
    

    There should be no function keyword and you are missing the => at the end.