Tài nguyên đang được tải lên... tải...

Bài hướng dẫn giới thiệu về ngôn ngữ PINE của FMZ Quant

Tác giả:FMZ~Lydia, Tạo: 2022-09-23 15:23:34, Cập nhật: 2024-02-27 16:47:41

.3, giới hạn=3)

Nếu không barstate.ishistory và đóng < mở chiến lược. hủy bỏ ((long1) chiến lược. hủy bỏ ((long2) chiến lược. hủy bỏ ((long3) isStop:= true


---------------------------

6. ```strategy.cancel_all```

The ```strategy.cancel_all``` function is similar to the ```strategy.cancel``` function. It can cancel/stop all pre-listed commands. The ```when``` parameter can be specified.

Parameters:

- ```when```: Execution conditions.

```pine
/*backtest
start: 2022-07-03 00:00:00
end: 2022-07-09 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/

strategy("strategy.cancel Demo", pyramiding=3)

var isStop = false 
if isStop 
    runtime.error("stop")

strategy.entry("long1", strategy.long, 0.1, limit=1)
strategy.entry("long2", strategy.long, 0.2, limit=2)
strategy.entry("long3", strategy.long, 0.3, limit=3)

if not barstate.ishistory and close < open 
    strategy.cancel_all()
    isStop := true 

  1. strategy.order

Các chức năng và cài đặt tham số củastrategy.orderchức năng gần như giống hệt vớistrategy.entrySự khác biệt làstrategy.orderkhông bị ảnh hưởng bởipyramidingcài đặt tham số củastrategychức năng, và không có giới hạn số lượng lệnh.

Các thông số:

  • id: Nó có thể được hiểu là cho một tên cho một vị trí giao dịch để tham chiếu.
  • direction: Nếu hướng lệnh dài (mua), truyền vào biến tích hợpstrategy.long, và nếu bạn muốn đi ngắn (bán), đi trong biếnstrategy.short.
  • qty: Xác định số lượng lệnh được đặt, nếu tham số này không được thông qua, số lượng lệnh mặc định sẽ được sử dụng.
  • when: Điều kiện thực thi, bạn có thể chỉ định tham số này để kiểm soát liệu hoạt động lệnh hiện tại này có được kích hoạt hay không.
  • limit: Xác định giá giới hạn lệnh.
  • stopGiá dừng lỗ.

Chúng tôi sẽ sử dụng tính năngstrategy.orderkhông có giới hạn về số lượng đơn đặt hàng được đặt, kết hợp vớistrategy.exithàm thoát điều kiện để xây dựng một kịch bản tương tự như giao dịch lưới. ví dụ rất đơn giản và chỉ cho mục đích học tập:

/*backtest
start: 2021-03-01 00:00:00
end: 2022-08-30 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"ETH_USDT"}]
args: [["ZPrecision",0,358374]]
*/

varip beginPrice = -1

if not barstate.ishistory
    if beginPrice == -1 or (math.abs(close - beginPrice) > 1000 and strategy.opentrades == 0) 
        beginPrice := close
    
    for i = 0 to 20
        strategy.order("buy"+i, strategy.long, 0.01, limit=beginPrice-i*200, when=(beginPrice-i*200)<close)
        strategy.exit("coverBuy"+i, "buy"+i, qty=0.01, profit=200)
        
        strategy.order("sell"+i, strategy.short, 0.01, limit=beginPrice+i*200, when=(beginPrice+i*200)>close)
        strategy.exit("coverSell"+i, "sell"+i, qty=0.01, profit=200)

Ví dụ về chiến lược

Các ví dụ về chiến lược trong hướng dẫn này chỉ dành cho mục đích hướng dẫn, để hướng dẫn các ý tưởng thiết kế chiến lược, và không phải là hướng dẫn hoặc lời khuyên giao dịch.

Chiến lược chỉ số siêu xu hướng

strategy("supertrend", overlay=true)

[supertrend, direction] = ta.supertrend(input(5, "factor"), input.int(10, "atrPeriod"))

plot(direction < 0 ? supertrend : na, "Up direction", color = color.green, style=plot.style_linebr)
plot(direction > 0 ? supertrend : na, "Down direction", color = color.red, style=plot.style_linebr)

if direction < 0
    if supertrend > supertrend[2]
        strategy.entry("entry long", strategy.long)
    else if strategy.position_size < 0
        strategy.close_all()
else if direction > 0
    if supertrend < supertrend[3]
        strategy.entry("entry short", strategy.short)
    else if strategy.position_size > 0
        strategy.close_all()

Nó rất dễ dàng để viết một chiến lược xu hướng bằng cách sử dụng ngôn ngữ Pine, và ở đây chúng tôi sẽ thiết kế một xu hướng đơn giản sau chiến lược với một chỉ số siêu xu hướng.

Đầu tiên, mã chiến lược bắt đầu với một số cài đặt đơn giản bằng cách sử dụngstrategychức năng:strategy("supertrend", overlay=true)``, which just sets a strategy title "supertrend". Thelớp phủparameter is set tođúng, so that the drawn indicator lines and other content are displayed on the main chart. The first thing we need to look at when designing a Pine strategy or learning a Pine strategy script is the strategy interface parameter design. Let's look at the source code of the ''supertrend indicator strategy'', which has theinput ` ` hàm chúng ta đã học trong khóa học trước

[supertrend, direction] = ta.supertrend(input(5, factor),input.int(10, trPeriod))

Cácinputgọi chức năng được sử dụng như một tham số trực tiếp đểta.supertrendchức năng chỉ số để tính toán chỉ số siêu xu hướng.

Theo mặc định, hàm đặt ra hai điều khiển tham số trên màn hình chiến lược ngôn ngữ Pine, như được hiển thị bên dưới:

img

Như chúng ta có thể thấy, giá trị mặc định trên điều khiển là tham số đầu tiên củainputchức năng vàinputchuỗi các chức năng (đây làinput.intVới hai chức năng này, chúng ta có thể đặt các tham số củata.supertrendchức năng trên màn hình chiến lược.supertrendchức năng tính toán một dữ liệu giásupertrendvà một dữ liệu hướngdirectionSau đó chúng ta sử dụngplotchức năng để vẽ một biểu đồ, lưu ý rằng khi vẽ biểu đồ, nó dựa trên hướng của chỉ số siêu xu hướng, chỉ có hướng hiện tại được vẽ.directionlà -1, xu hướng thị trường hiện tại là tăng, khidirectionlà 1, xu hướng thị trường hiện tại là giảm.plotchức năng vẽ biểu đồ khi phán quyếtdirectionlớn hơn hoặc nhỏ hơn 0.

Tiếp theo.if... else iflogic là sự phán xét của tín hiệu giao dịch.direction < 0là đúng, điều đó có nghĩa là thị trường hiện tại đang trong giai đoạn tăng.supertrendtrong chỉ số siêu xu hướng cao hơn giá của chỉ số siêu xu hướng trên hai BAR trước đó (tức làsupertrend[2], remember that the historical operator refers to the historical data of a variable), nó sẽ được sử dụng như là một tín hiệu nhập để đi dài. nhớ rằng? nếu có một vị trí hiện tại, gọi chức năng lệnh ngược sẽ đóng vị trí trước đó đầu tiên, và sau đó mở vị trí theo hướng giao dịch hiện tại.supertrend > supertrend[2]không được đáp ứng, miễn làstrategy.position_size < 0giữ các vị trí ngắn, nó sẽ kích hoạtstrategy.close_all()thực hiện chức năng để đóng tất cả các vị trí.

direction > 0Nếu có các vị trí dài, tất cả các vị trí sẽ được đóng, và sau đó khi điều kiệnsupertrend < supertrend[3]được đáp ứng, một tín hiệu ngắn sẽ được kích hoạt.[3]để tham chiếu dữ liệu giá của chỉ số siêu xu hướng trên BAR thứ ba của số trước? đó có thể là ý định của tác giả chiến lược. sau tất cả, rủi ro ngắn trong một số thị trường, chẳng hạn như thị trường giao dịch hợp đồng, lớn hơn một chút so với rủi ro dài.

Đối vớita.supertrendchỉ số, có ai quan tâm đến cách đánh giá liệu xu hướng hiện tại là lên hay xuống?

Trong thực tế, chỉ số này cũng có thể được thực hiện dưới dạng các hàm tùy chỉnh trong ngôn ngữ Pine:

pine_supertrend(factor, atrPeriod) =>
	src = hl2
	atr = ta.atr(atrPeriod)
	upperBand = src + factor * atr
	lowerBand = src - factor * atr
	prevLowerBand = nz(lowerBand[1])
	prevUpperBand = nz(upperBand[1])

	lowerBand := lowerBand > prevLowerBand or close[1] < prevLowerBand ? lowerBand : prevLowerBand
	upperBand := upperBand < prevUpperBand or close[1] > prevUpperBand ? upperBand : prevUpperBand
	int direction = na
	float superTrend = na
	prevSuperTrend = superTrend[1]
	if na(atr[1])
		direction := 1
	else if prevSuperTrend == prevUpperBand
		direction := close > upperBand ? -1 : 1
	else
		direction := close < lowerBand ? 1 : -1
	superTrend := direction == -1 ? lowerBand : upperBand
	[superTrend, direction]

Chức năng tùy chỉnh này là chính xác cùng một thuật toán như các chức năng tích hợp trongta.supertrend, và tất nhiên dữ liệu chỉ số được tính toán cũng là chính xác như nhau. Như chúng ta có thể thấy từ thuật toán chức năng tùy chỉnh này, Pines tích hợp trong chỉ số siêu xu hướng được tính bằng cách sử dụng cáchl2biến tích hợp (giá cao nhất và giá thấp nhất được cộng lại và sau đó chia cho 2, tức là mức trung bình của giá cao nhất và giá thấp nhất), sau đó chỉ số ATR (biến động) được tính toán cho một khoảng thời gian nhất định dựa trên tham số atrPeriod. Sau đó các đường dẫn trên và dưới được xây dựng bằng cách sử dụng hl2 và ATR.

Cập nhậtlowerBandupperBandtheo các biểu thức ba trong mã.

    lowerBand := lowerBand > prevLowerBand or close[1] < prevLowerBand ? lowerBand : prevLowerBand
    upperBand := upperBand < prevUpperBand or close[1] > prevUpperBand ? upperBand : prevUpperBand

lowerBand: lowerBand, được sử dụng để xác định xem xu hướng tăng có thay đổi hay không. upperBand: upperBand, được sử dụng để xác định xem xu hướng giảm có thay đổi hay không. lowerBand và upperBand luôn được tính toán, chỉ định hướng xu hướng hiện tại ở cuối hàm tùy chỉnh này.

    else if prevSuperTrend == prevUpperBand
        direction := close > upperBand ? -1 : 1
    else
        direction := close < lowerBand ? 1 : -1

Ở đây nó được đánh giá rằng nếu giá trị giá của BAR cuối cùng trên siêu xu hướng làprevUpperBand, tức là dải trên, nó có nghĩa là dòng là một xu hướng giảm.closevượt quáupperBandgiá đột phá, xu hướng được coi là đã thay đổi tại thời điểm này và chuyển đổi thành xu hướng tăng.directionlà -1 (hành động tăng trưởng). nếu không nó vẫn được thiết lập là 1 (hành động giảm). đó là lý do tại sao bạn thấy trong chiến lược siêu xu hướngif direction < 0khi các điều kiện tín hiệu được kích hoạt để đi dài.direction > 0, điều kiện tín hiệu được kích hoạt để đi ngắn.

    superTrend := direction == -1 ? lowerBand : upperBand
    [superTrend, direction]

Cuối cùng, dữ liệu giá và hướng của chỉ số Super Trend cụ thể được trả về dựa trên lựa chọn hướng.

Chiến lược cân bằng năng động

/*backtest
start: 2021-03-01 00:00:00
end: 2022-09-08 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Binance","currency":"ETH_USDT"}]
args: [["v_input_1",4374],["v_input_2",3],["v_input_3",300],["ZPrecision",0,358374]]
*/

varip balance = input(50000, "balance")
varip stocks = input(0, "stocks")

maxDiffValue = input(1000, "maxDiffValue")


if balance - close * stocks > maxDiffValue and not barstate.ishistory
    // more balance , open long 
    tradeAmount = (balance - close * stocks) / 2 / close
    strategy.order("long", strategy.long, tradeAmount)
    balance := balance - tradeAmount * close
    stocks := stocks + tradeAmount
    runtime.log("balance:", balance, ", stocks:", stocks, ", tradeAmount:", tradeAmount)

else if close * stocks - balance > maxDiffValue and not barstate.ishistory
    // more stocks , open short 
    tradeAmount = (close * stocks - balance) / 2 / close
    strategy.order("short", strategy.short, tradeAmount)
    balance := balance + tradeAmount * close
    stocks := stocks - tradeAmount
    runtime.log("balance:", balance, ", stocks:", stocks, ", tradeAmount:", tradeAmount)

plot(balance, title="balance value(quoteCurrency)", color=color.red)
plot(stocks*close, title="stocks value(quoteCurrency)", color=color.blue)

img

img

Hãy tiếp tục với một số ví dụ về thiết kế chiến lược ngôn ngữ Pine, lần này chúng ta sẽ học một chiến lược cân bằng năng động.BaseCurrencyvà số tiềnQuoteCurrency. Bất kể giá tương đối của tài sản nào tăng, giá trị được giữ trong tài khoản sẽ tăng và tài sản sẽ được bán. Nếu giá tương đối của tài sản giảm, giá trị được giữ trong tài khoản sẽ giảm và tài sản sẽ được mua. Điều này được gọi là chiến lược cân bằng năng động. Trên thực tế, chiến lược cân bằng năng động là một loại chiến lược lưới hoạt động tốt trong thị trường dao động. Nhưng trong thị trường xu hướng, nó sẽ tiếp tục mất tiền, chúng ta cần đợi giá trở lại để giảm lỗ từ từ để kiếm lợi nhuận, nhưng lợi thế là chiến lược cân bằng năng động luôn có thể nắm bắt xu hướng dao động của thị trường.

Nhược điểm, như được hiển thị trên biểu đồ backtest của chiến lược này, là chiến lược có một lỗ nổi lớn trong giai đoạn xu hướng giá chung tăng (hoặc giảm).

Chúng ta hãy nhìn vào thiết kế mã chiến lược:

Chúng tôi sử dụng một thiết kế đơn giản hóa mô phỏng mộtbalance(tức là, số lượng tài sản QuoteCurrency) vàstocksChúng tôi không đọc số lượng tài sản thực tế trong tài khoản, chúng tôi chỉ đơn giản là sử dụng số tiền mô phỏng để tính toán mua và bán thích hợp.maxDiffValue, là tiêu chí đánh giá để thực hiện cân bằng.BaseCurrencyQuoteCurrencyvượt quámaxDiffValuequá trình cân bằng diễn ra, bán tài sản với giá cao và mua tài sản với giá thấp để cân bằng lại tài sản.

Các chiến lược giao dịch tín hiệu kích hoạt phải là trong thời gian thực giai đoạn BAR, vì vậy nếu các phán đoán trong các điều kiện giao dịch chiến lược được thiết lập vớinot barstate.ishistory. Mua khibalancegiá trị vượt quástocksMột giao dịch bán hàng được thực hiện sau khi thực hiện báo cáo giao dịch.balancestocksCác biến được cập nhật và sau đó chờ đợi kích hoạt cân bằng tiếp theo.

Thông tin trên của backtest chiến lược chứa giá của loài tại thời điểm bắt đầu của backtest chiến lược, giá là 1458, vì vậy tôi đặt các thông sốbalanceđể: 4374 (1458 * 3) cố tình, đặt tham sốstocksĐể tài sản bắt đầu cân bằng.

Chiến lược siêu xu hướng với theo dõi dừng lỗ và lấy lợi nhuận

Trong khóa học trước, chúng ta đã học vềstrategy.exitTrong ví dụ thiết kế chiến lược này, chúng ta sẽ sử dụng cácstrategy.exitchức năng để tối ưu hóa một chiến lược siêu xu hướng.

Trước tiên hãy xem các thông số stop-loss và take-profit củastrategy.exitchức năng:

  1. Parametertrail_price: Vị trí kích hoạt hành động hợp lý của việc đặt lệnh dừng lỗ theo dõi và lệnh đóng cửa dừng lỗ (ở vị trí được chỉ định bởi giá).
  2. Parametertrail_offset: Khoảng cách từ giá cao nhất (khi mua) hoặc thấp nhất (khi mua) của một vị trí đóng được đặt sau khi thực hiện lệnh dừng lỗ theo dõi và lấy lợi nhuận.
  3. Parametertrail_pointsGiống nhưtrail_pricetham số, ngoại trừ việc nó lấy điểm lợi nhuận như là vị trí được chỉ định.

Không phải điều đó dễ hiểu sao? Không quan trọng! Hãy xem qua một kịch bản kiểm tra lại chiến lược để hiểu, thực sự khá đơn giản.

/*backtest
start: 2022-09-23 00:00:00
end: 2022-09-23 08:00:00
period: 1m
basePeriod: 1m
exchanges: [{"eid":"Binance","currency":"ETH_USDT"}]
args: [["RunMode",1,358374],["ZPrecision",0,358374]]
*/

strategy("test", overlay = true)

varip a = na
varip highPrice = na
varip isTrade = false 
varip offset = 30

if not barstate.ishistory and not isTrade
    strategy.entry("test 1", strategy.long, 1)
    strategy.exit("exit 1", "test 1", 1, trail_price=close+offset, trail_offset=offset)
    a := close + offset
    runtime.log("the price per point is:", syminfo.mintick, ", current close:", close)
    isTrade := true 

if close > a and not barstate.ishistory
    highPrice := na(highPrice) ? close : highPrice
    highPrice := close > highPrice ? close : highPrice

plot(a, "trail_price trigger line")    
plot(strategy.position_size>0 ? highPrice : na, "current highest price")
plot(strategy.position_size>0 ? highPrice-syminfo.mintick*offset : na, "moving stop trigger line")

img

img

img

Ngay lập tức đầu vào dài khi chiến lược bắt đầu thực hiện, và sau đó ngay lập tức đặt mộtstrategy.exitlệnh thoát (nó xác định các thông số theo dõi stop-loss và take-profit), khi giá của sự thay đổi thị trường tăng trên đường dẫn_price trigger, việc thực hiện logic stop-loss và take-profit, stop-loss và take-profit line (màu xanh) bắt đầu theo sự điều chỉnh động giá cao nhất, vị trí đường xanh là stop-loss và take-profit trigger để đóng vị trí, và cuối cùng khi giá thị trường giảm xuống dưới đường xanh kích hoạt việc đóng vị trí.

Sau đó chúng tôi sử dụng tính năng này để tối ưu hóa một chiến lược siêu xu hướng, chúng tôi chỉ đơn giản là chỉ định mộtstrategy.exitlệnh exit plan vào lệnh entry chiến lược để thêm tính năng stop-loss và take-profit sau này.

if not barstate.ishistory and findOrderIdx("open") >= 0 and state == 1
    trail_price := strategy.position_size > 0 ? close + offset : close - offset
    strategy.exit("exit", "open", 1, trail_price=trail_price, trail_offset=offset)
    runtime.log("the price per point is:", syminfo.mintick, ", current close:", close, ",trail_price:", trail_price)
    state := 2 
    tradeBarIndex := bar_index

Mã chiến lược đầy đủ:

/*backtest
start: 2022-05-01 00:00:00
end: 2022-09-27 00:00:00
period: 1d
basePeriod: 5m
exchanges: [{"eid":"Binance","currency":"ETH_USDT"}]
args: [["RunMode",1,358374],["ZPrecision",0,358374]]
*/

varip trail_price = na
varip offset = input(50, "offset")
varip tradeBarIndex = 0
// 0 : idle , 1 current_open , 2 current_close
varip state = 0  

findOrderIdx(idx) =>
    ret = -1 
    if strategy.opentrades == 0 
        ret
    else 
        for i = 0 to strategy.opentrades - 1 
            if strategy.opentrades.entry_id(i) == idx
                ret := i 
                break
        ret

if strategy.position_size == 0 
    trail_price := na 
    state := 0

[superTrendPrice, dir] = ta.supertrend(input(2, "atr coefficient"), input(20, "atr period"))

if ((dir[1] < 0 and dir[2] > 0) or (superTrendPrice[1] > superTrendPrice[2])) and state == 0 and tradeBarIndex != bar_index
    strategy.entry("open", strategy.long, 1)
    state := 1
else if ((dir[1] > 0 and dir[2] < 0) or (superTrendPrice[1] < superTrendPrice[2])) and state == 0 and tradeBarIndex != bar_index
    strategy.entry("open", strategy.short, 1)
    state := 1


// Reverse signal, close all positions
if strategy.position_size > 0 and dir[2] < 0 and dir[1] > 0
    strategy.cancel_all()
    strategy.close_all()
    runtime.log("trend reversal, long positions all closed")
else if strategy.position_size < 0 and dir[2] > 0 and dir[1] < 0
    strategy.cancel_all()
    strategy.close_all()
    runtime.log("trend reversal, short positions all closed")


if not barstate.ishistory and findOrderIdx("open") >= 0 and state == 1
    trail_price := strategy.position_size > 0 ? close + offset : close - offset
    strategy.exit("exit", "open", 1, trail_price=trail_price, trail_offset=offset)
    runtime.log("the price per point is:", syminfo.mintick, ", current close:", close, ", trail_price:", trail_price)
    state := 2 
    tradeBarIndex := bar_index


plot(superTrendPrice, "superTrendPrice", color=dir>0 ? color.red : color.green, overlay=true)

Thêm nữa