avatar of 发明者量化-小小梦 发明者量化-小小梦
집중하다 사신
4
집중하다
1271
수행원

Inventor 양적 PINE 언어 소개 튜토리얼

만든 날짜: 2022-05-30 16:23:43, 업데이트 날짜: 2022-09-28 17:10:21
comments   0
hits   11305

[TOC]

Inventor 양적 PINE 언어 소개 튜토리얼

비디오 강좌: 량화 거래에 진입하기 힘들어? 트레이딩 뷰를 사용 Pine 언어에서 작은 백에서 퀀트 대신 - Pine 언어 초보자

발명자의 양적 거래 플랫폼은 파이어 언어 작성 전략을 지원하고, 피드백을 지원하고, 파이어 언어 전략을 실전에서 실행하며, 파이어 언어의 더 낮은 버전을 호환한다. 발명자의 양적 거래 플랫폼 (FMZ.COM) 에서전략 스퀘어이 문서에는 많은 파인 전략 (Script) 이 수록되어 있습니다.

FMZ는 파인 언어를 지원할 뿐만 아니라 파인 언어의 강력한 그림 기능을 지원한다. FMZ 플랫폼의 다양한 기능, 풍부한 실용 도구, 효율적이고 간편한 관리, 또한 파인 전략의 실용성을 더욱 강화한다. FMZ는 파인 언어의 호환성을 기반으로, 파인 언어에 대한 어느 정도의 확장, 최적화, 절단 작업을 수행했다.

몇 가지 분명한 차이점들을 간단히 정리해 보겠습니다.

  • 1 FMZ에 있는 핀 정책, 코드 시작 버전 표시//@version코드가 시작됩니다.strategyindicator문장은 작성할 필요가 없습니다. FMZ는 현재 지원하지 않습니다.import수입library기능.

이 전략의 일부에는 다음과 같은 내용이 적혀 있습니다.

  //@version=5
  indicator("My Script", overlay = true)
  src = close
  a = ta.sma(src, 5)
  b = ta.sma(src, 50)
  c = ta.cross(a, b)
  plot(a, color = color.blue)
  plot(b, color = color.black)
  plotshape(c, color = color.red)

이 글은 “미국”의 한 문장입니다.

  //@version=5
  strategy("My Strategy", overlay=true)

  longCondition = ta.crossover(ta.sma(close, 14), ta.sma(close, 28))
  if (longCondition)
      strategy.entry("My Long Entry Id", strategy.long)

  shortCondition = ta.crossunder(ta.sma(close, 14), ta.sma(close, 28))
  if (shortCondition)
      strategy.entry("My Short Entry Id", strategy.short)

FMZ에서는 다음과 같이 줄여집니다.

  src = close
  a = ta.sma(src, 5)
  b = ta.sma(src, 50)
  c = ta.cross(a, b)
  plot(a, color = color.blue, overlay=true)
  plot(b, color = color.black, overlay=true)
  plotshape(c, color = color.red, overlay=true)

아니면:

  longCondition = ta.crossover(ta.sma(close, 14), ta.sma(close, 28))
  if (longCondition)
      strategy.entry("My Long Entry Id", strategy.long)

  shortCondition = ta.crossunder(ta.sma(close, 14), ta.sma(close, 28))
  if (shortCondition)
      strategy.entry("My Short Entry Id", strategy.short)
  • 2 , 전략 ((스크립트) 일부 거래 관련 설정은 FMZ 정책 인터페이스의 “파인 언어 거래 클래스 라이브러리” 파라미트에서 설정한다.

    • 종결 가격 모델과 실시간 가격 모델 트레이딩 뷰에서는strategy함수의calc_on_every_tick매개 변수는 가격의 모든 변화에 대해 실시간으로 전략 논리를 실행하는 전략 스크립트를 설정합니다.calc_on_every_tick이 변수는true◦ 기본calc_on_every_tick변수는false즉, 전략의 현재 K선 BAR이 완전히 다 지나갈 때만 전략 논리를 실행한다. FMZ에서는, “Pine 언어 거래 클래스 라이브러리” 템플릿의 파라미터를 통해 설정한다.

    Inventor 양적 PINE 언어 소개 튜토리얼

    • 전략 실행 시의 가격, 하위 주문량 등의 수치 정확도 제어 FMZ에 지정될 필요가 있다. 트레이딩 뷰에서는 시뮬레이션 테스트만 가능하기 때문에 실제 거래 시점의 정밀도 문제가 없습니다. FMZ에서는 실제적으로 파인 전략을 실행할 수 있습니다. 그러면 거래 품종의 가격 정밀도, 주문 수량 정밀도를 유연하게 지정할 수 있는 전략이 필요합니다. 이러한 정밀도 설정은 관련 데이터의 소수 수를 제어하여 거래소 신고 요구 사항에 해당하지 않는 데이터를 방지하여 주문을 할 수 없습니다.

    • 선물 계약 코드 FMZ에서 거래 품종이 계약이라면, 2개의 속성이 있다. 각각 “거래 쌍”과 “계약 코드”로, 실盘 및 회수시 거래 쌍을 명확하게 설정하는 것 외에도 “파인 언어 거래 클래식” 템플릿의 파라미터 “ 품종 코드”에서 구체적인 계약 코드를 설정해야 한다. 예를 들어 영구 계약만 채우면swap, 계약 코드는 거래소에서 이러한 계약이 있는지 여부에 따라 달라집니다. 예를 들어 거래소의 모든 분기 계약은 여기에서 작성할 수 있습니다.quarterᄒ 이 계약 코드들은 FMZ의 Javascript/python/c++ 언어 API 문서에서 정의된 선물 계약 코드와 일치한다。

다른 설정들, 예를 들어, 최소 하단 단위, 기본 하단 단위 등은 Pine 언어 문서에서 참조할 수 있습니다.“파인 언어 거래소”변수 소개.

  • 3、runtime.debugruntime.logruntime.errorFMZ 확장된 함수, 디비깅을 위해 쓰인다.

FMZ 플랫폼에는 3개의 함수가 디부팅을 위해 추가되었다.

  • runtime.debug: 컨트롤러에서 변수 정보를 인쇄할 때, 일반적으로 이 함수는 사용되지 않는다.

  • runtime.log: 로그에서 출력 내용 FMZ PINE 언어 특유의 함수

    runtime.log(1, 2, 3, close, high, ...),可以传多个参数。
    
  • runtime.error: 호출될 때, 실행 오류가 발생하고, message 파라미트에서 지정된 오류 메시지가 들어온다.

    runtime.error(message)
    
    1. 부분 그림 함수에서 확장overlay매개변수

FMZ에 있는 파인 언어, 그림 함수plotplotshapeplotchar더하기overlay매개 변수 지원, 그림이 메인 그래프 또는 하위 그래프에 지정되도록 허용한다.overlay설정true이 그림은 메인 그래프에서false하위 그림에서 그리기. FMZ 상의 Pine 전략이 실행될 때 주 그림과 하위 그림이 동시에 그려질 수 있도록 한다.

  • 5、syminfo.mintick내장 변수의 값

syminfo.mintick내장 변수는 현재 품종의 최소 측정값으로 정의된다. FMZ에서확정 제안/백테스팅인터페이스의 “파인 언어 거래 클래스 라이브러리”에 있는 템플릿 파라미트 Pricing Currency Accuracy가 이 값을 제어할 수 있다. Pricing Currency Accuracy 설정 2은 거래 시 가격이 소수점 2위까지 정확하며, 이 시점 가격의 최소 변동 단위는 0.01이다.syminfo.mintick0.01 ≠ 0.01 입니다.

  • 6. FMZ PINE 스크립트에서 평균 가격은 수수료가 포함된 가격입니다.

예를 들어: 주문 가격은 8000, 판매 방향, 수량 1손 ((하나, 장), 매매 후 평균 가격은 8000이 아닌 8000보다 낮다 ((비용에는 절차 수수료가 포함된다) .

파인 언어 기초

파인 언어의 기초를 배우기 시작했을 때, 아마도 몇몇 예의 명령어, 코드 문법이 우리에게 익숙하지 않을 것이다. 이해가 안 되는 것은 상관없고, 우리는 먼저 개념에 익숙해져 테스트의 목적을 이해할 수 있고, FMZ의 파인 언어 문서를 확인해 볼 수도 있다. 그리고는 튜토리얼을 따라 단계적으로 다양한 문법, 명령어, 함수, 내장 변수를 익숙해진다.

모델 실행

파이어 언어의 스크립트 프로그램 실행 과정과 같은 관련 개념을 이해하는 것은 매우 필수적이다. 파이어 언어 전략은 차트에 기반하여 운영되며, 파이어 언어 전략으로 이해될 수 있으며, 차트에 시간 순서 상향 순서로 차트에 이미 로드 된 가장 초기 데이터에서 시작하여 실행되는 일련의 계산과 동작이다. 차트에 초기 로드 된 데이터의 양은 제한되어 있다.bar_indexPine 스크립트 실행 시 현재 K선 Bar의 인덱스 값을 참조한다.

plot(bar_index, "bar_index")

Inventor 양적 PINE 언어 소개 튜토리얼

plot이 함수는 우리가 앞으로 더 많이 사용할 수 있는 함수 중 하나입니다. 아주 간단합니다. 입력된 변수들에 따라 그래프에 선을 그립니다. 입력된 데이터는bar_index, 라인 이름bar_indexᄒ 첫 번째 바에 있는 bar_index라는 선의 값은 0이고, 바가 오른쪽으로 증가함에 따라 1씩 증가한다.

정책의 설정에 따라 정책의 모델이 실행되는 방식도 다릅니다.收盘价模型그리고实时价模型ᄂ) 종식 가격 모델, 실시간 가격 모델의 개념은 이전에 간단하게 소개했습니다.

  • 종가 모델

전략 코드가 실행될 때, 현재 K라인 바의 주기 완전 실행이 완료되고, K라인 닫힐 때 K라인 주기 종료되었다. 이 때, 핀 전략 논리를 다시 실행하고, 촉발된 거래 신호는 다음 K라인 바가 시작될 때 실행된다.

  • 실시간 가격 모델

전략 코드가 실행될 때, 현재 K선 Bar는 닫히든 닫히든, 모든 거래의 움직임에 대해 Pine 전략 논리를 실행하고, 트레이드 신호는 즉시 실행된다.

파인 언어 전략이 그래프에서 왼쪽에서 오른쪽으로 실행될 때, 그래프의 K 라인 바는历史Bar그리고实时Bar다음으로:

  • 역사 바

“실장 가격 모델”으로 설정된 전략이 실행될 때, K선 바를 제외한 모든 K선 바는历史Bar◦ 전략적 논리历史Bar한 번만 실행하세요. 이 전략이 “폐쇄 가격 모델”로 설정되어 실행될 때, 모든 바는历史Bar◦ 전략적 논리历史Bar한 번만 실행하세요.

역사 바에 기초한 계산: 전략 코드는 히스토리 바 클로즈 상태에서 한 번 실행되고, 다음 히스토리 바에서 모든 히스토리 바가 한 번 실행될 때까지 계속 실행된다.

  • 실시간 바

전략이 가장 오른쪽에 있는 마지막 K선Bar에 실행되면, Bar는 실시간Bar이다. RealBar가 닫히면, 이 Bar는 지나간 RealBar가 된다.

전략이 ‘실시간 가격 모델’로 설정되어 실행이 시작되면, 실시간 바에서 거래의 변화마다 전략 논리가 실행됩니다. 전략이 “폐쇄 가격 모델”로 설정되어 실행이 시작될 때, 실시간 Bar는 표시되지 않습니다.

실시간 Bar의 계산에 따라: 전략이 “폐쇄 가격 모델”로 설정된 그래프에서 실시간 바르가 표시되지 않으면, 정책 코드는 현재 바르가 닫힐 때 한 번만 실행된다. 전략이 “실장 가격 모델”로 설정되면 실시간 바의 계산과 역사 바는 완전히 다릅니다. 실장 바의 모든 움직임에 따라 정책 코드가 실행됩니다. 예를 들어 내장 변수highlowclose역사 바에서는 확실하며, 실시간 바에서는 상황이 변할 때마다 이러한 값들이 변할 것이다. 따라서 이러한 값들을 기반으로 계산된 지표와 같은 데이터도 실시간으로 변할 것이다.close이 사이트는 항상 최신 가격을 나타냅니다.high그리고low항상 현재 실시간 바가 시작된 이래 도달한 최고 최고점과 최저 최저점을 나타냅니다. 이 내장 변수는 실시간 바가 마지막으로 업데이트되었을 때의 최종 값을 나타냅니다.

실시간 바에서 전략을 실행할 때 리볼 메커니즘 (실시간 가격 모델): 실시간 바에서 실행할 때, 정책의 각 새로운 연대마다 이전 사용자 정의의 변수를 실행하는 것을 리롤이라고 한다. 리롤 메커니즘을 예를 들어서 이해하자면, 다음과 같은 테스트 코드가 있다.

알아채다:

  /*backtest 
  ...
  ..
  .
  */

패키지의 내용은 FMZ 플랫폼에서 코드 형태로 저장된 회귀 구성 정보입니다.

  /*backtest
  start: 2022-06-03 09:00:00
  end: 2022-06-08 15:00:00
  period: 1m
  basePeriod: 1m
  exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
  */

  var n = 0
  if not barstate.ishistory
      runtime.log("n + 1之前, n:", n, " 当前bar_index:", bar_index)
      n := n + 1
      runtime.log("n + 1之后, n:", n, " 当前bar_index:", bar_index)

  plot(n, title="n")

Inventor 양적 PINE 언어 소개 튜토리얼

Inventor 양적 PINE 언어 소개 튜토리얼

우리는 리얼타임 바에서 실행되는 시나리오만을 조사했습니다.not barstate.ishistory표현식 제한은 실시간 Bar에서만 변수 n에 축적되며, 축적 작업을 수행하기 전과 후에 사용된다.runtime.log함수 출력 정보는 정책 로그에 있습니다.plot그려진 곡선 n은 전략이 히스토리 바에서 실행되는 동안 n이 항상 0이었다는 것을 볼 수 있다. 실시간 바에 실행될 때 n은 1을 누적하는 동작을 촉발하고, 실시간 바에서 실행될 때마다 n은 1을 누적하는 동작을 수행한다. 로그 정보에서 볼 수 있는 것은, 다시 실행하는 전략 코드의 각 라운드마다 n은 이전 실행된 Bar 전략의 최종 제출된 값으로 다시 설정된다.

결론을 말씀드리자면: 1 정책이 실시간 바에서 실행될 때, 상황 업데이트마다 정책 코드가 실행된다. 2. 리얼 타임 바에서 실행할 때, 정책 코드가 실행될 때마다 변수가 다시 돌아갑니다. 3. 리얼 타임 바에서 실행할 때, 변수는 클로즈오브 업데이트에 한번 제출한다.

데이터 회전으로 인해, 그래프의 곡선과 같은 도면 작업도 다시 그려질 수 있습니다. 예를 들어, 우리가 방금 테스트 코드를 수정했을 때, 리얼 디스크 테스트:

  var n = 0
  if not barstate.ishistory
      runtime.log("n + 1之前, n:", n, " 当前bar_index:", bar_index)
      n := open > close ? n + 1 : n
      runtime.log("n + 1之后, n:", n, " 当前bar_index:", bar_index)

  plot(n, title="n")

순간 A의 스크린샷 Inventor 양적 PINE 언어 소개 튜토리얼

순간 B의 스크린샷 Inventor 양적 PINE 언어 소개 튜토리얼

이 문장만 수정했습니다.n := open > close ? n + 1 : n현재 실시간 Bar가 음선 (즉, 개시 가격이 닫기 가격보다 높다) 이었을 때만 n에 1을 더한다. 첫 번째 그래프 (즉, 순간 A) 에서 개시 가격이 닫기 가격 (즉, 순간 B) 보다 높기 때문에 n이 1을 더했기 때문에 그래프 곡선 n이 표시되는 값은 5이다.

  • 함수 안의 변수의 맥락

다음은 파인 언어 함수의 변수를 함께 살펴보자. 몇몇 파인 튜토리얼의 설명에 따르면, 함수 안의 변수와 함수 밖의 변수는 다음과 같다:

파인 함수에서 사용되는 일련의 변수의 역사는 함수의 각각의 연속적인 호출에 의해 생성된다. 만약 스크립트에서 실행되는 각 기둥에 함수가 호출되지 않는다면, 이는 함수 로컬 블록 내부의 역사값과 외부의 일련의 역사값 사이에 차이를 초래할 것이다. 따라서, 만약 각 기둥에 함수가 호출되지 않는다면, 동일한 인덱스 값을 사용하여 함수 내부와 외부에서 참조되는 일련은 동일한 역사점을 참조하지 않을 것이다.

이 문장을 읽어보기가 어렵다고 생각하십니까? 괜찮습니다. FMZ에서 실행된 테스트 코드를 통해 알아봅시다.

  /*backtest
  start: 2022-06-03 09:00:00
  end: 2022-06-08 15:00:00
  period: 1m
  basePeriod: 1m
  exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
  */

  f(a) => a[1]
  f2() => close[1]  

  oneBarInTwo = bar_index % 2 == 0
  plotchar(oneBarInTwo ? f(close) : na, title = "f(close)", color = color.red, location = location.absolute, style = shape.xcross, overlay = true, char = "A")   
  plotchar(oneBarInTwo ? f2() : na, title = "f2()", color = color.green, location = location.absolute, style = shape.circle, overlay = true, char = "B")   
  plot(close[2], title = "close[2]", color = color.red, overlay = true)
  plot(close[1], title = "close[1]", color = color.green, overlay = true)

회색 실행 스크린샷

Inventor 양적 PINE 언어 소개 튜토리얼

테스트 코드는 비교적 간단하며, 주로 두 가지 방법으로 인용 된 데이터를 조사합니다.f(a) => a[1]그리고f2() => close[1]

  • f(a) => a[1]함수가 마지막으로 돌아오는 방법:a[1]

  • f2() => close[1]직접 내장 변수를 사용하세요:close함수가 마지막으로 돌아오는 것은close[1]

[]기호는 데이터 시리즈 변수의 역사값에 대한 참조 동작을 사용한다. close[1] 즉, 현재 폐쇄 가격 전 바의 폐쇄 가격 데이터를 참조하십시오. 우리의 테스트 코드는 전체적으로 4 가지 데이터를 도표에 그려냅니다.

  • plotchar(oneBarInTwo ? f(close) : na, title = "f(close)", color = color.red, location = location.absolute, style = shape.xcross, overlay = true, char = "A") 한 문자를 A에 그려, 빨간색으로, oneBarInTwo가 참일 때만 그려, 그려진 위치 (Y축에) 는:f(close)반환 값은

  • plotchar(oneBarInTwo ? f2() : na, title = "f2()", color = color.green, location = location.absolute, style = shape.circle, overlay = true, char = "B") 한 문자를 B로 그려, 녹색으로, oneBarInTwo가 참일 때만 그려, 그려진 위치 (Y축에) 는:f2()반환 값은

  • plot(close[2], title = "close[2]", color = color.red, overlay = true) 그리는 선은 빨간색이고, 그리는 위치 (Y축) 는close[2]즉, 현재 Bar 앞의 2번째 자리 ((왼쪽의 2번째 자리) Bar의 종결값이다.

  • plot(close[1], title = "close[1]", color = color.green, overlay = true) 그리는 선은 녹색이고, 그리는 위치 (Y축에) 는:close[1]즉, 현재 Bar 앞 1 자리 (→ 왼쪽으로 1 자리) Bar의 종결 가격.

전략 회귀를 통해 실행 스냅샷을 볼 수 있지만, 그림 A는 사용 함수를 표시f(a) => a[1]그리고 B를 표시하는 함수를 사용합니다.f2() => close[1]모두 사용되고 있습니다.[1] 데이터 시리즈의 역사적인 데이터를 참조하기 위해, 그러나 차트에서 “A”와 “B”의 표시 위치는 완전히 다릅니다. “A” 표시의 위치는 항상 빨간색의 선에 떨어집니다. 즉, 전략의 코드입니다.plot(close[2], title = "close[2]", color = color.red, overlay = true)그리고 그 선은, 그 선이 사용하는 데이터는close[2]

Inventor 양적 PINE 언어 소개 튜토리얼

왜냐하면 K선 바의 인덱스, 즉 내장 변수가bar_index“A”와 “B” 마크를 그리는지 아닌지를 계산한다. “A”와 “B” 마크는 모든 K 라인 바에 그리지 않는다.f(a) => a[1]이렇게 인용된 값은 함수가 모든 바에서 호출되지 않는 경우 함수와 일치합니다.f2() => close[1]이 방법으로 인용된 값은 서로 다르지만[1] 같은 인덱스) [2].

  • 어떤 내장 함수는 각 바에서 계산해야 합니다.

예를 들어서 간단하게 설명하자면,

  res = close > close[1] ? ta.barssince(close < close[1]) : -1
  plot(res, style = plot.style_histogram, color=res >= 0 ? color.red : color.blue)

함수를 호출합니다.ta.barssince(close < close[1])그리고 이 함수는 3차원 연산자입니다.condition ? value1 : value2그리고 그 결과로close > close[1]ta.barssince 함수를 호출할 때.ta.barssince함수는 가장 최근부터 계산됩니다.close < close[1]생성될 때 K줄의 수. ta.barssince 함수를 호출할 때 모두 close > close[1], 즉, 현재 마감값이 이전 Bar의 마감값보다 크며, 함수 ta.barssince가 호출될 때 그 조건 close < close[1]도 설립되지 않았기 때문에 가장 최근에 설립된 곳이 없습니다.

ta.barssince: 호출될 때, 만약 현재 K선 이전에 그 조건이 충족되지 않았다면, 이 함수는 na。를 반환한다.

그림에서 보는 바와 같이:

Inventor 양적 PINE 언어 소개 튜토리얼

그래서 그래프를 그리면, res 변수가 값이 있을 때만 데이터를 그리게 됩니다.

이 문제를 피하기 위해, 우리는 단지ta.barssince(close < close[1])함수 호출은 삼각형 연산자에서 가져와, 가능한 조건부 분기 외부에 쓰여진다. K줄 Bar마다 계산을 수행하도록 한다.

  a = ta.barssince(close < close[1])
  res = close > close[1] ? a : -1
  plot(res, style = plot.style_histogram, color=res >= 0 ? color.red : color.blue)

Inventor 양적 PINE 언어 소개 튜토리얼

시간계열

시간계열이라는 개념은 파인 언어에서 매우 중요하며, 우리가 파인 언어를 배울 때 반드시 이해해야 하는 개념이다. 시간계열은 타입이 아니라 시간이 지남에 따라 변수를 저장하는 연속적인 값의 기본 구조이다. 우리는 파인 스크립트가 도표에 기반하고, 도표에 표시되는 가장 기본적인 내용은 K선 도표이다. 시간계열은 각각의 값이 K선 바의 시간과 연관되어 있다.open파인 (Pine) 언어의 내장 변수 ((built-in) 이다. K선 바의 개시값을 저장하는 시간 연속으로 구성된다.open이 시간 순서 구조는 현재 K 선이 시작되는 첫 번째 바에서 현재 스크립트에서 실행되는 바에 이르기까지 모든 K 선 바의 오픈 가격을 나타냅니다. 현재 K 선이 5 분 주기라면, 우리는 Pine 전략 코드에서 참조합니다.openK선Bar의 개시값은 현재 실행되는 전략 코드를 사용하는 때입니다. 시간열의 역사값을 참조하려면 사용해야 합니다.[]연산자: K선Bar에서 Pine 정책이 실행될 때 사용된다.open[1]참조 표시open시간계 상에서 현재 스크립트가 실행하는 이 K선Bar의 이전 K선Bar의 개장값 ((즉, 이전 K선 주기의 개장값)

  • 시간열의 변수를 계산하는 것은 매우 편리합니다. 함수들을 내장하고 있습니다ta.cum예를 들어:
  ta.cum

  Cumulative (total) sum of `source`. In other words it's a sum of all elements of `source`.
  ta.cum(source) → series float
  RETURNS
  Total sum series.
  ARGUMENTS
  source (series int/float)
  SEE ALSO
  math.sum

테스트 코드:

  v1 = 1
  v2 = ta.cum(v1)
  plot(v1, title="v1")
  plot(v2, title="v2")
  plot(bar_index+1, title="bar_index")

많은 유사점이 있습니다.ta.cum이러한 내장 함수는 시간열의 데이터를 직접 처리할 수 있습니다.ta.cumK선Bar의 각 변수의 값을 합치면, 그 다음에는 그래프를 사용해서 이해하기 쉽죠.

정책 실행 과정에 있는 bar_index | - | - | - | - | 이 전략은 K-선 1에서 실행됩니다. 이 전략은 2차 K선에서 실행됩니다. 전략은 3번째 K선에서 실행됩니다. |…|…|…|…| 이 전략은 N+1 로그 K에서 실행됩니다.

볼 수 있듯이, 실제로 v1, v2 심지어 bar_index은 시간 연속 구조이며, 각 Bar에 대응하는 데이터가 있다. 이 테스트 코드는 “실시간 가격 모델” 또는 “폐쇄 가격 모델”을 사용하여 차트에 실제 Bar를 표시하는지 여부에 대한 차이만 있다. 속도를 재측정하기 위해 우리는 “폐쇄 가격 모델”을 사용하여 재측정 테스트를 한다.

Inventor 양적 PINE 언어 소개 튜토리얼

그리고 v1이 모든 바에 1이 되기 때문에ta.cum(v1)함수가 첫 번째 K선 Bar에서 실행될 때 첫 번째 Bar만 존재하기 때문에, 계산 결과는 1이며, 변수에 값이 부여된다. 언제ta.cum(v1)두 번째 K선 Bar에서 실행할 때, 이미 2개의 K선 Bar가 있습니다. 첫 번째 대응하는 내장 변수 bar_index은 0이고, 두 번째 대응하는 내장 변수 bar_index은 1이므로, 계산 결과는 2이며, 변수 v2에 값을 부여합니다. 실제로는 v2가 K선 Bar의 수라고 볼 수 있습니다.bar_index0에서 시작해서bar_index + 1실제로 K선 Bar의 수입니다.v2그리고bar_index정말 재발한 일이죠.

Inventor 양적 PINE 언어 소개 튜토리얼

그리고 저는 또한ta.cum내장된 함수는 현재 그래프에 있는 모든 Bar의 종식값의 합을 계산하고, 이렇게 쓸 수 있습니다:ta.cum(close), 전략이 가장 오른쪽에 있는 실시간 바에 실행될 때ta.cum(close)계산된 결과는 차트 상의 모든 Bar의 종결값의 합이다.

시간열의 변수는 또한 연산자를 사용하여 계산할 수 있습니다. 예를 들어 코드:ta.sma(high - low, 14)이 변수들은high(K선Bar 최고값) 빼기low(K선 바 최저 가격), 마지막 사용ta.sma함수는 평균값을 구한다.

  • 함수 호출 결과도 시간열에 값의 흔적을 남길 수 있습니다.
  v1 = ta.highest(high, 10)[1]
  v2 = ta.highest(high[1], 10)
  plot(v1, title="v1", overlay=true)
  plot(v2, title="v2", overlay=true)

이 테스트 코드는 재측정할 때 테스트가 실행되고,v1그리고v2함수 호출을 통해 계산된 결과는 시간 순서에서 값의 흔적을 남길 수 있습니다. 예를 들어 코드ta.highest(high, 10)[1]그 중 하나는ta.highest(high, 10)함수 호출으로 계산된 결과도 사용할 수 있습니다.[1] 그 역사값을 참조하기 위한 △ 현재 Bar의 앞 Bar에 대응하는ta.highest(high, 10)이 계산은ta.highest(high[1], 10)그래서ta.highest(high[1], 10)그리고ta.highest(high, 10)[1]완전히 동일합니다.

다른 그림 함수를 사용하여 출력 정보를 검증합니다:

  a = ta.highest(close, 10)[1]
  b = ta.highest(close[1], 10)
  plotchar(true, title="a", char=str.tostring(a), location=location.abovebar, color=color.red, overlay=true)
  plotchar(true, title="b", char=str.tostring(b), location=location.belowbar, color=color.green, overlay=true)

시간 순서에서 변수 a와 변수 b의 값이 해당 바의 위와 아래에 표시되는 것을 볼 수 있다. 학습 과정에서 이 그림 코드를 유지할 수 있다. 왜냐하면 테스트, 실험할 때 종종 차트에 정보를 출력하여 관찰할 필요가 있기 때문이다.

Inventor 양적 PINE 언어 소개 튜토리얼

스크립트 구조

일반 구조

이 튜토리얼의 시작 부분에서 우리는 FMZ에서 Pine 언어와 Trading View에서 Pine 언어의 사용에 대한 몇 가지 차이점을 요약했습니다.indicator()strategy()그리고, 당분간은 지원하지 않습니다.library()물론 이전 버전의 파인 스크립트와 호환하기 위해, 전략을 작성할 때 다음과 같은 것을 적었습니다.//@version=5indicator()strategy()일부 정책 설정은strategy()함수에서 전달자 설정.

<version>
<declaration_statement>
<code>

<version>버전 관리 정보는 삭제할 수 있습니다.

참고

파인어 사용//단행 주석으로, 파인 언어에는 다행 주석이 없기 때문에 FMZ는 주석을 확장했다./**/여러 줄의 주석으로 쓰인다.

코드

스크립트의 코멘트나 컴파일러 명령어가 아닌 줄은 문장이며, 그것은 스크립트의 알고리즘을 구현한다. 문장은 이 중 하나일 수 있다.

  • 변수 선언
  • 변수의 재확인
  • 함수 선언
  • 내장 함수 호출, 사용자 정의 함수 호출
  • ifforwhile또는switch등 구조

문장은 여러 가지 방식으로 구성될 수 있습니다.

  • 어떤 문장은 한 줄로 표현할 수 있는데, 예를 들어 대부분의 변수 선언은 하나의 함수 호출 줄만 포함하고, 또는 단일 라인 함수 선언이다. 다른 것들은, 구조와 같이, 항상 여러 줄이 필요하기 때문에, 그것들은 한 지역 블록이 필요하다.
  • 스크립트의 전체 범위에 속하는 문장 (즉, 지역 블록에 속하지 않는 부분) 은空格또는制表符(tab 키) 시작 그들의 첫 번째 문자는 또한 이 줄의 첫 번째 문자가 되어야 한다 줄의 첫 번째 위치에서 시작하는 줄은, 정의에 따라 스크립트의 전체 범위의 일부가 된다
  • 구조 또는 다중 행 함수 선언은 항상local block。 한 로컬 블록은 하나의 표기符 또는 네 개의 빈 공간으로 축소되어야 한다. 그렇지 않으면, 이전 라인의 연산 코드로 해독되며, 즉, 이전 라인의 코드의 연속으로 판단된다. 각 로컬 블록은 다른 로컬 범위를 정의한다.
  • 여러 개의 단행 문장은 쉼표 ((,) 를 사용하여 분리자 (separator) 로 한 줄에 연쇄될 수 있다.
  • 한 줄에는 코멘트가 포함될 수도 있고, 그냥 코멘트일 수도 있다.
  • 이 문장은 문장과 문장 사이를 두 번 묶을 수 있습니다.

예를 들어, 세 개의 로컬 블록을 포함하고, 사용자 정의 함수 선언에서 하나, 변수 선언에서 두 개가 if 구조를 사용하며, 다음과 같은 코드입니다:

indicator("", "", true)             // 声明语句(全局范围),可以省略不写

barIsUp() =>                        // 函数声明(全局范围)
    close > open                    // 本地块(本地范围)

plotColor = if barIsUp()            // 变量声明 (全局范围)
    color.green                     // 本地块 (本地范围)
else
    color.red                       // 本地块 (本地范围)

runtime.log("color", color = plotColor)  // 调用一个内置函数输出日志 (全局范围)

코드 변경

긴 줄은 여러 줄로 나눌 수 있고, 또는 “포직”될 수 있다. 포직된 줄은 4의 배수가 아닌 한, 임의의 수의 공백으로 축소되어야 한다. (이러한 경계들은 부분 블록으로 축소하기 위해 사용된다.)

a = open + high + low + close

이렇게 포장할 수 있습니다 (각 줄에 축소되는 빈 공간의 수는 4의 배수가 아니라는 점에 유의하십시오):

a = open +
      high +
          low +
             close

하나의 긴 plot ((() 호출은 으로 포장될 수 있다.

close1 = request.security(syminfo.tickerid, "D", close)      // syminfo.tickerid 当前交易对的日线级别收盘价数据系列
close2 = request.security(syminfo.tickerid, "240", close)    // syminfo.tickerid 当前交易对的240分钟级别收盘价数据系列
plot(ta.correlation(close, open, 100),                       // 一行长的plot()调用可以被包装
   color = color.new(color.purple, 40),
   style = plot.style_area,
   trackprice = true)

사용자 정의 함수 선언의 문장도 패키지 될 수 있다. 그러나, 지역 블록은 문법적으로 축소수로 시작해야 하기 때문에 ((4개의 빈 공간 또는 1개의 기호를 만드는), 다음 줄로 분할할 때, 문장의 계속되는 부분은 하나 이상의 축소수로 시작해야 한다 (((4개의 빈 공간의 곱과 같지 않다). 예를 들어:

test(c, o) =>
    ret = c > o ?
       (c > o+5000 ? 
          1 :
              0):
       (c < o-5000 ? 
          -1 : 
              0)
           
                   
a = test(close, open)
plot(a, title="a")

식별자 및 연산자

아이덴티커

변수를 알기 전에, 우리는 먼저 아이덴티커의 개념을 이해해야 한다.기능그리고변수이름의 (변수, 함수, 함수를 명명하기 위한)기능다음 강의에서 알 수 있듯이, 우리는 먼저 식별자 (識別符) 를 배웁니다.

  • 1호는 대문자로 써야 합니다.(A-Z)또는 작은 글자(a-z)글자 또는 밑줄(_)시작, 아이덴티커의 첫 번째 문자.
  • 2호기 첫 번째 문자 뒤에 있는 문자는알파벳밑줄또는숫자
  • 3 ᆞ 아이덴티커의 명칭은 대소문자로 구분한다.

예를 들어, 다음과 같은 이름의 아이덴티커:

fmzVar
_fmzVar
fmz666Var
funcName
MAX_LEN
max_len
maxLen
3barsDown  // 错误的命名!使用了数字字符作为标识符的开头字符

대부분의 프로그래밍 언어와 마찬가지로, 파인 언어에는 글쓰기 제안이 있다. 일반적으로 식별자의 명칭에 대해 다음과 같이 제안한다:

  • 1, 모든 글자는 대문자로 명칭 상수를 사용한다.
  • 2. 사용작은 峰 규칙다른 식별자에 사용되는 명칭
// 命名变量、常量
GREEN_COLOR = #4CAF50
MAX_LOOKBACK = 100
int fastLength = 7

// 命名函数
zeroOne(boolValue) => boolValue ? 1 : 0

연산자

연산자는 프로그래밍 언어에서 표현을 구축하는 데 사용되는 몇 가지 연산자이며, 표현은 우리가 전략을 작성할 때 어떤 계산 목적을 위해 설계된 계산 규칙입니다. 파인 언어의 연산자는 기능에 따라 다음과 같이 분류됩니다.

값 부여 연산자, 계산 연산자, 비교 연산자, 논리 연산자,? :3차원 연산자,[]역사 참조 연산자:

계산기*예를 들어, 트레이딩 뷰의 파인 언어 연산자가 반환한 결과와 다른 유형의 문제에는 다음과 같은 테스트 코드가 있습니다.

//@version=5
indicator("")
lenInput = input.int(14, "Length")
factor = year > 2020 ? 3 : 1
adjustedLength = lenInput * factor
ma = ta.ema(close, adjustedLength)  // Compilation error!
plot(ma)

트레이딩 뷰에서 이 스크립트를 실행할 때 컴파일 오류가 발생합니다.adjustedLength = lenInput * factor곱하면series int유형 (계), 그러나ta.ema함수의 두 번째 변수는 이러한 타입을 지원하지 않는다. 그러나 FMZ에는 이러한 엄격한 제한이 없으며, 위의 코드는 정상적으로 동작할 수 있다.

아래에서 우리는 다양한 연산자의 사용에 대해 살펴볼 것입니다.


부여 연산자

두 가지의 부여 연산자가 있다.=:=이 강좌의 시작 부분에서 몇 가지 예제에서 보았듯이,

=변수를 초기화하거나 선언할 때 사용하는 연산자=초기화, 선언 부여 이후의 변수는 그 이후의 모든 Bar에서 그 값으로 시작된다. 이들은 모두 유효한 변수 선언이다:

a = close           // 使用内置变量赋值给a
b = 10000           // 使用数值赋值
c = "test"          // 使用字符串赋值
d = color.green     // 使用颜色值赋值
plot(a, title="a")
plot(b, title="b")
plotchar(true, title="c", char=str.tostring(c), color=d, overlay=true)

알아채다a = close부여 문장, 각 바의 변수 a는 현재 그 바의 종료 가격 ((close) 이다. 다른 변수bcdFMZ에 있는 피드백 시스템에서 테스트할 수 있으며, 도면으로 결과를 볼 수 있다.

:=기존의 변수에 값을 재배치하기 위해 사용되며:=연산자는 이미 선언된, 초기화 된 변수의 값을 수정하는 데 사용됩니다. 사용된 경우:=오퍼레이터가 초기화되거나 선언되지 않은 변수에 값을 부여하면 오류가 발생한다. 예를 들어:

a := 0

그래서,:=부여 연산자는 일반적으로 기존의 변수에 대한 재배치를 위해 사용된다. 예를 들어:

a = close > open 
b = 0 
if a
    b := b + 1

plot(b)

판단하는 경우close > open(즉, 현재 BAR은 양선이고), a 변수는 참값 ((true)) 이다. 그러면 if 문장의 로컬 블록에 있는 코드를 실행한다.b := b + 1, assignment 연산자를 사용하세요:=b에 다시 값을 부여하고, 1을 더한다. 그리고 plot 함수를 사용하여 시간 순서 각 BAR에 있는 변수 b의 값을 도표에 그려, 연결 라인한다.

우리는 선선 BAR, b가 계속 1을 더한다고 생각합니까? 물론 그렇지 않습니다. 여기 우리는 변수 b를 선언하고 0으로 초기화할 때 어떤 키워드를 지정하지 않습니다.b=0그리고 이 코드는 모든 BAR에서 실행됩니다. 그래서 이 코드가 실행되는 것을 볼 수 있습니다. 이 코드는 매번 b 변수를 0으로 재설정합니다.close > open그러면 이 라운드에서 b는 1을 더하고, 플롯 함수 도면에는 1이 되지만, 다음 라운드에서 b는 0으로 재가치됩니다. 이것은 파인 언어 초보자가 쉽게 넘어질 수 있는 부분입니다.

이 두가지의 핵심 단어에 대해 설명하는 데에 있어서,varvarip

  • var

사실 이 키워드는 이전 강좌에서 사용되었으나, 그 당시에는 자세히 다루지 않았습니다. 먼저 이 키워드의 설명을 살펴봅시다.

var은 배분 및 일회성 초기화 변수의 키워드이다. 일반적으로, 키워드 var을 포함하지 않는 변수 부여 문법은 데이터를 업데이트 할 때마다 변수의 값을 덮게 만든다. 반대로, 키워드 var을 사용하여 변수를 배분할 때, 데이터가 업데이트 되더라도, 그들은 여전히 상태가 유지됩니다.

우리는 이 예제를 그대로 사용하지만 b에 값을 부여할 때var키워드

  a = close > open 
  var b = 0 
  if a
      b := b + 1

  plot(b)

var키워드는 b 변수가 처음의 첫 번째 부여값만 실행하도록 하고, 이후 정책 논리 실행 때마다 b를 다시 0으로 다시 설정하지 않기 때문에, 실행할 때 그려진 선에서 b를 관찰할 수 있다. 즉, 현재 K선 BAR에 나타난 양선 BAR의 수를 역측정한다.

var 선언의 변수는 전 세계적으로 쓰일 수 있을 뿐만 아니라 코드 블록에도 쓰일 수 있습니다. 예를 들어:

  strategy(overlay=true)
  var a = close
  var b = 0.0
  var c = 0.0
  var green_bars_count = 0
  if close > open
      var x = close
      b := x
      green_bars_count := green_bars_count + 1
      if green_bars_count >= 10
          var y = close
          c := y
  plot(a, title = "a")
  plot(b, title = "b")
  plot(c, title = "c")

변수 ‘a’는 시리즈의 첫 번째 기둥 선의 종료 값을 유지한다. 변수 ‘b’는 시리즈의 첫 번째 ?? 녹색 ?? 가격 막대의 종료 가격을 유지한다. 변수 ‘c’는 시리즈의 10번째 그린의 종전 가격을 유지한다.

  • varip

varip이 키워드를 처음 봤을 때, 이 키워드의 설명은 다음과 같습니다.

varip ((var intrabar persist) 는 배분 및 일회성 초기화 변수의 키워드이다. 이는 var 키워드와 비슷하지만, varip 선언을 사용하는 변수는 실시간 K선 업데이트 사이에 값을 유지한다.

이해가 좀 어렵다고 생각하시나요? 괜찮아요, 예를 들어서 설명하면 이해가 좀 쉬워요.

  strategy(overlay=true)

  // 测试 var varip
  var i = 0
  varip ii = 0  

  // 将策略逻辑每轮改变的i、ii打印在图上
  plotchar(true, title="ii", char=str.tostring(ii), location=location.abovebar, color=color.red)
  plotchar(true, title="i", char=str.tostring(i), location=location.belowbar, color=color.green)  

  // 每轮逻辑执行都给i、ii递增1
  i := i + 1
  ii := ii + 1

이 테스트 코드는 “폐쇄 가격 모델”과 “현실 가격 모델”에서 다르게 나타납니다.

실시간 가격 모델: 우리가 전에 설명한 전략이 실행되는 시기는 역사적인 BAR 단계와 실제적인 BAR 단계로 나뉘어졌다는 것을 기억하시나요?varvarip선언된 변수iii전략 코드가 실행되는 각 라운드마다 증가 동작이 수행된다. 따라서 K BAR 라인에 표시되는 숫자는 각각 1을 증가하는 것을 볼 수 있다. 역사 K 라인 단계가 끝나고 실시간 K 라인 단계가 시작되면. var, varip 선언의 변수는 다른 변화가 시작된다. 실시간 가격 모델이기 때문에, K BAR 라인 내에서 가격 변화가 있을 때마다 전략 코드가 실행된다.i := i + 1그리고ii := ii + 1항상 한 번 실행한다。 차이점은 ii가 매번 수정한다。 i는 매번 수정되기도 하지만, 다음 라운드 실행 전략 논리 때 이전 값이 복원된다 (기억하시오, 이전 “모델 실행” 장에서 설명한 회전 메커니즘은?), 현재 KBAR가 다 지나기 전까지는 i의 값을 업데이트하지 않는다 (즉, 다음 라운드 실행 전략 논리 때 이전 값이 복원되지 않는다). 따라서 변수 i는 여전히 각 BAR가 증가하는 것을 볼 수 있다。 그러나 변수 ii는 각 BAR가 여러 번 증가하는 것을 볼 수 있다。

종결 가격 모델: 클로즈 가격 모형은 K선 BAR가 다 지나면 한 번 전략 논리를 실행한다. 따라서 클로즈 가격 모형에서, 역사 K선 단계와 실시간 K선 단계, var, varip 선언의 변수는 위의 예제에서 증가 성능을 완전히 일치하며, 모든 K선 BAR이 증가한다.


계산기
연산자 설명하다
+ 가파
- 절제법
* 곱셈
/ 폐지
% 모범을 찾아라

+-연산자는 이진 연산자로도 사용할 수 있고, 단위 연산자로도 사용할 수 있다. 다른 수리 연산자는 오직 이진 연산자로만 사용할 수 있으며, 단위 연산자로 사용할 경우 오류가 발생한다.

1 , 대수 연산자는 양쪽 모두 수값 타입이며, 결과는 수값 타입, 정형 또는 부동소수점 수에 따라 연산 결과이다. 2, 만약 그 중 어떤 연산수가 문자열이라면, 연산자는+, 는 문자열로 계산되며, 값은 문자열 형태로 변환되고, 문자열이 함께 스피치된다. 다른 수수 연산자는 문자열을 숫자 값으로 변환하고, 연산한다. 3. 만약 그 중 어떤 연산수가 na일 경우, 계산 결과는 null값인 na이며, FMZ에서 인쇄할 때 NaN을 표시한다.

a = 1 + 1 
b = 1 + 1.1
c = 1 + "1.1"
d = "1" + "1.1"
e = 1 + na 

runtime.log("a:", a, ", b:", b, ", c:", c, ", d:", d, ", e:", e)   
// a: 2 , b: 2.1 , c: 11.1 , d: 11.1 , e: NaN

FMZ의 파인 언어는 여기서 트레이딩 뷰의 파인 언어와 약간의 차이가 있습니다. FMZ의 파인 언어는 변수 유형에 대한 요구 사항에 대해 매우 까다롭지 않습니다. 예를 들어:

a = 1 * "1.1"
b = "1" / "1.1"
c = 5 % "A" 

plot(a)
plot(b)
plot(c)

FMZ에서 실행할 수 있지만, 트레이딩 뷰에서 타입 에러를 보고한다. 계산 연산자의 양쪽의 연산수가 문자열일 경우, 시스템은 문자열을 숫자 값으로 변환한 후 계산한다. 비숫자 문자열을 계산할 수 없는 경우, 시스템 연산 결과는 null값이다.


비교 연산자

비교 연산자는 모두 이진 연산자입니다.

연산자 설명하다
< 미만
> 더 큰
<= 이보다 작은 것은
>= 더 크거나 같다는 것입니다.
== 동일
!= 불평등

테스트 예제:

a = 1 > 2 
b = 1 < 2 
c = "1" <= 2 
d = "1" >= 2 
e = 1 == 1 
f = 2 != 1 
g = open > close 
h = na > 1 
i = 1 > na

runtime.log("a:", a, ", b:", b, ", c:", c, ", d:", d, ", e:", e, ", f:", f, ", g:", g, ", h:", h, ", i:", i)   
// a: false , b: true , c: true , d: false , e: true , f: true , g: false , h: false , i: false

비교 연산자는 매우 간단하지만, 우리가 전략 작성할 때 가장 많이 사용하는 연산자입니다. 값과 내장 변수를 비교할 수 있습니다.closeopen기다리다. 연산 연산자와 마찬가지로, FMZ 상에서 트레이딩 뷰의 파인과는 차이가 있다. FMZ에는 특별히 엄격한 요구 유형이 없으므로, 이와 같은 문장은d = "1" >= 2FMZ에서는 오류가 발생하지 않으며, 실행할 때 문자열을 먼저 숫자 값으로 변환한 다음 비교 연산한다. Trading View에서는 오류가 발생한다.


논리 연산자
연산자 코드 기호 설명하다
아니 not 일자 연산자, 연산자 아닌
그리고 and 바이너리 연산자, 그리고 (그리고) 연산
또는 or 이진 연산자, 또는 연산

논리 연산자에 대해 이야기할 때, 반드시 사실값 표에 대해 이야기해야 합니다. 우리가 고등학교에서 배운 것과 마찬가지로, 여기서 우리는 피드백 시스템을 테스트하고 배웁니다:

a = 1 == 1  // 使用比较运算符构成的表达式,结果为布尔值
b = 1 != 1
c = not b   // 逻辑非操作符
d = not a   // 逻辑非操作符

runtime.log("测试逻辑操作符:and", "#FF0000")
runtime.log("a:", a, ", c:", c, ", a and c:", a and c)
runtime.log("a:", a, ", b:", b, ", a and b:", a and b)
runtime.log("b:", b, ", c:", c, ", b and c:", b and c)
runtime.log("d:", d, ", b:", b, ", d and b:", d and b)

runtime.log("测试逻辑操作符:or", "#FF0000")
runtime.log("a:", a, ", c:", c, ", a or c:", a or c)
runtime.log("a:", a, ", b:", b, ", a or b:", a or b)
runtime.log("b:", b, ", c:", c, ", b or c:", b or c)
runtime.log("d:", d, ", b:", b, ", d or b:", d or b)

runtime.error("stop")

그래서 우리는 추적 시스템에서 계속 인쇄되는 정보의 영향을 관찰하지 않기 위해,runtime.error("stop")문장은 한 번 인쇄한 후, 재검토를 멈추게 하는 비정상적인 오류를 던져, 그 후에 출력된 정보를 관찰할 수 있으며, 인쇄된 내용과 사실값 표가 실제로 동일하다는 것을 발견할 수 있다.


삼차 연산자

삼차원 연산자를 사용함? :연산수와 결합된 삼차원 표현식condition ? valueWhenConditionIsTrue : valueWhenConditionIsFalse우리는 이전 강의에서도 이미 익숙해져 있었습니다. 소위 삼차원 표현식, 삼차원 연산자는 그 중의 연산수가 총 세 개라는 것을 의미합니다.

condition ? valueWhenConditionIsTrue : valueWhenConditionIsFalse그 중 하나는condition정의 조건은, 만약 진실 표현의 값이:valueWhenConditionIsTrue만약condition이 표현의 값은valueWhenConditionIsFalse

실제적인 용도가 거의 없으나, 예를 들어 설명해 보겠습니다.

a = close > open
b = a ? "阳线" : "阴线"
c = not a ? "阴线" : "阳线"
plotchar(a, location=location.abovebar, color=color.red, char=b, overlay=true)
plotchar(not a, location=location.belowbar, color=color.green, char=c, overlay=true)

만약 십자성 (cross star) 을 만나면 어떻게 하든 상관없습니다. 삼각형 표현식 (triangular expression) 도 삽입할 수 있습니다. 지난 강의에서도 그랬습니다.

a = close > open
b = a ? math.abs(close-open) > 30 ? "阳线" : "十字星" : math.abs(close-open) > 30 ? "阴线" : "十字星"
c = not a ? math.abs(close-open) > 30 ? "阴线" : "十字星" : math.abs(close-open) > 30 ? "阳线" : "十字星"
plotchar(a, location=location.abovebar, color=color.red, char=b, overlay=true)
plotchar(not a, location=location.belowbar, color=color.green, char=c, overlay=true)

그리고 이것은 실제로condition ? valueWhenConditionIsTrue : valueWhenConditionIsFalse~ 안에valueWhenConditionIsTruevalueWhenConditionIsFalse, 또한 다른 삼위일체 표현을 사용한다.


역사 연산자

역사 연산자를 사용함[], 참조 시간 순서 상의 역사값 。 이 역사값은 변수가 스크립트를 실행할 때 현재 K선 BAR 이전에 K선 BAR 상의 값 。[]연산자는 변수, 표현식, 함수 호출 후에 쓰인다.[]이 사각형 괄호의 값은 우리가 참조하고자 하는 역사 데이터의 현재 K선 BAR의 오차량이다. 예를 들어, 내가 K선 BAR의 마지막 종식 가격을 인용하고자 한다면, 다음과 같이 쓸 수 있다:close[1]

우리는 이전 강의에서 이와 비슷한 문자를 보았습니다.

high[10]
ta.sma(close, 10)[1]
ta.highest(high, 10)[20]
close > nz(close[1], open)

[]연산자는 같은 값에 한 번만 사용할 수 있기 때문에 이렇게 쓰면 오류가 발생한다:

a = close[1][2]   // 错误

그리고 여기서는, 어떤 학생이,[]이것은 array의 구조와 비슷합니다. 아래에서 우리는 하나의 예를 통해 파인 언어의 일련 (series) 과 배열 (array) 이 다르지 않다는 것을 설명해 보겠습니다.

strategy("test", overlay=true)

a = close
b = close[1]
c = b[1]

plot(a, title="a")
plot(b, title="b")
plot(c, title="c")

하지만a = close[1][2]하지만, 저는 이 글이 틀렸다고 생각합니다.

b = close[1]
c = b[1]

이 경우, 이 숫자는 보통의 배열로 이해하면 실수하지 않습니다.b = close[1]b가 값이 되어야 합니다.c = b[1], b는 여전히 역사 연산자를 사용하여 역사 값을 다시 참조할 수 있다. Pine 언어의 시리즈 (series) 개념은 배열만큼 간단하지 않다. close의 상단의 Bar의 역사 값 (attribute to b), b는 시간 연속 구조 (time series) 이며, 그 역사 값을 계속 참조할 수 있다. 그래서 우리는 그려진 3개의 선 a, b, c 중, b 선은 a 선보다 느리고, b 선은 b 선보다 느리고, b 선은 a 선보다 느리고, b 선은 b 선보다 느리고, b 선은 a 선보다 느리고, a 선은 a 선보다 느리고 있다.

우리는 그래프를 가장 왼쪽으로 눌러서, 첫 번째 K 줄에서 b와 c의 값이 모두 null이라는 것을 관찰할 수 있습니다. 그 이유는 스크립트가 첫 번째 K 줄 BAR에서 실행될 때, 앞을 참조하는 1~2주기의 역사값은 null이므로 존재하지 않기 때문입니다. 그래서 우리는 전략을 작성할 때 항상 주의를 기울여야 합니다.nanz내장 함수를 판단하기 위해서요.nzna함수, 어떤 장을 기억하십니까?)

close > nz(close[1], open)    // 当引用close内置变量前一个BAR的历史值时,如果不存在,则使用open内置变量

이것은 null을 참조할 수 있는 의 처리이다.


오퍼레이터 우선 순위

우리는 이미 파인 언어의 많은 연산자를 배웠고, 이 연산자들은 연산자와 연산수의 다양한 조합을 통해 표현을 형성한다. 그렇다면 표현에서 계산할 때, 이 연산들의 우선순위는 어떻게 될까요? 마치 우리가 학교에 다닐 때 배운 4항 연산과 같이, 곱셈을 우선 계산하는 곱셈, 그리고 덧셈을 계산하는 곱�