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

FMZ PINE 스크립트 문서

저자:발명가들의 수량화 - 작은 꿈, 창작: 2022-04-28 16:05:05, 업데이트: 2024-10-12 17:25:27

[TOC]

img

키워드, 문법, 설정에 대한 소개

코드 구조

파인 언어의 일반적인 구조는 다음과 같습니다.

<version>
<declaration_statement>
<code>

참고문서

참고자료 FMZ의 소나무 언어로 지원되는 기호: 단선 메모//, 여러 줄의 메모/* */, 예를 들어 다음 예제에서 노트 방법과 같이:

[macdLine, signalLine, histLine] = ta.macd(close, 12, 26, 9)  // calculate the MACD indicator

/*
The plot function draws the indicator line on the chart
*/
plot(macdLine, color = color.blue, title='macdLine')
plot(signalLine, color = color.orange, title='signalLine')
plot(histLine, color = color.red, title='histLine')

버전

다음 형태의 컴파일러 명령어는 컴파일러에 스크립트가 작성된 파이인의 버전을 알려줍니다.

//@version=5

기본 버전은 V5 버전입니다.//@version=5.

선언문

  • indicator()
  • strategy()

선언 명령어는 스크립트의 유형을 결정하고, 그 결과 스크립트에서 허용되는 것과 사용 및 실행 방법을 결정합니다. 스크립트의 주요 특성을 설정합니다. 예를 들어 이름, 차트에 추가되면 표시되는 위치, 표시되는 수치 값의 정확성 및 형식, 실행시 동작을 지배하는 특정 수치 값, 예를 들어 차트에 표시되는 최대 수의 드로잉 객체. 전략의 특성은 초기 자본, 수수료, 미끄러움 등과 같은 백테스팅을 제어하는 인수를 포함합니다.indicator()또는strategy()선언표는 FMZ의 파인에서 전략 코드에 포함되어야 합니다.

코드

코멘트나 컴파일러 명령어가 아닌 스크립트의 라인, 즉 코멘트 알고리즘을 구현하는 명령어. 명령어는 이러한 내용 중 하나가 될 수 있습니다.

  • 변수 선언
  • 변수 재분배
  • 기능 선언
  • 내장 함수 호출, 사용자 정의 함수 호출
  • if, for, while또는switch그리고 다른 구조물

진술서 는 여러 가지 로 정리 될 수 있다

  • 일부 명령어는 대부분의 변수 선언, 하나의 함수 호출만 포함된 줄 또는 단일 줄 함수 선언과 같은 하나의 줄로 표현될 수 있다. 다른 것들은 구조와 같이 로컬 블록이 필요하기 때문에 항상 여러 줄이 필요하다.
  • 스크립트의 글로벌 범위에 있는 명령어 (즉 로컬 블록의 일부가 아닌 부분) 는space또는tab(tab 키). 첫 번째 문자는 또한 줄의 첫 번째 문자가어야 합니다. 줄의 첫 번째 위치에서 시작하는 줄은 정의에 따라 스크립트의 글로벌 범위의 일부입니다.
  • Alocal block구조 또는 여러 줄 함수 선언에 항상 필요합니다. 로컬 블록은 하나의 탭 또는 네 개의 간격으로 간격화되어야 합니다 (그렇지 않으면 이전 줄의 연속된 코드로 분석됩니다. 이는 이전 코드 줄의 연속적인 내용으로 결정됩니다.) 그리고 각 로컬 블록은 다른 로컬 스코프를 정의합니다.
  • 여러 개의 단일 라인 문장을 한 줄에 묶을 수 있습니다.
  • 한 줄에는 댓글이나 그냥 댓글이 있을 수 있습니다.
  • 라인은 또한 포장 될 수 있습니다 (다중 라인에 계속됩니다).

예를 들어, 세 개의 로컬 블록을 포함, 사용자 정의 함수 선언에 하나, 그리고 변수 선언에 두 if 구조를 사용하여 다음과 같이:

indicator("", "", true)             // Declaration statement (global scope), can be omitted

barIsUp() =>                        // Function declaration (global scope)
    close > open                    // Local block (local scope)

plotColor = if barIsUp()            // Variable declaration (global scope)
    color.green                     // Local block (local scope)
else
    color.red                       // Local block (local scope)

runtime.log("color", color = plotColor)  // Call a built-in function to output the log (global scope)

뉴라인 코드

긴 선은 여러 선으로 나눌 수 있다. 또는 wrapped . wrapped line는 4의 배수가 아니라면 모든 양의 빈 공간으로 인드런트되어야 한다. (이 경계는 로컬 블록을 인드런트하는 데 사용됩니다.)

a = open + high + low + close

이렇게 포장할 수 있습니다 (선당 간격이 4의 배수가 아니라는 점에 유의하십시오):

a = open +
      high +
          low +
             close

긴 플롯 (plot)) 호출은 다음과 같이 포장 될 수 있습니다:

close1 = request.security(syminfo.tickerid, "D", close)      // closing price data series of syminfo.tickerid daily level of the current trading pair
close2 = request.security(syminfo.tickerid, "240", close)    // closing price data series of syminfo.tickerid 240-minute level of the current trading pair
plot(ta.correlation(close, open, 100),                       // Line-long plot() calls can be wrapped
   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")

시간 계열

시간 계열은 데이터 타입이나 형식이 아니라, PINE 언어의 기본 구조의 개념이다. 시간에 따라 지속적으로 변화하는 값을 저장하는 데 사용되며, 각 값은 시간적 지점에 해당한다. 시간 계열 개념의 구조는 시간에 따라 변화하는 일련의 데이터를 처리하고 기록하는 데 적합하다.

내장 변수를 사용하세요.open예를 들어,open내장 변수는 각 int 표현식 BAR의 시작 가격을 기록합니다.open5분 int 표현 기간 데이터입니다.open변수는 각 5분 int 표현식 BAR (바) 의 개시 가격을 기록합니다. 전략 프로그램이 실행될 때,open코드의 현재 int 표현 BAR의 시작 가격을 참조 합니다. 시간 계열의 이전 값 (과거 값) 을 참조하기 위해, 우리는[]이 전략이 특정 int 표현식 BAR에 실행될 때,open[1]그 의미는 현재의 int 표현식 BAR의 이전 int 표현식 BAR의 시작 가격을 참조하는 것입니다.

하지만시간 계열PINE 언어에도 배열 유형이 있지만, array 데이터 구조와 매우 유사합니다. 하지만 그들은 시간 계열과 완전히 다른 개념입니다.

소나무 언어로 설계 된 시간 시리즈는 전략 코드에서 폐쇄 가격의 누적 값을 쉽게 계산 할 수 있으며, 단지 내장 기능과 같은 루프 구조를 사용할 필요가 없습니다.ta.cum(close)다른 예로, 우리는 마지막 14 int 표현식 BAR의 가장 높은 가격과 가장 낮은 가격 사이의 차이의 평균 값을 계산해야 합니다.ta.sma(high - low, 14)

시간 계열에 함수를 호출하는 결과 또한 시간 계열에 흔적을 남길 것입니다[]예를 들어, 현재 int 표현 BAR의 닫기 가격이 마지막 10 int 표현 BAR (현재 int 표현 BAR를 제외한) 의 가장 높은 가격의 최대 값을 초과하는지 테스트 할 때.breach = close > ta.highest(close, 10)[1]그리고 우리는 또한 쓸 수 있습니다breach = close > ta.highest(close[1], 10)그래서ta.highest(close, 10)[1]그리고ta.highest(close[1], 10)동등합니다.

다음 코드로 확인할 수 있습니다.

strategy("test pine", "test", true) 

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)
plotchar(true, title="b", char=str.tostring(b), location=location.belowbar, color=color.green)

위의 테스트 코드는 각 BAR에 대한 a와 b의 값을 해당 시간 계열에서 출력합니다. a와 b의 값이 항상 같다는 것을 볼 수 있습니다. 따라서이 두 표현 방법은 동등합니다.

소나무 언어 무역 클래스 라이브러리의 템플릿 주장

PINE 전략의 내장 Pine Language Trade Class Library 템플릿의 논리를 설정하는 지침.

img

거래 설정

  • 실행 모드 종료 가격 모델: 모델은 현재 BAR가 완료된 후에만 실행되며, 거래는 다음 BAR가 시작될 때 실행됩니다. 실시간 가격 모델: 이 모델은 가격이 움직일 때마다 실행되며 즉시 거래를 실행하는 신호가 있습니다.
  • 기본 오픈 롯 크기: 트레이드 주문에 트레이드 금액이 명시되어 있지 않은 경우, 트레이드는 설정된 금액에 따라 실행됩니다.
  • 단일 거래에 대한 최대 주문 양: 실제 시장과 이 주장 설정에 따라 시장에 영향을 미치지 않도록 각 주문의 최대 금액을 결정합니다.
  • 미끄러짐 포인트: 미끄러짐을 결정Pricing Currency Precision예를 들어, 가격화폐 정밀도는 2로 설정되어 있으며, 두 번째 소수점까지 정확하고 0.01까지 정확합니다. 그 다음 슬리핑 포인트의 각 포인트는 0.01 가격 단위를 나타냅니다. 이 시점에서 슬리핑 포인트는 5으로 설정되며, 주문을 할 때 슬리핑은 0.05입니다 (슬리핑은 더 나은 주문 및 핸디캡 주문 거래를 할 때 넘치는 가격의 부분을 의미합니다).
  • 가장 긴 기간 변수 번호: 차트에서 K-라인 BAR의 수에 영향을줍니다. 함수를 호출하는 것과 동일합니다.SetMaxBarLenjavascript srategy.

선물 옵션

  • 변수 코드: 계약 코드, 교환 대상이 점유가 아닌 교환 대상이 될 때만 설정할 필요가 있습니다.
  • 최소 계약 크기: 주문을 할 때 계약의 최소 거래량.

라이브 거래 옵션

  • 자동 복원 진행: 마지막 전략 정지 전에 상태를 자동 복원합니다.
  • 주문 재시험 시간: 주문이 완료되지 않으면 주문이 취소되고 거래 시도를 위해 주문이 다시 배치됩니다. 이 문서는 최대 재시험 수를 제한하는 데 사용됩니다.
  • 네트워크 투표 간격 (밀리초): REST 프로토콜에서만 유효하며, 요청이 너무 빈번하고 교환 한도를 초과하는 것을 방지하기 위해 네트워크 요청 간격을 제어합니다.
  • 계정 동기화 시간 (초): 계정 데이터를 동기화하는 시간.
  • 포지션 개시 후 포지션 동기화 시간 (밀리 초): 일부 거래소에서 데이터 지연으로 인한 반복 포지션에서만 더 큰 동기화 시간을 설정하면 그러한 문제를 완화 할 수 있습니다.
  • 레버리지 멀티플릭스: 레버리지 멀티플릭스를 설정합니다.

현시 거래, 다른 설정

  • 1 롯의 거래 부피: 1 롯의 기본 거래 부피, 즉 현장 거래에만 유효합니다.
  • 최소 거래량: 최소 거래량.
  • 가격 통화 정확성: 가격 정확성, 즉 가격의 소수점 수.
  • 거래 품종의 정확성: 주문 양의 정확성, 즉 주문 양의 소수점 수.
  • 처리 수수료: 이 설정에 따라 일부 데이터를 계산합니다. 0.002는 2/1000입니다.
  • 이익 및 손실 통계 간격: 실제 시장에서 이익 및 손실 통계 표시를 위해만 사용됩니다.
  • 실패한 재시험 (ms): 네트워크 요청이 실패할 때 재시험 간격.
  • 프록시 사용: REST 프로토콜에서만 유효합니다.
  • 일반적인 네트워크 오류를 숨기기: 로그 영역에서 일반적인 오류 로그를 숨기기.
  • 스위치 기본 주소: REST 프로토콜에서만 유효합니다.
  • 푸시 알림: 메일박스에 푸시 메시지, 등

주문 거래

오픈 포지션

strategy(title = "open long example", pyramiding = 3)                                // The number of orders placed in the same direction allowed by pyramiding
strategy.entry("long1", strategy.long, 0.01)                                         // Open a long position at the market price, specify the group label as long1
strategy.entry("long2", strategy.long, 0.02, when = close > ta.ema(close, 10))       // The condition is triggered, the order is executed, and the market price opens a long position
strategy.entry("long3", strategy.long, 0.03, limit = 30000)                          // Specify the (lower) price, plan to place a buy order, wait for a deal to open a position, and open a position at a limit price

근접 위치

strategy(title = "close long example", pyramiding = 2)                              // The number of orders placed in the same direction allowed by pyramiding
strategy.entry("long1", strategy.long, 0.1)                                         // Open a long position at the market price, specify the group label as long1
strategy.entry("long2", strategy.long, 0.1)                                         // Open a long position at the market price, specify the group label as long2
strategy.close("long1", when = strategy.position_size > 0.1, qty_percent = 50, comment = "close buy entry for 50%")   // To close a position, specify to close 50% of the positions whose group label is long1
strategy.close("long2", when = strategy.position_size > 0.1, qty_percent = 80, comment = "close buy entry for 80%")   // To close a position, specify to close 80% of the positions whose group label is long2

무역기제

PINE 언어의 위치 메커니즘은 일방적 위치와 유사합니다. 예를 들어, 긴 방향으로 포지션을 보유 할 때 (장장 위치), 판매 작업, 계획 된 주문, 기타 (포지션의 반대 방향으로) 경우 실행이 시작되며, 긴 방향으로의 포지션은 먼저 닫힐 것입니다. (모든 긴 포지션을 닫고), 그리고 트리거 된 명령을 실행합니다 (폐기 전 위치와 비교하여 반대 방향으로).

계획된 순서

주문 배치 명령을 사용하여 주문을 할 때, 가격이 지정되지 않으면 기본값은 시장 주문입니다. 시장 주문 외에도 주문을 할 때 즉시 작동하지 않는 계획 된 주문을 통해 주문을 할 수 있습니다. 계획 된 주문은 프로그램이 활성화되지 않을 때 계획 된 순서 대기열에 존재하며 상태 정보의 계획 된 주문 테이블 탭에서 볼 수 있습니다 (즉 전략이 실행되는 상태 표시줄)실제 주문/후기 테스트이 시스템은 실시간 시장 가격이 이러한 계획된 주문을 유발하는 조건을 충족시킬 때만 주문을 할 것입니다. 따라서 이러한 주문이 거래 가격에서 약간의 오차를 갖는 것은 정상입니다.strategy.entry주문을 할 수 있는 함수limit, stop arguments.

var isTrade = false 
if not barstate.ishistory and not isTrade
    isTrade := true 
    strategy.entry("test 1", strategy.long, 0.1, stop=close*1.3, comment="test 1 order")                     // stop
    strategy.entry("test 2", strategy.long, 0.2, limit=close*0.7, comment="test 2 order")                    // limit
    strategy.entry("test 3", strategy.short, 0.3, stop=close*0.6, limit=close*1.4, comment="test 3 order")   // stop-limit    
  • 제한 순서

    주문의 한계 가격을 설정합니다. 주문은 구매 주문 (즉,direction주장은strategy.long), 현재 시장 가격이 이 가격보다 낮을 때만 주문이 실행됩니다. 주문은 판매 주문 (즉,direction주장은strategy.short), 현재 시장 가격이 이 가격보다 높을 때만 주문이 실행됩니다.

  • 정지 명령

    주문의 스톱 로스 가격을 설정합니다. 주문이 구매 주문이라면, 현재 시장 가격이 이 가격보다 높을 때만 주문이 실행됩니다. 주문이 판매 주문인 경우, 시장의 현재 가격이 그 가격보다 낮을 경우에만 주문이 실행됩니다.

  • 정지 제한 명령

    limit그리고stop이 두 가지 조건은 동시에 설정될 수 있고, 조건이 먼저 충족되는 가격으로 주문이 트리거됩니다.

자기자본의 비율 순서

//@version=5
strategy("Percent of Equity Order", overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=100)  

// Simple moving average crossover strategy
longCondition = ta.crossover(ta.sma(close, 14), ta.sma(close, 28))
shortCondition = ta.crossunder(ta.sma(close, 14), ta.sma(close, 28))  

// If the moving average crossover condition is met, buy or sell
if (longCondition)
    strategy.entry("Long", strategy.long)  

if (shortCondition)
    strategy.entry("Short", strategy.short)
  

정한 후default_qty_type=strategy.percent_of_equity, 세트default_qty_value1은 1을 의미합니다. 주문 양은 계좌에 있는 통화 금액에 따라 계산됩니다. 예를 들어: 현재 계좌에 10,000 USDT가 있다면 1% 주문을 설정하는 것은 100 USDT의 규모로 주문을 하는 것을 의미합니다. (판매시 현재 가격에 기초하여 계산됩니다).

선언, 논리 구조 키워드

var

var는 변수를 할당하고 한번에 초기화하는 데 사용되는 키워드입니다. 일반적으로 키워드 var를 포함하지 않는 변수 할당 문법은 데이터가 업데이트 될 때마다 변수s 값이 덮여지는 것을 유발합니다. 반대로, 변수가 키워드 var를 사용하여 할당되면 데이터 업데이트에도 불구하고 상태를 유지할 수 있으며 if-expressions의 조건이 충족되면만 변경됩니다.

var variable_name = expression

설명:

  • variable_name- 파이인 스크립트에서 허용되는 사용자 변수의 모든 이름 (대문자와 소문자 라틴 문자, 숫자 및 하부자 (_) 를 포함 할 수 있지만 숫자로 시작할 수 없습니다.)
  • expression- 어떤 수학적 표현식도 정규 변수를 정의하는 것과 같습니다.

예제

// Var keyword example
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번째 녹색 바의 종료 가격을 포함합니다.

FMZ에서, 그것은 실시간 가격 모델과 폐쇄 가격 모델로 나뉘어 있습니다.var그리고varip.

strategy("test pine", "test 1", true) 

// Test var varip
var i = 0
varip ii = 0

// Print the i and ii changed in each round of the strategy logic on the graph
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)

// Each round of logic execution increments i and ii by 1
if true
    i := i + 1
    ii := ii + 1
  • 실시간 가격 모델 위의 테스트 코드는 두 단계로 실행됩니다: 1. 역사 int 표현 단계. 2. 실시간 int 표현 단계. 실시간 가격 모델에서 역사 int 표현 단계, 변수 i 및 ii는var, varip전략 코드 실행의 각 라운드에서 점진적으로 실행됩니다.if true따라서, 백테스트 결과의 int 표현식 BAR에 표시된 숫자가 1으로 하나씩 증가하는 것을 볼 수 있습니다. 역사적인 int 표현식 단계가 끝나면 실시간 int 표현식 단계가 시작됩니다.var, varip선언 변수들은 다르게 변하기 시작합니다. 그것은 실시간 가격 모델이기 때문에, 전략 코드는 int 표현식 BAR의 각 가격 변화에 대해 한 번 실행됩니다.i := i + 1그리고ii := ii + 1i는 매번 수정된다. i도 매번 수정되지만, 전략 논리가 다음 라운드에서 실행될 때 이전 값은 복원되며, 현재 int 표현 BAR가 완료될 때까지 i의 값은 업데이트되지 않습니다 (즉, 전략 논리가 다음 라운드에서 실행될 때 이전 값은 복원되지 않습니다). 따라서 변수 i는 여전히 각 BAR에 대해 1로 증가하는 것을 볼 수 있습니다. 그러나 변수 ii는 각 BAR에 대해 여러 번 축적됩니다.

  • 종료 가격 모델 닫기 가격 모델은 int 표현식 BAR에 한 번만 전략 논리를 실행하기 때문에 사라졌다. 그래서 변수var그리고varip위의 예제에서 닫기 가격 모델에서 정확히 동일한 증가율을 나타냅니다. 역사적인 int 표현 단계와 실시간 int 표현 단계 모두에서 int 표현 BAR에 1씩 증가합니다.

다양성

varp (var intrabar persist) 는 변수를 할당하고 한 번 초기화하는 데 사용되는 키워드이다. var 키워드와 유사하지만 varp로 선언된 변수는 라이브 촛불 업데이트 사이 값을 유지한다.

varip variable_name = expression

설명:

  • variable_name- 파인 스크립트에서 허용되는 사용자 변수의 모든 이름 (대문자와 소문자를 포함 할 수 있습니다. 라틴 문자, 숫자, 하부 표시 (_), 그러나 숫자로 시작할 수 없습니다.)
  • expression- 정규 변수를 정의하는 시간과 같은 어떤 수학적 표현식. 첫 번째 K-라인 바에서, 표현식은 평가되고 변수에 한 번만 할당됩니다.

예제

// varip
varip int v = -1
v := v + 1
plot(v)

var를 사용할 때, 그래프는 bar_index의 값을 반환합니다. varip와 함께, 동일한 행동은 역사 바에서 발생하지만, 라이브 바에서 차트는 각 틱에 대해 하나씩 증가하는 값을 반환합니다.

언급float, int, bool, string, 그리고 이러한 타입의 배열과 같은 간단한 타입에서만 사용할 수 있습니다.

사실

bool 변수의 값, 또는 표현식이 bool 변수를 사용할 때 계산할 수 있는 값을 나타냅니다.비교또는논리적 operator.

언급설명 참조하십시오비교사업자 및논리적이죠 Operators.

또한 참조 bool

거짓

bool 변수의 값과 비교 연산과 논리 연산의 결과를 나타냅니다.

언급설명 참조하십시오비교사업자 및논리적이죠 Operators.

또한 참조 bool

만약

If 명령어는 표현식의 조건이 충족되면 실행되어야하는 명령어 블록을 정의합니다. 파이프 스크립트 언어의 버전 4에서는 else if 문법을 사용할 수 있습니다.

유니버설 코드:

var_declarationX = if condition
    var_decl_then0
    var_decl_then1
    ...
    var_decl_thenN
    return_expression_then
else if [optional block]
    var_decl_else0
    var_decl_else1
    ...
  var_decl_elseN
  return_expression_else
else
    var_decl_else0
    var_decl_else1
    ...
    var_decl_elseN
    return_expression_else

언급 var_declarationX- 이 변수는 if 명령어의 값을 얻습니다condition- 조건이 사실이라면, 명령어 블록의 논리는then사용되고 있습니다 (var_decl_then0, var_decl_then1만약 조건이 거짓이라면, 명령어 블록의 논리는else if또는else사용되고 있습니다 (var_decl_else0, var_decl_else1, 등).return_expression_then그리고return_expression_else- 모듈의 마지막 표현식 또는 else 블록의 표현식은 명령어의 최종 값을 반환합니다. 변수가 마지막으로 선언된 경우 그 값은 결과 값입니다.

if 명령어의 반환 값의 종류는return_expression_then그리고return_expression_else. 트레이딩뷰에서 실행할 때, 그들의 유형이 일치해야 합니다: else 블록에서 문자열 값을 가질 때, 해당 블록에서 정수 값을 반환할 수 없습니다. FMZ에서 실행할 때, 다음 예제는 오류를 보고하지 않습니다. y 값이 open일 때, 도면 때 플롯의 값은 n/a입니다.

예제

// This code compiles
x = if close > open
    close
else
    open  

// This code doesn't compile by trading view
// y = if close > open
//     close
// else
//     "open"
plot(x)

else이 경우 조건이 false라면 var_declarationX 변수에는 empty 값 (na, false, 또는 ) 이 부여됩니다.

예제

// if
x = if close > open
    close
// If current close > current open, then x = close.
// Otherwise the x = na.
plot(x)

여러 개의 else if 블록이 사용되거나 전혀 사용할 수 있습니다. then, else if, else 블록은 네 개의 공간으로 이동됩니다.

예제

// if
x = if open > close
    5
else if high > low
    close
else
    open
plot(x)

그 결과 값은if표현식의 부작용이 필요한 경우 유용할 수 있습니다. 예를 들어 전략 거래에서:

예제

if (ta.crossover(high, low))
    strategy.entry("BBandLE", strategy.long, stop=low)
else
    strategy.cancel(id="BBandLE")

만약 명령어들이 서로 포함될 수 있다면:

예제

// if
float x = na
if close > open
    if close > close[1]
        x := close
    else
        x := close[1]
else
    x := open
plot(x)

에 대해

for 구조는 여러 명령어를 반복적으로 실행할 수 있습니다.

[var_declaration =] for counter = from_num to to_num [by step_num]
    statements | continue | break
    return_expression

var_declaration- 루프의 return_expression의 값으로 할당되는 선택적 변수 선언.counter- 루프 카운터 값을 유지하는 변수, 루프의 각 반복에서 1 또는 step_num 값을 증가 / 감소.from_num- 카운터의 시작 값. series int/float 값/표현은 허용됩니다.to_num- 카운터의 최종 값. 카운터가 to_num보다 크거나 to_num > to_num의 경우 to_num보다 작을 때 루프는 끊어집니다. series int/float 값/표현은 허용되지만 루프의 첫 번째 반복에서만 평가됩니다.step_num- 카운터의 인크리멘트/디크레멘트 값. 선택 사항입니다. 기본값은 from_num 또는 to_num의 최대에 따라 +1 또는 -1입니다. 값을 사용할 때 카운터는 또한 from_num 또는 to_num의 최대에 따라 인크리멘트/디크레멘트됩니다. 따라서 step_num의 +/- 기호는 선택 사항입니다.statements | continue | break- 4개의 빈자 또는 하나의 탭으로 continue 또는 break 키워드를 입력한return_expression- 루프의 반환 값은 존재한다면 var_declaration의 변수에 할당됩니다. 루프가 continue 또는 break 키워드 때문에 종료되면 루프의 반환 값은 루프 종료 전에 값을 할당 한 마지막 변수의 반환 값입니다.continue루프에서만 사용할 수 있는 키워드입니다. 루프의 다음 반복이 실행되도록 합니다.break- 루프에서 빠져나가는 키워드

예제

// Here, we count the quantity of bars in a given 'lookback' length which closed above the current bar's close
qtyOfHigherCloses(lookback) =>
    int result = 0
    for i = 1 to lookback
        if close[i] > close
            result += 1
    result
plot(qtyOfHigherCloses(14))

또한 참조 for...in while

내... 내

for...inconstruct는 배열의 각 요소에 대해 여러 개의 문장을 반복할 수 있습니다. 이 문서는array_element, 또는 두 개의 논증으로:[index, array_element]. 두 번째 형태는 루프의 기능에 영향을 미치지 않습니다. 그것은 튜플의 첫 번째 변수에서 현재 반복의 인덱스를 추적합니다.

[var_declaration =] for array_element in array_id
    statements | continue | break
    return_expression

[var_declaration =] for [index, array_element] in array_id
    statements | continue | break
    return_expression

var_declaration- 루프의 값을 할당하는 선택적 변수 선언return_expression. index- 현재 반복 인덱스를 추적하는 선택적 변수. 인덱스는 0에서 시작합니다. 변수는 루프 몸 내에서 변하지 않습니다. 사용되면 또한 포함 된 튜플에 포함되어야합니다.array_element. array_element- 루프에서 처리해야 할 각각의 연속 배열 요소를 포함하는 변수. 이 변수는 루프 몸 안에서 변하지 않습니다.array_id- 루프 반복의 배열 ID.statements | continue | break- 4개의 빈자 또는 하나의 탭으로 continue 또는 break 키워드를 입력한return_expression- 루프의 반환 값은var_declarationcontinue 또는 break 키워드 때문에 루프가 종료되는 경우, 루프의 반환 값은 루프가 종료되기 전에 마지막으로 할당된 변수입니다.continue루프에서만 사용할 수 있는 키워드입니다. 루프의 다음 반복이 실행되도록 합니다.break- 루프에서 빠져나가는 키워드

배열의 요소나 그 크기를 루프 내에서 수정할 수 있습니다. 여기서는 1개항을 사용해서for...in각 바에 대한 OHLC 값이 close 값의 SMA보다 많은 바의 수를 결정하기 위해:

예제

// Here we determine on each bar how many of the bar's OHLC values are greater than the SMA of 'close' values
float[ ] ohlcValues = array.from(open, high, low, close)
qtyGreaterThan(value, array) =>
    int result = 0
    for currentElement in array
        if currentElement > value
            result += 1
        result
plot(qtyGreaterThan(ta.sma(close, 20), ohlcValues))

여기, 우리는 두 개의 논증의 형태를 사용 합니다 for...inisPos배열로true우리의 대응 값에valuesArray배열은 양수입니다.

예제

// for...in
var valuesArray = array.from(4, -8, 11, 78, -16, 34, 7, 99, 0, 55)
var isPos = array.new_bool(10, false)  

for [index, value] in valuesArray
    if value > 0
        array.set(isPos, index, true)  

if barstate.islastconfirmedhistory
    runtime.log(str.tostring(isPos))

또한 참조 for while array.sum array.min array.max

한동안

while이 문서는 네이티브 코드 블록의 조건부 반복을 허용합니다.

variable_declaration = while boolean_expression
    ...
    continue
    ...
    break
    ...
    return_expression

설명:variable_declaration- 선택적 변수 선언return expression이 변수의 초기화 값을 제공할 수 있습니다.boolean_expression- 만약 사실이라면, 로컬 블록을 실행while만약 사실이 아니라면 스크립트 실행은while statement. continue- 그...continue키워드는 루프를 다음 반복으로 갈라지게 합니다.break- 그...break키워드는 루프를 종료합니다. 스크립트 실행은 종료 후 다시 시작됩니다.while statement. return_expression- 선택적 라인while statement.

예제

// This is a simple example of calculating a factorial using a while loop.
int i_n = input.int(10, "Factorial Size", minval=0)
int counter   = i_n
int factorial = 1
while counter > 0
    factorial := factorial * counter
    counter   := counter - 1

plot(factorial)

언급초기 다음 네이티브 코드 블록while라인은 4개의 간격 또는 탭으로 간격되어야 합니다.while루프, 다음의 부울 표현식while결국 거짓이 될 수 있어야 합니다.break실행되어야 합니다.

전환

스위치 운영자는 조건과 표현식의 값을 기반으로 여러 명령어 중 하나에 컨트롤을 전송합니다.

[variable_declaration = ] switch expression
    value1 => local_block
    value2 => local_block
    ...
    => default_local_block

[variable_declaration = ] switch
    boolean_expression1 => local_block
    boolean_expression2 => local_block
    ...
    => default_local_block

표현식과 함께 전환:

예제

// Switch using an expression

string i_maType = input.string("EMA", "MA type", options = ["EMA", "SMA", "RMA", "WMA"])

float ma = switch i_maType
    "EMA" => ta.ema(close, 10)
    "SMA" => ta.sma(close, 10)
    "RMA" => ta.rma(close, 10)
    // Default used when the three first cases do not match.
    => ta.wma(close, 10)

plot(ma)

표현 없이 전환:

예제

strategy("Switch without an expression", overlay = true)

bool longCondition  = ta.crossover( ta.sma(close, 14), ta.sma(close, 28))
bool shortCondition = ta.crossunder(ta.sma(close, 14), ta.sma(close, 28))

switch
    longCondition  => strategy.entry("Long ID", strategy.long)
    shortCondition => strategy.entry("Short ID", strategy.short)

반환실행된 로컬 명령어 블록의 마지막 표현식의 값.

언급오직 하나만local_block사례 또는default_local_block실행될 수 있습니다.default_local_block이 제품은=>태그, 그리고 단지 전 블록이 실행되지 않는 경우에 실행됩니다.switch문장은 변수에 할당되고default_local_block표시가 되지 않으면, 명령어는 반환됩니다na만약local_block실행되지 않습니다. a의 결과를 할당 할 때switch변수에 대한 문장, 모든local_block인스턴스는 같은 타입의 값을 반환해야 합니다.

또한 참조 if ?:

시리즈

일련은 데이터 시리즈 유형을 나타내는 키워드입니다.series keyword.

운영자

=

변수에 값을 할당하는데 사용되는데 변수가 선언될 때만 사용된다 (처음 사용)

:=

할당 연산자는 왼쪽 변수에 값을 할당합니다. 이전에 선언된 변수에 값을 할당하는 데 사용됩니다.

!=

모든 종류의 표현식에 적용됩니다.

expr1 != expr2

반환부엘 값, 또는 부엘 값의 연속

%

모두로 (진수 잔치) 숫자 표현식에 적용됩니다.

expr1 % expr2

반환정수 또는 부동 값, 또는 일련의 값.

언급파인 스크립트에서 정수 나머지가 계산될 때, 분수는 절단, 즉 가장 낮은 절대값으로 둥글게 된다. 그 결과 값은 배당과 같은 기호를 가질 것이다.

예제: -1 % 9 = -1 - 9 * 줄여진(-1/9) = -1 - 9 * 줄여진(-0.111) = -1 - 9 * 0 = -1.

%=

모두로 할당. 숫자 표현식에 적용됩니다.

expr1 %= expr2

예제

// Equals to expr1 = expr1 % expr2.
a = 3
b = 3
a %= b
// Result: a = 0.
plot(a)

반환정수 또는 부동 값, 또는 일련의 값.

*

곱셈 할당. 숫자 표현식에 적용됩니다.

expr1 * expr2

반환정수 또는 부동 값, 또는 일련의 값.

*=

곱셈 할당. 숫자 표현식에 적용됩니다.

expr1 *= expr2

예제

// Equals to expr1 = expr1 * expr2.
a = 2
b = 3
a *= b
// Result: a = 6.
plot(a)

반환정수 또는 부동 값, 또는 일련의 값.

+

덧셈 또는 유너리 플러스. 숫자 표현식이나 문자열에 적용됩니다.

expr1 + expr2
+ expr

반환바이너리+문자열의 expr1과 expr2의 조합을 반환 Number 는 정수 또는 변함수 값 또는 값의 연속을 반환합니다. 이진 +은 expr1 더하기 expr2를 반환합니다. 유너리 +는 expr를 반환합니다 (유너리 연산자 대칭에 아무것도 추가되지 않습니다).

언급수학적 연산자는 숫자와 함께 일련 변수와 함께 사용할 수 있습니다. 일련의 경우 연산자는 요소별로 적용됩니다.

+=

덧셈 할당. 숫자 표현식이나 문자열에 적용됩니다.

expr1 += expr2

예제

// Equals to expr1 = expr1 + expr2.
a = 2
b = 3
a += b
// Result: a = 5.
plot(a)

반환문자열의 경우, expr1과 expr2의 연쇄를 반환합니다. 숫자의 경우, 정수 또는 부동 값 또는 값의 일련을 반환합니다.

언급수학적 연산자는 숫자와 함께 일련 변수와 함께 사용할 수 있습니다. 일련의 경우 연산자는 요소별로 적용됩니다.

-

빼기 또는 유너리 마이너스 숫자 표현식에 적용됩니다.

expr1 - expr2
- expr

반환정수 또는 부동 소수점 값 또는 값 시리즈를 반환합니다: 이진 +은 expr1 빼기 expr2를 반환합니다. 유나리-expr의 부정값을 반환합니다

언급수학적 연산자는 숫자뿐만 아니라 일련 변수와 함께 사용할 수 있습니다. 시리즈와 함께 사용하는 경우 연산자는 요소별로 적용됩니다.

-=

빼기 할당. 숫자 표현식에 적용됩니다.

expr1 -= expr2

예제

// Equals to expr1 = expr1 - expr2.
a = 2
b = 3
a -= b
// Result: a = -1.
plot(a)

반환정수 또는 부동 값, 또는 일련의 값.

/

분할 할당. 숫자 표현식에 적용됩니다.

expr1 / expr2

반환정수 또는 부동 값, 또는 일련의 값.

/=

분할 할당. 숫자 표현식에 적용됩니다.

expr1 /= expr2

예제

// Equals to expr1 = expr1 / expr2.
a = 3
b = 3
a /= b
// Result: a = 1.
plot(a)

반환정수 또는 부동 값, 또는 일련의 값.

<

그보다 작습니다. 숫자 표현식에 적용됩니다.

expr1 < expr2

반환부엘 값, 또는 부엘 값의 일련

<=

이보다 작거나 같고 숫자 표현식에 적용됩니다.

expr1 <= expr2

반환부엘 값, 또는 부엘 값의 일련

==

어떤 종류의 표현식에도 적용됩니다.

expr1 == expr2

반환부엘 값, 또는 부엘 값의 일련

=>

=> 연산자는 사용자 정의 함수 선언과switch statements.

함수 선언 문법은 다음과 같습니다.

<identifier>([<argument_name>[=<default_value>]], ...) =>
    <local_block>
    <function_result>

A<local_block>0개 이상의 파이인 스크립트 명령어입니다.<function_result>변수, 표현식, 또는 튜플입니다.

예제

// single-line function
f1(x, y) => x + y
// multi-line function
f2(x, y) => 
    sum = x + y
    sumChange = ta.change(sum, 10)
    // Function automatically returns the last expression used in it
plot(f1(30, 8) + f2(1, 3))

언급사용자 정의 함수에 대해 더 많은 것을 알 수 있습니다. 사용자 설명서 페이지에서 선언 함수 및 스크립트 라이브러리.

>

그보다 크다. 숫자 표현식에 적용된다.

expr1 > expr2

반환부엘 값, 또는 부엘 값의 일련

>=

더 크거나 같거나 숫자 표현식에 적용됩니다.

expr1 >= expr2

반환부엘 값, 또는 부엘 값의 일련

?:

세차 조건 연산자

expr1 ? expr2 : expr3

예제

// Draw circles at the bars where open crosses close
s2 = ta.cross(open, close) ? math.avg(open,close) : na
plot(s2, style=plot.style_circles, linewidth=2, color=color.red)  

// Combination of ?: operators for 'switch'-like logic
c = timeframe.isintraday ? color.red : timeframe.isdaily ? color.green : timeframe.isweekly ? color.blue : color.gray
plot(hl2, color=c)

반환expr2는 expr1이 true로 평가되면 expr3는 그렇지 않으면 true로 평가됩니다. 제로 값 (0과 또한 NaN, +Infinity, -Infinity) 은 거짓으로 간주되며 다른 값은 true입니다.

언급필요없으면 else 지점을 위해 na를 사용하세요. 두 개 이상의?: 연산자를 결합하여 스위치 같은 문장을 얻을 수 있습니다 (위 예제 참조). 수학적 연산자는 숫자와 함께 일련 변수와 함께 사용할 수 있습니다. 일련의 경우 연산자는 요소별로 적용됩니다.

또한 참조 na

[]

시리즈 서브스크립트. 시리즈 expr1의 이전 값에 액세스 할 수 있습니다. expr2는 과거에 바의 수이며 숫자가어야합니다. 부동는 아래로 둥글게됩니다.

expr1[expr2]

예제

// [] can be used to "save" variable value between bars
a = 0.0 // declare `a`
a := a[1] // immediately set current value to the same as previous. `na` in the beginning of history
if high == low // if some condition - change `a` value to another
    a := low
plot(a)

반환일련의 가치들

또한 참조 math.floor

그리고

논리적 AND. 부울 표현식에도 적용됩니다.

expr1 and expr2

반환부엘 값, 또는 부엘 값의 일련

또는

논리적 OR. 부울 표현식에 적용됩니다.

expr1 or expr2

반환부엘 값, 또는 부엘 값의 일련

아니

논리적 부정 (NOT) 부울 표현식에 적용됩니다.

not expr1

반환부엘 값, 또는 부엘 값의 일련

데이터 타입 키워드

bool

변수 또는 논리의 bool (boolean) 유형을 명시적으로 선언하는 키워드. Bool 변수는 true, false 또는 na 값을 가질 수 있습니다.

예제

// bool
bool b = true    // Same as `b = true`
b := na
plot(b ? open : close)

언급변수 선언에서 유형을 명시적으로 언급하는 것은 선택 사항이며, na로 초기화되는 경우를 제외하고는 선택 사항입니다. 타입 시스템에서 사용자 설명서 페이지에서 파이인 스크립트 유형에 대해 자세히 알아보십시오.

또한 참조 var varip int float color string true false

int

키워드 변수 또는 논리의 int (전수) 타입을 명시적으로 선언하는 데 사용됩니다.

예제

// int
int i = 14    // Same as `i = 14`
i := na
plot(i)

언급변수 선언에서 유형을 명시적으로 언급하는 것은 선택 사항이며, na로 초기화되는 경우를 제외하고는 선택 사항입니다. 타입 시스템에서 사용자 설명서 페이지에서 파이인 스크립트 유형에 대해 자세히 알아보십시오.

또한 참조 var varip float bool color string

플라트

변수 또는 논리의 float (floating point) 타입을 명시적으로 선언하는 키워드.

예제

// float
float f = 3.14    // Same as `f = 3.14`
f := na
plot(f)

언급변수 선언에서 타입을 명시적으로 언급하는 것은 선택적입니다.

또한 참조 var varip int bool color string

문자열

변수 또는 논리의 string 타입을 명시적으로 선언하는 키워드

예제

// string
string s = "Hello World!"    // Same as `s = "Hello world!"`
// string s = na // same as "" 
plot(na, title=s)

언급변수 선언에서 유형을 명시적으로 언급하는 것은 선택 사항이며, na로 초기화되는 경우를 제외하고는 선택 사항입니다. 타입 시스템에서 사용자 설명서 페이지에서 파이인 스크립트 유형에 대해 자세히 알아보십시오.

또한 참조 var varip int float bool str.tostring str.format

색상

키워드 변수 또는 논리의 color 타입을 명시적으로 선언하는 데 사용됩니다.

예제

// color
color textColor = color.green
if barstate.islastconfirmedhistory
    runtime.log("test", textcolor = textColor)

언급컬러 리터럴은 다음과 같은 형식을 가지고 있다: #RRGGBB 또는 #RRGGBBAA. 문자 쌍은 00에서 FF의 열다섯 자리 값을 (0에서 255까지 십자수) 나타냅니다. 여기서 RR, GG 및 BB 쌍은 색의 빨간색, 녹색 및 파란색 구성 요소의 값입니다. AA는 색의 투명성 (또는 알파 구성 요소) 의 선택 값입니다. 00은 보이지 않으며 FF는 불투명합니다. AA 쌍이 제공되지 않을 때 FF가 사용됩니다. 열다섯 자리 글자는 상자 또는 소자수가 될 수 있습니다.

변수 선언에서 유형을 명시적으로 언급하는 것은 선택 사항이며, na로 초기화되는 경우를 제외하고는 선택 사항입니다. 타입 시스템에서 사용자 설명서 페이지에서 파이인 스크립트 유형에 대해 자세히 알아보십시오.

또한 참조 var varip int float string color.rgb color.new

배열

변수 또는 논리의 array 타입을 명시적으로 선언하는 키워드array.new<type>, array.from function.

예제

// array
array<float> a = na
a := array.new<float>(1, close)
plot(array.get(a, 0))

언급배열 객체는 항상 series 형태입니다.

또한 참조 var array.new array.from

물체

PINE 언어의 객체는 사용자 정의 타입 (UDT) 의 인스턴스이며, 이는 사용자가 엔티티의 다른 값을 조직하기 위한 전략에서 사용자 정의 타입을 만들 수 있는 방법 없는 클래스로 이해될 수 있다.

종류 정의

주문 정보를 저장하기 위해 주문 유형을 정의하자:

type order
    float price
    float amount
    string symbol
  • 타입은type keyword.
  • 타입 키워드는 타입 이름으로 이어집니다.
  • 첫 번째 라인 타입은 타입 이름을 정의하고, 네 개의 간격을 뚫고, 타입에 포함된 필드를 정의합니다.
  • 각 필드는 int, float, string 같은 데이터 타입을 선언해야 합니다.

객체를 만드는 것

표시된 타입을 사용하여new()객체를 만드는 함수:

order1 = order.new()
order1 = order.new(100, 0.1, "BTC_USDT")
order1 = order.new(amount = 0.1, symbol = "BTC_USDT", price = 100)

또한 빈 객체를 만들 수 있습니다:

order order1 = na

실제 사례를 살펴보겠습니다.

type order
    float price
    float amount
    string symbol

if strategy.position_size == 0 and open > close
    strategy.entry("long", strategy.long, 1)

order1 = order.new(strategy.opentrades.entry_price(strategy.opentrades - 1), strategy.opentrades.size(strategy.opentrades - 1), syminfo.ticker)
// runtime.log(order1)   // Output {"data":{"price":46002.8,"amount":1,"symbol":"swap"},"_meta":0,"_type":"order"}

이 예에서:

order1 = order.new(strategy.opentrades.entry_price(strategy.opentrades - 1), strategy.opentrades.size(strategy.opentrades - 1), syminfo.ticker)

이렇게 쓸 수도 있습니다.

order order1 = na
order1 := order.new(strategy.opentrades.entry_price(strategy.opentrades - 1), strategy.opentrades.size(strategy.opentrades - 1), syminfo.ticker)

var 키워드 사용에 대한 객체 타입

//@version=5
indicator("Objects using `var` demo")

//@type A custom type to hold index, price, and volume information.
type BarInfo
    int   index = bar_index
    float price = close
    float vol   = volume

//@variable A `BarInfo` instance whose fields persist through all iterations, starting from the first bar.
var BarInfo firstBar = BarInfo.new()
//@variable A `BarInfo` instance declared on every bar.
BarInfo currentBar = BarInfo.new()

// Plot the `index` fields of both instances to compare the difference.
plot(firstBar.index, "firstBar")
plot(currentBar.index, "currentBar")

var 키워드를 사용하여 사용자 정의 타입의 객체에 할당된 변수를 선언할 때, 키워드는 자동으로 객체의 모든 필드에 적용됩니다. 이것은 var 키워드를 통해 선언된 객체가 각 반복 사이에 필드 값을 다시 초기화 할 필요없이 상태를 유지할 것이라는 것을 의미합니다.

  • firstBar 객체는 var 키워드를 사용하여 선언되므로 그 필드 (인덱스, 가격, 볼륨) 는 첫 항목에서 시작하여 마지막 항목으로 끝나는 각 반복에서 값을 유지할 것입니다.
  • currentBar 객체는 var 키워드로 선언되지 않으므로 각 항목에 해당 필드가 다시 초기화되며, 반복마다 새로운 객체가 있습니다.

두 개체의 인덱스 필드를 그래프화하면 그 사이의 차이를 비교할 수 있습니다. firstBar.index는 각 반복에서 이전에 설정된 값을 유지하며, currentBar.index는 현재 항목의 bar_index 값으로 각 반복에서 다시 초기화됩니다.

varip 키워드를 사용하는 객체 타입

//@version=5
indicator("Objects using `varip` fields demo")

//@type A custom type that counts the bars and ticks in the script's execution.
type Counter
    int       bars  = 0
    varip int ticks = 0

//@variable A `Counter` object whose reference persists throughout all bars.
var Counter counter = Counter.new()

// Add 1 to the `bars` and `ticks` fields. The `ticks` field is not subject to rollback on unconfirmed bars.
counter.bars  += 1
counter.ticks += 1

// Plot both fields for comparison.
plot(counter.bars, "Bar counter", color.blue, 3)
plot(counter.ticks, "Tick counter", color.purple, 3)

파인에서는 varip 키워드를 사용하여 스크립트 실행 내내 객체의 필드가 지속되고 확인되지 않은 바에 되돌리지 않는다는 것을 나타냅니다. 카운터 타입의 선언에서, bars 필드는 varip 키워드를 사용하지 않으므로 확인되지 않은 모든 바에 대해 다시 롤링합니다. ticks 필드는 varip 키워드를 사용합니다. 따라서 확인되지 않은 바에 대해 다시 롤링하지 않습니다. 카운터 객체는 var 키워드를 사용하여 선언되므로 스크립트 실행 내내 지속됩니다. 각 반복에서 바 필드와 틱 필드 모두 1으로 증가합니다. 바 필드는 확인되지 않은 각 바에 다시 롤되며 틱 필드는 다시 롤되지 않습니다. 마지막으로, counter.bars와 counter.ticks 필드를 그래프화하면 그 사이의 차이를 비교할 수 있습니다. counter.bars의 값은 확인되지 않은 각 바에 다시 롤되며, counter.ticks의 값은 스크립트 실행이 끝날 때까지 계속 증가합니다.


더 많은

구걸자왜 전략 광장 복제 피인 전략이 현실화되지 않는지

발명가들의 수량화 - 작은 꿈자, 우리는 그것을 확인합니다.

구걸자의 최적화된 트렌드 트래커

발명가들의 수량화 - 작은 꿈안녕하세요, 구체적으로 어떤 전략이 있을까요?