กล่าวสวัสดีกับไพน์สคริปต์ v5

Oct 7, 2021

วันนี้ภาษาไพน์ได้รับการพัฒนาเป็น v5! เวอร์ชันใหม่ของภาษาโปรแกรมของอินดิเคเตอร์และกลยุทธ์ของเรานำเสนอคุณสมบัติและการปรับปรุงใหม่ที่น่าตื่นเต้นมากมาย ตอนนี้ไพน์มีประสิทธิภาพมากกว่าที่เคย และการเปลี่ยนแปลงใน v5 จะช่วยให้เราพัฒนาภาษาไปอีกระดับ โพสต์นี้แนะนำคุณสมบัติล่าสุดเพียงไม่กี่อย่าง อย่าลืมอ่าน บันทึกประจำรุ่น และ คู่มือการย้ายเวอร์ชั่น ของเรา

ตัวแปลง V4 เป็น V5

ไพน์สคริปต์ที่มีอยู่ซึ่งใช้ไพน์เวอร์ชันก่อนหน้าจะยังคงทำงานต่อไปโดยไม่มีการเปลี่ยนแปลง แต่เราได้จัดเตรียมเครื่องมือการแปลงใน Pine Editor เพื่อช่วยผู้เขียนโค้ดในการแปลงสคริปต์ v4 เป็น v5 การปรับปรุงไพน์ในอนาคตจะมีเฉพาะในเวอร์ชัน 5 เท่านั้น ดังนั้นเราขอแนะนำให้แปลงอินดิเคเตอร์และกลยุทธ์ของคุณหากคุณต้องการรับประโยชน์จากคุณสมบัติใหม่ เครื่องมือแปลง v4 เป็น v5 จะใช้งานได้เมื่อมีการโหลดสคริปต์ v4 ใน Pine Editor จากดรอปดาวน์เมนู เพิ่มเติม:

โปรดทราบว่าโค้ด v4 ทั้งหมดไม่สามารถแปลงโดยอัตโนมัติได้ หากคุณประสบปัญหาในการแปลงหรือต้องการแปลงสคริปต์ด้วยตนเอง คู่มือการย้ายเวอร์ชั่น ซึ่งบันทึกการเปลี่ยนแปลงทั้งหมดระหว่าง v4 และ v5 จะแนะนำคุณ

ไลบรารี

การเพิ่มเข้ามาที่สำคัญของไพน์ ที่มาพร้อมกับ v5 คือไลบรารี ไลบรารีเป็นสิ่งพิมพ์ประเภทใหม่ที่ช่วยให้คุณสามารถสร้างฟังก์ชันแบบกำหนดเองเพื่อนำกลับมาใช้ใหม่ในสคริปต์อื่นได้ เมื่อเผยแพร่ไลบรารีแล้ว สคริปต์อื่นๆ (ไม่ว่าจะเป็นอินดิเคเตอร์ กลยุทธ์ หรือแม้แต่ไลบรารีอื่นๆ) สามารถนำเข้าและใช้ฟังก์ชันของไลบรารีได้ คุณสามารถใช้ไลบรารีเพื่อรวมอัลกอริธึมที่ซับซ้อนหรือฟังก์ชันที่ใช้บ่อย เพื่อให้คุณหรือชุมชนไพน์ทั้งหมดสามารถนำกลับมาใช้ใหม่ได้อย่างง่ายดาย

ในการเริ่มทำงานกับไลบรารี ดูหน้า คู่มือผู้ใช้งานไลบรารีของเรา ที่ส่วนท้ายของโพสต์นี้ คุณจะพบตัวอย่างไลบรารีที่เผยแพร่โดยสมาชิกของทีม PineCoders ของเรา คุณสามารถดูไลบรารีที่เผยแพร่จากฟีดสคริปต์ได้ ที่นี่

ค่าเริ่มต้นสำหรับฟังก์ชันที่ผู้ใช้กำหนด

การปรับปรุงที่ควบคู่ไปกับไลบรารี: สามารถกำหนดค่าเริ่มต้นสำหรับพารามิเตอร์ในฟังก์ชันที่ผู้ใช้กำหนดเอง ซึ่งทำให้เป็นทางเลือกได้อย่างมีประสิทธิภาพ ในตัวอย่างด้านล่าง เราประกาศฟังก์ชันแบบกำหนดเอง customPow() ที่เพิ่ม base เป็นกำลังของ exp หากไม่ได้ระบุ exp เมื่อเรียกใช้ฟังก์ชัน 2 จะถูกใช้:

//@version=5
indicator("")
customPow(base, exp = 2) =>
    result = 1
    for i = 1 to exp
        result *= base
plot(customPow(11)) // 11^2
plot(customPow(11, 4)) // 11^4

Switch

คำสั่ง switch ใหม่เป็นการดัดแปลงคำสั่ง if ที่คุ้นเคย หากคุณเคยต้องสร้างโครงสร้างขนาดใหญ่ของคำสั่ง if-else คุณจะประทับใจกับความสะดวกมากขึ้นในการบรรลุผลลัพธ์ที่ต้องการด้วย switch คุณสามารถเรียนรู้เพิ่มเติมเกี่ยวกับเรื่องนี้ได้ในคู่มืออ้างอิง ของเรา ดูการใช้งานจริงในโค้ดด้านล่าง ซึ่งเป็นบิวท์อินอินดิเคเตอร์ Average True Range ของเรา ซึ่งตอนนี้ใช้คำสั่ง switch เพื่อจัดเตรียมอัลกอริธึมการปรับให้เรียบที่แตกต่างกันในการคำนวณ:

//@version=5
indicator(title="Average True Range", shorttitle="ATR", timeframe="")
lengthInput = input.int(title="Length", defval=14, minval=1)
smoothingInput = input.string(title="Smoothing", defval="RMA", options = ["RMA", "SMA", "EMA", "WMA"])

maFunction(source, length) =>
    switch smoothingInput
        "RMA" => ta.rma(source, length)
        "SMA" => ta.sma(source, length)
        "EMA" => ta.ema(source, length)
        => ta.wma(source, length)

plot(maFunction(ta.tr(true), lengthInput), title = "ATR", color=#B71C1C)

คอลเลกชันของภาพวาด

การปรับปรุงครั้งใหญ่สำหรับการทำงานกับภาพวาดไพน์: ตัวแปรอาร์เรย์ในตัว line.all, label.all, box.all และ table.all ใหม่จะมี ID ของภาพวาดทั้งหมดของประเภทที่วาดเสมอโดยสคริปต์ของคุณ

ตัวอย่างเช่น คุณสามารถใช้เพื่อตัดแต่งจำนวนภาพวาดที่แสดงบนแผนภูมิตามค่าที่ผู้ใช้กำหนด ในสคริปต์ด้านล่าง เราวาดเส้นในแต่ละการเปิดใหม่ในแต่ละวัน (ไม่เกิน ~50 ตามข้อจำกัดบรรทัดเริ่มต้นของสคริปต์) จากนั้นเราจะตรวจสอบว่าจำนวนบรรทัดที่อนุญาตแม้ว่าอินพุตของสคริปต์จะเกินหรือไม่ และลบบรรทัดที่เก่าที่สุดหากใช่:

//@version=5
indicator("Daily Open", overlay = true)

qtyOfLinesInput = input.int(10, "Draw only last n lines", minval = 0, maxval = 50)

if ta.change(time("1D"))
    line.new(bar_index, open, bar_index + 1, open, extend = extend.right)
    if array.size(line.all) > qtyOfLinesInput
        line.delete(array.get(line.all, 0))

While

คุณสมบัติของไพน์ที่รอคอยมานานที่มาพร้อมกับ v5 คือ while loop คำสั่ง while สร้างลูปที่จะหยุดเมื่อเงื่อนไขเป็นเท็จ หรือใช้คำสั่ง break ในลูป

ตัวอย่างเช่น นี่คืออินดิเคเตอร์ที่คำนวณความแตกต่างระหว่างระยะทางเฉลี่ยที่เราต้องมองย้อนกลับไปเพื่อหาปริมาณขึ้นและลงที่เท่ากับปริมาณรวมของ n แท่งสุดท้าย ยิ่งเราต้องมองย้อนกลับไปเพื่อหาปริมาณขึ้นหรือลง มูลค่าของตลาดหมีหรือตลาดกระทิงก็ยิ่งมากขึ้นเท่านั้น:

//@version=5
var int MAX_BARS_BACK = 500
indicator("Volume bias", max_bars_back = MAX_BARS_BACK)

int lookBackInput = input.int(20, "Volume Look Back (bars)", minval = 2, maxval = int(MAX_BARS_BACK / 4))

// Stop the script if the chart does not contain volume data.
bool noVol = na(volume) and nz(math.sum(nz(volume), 200) == 0, true)
if noVol
    runtime.error("No volume data.")

volumeBias(lookBack, maxLookBack) =>
    bool  barUp = ta.rising(close, 1)
    bool  barDn = ta.falling(close, 1)
    float upVolume = 0.
    float dnVolume = 0.
    float avgVolume = math.sum(nz(volume), lookBack)
    int[] upBarNos = array.new_int(0)
    int[] dnBarNos = array.new_int(0)
    int   bar = 1
    bool  volumeFound = false
    while (not volumeFound) and bar < maxLookBack
        if barUp[bar] and upVolume < avgVolume
            upVolume += nz(volume[bar])
            array.push(upBarNos, bar)
        else if barDn[bar] and dnVolume < avgVolume
            dnVolume += nz(volume[bar])
            array.push(dnBarNos, bar)
        bar += 1
        volumeFound := upVolume >= avgVolume and dnVolume >= avgVolume
    float volumeBias = bar >= maxLookBack ? na : array.avg(dnBarNos) - array.avg(upBarNos)

float bias = volumeBias(lookBackInput, MAX_BARS_BACK)
plot(bias, "Volume Bias", bias > 0 ? color.lime : color.fuchsia)
hline(0)

สคริปต์ while loop จะทำงานจนกว่าจะพบโวลุ่มที่ต้องการทั้งในวอลุ่มขึ้นและลง และเราไม่ได้มองย้อนกลับไปที่จำนวนแท่งสูงสุดที่อนุญาต สคริปต์ยังแสดงคุณลักษณะอื่นที่เพิ่มเข้ามาในไพน์ v5: runtime.error()

runtime.error()

ฟังก์ชัน runtime.error() ทำให้สามารถหยุดการทำงานของสคริปต์และแสดงข้อความแสดงข้อผิดพลาดในเงื่อนไขใดๆ ที่คุณสามารถกำหนดได้ในไพน์ สิ่งนี้จะมีประโยชน์สำหรับผู้สร้างสคริปต์ที่ต้องการป้องกันไม่ให้ผู้ใช้ใช้อินดิเคเตอร์อย่างไม่ถูกต้อง นอกจากนี้ยังสามารถใช้เป็นเครื่องมือดีบัก เพื่อหยุดการดำเนินการระหว่างลูปหรือจากภายในฟังก์ชัน เป็นต้น

หากต้องการใช้ฟังก์ชันใหม่ ให้เรียกใช้ฟังก์ชัน runtime.error() เมื่อตรงตามเงื่อนไขของคุณ เมื่อดำเนินการ สคริปต์จะหยุดทำงานและแสดงเครื่องหมายอัศเจรีย์ที่คุ้นเคยถัดจากชื่ออินดิเคเตอร์ เมื่อผู้ใช้คลิกที่ไอคอนเครื่องหมายอัศเจรีย์ ข้อความที่คุณใช้ในการเรียกฟังก์ชันจะปรากฏขึ้น

โค้ดด้านล่างเป็นอินดิเคเตอร์ VWAP แบบ barebones ที่มีข้อผิดพลาดที่กำหนดเองสองข้อ อันแรกปรากฏขึ้นเมื่อสัญลักษณ์ไม่มีข้อมูลโวลุ่ม: VWAP คำนวณตามปริมาณ ดังนั้นหากไม่มีโวลุ่ม สคริปต์จะไม่ทำงาน อันที่สองจะปรากฏขึ้นเมื่อกรอบเวลาบนแผนภูมิเป็น 1D หรือสูงกว่า การคำนวณพื้นฐานของ VWAP จะรวบรวมข้อมูลค่าเฉลี่ยเคลื่อนที่ที่ถ่วงน้ำหนักตามปริมาตรในแต่ละแถบใหม่ และรีเซ็ตเมื่อเริ่มต้นวันใหม่ ดังนั้นอินดิเคเตอร์จึงมีประโยชน์เฉพาะในกรอบเวลาระหว่างวัน

//@version=5
indicator("VWAP with custom errors")
if na(volume) // Will be true on symbols with no volume data e.g. TVC:SPX
    runtime.error("There is no volume data for this symbol.")
else if timeframe.isdwm // Will be true on 1D and higher timeframes
    runtime.error("Session-based VWAP does not show meaningful data on timeframes >= 1D.
     Please switch to a lower timeframe.")
plot(ta.vwap)

พารามิเตอร์กลยุทธ์ใหม่

ข่าวดีสำหรับผู้เขียนโค้ดกลยุทธ์! เราได้เพิ่มตัวแปรและฟังก์ชันใหม่ๆ มากมายที่ช่วยให้คุณมองเห็นคุณสมบัติทางการเทรด สถิติ และอินดิเคเตอร์ ค่าของมันจะอัปเดตเมื่อโปรแกรมจำลองโบรกเกอร์ดำเนินการตามคำสั่งของคุณ ดังนั้นคุณจึงสามารถติดตามค่าต่างๆ ได้ในขณะที่กลยุทธ์ของคุณดำเนินไป

คลิกที่นี่เพื่อดูคู่มืออ้างอิงไพน์สำหรับรายละเอียดเกี่ยวกับแต่ละรายการ

strategy.closedtrades.entry_price() / strategy.opentrades.entry_price()

strategy.closedtrades.entry_bar_index() / strategy.opentrades.entry_bar_index()

strategy.closedtrades.entry_time() / strategy.opentrades.entry_time()

strategy.closedtrades.size() / strategy.opentrades.size()

strategy.closedtrades.profit() / strategy.opentrades.profit()

strategy.closedtrades.commission() / strategy.opentrades.commission()

strategy.closedtrades.max_runup() / strategy.opentrades.max_runup()

strategy.closedtrades.max_drawdown() / strategy.opentrades.max_drawdown()

strategy.closedtrades.exit_price()

strategy.closedtrades.exit_bar_index()

strategy.closedtrades.exit_time()

strategy.convert_to_account()

strategy.convert_to_symbol()

strategy.account_currency

Namespaces ใหม่

ชุมชน Pine coders ของเราบอกเราว่าพวกเขาชื่นชมอัตราการเติบโตที่ไพน์อย่างที่ไม่เคยเกิดขึ้นมาก่อนในช่วงไม่กี่ปีที่ผ่านมา และเราตั้งใจที่จะรักษาระดับเดียวกันในอนาคต อย่างไรก็ตาม สิ่งนี้สร้างกระแสของฟังก์ชันไพน์ใหม่และตัวแปรในตัว เพื่อรองรับการเติบโตอย่างบ้าคลั่งนี้ เราจำเป็นต้องจัดระเบียบชื่อปัจจุบันประมาณ 600 ชื่อที่ใช้ในภาษานั้นให้ดียิ่งขึ้น เราทำสิ่งนี้โดยเพิ่มเนมสเปซใหม่เพื่อจัดกลุ่มฟังก์ชันในลักษณะที่สะท้อนถึงการใช้งานได้ดียิ่งขึ้น นอกจากนี้ ยังมีการเปลี่ยนชื่อพารามิเตอร์ของฟังก์ชันจำนวนมากเพื่อให้เข้าใจได้ง่ายขึ้น

ตัวอย่างของเนมสเปซใหม่คือ ta. ซึ่งตอนนี้รวมตัวแปรและฟังก์ชันทั้งหมดที่เกี่ยวข้องกับการวิเคราะห์ทางเทคนิค ซึ่งจะทำให้ง่ายต่อการเรียกดูคู่มืออ้างอิงและค้นหาตัวแปรและฟังก์ชันทั้งหมดที่คืนค่าของตัวบ่งชี้ทั่วไป ดังนั้น sma() จึงเป็น ta.sma() ไม่จำเป็นต้องจำเนมสเปซใหม่ หากคุณพิมพ์ชื่อเก่าของฟังก์ชันโดยไม่มีเนมสเปซในตัวแก้ไขและกดปุ่มลัด เติมข้อความอัตโนมัติ (Ctrl + Space หรือ Cmd + Space บน MacOS) ป๊อปอัปที่แสดงคำแนะนำที่ตรงกันจะปรากฏขึ้น:

เช่นเดียวกันเมื่อค้นหาคู่มืออ้างอิง การพิมพ์ชื่อฟังก์ชันที่คุ้นเคยโดยไม่มีเนมสเปซจะทำให้ชื่อใหม่ปรากฏขึ้น คุณสามารถดูรายการการเปลี่ยนแปลงทั้งหมดใน v5 ได้ใน คู่มือการย้ายเวอร์ชั่น ของเรา

ไลบรารีที่เผยแพร่

สิ่งตีพิมพ์ต่อไปนี้เป็นตัวอย่างของไลบรารีที่เผยแพร่บน TradingView โดย PineCoders ที่ช่วยเราทดสอบคุณสมบัติใหม่ของไพน์:

ColorScheme โดย RicardoSantos

Matrix_Functions_Lib_JD โดย Duyck

Enchanced_ta โดย HeWhoMustNotBeNamed

เราหวังว่าคุณจะพบว่าคุณสมบัติใหม่มีประโยชน์ และโปรดให้ข้อเสนอแนะและข้อแนะนำแก่เราอยู่เสมอ เรากำลังสร้าง TradingView ให้กับคุณ และเราอยากรู้เสมอว่าคุณคิดอย่างไรเกี่ยวกับการอัปเดตแพลตฟอร์มของเรา

Look first Then leap

TradingView is built for you, so make sure you're getting the most of our awesome features
เปิดชาร์ต