리소스 로딩... 로딩...

발명자 양적화 된 PINE 언어의 소개 교과서

저자:발명가들의 수량화 - 작은 꿈, 창작: 2022-05-30 16:23:43, 업데이트: 2022-09-28 17:10:21

예를 들어:

var lineColor = na

n = if bar_index > 10 and bar_index <= 20
    lineColor := color.green
else if bar_index > 20 and bar_index <= 30
    lineColor := color.blue
else if bar_index > 30 and bar_index <= 40
    lineColor := color.orange
else if bar_index > 40
    lineColor := color.black
else 
    lineColor := color.red
    
plot(close, title="close", color=n, linewidth=5, overlay=true)
plotchar(true, title="bar_index", char=str.tostring(bar_index), location=location.abovebar, color=color.red, overlay=true)

핵심: 판단용 표현식, 풀값을 반환한다. ▲ 축소 주의. ▲ 최대 한 개의else 분포만 있을 수 있다. ▲ 모든 branch 표현식들은 사실이 아니다.

x = if close > open
    close
plot(x, title="x")

K선BAR가 음선인 경우, 즉 close

스위치 문장

스위치 문장은 특정 조건에 따라 다른 경로를 수행하도록 설계하는 분기 구조의 문장이기도 합니다. 스위치 문장은 일반적으로 다음과 같은 몇 가지 핵심 지식을 가지고 있습니다.

1, 스위치 문장은 if 문장과 마찬가지로 값을 반환합니다. 2, 다른 언어의 스위치 문장과 달리, 스위치 구조를 실행할 때 코드 내의 로컬 블록만을 실행하므로 break 선언이 필요하지 않습니다. 3, 스위치의 각 부문은 로컬 코드 블록을 쓸 수 있으며, 로컬 코드 블록의 마지막 줄은 반환 값 (그것이 값의 계열이 될 수 있다) 이다. 만약 브랜치된 로컬 코드 블록이 실행되지 않으면 na 를 반환한다. 4. 스위치 구조의 표현식 위치 판단, 문자열, 변수, 표현식 또는 함수 호출을 쓸 수 있다. 5, 스위치는 구조에서 다른 상황이 실행되지 않을 때 사용되는 기본값으로 반환되는 값을 지정하도록 허용한다.

스위치는 두 가지 형태로 나뉘어 있습니다. 예를 하나씩 살펴보고 사용법을 알아봅니다.

1과 같은 표현식을 가지고 있습니다.switch예를 들어:

// input.string: defval, title, options, tooltip
func = input.string("EMA", title="指标名称", tooltip="选择要使用的指标函数名称", options=["EMA", "SMA", "RMA", "WMA"])

// input.int: defval, title, options, tooltip
// param1 = input.int(10, title="周期参数")
fastPeriod = input.int(10, title="快线周期参数", options=[5, 10, 20])
slowPeriod = input.int(20, title="慢线周期参数", options=[20, 25, 30])

data = input(close, title="数据", tooltip="选择使用收盘价、开盘价、最高价...")
fastColor = color.red
slowColor = color.red

[fast, slow] = switch func
    "EMA" =>
        fastLine = ta.ema(data, fastPeriod)
        slowLine = ta.ema(data, slowPeriod)
        fastColor := color.red
        slowColor := color.red
        [fastLine, slowLine]
    "SMA" =>
        fastLine = ta.sma(data, fastPeriod)
        slowLine = ta.sma(data, slowPeriod)
        fastColor := color.green
        slowColor := color.green
        [fastLine, slowLine]
    "RMA" =>
        fastLine = ta.rma(data, fastPeriod)
        slowLine = ta.rma(data, slowPeriod)
        fastColor := color.blue
        slowColor := color.blue
        [fastLine, slowLine]
    =>
        runtime.error("error")
        
plot(fast, title="fast" + fastPeriod, color=fastColor, overlay=true)
plot(slow, title="slow" + slowPeriod, color=slowColor, overlay=true)

이제, 우리가 입력 함수를 배웠을 때, 우리는 입력과 비슷한 두 가지 함수를 더 배우게 됩니다.input.stringinput.int이 함수들은input.string이 문자는 문자열을 되돌리는 데 사용되는데,input.int이 함수들은 전체값을 반환합니다. 이 예에서는 실제로 새로운 함수를 추가합니다.options이 경우,options변수는 선택값으로 구성된 배열에 전달될 수 있다. 예를 들어options=["EMA", "SMA", "RMA", "WMA"]그리고options=[5, 10, 20](하나가 문자열 타입이고, 다른 하나는 숫자 타입이다.);; 이렇게 하면 정책 인터페이스의 컨트롤은 특정 숫자를 입력할 필요가 없으며, 대신 컨트롤은 드래그아웃으로 바뀌고, options 파라미터에서 제공되는 옵션을 선택한다.

변수 func의 값은 문자열로, 변수 func는 스위치의 표현식 (변수, 함수 호출, 표현식) 으로 실행되는 스위치의 어떤 브랜치를 결정합니다. 변수 func가 스위치의 어느 브랜치의 표현식과 일치하지 않으면 (즉, 동등) 기본 브랜치 코드 블록을 실행합니다.runtime.error("error")함수들은 정책에서 예외를 던지는 것을 멈추게 합니다.

위의 테스트 코드에서 스위치의 기본 브래치 코드 블록의 마지막 라인 runtime.error 이후, 우리는 [na, na] 같은 코드를 추가하지 않고 호환값을 반환하고, 트레이딩 뷰에서는 이 문제를 고려해야 합니다. 타입이 일치하지 않으면 오류가 발생합니다. 그러나 FMZ에서는 엄격한 타입 요구가 없기 때문에 이러한 호환 코드를 무시할 수 있습니다. 따라서 FMZ에서는 if, 스위치 브래치가 반환하는 타입 호환 문제를 고려할 필요가 없습니다.

strategy("test", overlay=true)
x = if close > open
    close
else
    "open"
plotchar(true, title="x", char=str.tostring(x), location=location.abovebar, color=color.red)

FMZ에서는 오류를 보고하지 않으며, 트레이딩 뷰에서는 오류를 보고합니다. if 브래치가 반환되는 타입이 일치하지 않기 때문입니다.

2는 표현식이 없습니다.switch

이 모든 것은 우리가 할 수 있는 일입니다switch이 글은 다른 말로 쓰여지는데, 표현이 없는 글이다.

up = close > open     // up = close < open 
down = close < open 
var upOfCount = 0 
var downOfCount = 0 

msgColor = switch
    up  => 
        upOfCount += 1 
        color.green 
    down => 
        downOfCount += 1
        color.red

plotchar(up, title="up", char=str.tostring(upOfCount), location=location.abovebar, color=msgColor, overlay=true)
plotchar(down, title="down", char=str.tostring(downOfCount), location=location.belowbar, color=msgColor, overlay=true)

테스트 코드 예제에서 볼 수 있듯이, 스위치는 실행 브래치 조건에 따라 실제 로컬 코드 블록을 매칭한다. 일반적으로 스위치 문장을 따르는 브래치 조건은 서로 반박되어야 한다. 즉, 예제에서 위와 아래는 동시에 진실이 될 수 없다. 스위치가 하나의 브래치로만 실행할 수 있는 로컬 코드 블록을 실행하기 때문에, 코드에서 다음과 같은 문장을 넣는 것이 흥미롭다.up = close > open // up = close < open참고문헌의 내용을 대신하여, 결과를 다시 관찰한다. 스위치 부문은 첫 번째 부문을만 실행할 수 있다는 것을 발견한다. 또한, 스위치의 부문에 함수 호출을 작성하지 않도록 주의해야 한다. 함수들은 각 BAR에서 호출될 수 없으며, "표현이 있는 함수"와 같은 경우를 제외하고는 일부 데이터 계산 문제를 일으킬 수 있다.switch"사례에서, 실행 부문은 정해져 있으며, 전략 실행 중에 변경되지 않습니다".)

순환 구조

for 문장

返回值 = for 计数 = 起始计数 to 最终计数 by 步长
    语句                                            // 注释:语句里可以有break,continue
    语句                                            // 注释:最后一条语句为返回值

for 문장의 사용은 매우 간단하며, for 루프는 최종적으로 하나의 값을 (또는 [a, b, c]와 같은 형태로 여러 값을 반환할 수 있습니다.);; 위 위 위 위조코드에서 "귀환 값" 위치에 지정된 변수와 같습니다. for 문장의 다음에는 "수정" 변수가 있습니다. 이는 루프 수를 제어하고 다른 값을 참조하는 데 사용됩니다. "수정" 변수는 루프 시작 전에 "초기 수정"으로 지정되어 있으며, "증대" 설정에 따라 "수정"이 "최종 변수"보다 많을 때 루프는 중단됩니다.

for 순환에서 사용된break키워드: 실행break문장을 마친 후 순환은 멈춘다. for 순환에서 사용된continue키워드: 실행continue문장 후에, 루프는 무시됩니다.continue다음 코드는 다음 라운드를 직접 실행한다. for 문장은 마지막 라운드를 실행했을 때 반환된 값을 반환한다.

이 글의 내용은 한 가지 간단한 예로 보여드리겠습니다.

ret = for i = 0 to 10       // 可以增加by关键字修改步长,暂时FMZ不支持 i = 10 to 0 这样的反向循环
    // 可以增加条件设置,使用continue跳过,break跳出
    runtime.log("i:", i)
    i                       // 如果这行不写,就返回空值,因为没有可返回的变量
    
runtime.log("ret:", ret)
runtime.error("stop")

for... in 문장

for ... in이 문장은 두 가지 형태를 가지고 있으며 아래의 위조 코드가 설명합니다.

返回值 = for 数组元素 in 数组 
    语句                        // 注释:语句里可以有break,continue
    语句                        // 注释:最后一条语句为返回值
返回值 = for [索引变量, 索引变量对应的数组元素] in 数组
    语句                        // 注释:语句里可以有break,continue
    语句                        // 注释:最后一条语句为返回值 

두 형태의 주요 차이점은 for 키워드 뒤에 따르는 내용으로 볼 수 있다. 하나는 변수를 기호분석 요소의 변수로 사용하는 것이다. 하나는 인덱스 변수, 기호분석 요소 변수들의 기호분석을 포함하는 구조를 사용하는 것이다. 다른 하나는 반환값 규칙, break, continuue 등의 규칙을 사용하는 것이다. 우리는 또한 간단한 예를 통해 사용에 대해 설명한다.

testArray = array.from(10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
for ele in testArray            // 修改成 [i, ele]的形式:for [i, ele] in testArray , runtime.log("ele:", ele, ", i:", i)
    runtime.log("ele:", ele)

runtime.error("stop")

인덱스를 사용해야 할 때 사용합니다.for [i, ele] in testArray이 글의 글씨는 ᅳ

for 순환용

파인어를 통해 제공되는 내장 함수를 사용하여 어떤 루킹 논리 계산을 수행할 수 있는 경우, 루킹 구조를 사용하여 직접 작성할 수 있고, 내장 함수 처리도 사용할 수 있다. 두 가지 예를 들어보자.

1, 계산 평균값

순환 구조 디자인을 사용하는 경우:

length = 5
var a = array.new(length)
array.push(a, close)

if array.size(a) >= length
	array.remove(a, 0)
	
sum = 0 	
for ele in a
    sum += ele 

avg = sum / length
plot(avg, title="avg", overlay=true)

예를 들어, for 회로 합을 사용 하 고, 그리고 평가를 계산 합니다.

기본 함수를 사용하여 직렬을 계산합니다:

plot(ta.sma(close, length), title="ta.sma", overlay=true)

내장 함수를 직접 사용하세요ta.sma, 평선 지표를 계산하는 것은 평선을 계산하는 데 내장 함수를 사용하는 것이 분명하게 더 간단하다. 그래프에서 비교하면 계산된 결과가 완전히 일치하는 것을 볼 수 있다.

2 곱하기

그리고 이 예제를 사용해서 설명할 수도 있습니다.

순환 구조 디자인을 사용하는 경우:

length = 5
var a = array.new(length)
array.push(a, close)

if array.size(a) >= length
	array.remove(a, 0)
	
sum = 0 	
for ele in a
    sum += ele 

avg = sum / length
plot(avg, title="avg", overlay=true)
plot(ta.sma(close, length), title="ta.sma", overlay=true)

배열의 모든 요소를 계산하기 위해 회로를 사용할 수 있고, 내장 함수를 사용할 수도 있습니다.array.sum 내장 함수를 직접 사용하여 합을 계산합니다:

length = 5
var a = array.new(length)
array.push(a, close)

if array.size(a) >= length
	array.remove(a, 0)
	
plot(array.sum(a) / length, title="avg", overlay=true)
plot(ta.sma(close, length), title="ta.sma", overlay=true)

계산된 데이터를 볼 수 있고, 플롯 그림을 사용하여 그래프에 완벽하게 일치하는 것을 볼 수 있습니다.

이 모든 작업은 내장 함수로 수행될 수 있기 때문에 왜 루킹을 설계해야 할까요? 루킹을 사용하는 것은 주로 다음 3가지에 기반한 응용입니다: 1, 배열에 대한 몇 가지 동작, 계산. 2, 역사를 회상하여, 예를 들어, 현재 BAR의 높이에 비해 얼마나 많은 과거 높이를 발견하는 것. 현재 BAR의 높이는 스크립트가 실행되는 BAR에서만 알려져 있기 때문에, 시간을 되돌려서 과거의 BAR를 분석하는 루프가 필요합니다. 3, 파인 언어를 사용하는 내장 함수가 과거 BAR에 대한 계산을 완료할 수 없는 경우.

while 문장

while문장은 while 구조의 판단 조건이 false가 될 때까지 루킹 부분의 코드를 계속 실행하도록 합니다.

返回值 = while 判断条件
    语句                    // 注释:语句里可以有break,continue
    语句                    // 注释:最后一条语句为返回值

while의 다른 규칙은 for 루킹과 비슷하며, 루킹의 로컬 코드 블록의 마지막 줄은 반환 값이며, 여러 값을 반환할 수 있다. "루킹 조건"이 적당한 경우 루킹을 실행하고, 조건이 적당한 경우 루킹을 중지한다. 루킹에 break, continue 문장을 사용할 수도 있다.

이 모든 것은 우리가 어떻게 해야 하는 일이고, 어떻게 해야 하는 일이고,

length = 10

sma(data, length) => 
    i = 0 
    sum = 0 
    while i < 10 
        sum += data[i]
        i += 1
        sum / length

plot(sma(close, length), title="sma", overlay=true)
plot(ta.sma(close, length), title="ta.sma", overlay=true)

볼 수 있듯이 while 루킹은 매우 간단하게 사용되기도 하고, 또한 내장 함수와 대체할 수 없는 계산 논리를 설계할 수도 있습니다. 예를 들어, 계산 계수:

counter = 5
fact = 1

ret = while counter > 0
    fact := fact * counter
    counter := counter - 1
    fact

plot(ret, title="ret")  // ret = 5 * 4 * 3 * 2 * 1

대수군

파인 언어의 배열 정의는 다른 프로그래밍 언어의 배열 정의와 비슷하다. 파인 언어의 배열은 1차원 배열이다. 일반적으로 연속적인 일련의 데이터를 저장하는 데 사용됩니다. 배열에 저장된 개별 데이터의 요소는 배열의 요소라고 불리며, 이러한 요소의 유형은 다음과 같습니다. 전체형, 점수형, 문자열, 색상 값, 부르 값. FMZ의 파인 언어는 매우 엄격하게 유형을 요구하지 않으며 문자열과 숫자를 동시에 배열에 저장할 수 있습니다. 배열의 밑부분이 또한 일련 구조이기 때문에 역사 연산자가 이전 BAR의 배열 상태를 참조하는 경우 역사 연산자를 사용하지 않습니다.[]우리는 그것을 사용해야 합니다.array.get()그리고array.set()함수. 대수열에 있는 요소의 인덱스 순서는 대수열의 첫 번째 요소의 인덱스가 0이고 다음 요소의 인덱스는 1로 증가한다.

우리는 간단한 코드를 사용하여 설명합니다.

var a = array.from(0)
if bar_index == 0 
    runtime.log("当前BAR上的a值:", a, ", 上1根BAR上的a,即a[1]值:", a[1])
else if bar_index == 1 
    array.push(a, bar_index)
    runtime.log("当前BAR上的a值:", a, ", 上1根BAR上的a,即a[1]值:", a[1])
else if bar_index == 2
    array.push(a, bar_index)
    runtime.log("当前BAR上的a值:", a, ", 上1根BAR上的a,即a[1]值:", a[1], ", 向前数2根BAR上的a,即a[2]值:", a[2])
else if bar_index == 3 
    array.push(a, bar_index)
    runtime.log("当前BAR上的a值:", a, ", 上1根BAR上的a,即a[1]值:", a[1], ", 向前数2根BAR上的a,即a[2]值:", a[2], ", 向前数3根BAR上的a,即a[3]值:", a[3])
else if bar_index == 4 
    // 使用array.get 按索引获取元素,使用array.set按索引修改元素
    runtime.log("数组修改前:", array.get(a, 0), array.get(a, 1), array.get(a, 2), array.get(a, 3))
    array.set(a, 1, 999)
    runtime.log("数组修改后:", array.get(a, 0), array.get(a, 1), array.get(a, 2), array.get(a, 3))

선언 배열

사용array<int> afloat[] b선언된 배열 또는 오직 하나의 변수를 선언한 배열은 배정 배열로 지정될 수 있습니다. 예를 들어:

array<int> a = array.new(3, bar_index)
float[] b = array.new(3, close)
c = array.from("hello", "fmz", "!")
runtime.log("a:", a)
runtime.log("b:", b)
runtime.log("c:", c)
runtime.error("stop")

대수 변수 초기화 일반적으로 사용array.new그리고array.from函数。Pine语言中还有很多和类型相关的与array.new类似的函数:array.new_int()array.new_bool()array.new_color()array.new_string()

var 키워드는 또한 배열의 선언 모드와 함께 작용할 수 있으며, var 키워드를 사용하여 선언된 배열은 첫 번째 BAR에서만 초기화된다. 예를 들어 다음과 같이 볼 수 있다.

var a = array.from(0)
b = array.from(0)

if bar_index == 1
    array.push(a, bar_index)
    array.push(b, bar_index)
else if bar_index == 2 
    array.push(a, bar_index)
    array.push(b, bar_index)
else if barstate.islast
    runtime.log("a:", a)
    runtime.log("b:", b)
    runtime.error("stop")

a 행렬의 변동은 계속적으로 정해져 있고, 다시 배치되지 않습니다. b 행렬은 각 BAR에서 초기화됩니다.barstate.islast실시간으로 인쇄할 때 여전히 하나의 요소, 값은 0이다.

배열에 있는 요소들을 읽고, 쓰고

array.get로 배열에서 지표 위치를 지정하는 요소를 얻거나 array.set로 배열에서 지표 위치를 지정하는 요소를 수정하십시오.

array.get의 첫 번째 매개변수는 처리해야 할 배열이고 두 번째 매개변수는 지정된 인덱스이다. array.set의 첫 번째 매개 변수는 처리해야 할 배열, 두 번째 매개 변수는 지정된 인덱스, 세 번째 매개 변수는 작성해야 할 요소입니다.

예를 들어, 이 간단한 예제를 사용해서 설명해 보겠습니다.

lookbackInput = input.int(100)
FILL_COLOR = color.green

var fillColors = array.new(5)
if barstate.isfirst
    array.set(fillColors, 0, color.new(FILL_COLOR, 70))
    array.set(fillColors, 1, color.new(FILL_COLOR, 75))
    array.set(fillColors, 2, color.new(FILL_COLOR, 80))
    array.set(fillColors, 3, color.new(FILL_COLOR, 85))
    array.set(fillColors, 4, color.new(FILL_COLOR, 90))

lastHiBar = - ta.highestbars(high, lookbackInput)
fillNo = math.min(lastHiBar / (lookbackInput / 5), 4)

bgcolor(array.get(fillColors, int(fillNo)), overlay=true)
plot(lastHiBar, title="lastHiBar")
plot(fillNo, title="fillNo")

이 예제에서는 기본 색상 녹색을 초기화하여 색상을 저장하기 위한 배열을 선언하고 초기화하고 색값에 다른 투명성을 부여합니다 (color.new 함수를 사용하십시오). 현재 BAR 거리의 100 회전 동안의 최대의 high값 거리를 계산하여 색 순위를 계산합니다. 최근 100 회전 동안의 최대의 high값에 가까운 거리가 높을수록 해당 색값이 깊어집니다 (투명성이 낮습니다). 많은 유사한 전략이 N 회전 동안의 현재 가격 수준을 나타냅니다.

배열 요소를 탐색합니다.

어떻게 행렬을 횡단할 수 있는지, 우리는 전에 배운 for/for in/while 문장을 사용할 수 있습니다.

a = array.from(1, 2, 3, 4, 5, 6)

for i = 0 to (array.size(a) == 0 ? na : array.size(a) - 1)
    array.set(a, i, i)
    
runtime.log(a)
runtime.error("stop")
a = array.from(1, 2, 3, 4, 5, 6)

i = 0
while i < array.size(a)
    array.set(a, i, i)
    i += 1

runtime.log(a)
runtime.error("stop")
a = array.from(1, 2, 3, 4, 5, 6)

for [i, ele] in a 
    array.set(a, i, i)

runtime.log(a)
runtime.error("stop")

이 세 가지 탐색 방식의 실행 결과는 동일합니다.

배열은 스크립트의 글로벌 범위에서 선언할 수 있고 함수 또는 if 브랜치의 로컬 범위에서 선언할 수 있습니다.

역사 자료 참조

배열의 요소를 사용하는 경우, 다음과 같은 방법이 동등합니다. 다음 예제를 통해 그래프에서 두 개의 줄의 집합을 그려 볼 수 있습니다.

a = array.new_float(1)
array.set(a, 0, close)
closeA1 = array.get(a, 0)[1]
closeB1 = close[1]
plot(closeA1, "closeA1", color.red, 6)
plot(closeB1, "closeB1", color.black, 2)

ma1 = ta.sma(array.get(a, 0), 20)
ma2 = ta.sma(close, 20)
plot(ma1, "ma1", color.aqua, 6)
plot(ma2, "ma2", color.black, 2)

배열을 추가하고 동작 함수를 삭제합니다.

1, 배열의 추가 연산과 관련된 함수:

array.unshift()array.insert()array.push()

2, 행렬의 삭제 작업에 관련된 함수:

array.remove()array.shift()array.pop()array.clear()

우리는 다음과 같은 예제를 사용하여 이 배열의 덧셈, 셈 동작 함수를 테스트합니다.

a = array.from("A", "B", "C")
ret = array.unshift(a, "X")
runtime.log("数组a:", a, ", ret:", ret)

ret := array.insert(a, 1, "Y")
runtime.log("数组a:", a, ", ret:", ret)

ret := array.push(a, "D")
runtime.log("数组a:", a, ", ret:", ret)

ret := array.remove(a, 2)
runtime.log("数组a:", a, ", ret:", ret)

ret := array.shift(a)
runtime.log("数组a:", a, ", ret:", ret)

ret := array.pop(a)
runtime.log("数组a:", a, ", ret:", ret)

ret := array.clear(a)
runtime.log("数组a:", a, ", ret:", ret)

runtime.error("stop")

추가, 삭제 응용 프로그램: 행렬로 행렬

수직선, 그리고 수직선의 일부 추가, 삭제 함수들을 사용하여 우리는 "열" 데이터 구조를 구성할 수 있습니다.

큐어 (queue) 는 프로그래밍 분야에서 자주 사용되는 구조로, 큐어의 특징은 다음과 같습니다.

쿼리에 들어간 첫 번째 요소, 쿼리에서 먼저 나오십시오.

이렇게 하면 줄에 존재하는 데이터가 최신 데이터이고 줄의 길이가 무한히 팽창하지 않는다는 것을 보장할 수 있습니다. (한계적으로 팽창하는 코드는 낮에만 작성할 수 있습니다.

다음 예제에서 우리는 틱 레벨의 이동 평균값을 계산하고 1분 K 라인 레벨의 이동 평균값과 비교하여 각 틱의 가격을 기록하는 줄 구조를 사용합니다.

strategy("test", overlay=true)

varip a = array.new_float(0)
var length = 10

if not barstate.ishistory
    array.push(a, close)

    if array.size(a) > length
        array.shift(a)

sum = 0.0
for [index, ele] in a 
    sum += ele

avgPrice = array.size(a) == length ? sum / length : na

plot(avgPrice, title="avgPrice")
plot(ta.sma(close, length), title="ta.sma")

a 행렬을 선언할 때 a 행렬의 패턴을 지정하고varipᅳ 이렇게 모든 가격 변화는 a 배열에 기록됩니다.

일반적으로 사용되는 배열 계산, 동작 함수

관련 함수를 계산합니다:

array.avg()수직선에 있는 모든 원소들의 평균값을 구합니다.array.min()소수함수의 가장 작은 요소,array.max()이 수직선에서 가장 큰 요소는array.stdev()소수함수의 모든 요소의 표준편차는array.sum()소수함수의 모든 요소들의 합이다.

운영 관련 함수:array.concat()두 대의 행렬을 합치거나 연결합니다.array.copy()복제 행렬.array.join행렬의 모든 요소를 하나의 문자열로 연결합니다.array.sort()위층 또는 하위 순서로 정렬하십시오.array.reverse()역수군.array.slice()행렬을 조각합니다.array.includes()이 글은 다른 글과 비교해 볼 수 있습니다.array.indexof()파러그램 입력 값이 처음 나타난 인덱스를 반환한다. 값이 발견되지 않으면 -1를 반환한다.array.lastindexof()마지막으로 나타난 값을 찾습니다.

대수 계산에 관련된 함수의 테스트 예제:

a = array.from(3, 2, 1, 4, 5, 6, 7, 8, 9)

runtime.log("数组a的算数平均:", array.avg(a))
runtime.log("数组a中的最小元素:", array.min(a))
runtime.log("数组a中的最大元素:", array.max(a))
runtime.log("数组a中的标准差:", array.stdev(a))
runtime.log("数组a的所有元素总和:", array.sum(a))
runtime.error("stop")

이것은 비교적 일반적으로 사용되는 대수학적 계산 함수입니다.

관련 함수를 작동하는 예제:

a = array.from(1, 2, 3, 4, 5, 6)
b = array.from(11, 2, 13, 4, 15, 6)

runtime.log("数组a:", a, ", 数组b:", b)
runtime.log("数组a,数组b连接在一起:", array.concat(a, b))
c = array.copy(b)

runtime.log("复制一个数组b,赋值给变量c,变量c:", c)

runtime.log("使用array.join处理数组c,给每个元素中间增加符号+,连接所有元素结果为字符串:", array.join(c, "+"))
runtime.log("排序数组b,按从小到大顺序,使用参数order.ascending:", array.sort(b, order.ascending))     // array.sort函数修改原数组
runtime.log("排序数组b,按从大到小顺序,使用参数order.descending:", array.sort(b, order.descending))   // array.sort函数修改原数组

runtime.log("数组a:", a, ", 数组b:", b)
array.reverse(a)   // 此函数修改原数组
runtime.log("反转数组a中的所有元素顺序,反转之后数组a为:", a)    

runtime.log("截取数组a,索引0 ~ 索引3,遵循左闭右开区间规则:", array.slice(a, 0, 3))
runtime.log("在数组b中搜索元素11:", array.includes(b, 11))
runtime.log("在数组a中搜索元素100:", array.includes(a, 100))
runtime.log("将数组a和数组b连接,搜索其中第一次出现元素2的索引位置:", array.indexof(array.concat(a, b), 2), " , 参考观察 array.concat(a, b):", array.concat(a, b))
runtime.log("将数组a和数组b连接,搜索其中最后一次出现元素6的索引位置:", array.lastindexof(array.concat(a, b), 6), " , 参考观察 array.concat(a, b):", array.concat(a, b))

runtime.error("stop")

함수

사용자 정의 함수

파인 언어는 사용자 정의 함수를 설계할 수 있으며 일반적으로 파인 언어의 사용자 정의 함수는 다음과 같은 규칙을 가지고 있습니다.

1, 모든 함수는 스크립트의 범위에 정의된다. 다른 함수에서 함수를 선언할 수 없다. 2, 함수가 자신의 코드에서 자신을 호출하는 것을 허용하지 않습니다. 3, 원칙적으로 모든 PINE 언어에는 그림자 함수가 내장되어 있습니다.barcolor()、 fill()、 hline()、plot()、 plotbar()、 plotcandle()) 는 사용자 정의 함수에서 호출할 수 없습니다. 4, 함수는 단열, 다열로 쓸 수 있다. 마지막 문장의 반환 값은 현재 함수의 반환 값이며, 반환 값은 계열 형식을 반환할 수 있다.

이전 튜토리얼에서 우리는 여러 번 사용자 정의 함수를 사용했습니다. 예를 들어, 한 줄의 사용자 정의 함수를 디자인합니다.

barIsUp() => close > open

이 함수는 현재 BAR가 햇빛인지 여부를 반환합니다.

여러 줄의 사용자 정의 함수로 설계되었습니다.

sma(data, length) => 
    i = 0 
    sum = 0 
    while i < 10 
        sum += data[i]
        i += 1
        sum / length

plot(sma(close, length), title="sma", overlay=true)
plot(ta.sma(close, length), title="ta.sma", overlay=true)

우리가 직접 사용자 정의 함수로 구현한 SMA 평균선을 계산한 함수.

또한, 두 개의 변수를 반환하는 사용자 정의 함수의 예를 볼 수 있습니다:

twoEMA(data, fastPeriod, slowPeriod) =>
    fast = ta.ema(data, fastPeriod)
    slow = ta.ema(data, slowPeriod)
    [fast, slow]

[ema10, ema20] = twoEMA(close, 10, 20)
plot(ema10, title="ema10", overlay=true)
plot(ema20, title="ema20", overlay=true)

하나의 함수는 빠른 라인, 느린 라인, 두 개의 EMA 평선 지표를 계산할 수 있다.

내장 함수

이 함수들은FMZ PINE 스크립트 문서이 문서는

파인 언어의 내장 함수 분류:

1, 문자열 처리 함수str.이 시리즈는 2, 색값 처리 함수color.이 시리즈는 3, 변수 입력 함수input.이 시리즈는 4, 지표 계산 함수ta.이 시리즈는 5 그래프 함수plot.이 시리즈는 6, 배열 처리 함수array.이 시리즈는 7 거래 관련 함수strategy.이 시리즈는 8, 수학 연산 관련 함수math.이 시리즈는 9, 다른 함수 (시간 처리, 비 플롯 시리즈 그림 함수,request.일련 함수, 타입 처리 함수 등) ^

거래 함수

strategy.일련 함수들은 우리가 설계 전략에서 자주 사용하는 함수이며, 이 함수와 전략이 특정 실행 시 거래 작업을 수행하는 데 밀접한 관련이 있다.


1、strategy.entry

strategy.entry함수는 우리가 정책을 작성할 때 더 중요한 하위 함수입니다. 이 함수는 몇 가지 매개 변수보다 더 중요합니다.id, direction, qty, when

파라미터:

  • id: 어떤 거래 포지션에 대한 이름을 참조로 사용할 수 있습니다. 이 id를 취소, 변경 주문, 평정으로 참조할 수 있습니다.
  • direction: 주문 방향이 더하기 (구입) 이면 이 매개 변수가 전달됩니다.strategy.long이 내장 변수는, 만약 빈 (~) 을 팔면 전달됩니다.strategy.short이 변수는
  • qty: 주문할 수 있는 양을 지정합니다. 이 매개 변수를 전달하지 않으면 기본 주문할 수 있는 양을 사용합니다.
  • when: 실행 조건, 이 매개 변수를 지정하여 현재 하위 동작이 발동되는지 여부를 제어할 수 있습니다.
  • limit: 주문 한계 가격을 지정합니다.
  • stop: 손해배상금지.

strategy.entry함수의 구체적인 실행 세부 사항strategy함수를 호출할 때 설정을 설정하는 것을 제어할 수 있습니다"Pine 언어 거래소 템플릿 매개 변수"설정 컨트롤, 파인 언어 거래 클래스 라이브러리 템플릿 매개 변수 컨트롤 거래 세부 사항은 더 자세히 참조하십시오.

이 부분의 본문은strategy이 함수에서pyramidingdefault_qty_value파라미터. 다음 코드를 사용하여 테스트:

/*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(title = "open long example", pyramiding = 3, default_qty_value=0.1, overlay=true)

ema10 = ta.ema(close, 10)

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

if not findOrderIdx("long1")
    strategy.entry("long1", strategy.long)

if not findOrderIdx("long2")
    strategy.entry("long2", strategy.long, 0.2, when = close > ema10)

if not findOrderIdx("long3")
    strategy.entry("long3", strategy.long, 0.2, limit = low[1])
    strategy.entry("long3", strategy.long, 0.3, limit = low[1])

if not findOrderIdx("long4")
    strategy.entry("long4", strategy.long, 0.2)

plot(ema10, title="ema10", color=color.red)

코드 시작/*backtest ... */패키지 부분은 재검토 설정으로 설정되어 있으며, 당시 재검토 설정 시간 등의 정보를 기록하기 위해 설정되어 있으며, 정책 코드가 아닙니다.

코드는:strategy(title = "open long example", pyramiding = 3, default_qty_value=0.1, overlay=true)그리고 우리는pyramiding만약 3가 변수라면, 같은 방향으로 최대 3번 거래할 수 있습니다.strategy.entry다음 명령어 중 한 번은 실행되지 않았습니다.default_qty_value변수는 0.1, 그래서 ID는 long 1입니다.strategy.entry하위 계열 작업의 하위 계열량은 기본 설정으로 0.1이다.strategy.entry이 함수들은direction모두strategy.long이 모든 것은 다른 사람들에게도 적용될 수 있습니다.

코드에 주의하세요.strategy.entry("long3", ...다음 동작은 동일한 ID:long3에 대해 두 번 호출됩니다.strategy.entry다음 명령에 대한 거래가 완료되지 않아서 두 번째 호출strategy.entry함수는 이 ID를 수정하는 주문을 표시합니다. (회검시 표시된 데이터는 또한 이 제한 주문 아래 주문량이 0.3로 변경되었다는 것을 볼 수 있습니다.) 또 다른 경우, 예를 들어 첫 번째 ID가 long3의 주문을 지불했을 때, 이 거래된 ID long3에 따라 계속 사용하십시오.strategy.entry함수에서 주문하면 주문 포지션은 IDlong3에 누적됩니다.


2、strategy.close

strategy.close이 함수는 평상시에서 아이디를 지정하는 입시 보유 지위를 사용한다. 주요 매개 변수는 다음과 같다.idwhenqtyqty_percent

파라미터:

  • id: 평평한 로그인 아이디가 필요합니다.strategy.entry입구에 입력 하 여 단 하나의 함수를 열 때 지정 된 ID.
  • when: 실행 조건.
  • qty: 거래소 수.
  • qty_percent: 평형 비율.

이 함수의 사용에 대한 자세한 내용은 다음과 같은 예를 통해 알아볼 수 있습니다. 코드에서/*backtest ... */是FMZ.COM国际站回测时的配置信息,可以删掉,设置自己需要测试的市场、品种、时间范围等信息。

/*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("close Demo", pyramiding=3)

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

strategy.entry("long1", strategy.long, 0.2)
if strategy.opentrades >= 3 
    strategy.close("long1")                   // 多个入场订单,不指定qty参数,全部平仓
    // strategy.close()                          // 不指定id参数,会平掉当前的持仓
    // strategy.close("long2")                   // 如果指定一个不存在的id则什么都不操作
    // strategy.close("long1", qty=0.15)         // 指定qty参数平仓
    // strategy.close("long1", qty_percent=50)   // qty_percent设置50即为平掉long1标识仓位的50%持仓
    // strategy.close("long1", qty_percent=80, when=close<open)  // 指定when参数,修改为close>open就不触发了
    enableStop := true

테스트 전략은 3번 연속으로 복수의 로그인을 시작하여 로그인 ID가 1long이며,strategy.close함수의 다른 매개 변수들을 평형으로 설정할 때 다시 측정되는 다른 결과들.strategy.close이 함수는 평준화 시세를 지정할 수 있는 매개 변수가 없으며, 이 함수는 주로 현재 시장 가격으로 즉각적인 평준화를 위해 사용됩니다.


3、strategy.close_all

strategy.close_all함수는 현재 모든 포즈를 평준화하는데 사용된다. 파인 언어 스크립트의 포즈를 단 한 방향으로만 사용할 수 있기 때문에, 현재 포즈를 평준화하고 신호에 따라 포즈를 개시한다.strategy.close_all부름이 되면 현재 방향의 모든 지분을 동그라미화한다.strategy.close_all함수의 주요 매개 변수는 다음과 같습니다.when

파라미터:

  • when: 실행 조건.

이 사례를 살펴보면,

/*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("closeAll Demo")

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

strategy.entry("long", strategy.long, 0.2, when=strategy.position_size==0 and close>open)
strategy.entry("short", strategy.short, 0.3, when=strategy.position_size>0 and close<open)

if strategy.position_size < 0 
    strategy.close_all()
    enableStop := true 

테스트 코드가 시작될 때, 보유량은 0 (즉,strategy.position_size==0true) 로 정해져 있기 때문에 when 파라그램 설정 조건에 맞을 때만 ID를 long로 실행합니다.strategy.entry입력 함수.strategy.position_size0보다 크면 ID가 short의 입문 함수가 실행될 수 있다. 현재 다중 포지션을 보유하고 있기 때문에, 이 때 나타나는 이 공백 역전 신호는 다중 포지션을 평평화 한 후 다시 역공백으로 이어진다.strategy.position_size < 0즉, 빈 헤드 포스팅을 할 때 현재 포스팅 방향의 모든 포스팅을 평정합니다.enableStop := true▲ 정책 실행을 중지하여 로그를 쉽게 볼 수 있습니다.

그리고 그 결과strategy.close_all이 함수는 평준화 시세를 지정할 수 있는 매개 변수가 없으며, 이 함수는 주로 현재 시장 가격으로 즉각적인 평준화를 위해 사용됩니다.


4、strategy.exit

strategy.exit이 함수는 입금 포지션의 평준화 동작에 사용됩니다. 이 함수와는 다릅니다.strategy.close그리고strategy.close_all이 함수는 현재 시장 가격에 즉시 평준화됩니다.strategy.exit함수는 매개 변수 설정에 따라 계획 평형을 수행합니다.

파라미터:

  • id: 현재 평형 조건 목록의 주문 아이디.
  • from_entry: 평형 작업을 수행하려는 로그인 ID를 지정하는 데 사용됩니다.
  • qty: 거래소 수.
  • qty_percent: 평준화 비율, 범위: 0 ~ 100。
  • profit: 수익 목표, 점수로 표시됩니다.
  • loss: 손해를 막는 목표, 점수로 표시됩니다.
  • limit: 수익 목표, 가격에 의해 지정됩니다.
  • stop[중고] [중고]
  • when: 실행 조건.

각 매개 변수 사용에 대한 이해를 위해 테스트 전략을 사용하십시오.

/*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"}]
args: [["RunMode",1,358374],["ZPrecision",0,358374]]
*/

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

varip isExit = false 

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

strategy.entry("long1", strategy.long, 0.1, limit=1, when=findOrderIdx("long1") < 0)
strategy.entry("long2", strategy.long, 0.2, when=findOrderIdx("long2") < 0)
strategy.entry("long3", strategy.long, 0.3, when=findOrderIdx("long3") < 0)

if not isExit and strategy.opentrades > 0
    // strategy.exit("exitAll")          // 如果仅仅指定一个id参数,则该退场订单无效,参数profit, limit, loss, stop等出场条件也至少需要设置一个,否则也无效
    strategy.exit("exit1", "long1", profit=50)                    // 由于long1入场订单没有成交,因此ID为exit1的出场订单也处于暂待状态,直到对应的入场订单成交才会放置exit1
    strategy.exit("exit2", "long2", qty=0.1, profit=100)          // 指定参数qty,平掉ID为long2的持仓中0.1个持仓
    strategy.exit("exit3", "long3", qty_percent=50, limit=strategy.opentrades.entry_price(findOrderIdx("long3")) + 1000)   // 指定参数qty_percent,平掉ID为long3的持仓中50%的持仓
    isExit := true 

if bar_index == 0 
    runtime.log("每点价格为:", syminfo.mintick)    // 每点价格和Pine语言模板参数上「定价货币精度」参数设置有关

이 테스트 전략은 실시간 가격 모형 역 테스트를 사용하여 3개의 입구 동작을 실행하기 시작합니다.strategy.entry함수), long1은 의도적으로 설정되었습니다limit매개 변수, 주문 가격은 1이므로 거래가 불가능하다. 그리고 테스트 조건 출력 함수strategy.exit▲ 점수 정지, 가격 정지, 고정된 수의 포지션, 비율 정지 등을 사용하였다.strategy.exit이 함수에는 더 복잡한 추적 중지 매개 변수도 있습니다.trail_pricetrail_pointstrail_offset이 예제에서 사용법을 배우기 위해 테스트를 할 수도 있습니다.


5、strategy.cancel

strategy.cancel함수는 모든 예약 목록 명령어를 취소 / 중지하는 데 사용됩니다. 이 함수는strategy.order, strategy.entry , strategy.exit로그인 ID를 생성할 수 있다. 이 함수의 주요 매개변수는:idwhen

파라미터:

  • id이 글은 이쪽에서 읽었습니다.
  • when: 실행 조건.

이 함수는 트랜잭션이 없는 로그인 명령어를 취소하는 것으로 잘 이해됩니다.

/*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("long1")
    strategy.cancel("long2")
    strategy.cancel("long3")
    isStop := true 

6、strategy.cancel_all

strategy.cancel_all함수와strategy.cancel함수와 비슷하다. ▲ 모든 미리 설치된 명령어를 취소/잠재한다. ▲ 지정할 수 있다.when파라미터.

파라미터:

  • when: 실행 조건.
/*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 

7、strategy.order

strategy.order함수의 함수, 변수 설정 등은 거의strategy.entry이 모든 것은strategy.order이 함수들은strategy이 함수들의pyramiding변수 설정 영향, 다음 단기 제한 없습니다.

파라미터:

  • id: 어떤 거래 포지션에 대한 이름을 참조로 사용할 수 있습니다. 이 id를 취소, 변경 주문, 평정으로 참조할 수 있습니다.
  • direction: 주문 방향이 더하기 (구입) 이면 이 매개 변수가 전달됩니다.strategy.long이 내장 변수는, 만약 빈 (~) 을 팔면 전달됩니다.strategy.short이 변수는
  • qty: 주문할 수 있는 양을 지정합니다. 이 매개 변수를 전달하지 않으면 기본 주문할 수 있는 양을 사용합니다.
  • when: 실행 조건, 이 매개 변수를 지정하여 현재 하위 동작이 발동되는지 여부를 제어할 수 있습니다.
  • limit: 주문 한계 가격을 지정합니다.
  • stop: 손해배상금지.

우리는 그것을 사용합니다.strategy.order이 특성은 다음의 단수 없이 제한됩니다.strategy.exit조건적 출구 함수─그레이드 트랜잭션과 유사한 스크립트를 구성한다─예제들은 매우 간단하고 학습용일 뿐이다:

/*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)

전략적 모범

이 튜토리얼의 전략 예제들은 교육 전략, 지도 전략 설계 아이디어만을 위해 사용되며, 어떠한 거래지도, 조언도 하지 않습니다.

슈퍼 트렌드 지표 전략

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()

파인 언어를 사용하여 트렌드 전략을 작성하는 것은 매우 간단합니다. 여기서 우리는 슈퍼 트렌드 지표로 간단한 트렌드 추적 전략을 설계합니다.

먼저 전략 코드가 사용되기 시작합니다.strategy이 함수는 몇 가지 간단한 설정을 수행합니다.strategy("supertrend", overlay=true), 그냥 supertrend 트렌드 트렌드 트렌드 트렌드를 설정합니다.overlay변수는true, 그리는 지표 라인 등의 내용을 주사면에 표시하도록 합니다. 우리는 파이프 전략을 설계하거나 파이프 전략 스크립트를 배우기 위해 먼저 살펴봐야 할 것은 전략 인터페이스 파라미터 디자인입니다. 우리는 "슈퍼 트렌드 지표 전략"의 소스를 살펴보고 있습니다.input함수

[슈퍼트렌드, 방향] = ta.슈퍼트렌드 (입수), 팩터 (faktor) ]input.int(10, atr 기간))

input함수 호출은 직접적으로ta.supertrend지표 함수의 매개 변수는 초동향 지표를 계산하는 데 사용됩니다.

  • input ((5, faktor)
  • input.int(10, atr 기간)

함수는 파인 언어 정책 인터페이스에서 기본으로 두 개의 매개 변수 컨트롤을 설정합니다.

img

그리고 여러분이 볼 수 있듯이, 컨트롤의 기본값은input함수와input이 함수들은input.int이 두 가지 함수를 통해 우리는 전략 인터페이스에서 설정할 수 있습니다.ta.supertrend함수의 파라미터. 슈퍼 트렌드 지표 함수는 가격 데이터를 계산합니다.supertrend그리고 한 방향의 데이터direction그리고 그것을 사용하십시오.plot함수 그래프, 그래프를 그리는 때 초동향 지표의 방향에 따라 그래프를 그리는 것을 주의하십시오.direction현재 시장의 추세는 상향 시장입니다.direction1시 현재 시장은 하향 추세를 보이고 있습니다.plot함수 그래프를 그리면서 판단합니다.direction0보다 크거나 0보다 작거나

다음으로if ... else if이 표현은,direction < 0실시간으로 현재 시장이 상위 단계에 있음을 나타냅니다.supertrend앞의 2개의 BAR에 있는 초트렌드 지표값보다 높습니다.supertrend[2],还记得历史操作符引用某个变量历史数据吧이 경우, 현재 지점이 있는 경우, 이 때 역으로 아래로 단일 함수 호출을 하면, 이전 지점이 평평해지기 전에, 현재 거래 방향에 따라 지점을 열게 된다.supertrend > supertrend[2]이 모든 조건이 충족되지 않았다면,strategy.position_size < 0그리고 그 다음에는,strategy.close_all()함수 실행, 모든 평형을 수행합니다.

direction > 0하락 추세 단계에 있는 경우도 마찬가지입니다. 다중 보유가 모두 평형되면 조건이 충족됩니다.supertrend < supertrend[3]이 경우, 이 신호를 입력하면[3]상위 세 번째 바르에 있는 슈퍼 트렌드 지표 가격 데이터에 대한 참조는 어떨까요? 전략가들이 의도한 것일 수도 있습니다. 어떤 시장에서, 예를 들어 계약 거래 시장에서, 빈 위험은 더 많은 위험보다 약간 더 크죠.

이 문제에 대해ta.supertrend이 지표는 어떤 학우들이 관심을 가지고 있는지, 현재 추세가 상승하고 있는지, 아니면 하락하고 있는지 판단하는 방법일까요?

실제로 이 지표는 파이인 언어의 사용자 정의 함수 형태로도 구현될 수 있습니다.

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]

이 정의 함수와 내장 함수ta.supertrend같은 알고리즘, 물론 계산된 지표 데이터도 동일합니다. 이 사용자 정의 함수 알고리즘에서 볼 수 있듯이 Pine의 내장된 슈퍼 트렌드 지표 계산은hl2내장 변수 (최고 가격, 최저 가격 더하기, 그리고 2로 나누기, 즉 최고 가격, 최저 가격의 평균) 를 계산하고, 그 다음 atrPeriod 변수에 따라 특정 주기의 ATR 지표를 계산합니다. 그리고 hl2와 ATR을 사용하여 궤도, 궤도 아래를 구성합니다.

코드에 있는 삼중표현에 따라 업데이트lowerBand그리고upperBand

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

lowerBand: 상승 추세의 변화를 판단하기 위한 하단선. upperBand: 상승 추세의 변화를 판단하기 위한 하단선. lowerBand와 upperBand은 항상 계산되고 있지만, 이 사용자 정의 함수에서 현재 추세 방향을 결정하는 것 만이다.

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

여기서는 지난 바에 있는 슈퍼 트렌드의 값이prevUpperBand현재 추세가 하향하는 것을 나타냅니다.close더 많은upperBand가격의 돌파는 추세가 변하고 상승 추세로 전환되는 것을 의미합니다.direction방향 변수는 -1 (상향) 로 설정되어 있습니다. 그렇지 않으면 여전히 1 (하향) 로 설정되어 있습니다. 그래서 당신은 슈퍼 트렌드 전략에서 볼 수 있습니다.if direction < 0이 경우, 신호 조건이 촉발되면 더 많이하십시오.direction > 0이 경우, 신호 조건이 발사되면 공백합니다.

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

마지막으로, 방향에 따라 선택된 특정 슈퍼트렌드 지표 가격 데이터와 방향 데이터를 반환합니다.

동적 균형 전략

/*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

우리는 파인 언어의 몇 가지 전략 설계 사례를 계속 공부합니다. 이번에는 동적 균형 전략을 살펴볼 것입니다.BaseCurrency(거래 품종) 의 금액과QuoteCurrency(평화) 금액은 항상 균형 처리를 한다. 어떤 자산의 상대 가격이 상승하면 어떤 자산이 계좌에서 보유한 가치가 증가하면 어떤 자산이 판매된다. 어떤 자산의 상대 가격이 감소하면 계좌에서 보유한 가치가 감소하면 이러한 자산을 구매한다. 이것이 동적 균형 전략이라고 불리는 것이다. 실제로 동적 균형 전략은 격자 전략이며, 불안정한 상황에서 잘 작동한다. 그러나 트렌드 시장에서는 지속적인 손실이 필요하며, 가격 회귀를 기다려야 손실을 천천히 줄여 수익을 창출할 수 있지만, 동적 균형 전략은 항상 시장의 불안정한 상황을 포착할 수 있다.

이 전략의 단점은, 이 전략의 재검토 그래프에서 보이는 것처럼, 가격의 큰 상승 (또는 큰 하락) 단계에서는 이 전략이 더 큰 파손을 일으킨다는 것입니다. 따라서 이 전략은 현장 전략에 적합하며, 선물에 사용하려면 위험을 조절해야 합니다.

이 문서는 이 문서를 작성하는 데에 도움이 될 것입니다.

우리는 단순화 된 디자인을 사용하여balance이 자금의 양은stocks(즉, 기본 통화 자산 수) 균형 정보. 우리는 계좌의 실제 자산 수를 읽지 않고, 우리는 단지 모의 금액을 사용하여 적절한 구매 및 판매를 계산합니다. 그리고 이 동적 균형 전략에 영향을 미치는 격자에서 뽑는 중요한 매개 변수는 다음과 같습니다.maxDiffValue이 매개 변수는 평형 판단 기준입니다.BaseCurrency그리고QuoteCurrency오차가 더 커졌어요.maxDiffValue이 때, 높은 가격의 자산을 팔고 낮은 가격의 자산을 구입하여 재균형을 할 때입니다.

전략 거래 신호의 트리거는 실시간 BAR 단계에서만 의미가 있어야 하기 때문에 전략 거래 조건은 if 판단에 모두 설정되어 있습니다.not barstate.ishistoryᅳ 현재 가격에 따라 계산하면,balance그 가치는stocks값이 있을 때 구매한다. 반대로 판매한다. 거래 문장을 실행한 후 업데이트한다.balance그리고stocks다른 변수를 선택하고 다음 평형이 시작될 때까지 기다립니다.

위 전략 재검토 메시지는 전략 재검토 시작 시점의 품종 가격을 포함하고 있습니다. 가격은 1458입니다. 그래서 저는 의도적으로 매개 변수를 설정했습니다.balance4374 ((1458*3) 로 설정된 매개 변수stocks세 번째: 자산이 시작될 때 균형을 유지하십시오.

스톱 손실을 막는 슈퍼 트렌드 전략

우리는 이 모든 것을 다른 방법으로 할 수 있습니다.strategy.exit포지션 탈퇴 함수, 그 중 추적 중지 손실 차단 함수는 예제 설명이 없습니다. 이 섹션의 전략 설계 예제에서는 사용 합니다.strategy.exit함수의 추적 스톱/손실 스톱/ 기능을 사용하여 슈퍼 트렌드 전략을 최적화한다.

먼저 살펴봅시다.strategy.exit함수의 추적 스톱/손실 스톱/변수:

1、trail_price매개 변수: 트리거 위치 위치 (값으로 지정)


더 많은