FMZ PINE Script documentation is provided.

Author: The Little Dream, Created: 2022-05-06 14:27:06, Updated: 2024-02-23 15:36:48

[TOC]

Keywords, grammar, setting up a profile

Code structure

The general structure of the code in Pine is:

<version>
<declaration_statement>
<code>

Notes

FMZ's Pine language supported annotation symbols: single line annotation//This is the first time I've seen it./* */For example, the following examples of commentary spelling:

[macdLine, signalLine, histLine] = ta.macd(close, 12, 26, 9)  // 计算MACD指标

/*
plot函数在图表上画出指标线
*/
plot(macdLine, color = color.blue, title='macdLine')
plot(signalLine, color = color.orange, title='signalLine')
plot(histLine, color = color.red, title='histLine')

The version

A compiler instruction in the following form tells the compiler which version of Pine the script is written in:

//@version=5

The default version is v5, which can be omitted from the code.//@version=5

Statement of purpose

  • indicator()
  • strategy()

Statements define the type of script, which in turn determines what content is allowed in it, and how it is used and executed. Sets the key attributes of the script, such as its name, where it will appear when it is added to the chart, the precision and format of the values it displays, and controls certain values of its behavior at runtime, such as the maximum number of drawing objects it will display in the chart. For a policy, the attributes include parameters that control retrieval, such as initial capital, commissions, slippage points, etc. FMZ's Pine does not require a policy code to includeindicator()Orstrategy()The statement is as follows:

The Code

A line in a script that is not a comment or a compiler instruction is a statement that implements the script's algorithm. A statement can be one of these.

  • Variable declaration
  • Reassignment of variables
  • The function declaration
  • Built-in function calls, user defined function calls
  • ifforwhileorswitchand so on.

Sentences can be arranged in many ways.

  • Some statements can be expressed in a single line, such as most variable declarations, which contain only one function call line, or single-line function declarations; others, like structures, always require multiple lines because they require a local block.
  • The global statements of the script (i.e. the parts that do not belong to the sub-block) cannot be used to describe the entire script.空格or制表符(tab key) start. Their first character must also be the first character of the line. A line that starts at the first position in the line is, by definition, part of the global scope of the script.
  • A structure or multi-line function statement always requires alocal blockA local block must be compressed into a semicolon or four spaces (otherwise, it will be parsed as the serial code of the previous line, i.e. determined to be the continuous content of the previous line of code), and each local block defines a different local range.
  • Multiple single-line statements can be connected in a single line by using the comma ((,) as a separator.
  • A line can contain a commentary or just a commentary.
  • A line can also be wrapped (continue on multiple lines).

For example, include three local blocks, one in a custom function declaration, two in a variable declaration using an if structure, code as follows:

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

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

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

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

Change the code

Long rows can be split into multiple rows, or "wrapped" up. The wrapped row must compress any number of spaces, as long as it is not a multiple of 4 (these boundaries are used to compress local blocks).

a = open + high + low + close

It can be packaged as (note that the number of spaces that are compressed per line is not a multiple of 4):

a = open +
      high +
          low +
             close

A long plot ((()) call can be wrapped up in a.

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)

Statements in user-defined function declarations can also be wrapped. However, since the local block must syntactically start with a contraction (four spaces or one check mark), when dividing it into the next line, the continuation of the statement must start with more than one contraction (not equal to a multiple of four spaces). For example:

test(c, o) =>
    ret = c > o ?
       (c > o+5000 ? 
          1 :
              0):
       (c < o-5000 ? 
          -1 : 
              0)

a = test(close, open)
plot(a, title="a")

Time series

Time series is not a data type or format, but a basic structure concept in the PINE language. It is used to store values that change continuously over time, each value corresponding to a point in time. The structure of this concept is well suited for processing and recording a series of data that changes over time. with built-in variablesopenFor example,openThe built-in variable records the opening price of each K-line BAR, if thisopenSo this is the data for the five-minute K-line cycle.openWhat is recorded in the variable is the opening price of the K-line BAR (column) every 5 minutes.openThis refers to the opening price of the current location of the K-line BAR. To refer to the previous value in the time sequence (past value), we use[]The history operator, when a policy is executed on a certain K-line BAR, is used to display the policy.open[1]This means that the opening price of the previous K line BAR of the current K line BAR is referenced.

AlthoughTime seriesIt's easy to think of data structures as "array", although the PINE language also has array types.

The PINE language designed time sequences in this way to calculate the cumulative value of the closing price in the strategy code very easily, and without the need to use loop structures such as for, just using the built-in functions of the PINE language.ta.cum(close)To give another example, we need to calculate the average of the maximum price and minimum price difference of the last 14 K-string BAR (i.e. the 14 K-string BAR closest to the current moment of execution of the code) which can be written as:ta.sma(high - low, 14)

The result of calling a function on a time sequence also leaves a trace on the time sequence.[]The historical operator refers to the previous value. For example, we can write that the closing price of the current K-line BAR exceeds the maximum value of the highest price in the last 10 K-line BARs (excluding the current K-line BAR).breach = close > ta.highest(close, 10)[1]It can also be written asbreach = close > ta.highest(close[1], 10)So what?ta.highest(close, 10)[1]andta.highest(close[1], 10)It's not just a question of time.

The following code can be used to verify:

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)

The above test code outputs a and b on each BAR with their corresponding values in the time series, and it can be seen that a and b are always equal, so the two representation methods are equivalent.

Template parameters for the Pine language transaction library

The built-in template for the PINE policy, "Pine language transaction library", has parametric settings.

Settings for transactions

  • How to execute Closing price model: The model is executed at the end of the current BAR and executes the transaction at the beginning of the lower root BAR. Real-time price model: The model is executed every time the price changes, with signals to execute the transaction immediately.
  • Default number of open positions: If the trading instruction does not specify the number of trades, the number of trades executed according to this setting;
  • Maximum number of orders per transaction: based on the actual discount, in combination with this parameter setting, determine the maximum number of orders per transaction to avoid impacting the discount.
  • The number of price points:定价货币精度Parameters and this parameter determine the slippage price when the order is placed. For example, if the pricing currency precision is set to 2, i.e. precise to the second decimal place, precise to 0.01 then the slippage point number represents 0.01 of each pricing unit.
  • The number of longest cycles of the variable: affects the number of K-line BARs in the graph, withjavascriptCalls in policySetMaxBarLenThe function works the same way.

Futures options

  • Variety codes: Contract codes, which are only required when the exchange object is a non-cash exchange object.
  • Minimum number of contracts: the minimum amount of contracts traded when the order is placed.

The real disk option

  • Auto-reset progress: Auto-reset to the state before the last policy was stopped.
  • Order retry number: The order is not executed and the order is cancelled and the order is retried. This parameter is used to limit the maximum number of retries.
  • Network query interval ((milliseconds): valid only for the REST protocol, control the network request interval, avoid requests that are too frequent and exceed the limits of the exchange.
  • Account synchronization time ((seconds): The time period for synchronizing account data.
  • Post-opening position synchronization time (milliseconds): Only for repeated openings caused by data delays on some exchanges, setting the synchronization time to be larger can mitigate such problems.
  • Leverage multiplier: Set the leverage multiplier.

Cash transactions, other settings

  • One-handed transaction volume: The default one-handed transaction volume is only valid for spot transactions.
  • Minimum trading volume: Minimum trading volume is the minimum amount of transactions.
  • Price accuracy: Price accuracy, i.e. the small number of digits of the price.
  • Transaction variety accuracy: the precision of the next unit, i.e. the small number of digits of the next unit.
  • Fee: 0.002 is 2 parts per thousand for some data calculated according to this setting.
  • Gain-loss statistics interval: only on the physical disk shows the use of gain-loss statistics.
  • Failed retry (millisecond): Interval of retry when network request fails.
  • Use of proxies: valid only for the REST protocol.
  • Hide common network errors: Hide common error logs in the log area.
  • Switch base addresses: valid only for the REST protocol.
  • Push notifications: Push messages to the inbox etc.

Subscribe

Opening of the market

strategy(title = "open long example", pyramiding = 3)                                // pyramiding 允许的同方向下单的次数
strategy.entry("long1", strategy.long, 0.01)                                         // 市价开多仓,指定分组标签为long1
strategy.entry("long2", strategy.long, 0.02, when = close > ta.ema(close, 10))       // 条件触发,执行下单,市价开多仓
strategy.entry("long3", strategy.long, 0.03, limit = 30000)                          // 指定(较低的)价格,计划下买单订单,等待成交开仓,限价开仓

Plainly

strategy(title = "close long example", pyramiding = 2)                              // pyramiding 允许的同方向下单的次数
strategy.entry("long1", strategy.long, 0.1)                                         // 市价开多仓,指定分组标签为long1
strategy.entry("long2", strategy.long, 0.1)                                         // 市价开多仓,指定分组标签为long2
strategy.close("long1", when = strategy.position_size > 0.1, qty_percent = 50, comment = "close buy entry for 50%")   // 平仓,指定平掉分组标签为long1的仓位的50%持仓
strategy.close("long2", when = strategy.position_size > 0.1, qty_percent = 80, comment = "close buy entry for 80%")   // 平仓,指定平掉分组标签为long2的仓位的80%持仓

Mechanism of trade

The PINE language holdings mechanism is similar to one-way holdings. For example, when holding a multi-headed position ("multi-headed holdings"), if there are sell orders, plan lists, etc. (in the reverse direction of the holdings), the order is triggered to execute. The multi-headed position is first flattened ("flatten all multi-headed holdings") and then executed (in the reverse direction of the holdings).

Schedule of events

When using the order ordering command, the default is market ordering if no price is specified. In addition to market ordering, you can also order from a plan order, which does not immediately operate the order. Plan ordering can be performed in the plan order queue of a program that exists when it is not triggered.Discs and re-testsThe time status information (i.e. the status bar when the policy is running) is seen in the "schedule orders" tab section. The system will only actually place orders when the real-time market price conditions are met to trigger these orders.strategy.entrySo we can specify that when we order a function, we can specifylimitstopParameters are.

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    
  • Limit orders

    Set a limit price for the order, i.e. when the order is for paymentdirectionThe parameter isstrategy.longThe order is triggered only when the current market price is below that price. When the order is for sale (i.e.directionThe parameter isstrategy.shortThe order is triggered only when the current market price is higher than that price.

  • Stop order

    Set the stop-loss price of the order, when the order is a buy, and only trigger the order when the current market price is higher than that price. When the order is a sell order, the order is triggered only when the current market price is below that price.

  • Stop-limit orders

    Can be set simultaneouslylimitstopParameters, orders are triggered at the first price that meets the conditions.

Statements, logical structure keywords and so on.

var

var is the keyword for assignment and one-time initialization of variables. Typically, variable assignment syntax that does not include the keyword var will result in variable values being overlaid each time the data is updated. Conversely, when variables are assigned with the keyword var, they can be kept in a state-like state even though the data is updated, changing it only when the conditions in the if-expressions are met.

var variable_name = expression

Explained:

  • variable_name- Any name of user variable allowed in Pine Script ((can contain uppercase and lowercase Latin characters, numbers and underscores ((_), but cannot begin with a number) )).
  • expression- any arithmetic expression, like defining a regular variable.

Examples

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

The variable a maintains the closing price of the first column of each column in the series. Variable b remained the closing price of the first in the series. Variable c remained the closing price of the tenth in the series.

The FMZ is divided into real-time price models, closing price models, and price comparisons.varvaripWe test the declared variable using the following code.

strategy("test pine", "test 1", 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
if true
    i := i + 1
    ii := ii + 1
  • Real-time pricing model The above test code is divided into two phases during execution: 1st, the historical K-line phase; 2nd, the real-time K-line phase.varvaripThe declared variable i, ii will perform incremental operations every time the policy code is executed, becauseif trueSo it is certain to execute the corresponding conditional code block); so it can be seen that the numbers shown on the retrieval result K line BAR are each incremented by 1; when the historical K line phase ends, the real-time K line phase begins.varvaripThe declared variables start to change differently. Because it is a real-time price model, every price change in a K-line BAR is executed with a repeated strategy code.i := i + 1andii := ii + 1The difference is that ii is modified every time. Although i is also modified each time, the value of i is restored when the next round of execution of the policy logic is executed, until the current K-line BAR runs out and the update determines the value of i (i.e. the value is no longer restored when the next round of execution of the policy logic is executed).

  • The closing model Since the closing price model executes one strategy logic at the end of each K-line BAR, the historical K-line phase and the real-time K-line phase are used in the closing price model.varvaripThe declared variables are perfectly consistent in the incremental representation in the above example, with BAR incrementing by 1 for each K line.

varip

varip (var intrabar persist) is a keyword used to allocate and initialize variables once. It is similar to the var keyword, but a variable with a varip declaration retains its value between real-time K-line updates.

varip variable_name = expression

Explained:

  • variable_name- Any name of user variable allowed in the Pine script ((can include uppercase and lowercase Latin characters, numbers and underscores ((_), but cannot begin with a number)).
  • expression- any arithmetic expression, as when defining a regular variable. On the first K line, the expression is computed only once and assigned to the variable once.

Examples

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

When var is used, the graph returns the value of bar_index. Using varip, the same behavior occurs on the historical K line, but on the real-time K line, the graph returns a value that increases by one for each tick.

NotesCan only be used with simple types such as float, int, boolean, string, and arrays of these types.

true

Indicates the value of a Boolean variable, or when an expression is usedComparisonorLogicThe value that can be calculated when the operator is used.

NotesSee alsoComparisonOperators andLogicDescription of the operator.

See you later bool

false

Indicates the value of a Boolean variable, as well as the results of comparison operations, logic operations.

NotesSee alsoComparisonOperators andLogicDescription of the operator.

See you later bool

if

The if statement defines a block of statements that must be executed when the expression condition is met. The 4th edition of the Pine scripting language allows you to use the else if syntax.

The common codes come from:

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

Notes var_declarationX- This variable takes the value of the if statementcondition- Use the sentence block if the condition is truethenThe logic of thevar_decl_then0var_decl_then1etc) ⇒ If the condition is false, use the sentence blockelse ifOrelseThe logic of thevar_decl_else0var_decl_else1I'm not sure what you mean.return_expression_then , return_expression_else- The last expression in the module or an expression from the blockelse will return the final value of the statement. If the variable is declared at the end, its value will be the result value.

The type of the return value of the if statement depends onreturn_expression_thenandreturn_expression_elseTypes. When running on TradingView, their types must match: it is impossible to return an integer value from the then statement block when you have a string value in theelse block. When running on FMZ, the following example does not return an error, when the y value is taken to be "open", the value when the plot is drawn is n/a.

Examples

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

Can be omittedelseblocks. In this case, if the condition is false, the variable var_declarationX is assigned a??empty threshold ((na、false or??):

Examples

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

You can use multiple else if blocks or not use them at all. then, else if, else if blocks are moved to four spaces:

Examples

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

Can be ignoredifThe result value of the statement ((var_declarationX= can be omitted)). It can be useful if you need a side effect of the expression, for example in strategy trading:

Examples

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

If statements can contain each other:

Examples

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

for

The 'for' string structure allows multiple statements to be executed repeatedly:

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

var_declaration- An optional variable declaration that will be assigned as the value of the return_expression of the return loop.counter- Stores the variable of the countdown counter value, increasing/decreasing 1 or step_num value in each iteration of the countdown;from_num- Start value of the counter. It allows the use of the int/float threshold/expression of the array.to_num- The final value of the counter. The loop is interrupted when the counter is greater than to_num (or less than to_num in the case of from_num > to_num). The use of the int/float thresholds/expressions of the arrays is allowed, but they are evaluated only at the first iteration of the loop.step_num- Increase/decrease the value of the counter. It is optional. The default value is +1 or −1, depending on the largest from_num or to_num. When using the value, the counter also increases/decrease according to the largest from_num or to_num, so the +/- symbol for step_num is optional.statements | continue | break- Any number of statements, or the keyword "continue" or "break", compressed into 4 spaces or one tab.return_expression- The return value of the loop, if any, is assigned to a variable in the var_declaration. If the loop exits due to the keyword "continue" or "break", the return value of the loop is the value of the last variable assigned a value before the loop exits.continue- keyword that can only be used in the loop. It causes the next iteration of the loop to be executed.break- The key word to get out of the loop.

Examples

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

See you later for...in while

for…in

for...inThe structure allows multiple statements to be executed repeatedly for each element in the array. It can be used with any of the following parameters:array_element, or used with two parameters:[index, array_element]The second form does not affect the function of the loop. It tracks the index of the current iteration in the first variable of the array.

[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- an optional variable declaration that will be assigned to the loopreturn_expressionThe value of.index- Tracks the optional variables of the current iterative index. The index starts at zero. The variable is invariant in the loop. When used, it must be contained in a also containedarray_elementIn the elementary group of.array_element- contains a variable for each successive array element to be processed in the loop. This variable is invariant in the loop.array_id- Array ID of the loop iteration.statements | continue | break- Any number of statements, or the keyword "continue" or "break", compressed into 4 spaces or one tab.return_expression- the return value of the loop is assigned tovar_declarationThe variables in the loop, if any. If the loop exits due to the keyword "continue loop" or "break loop", the return value of the loop is the last variable assigned before the loop exits.continue- keyword that can only be used in the loop. It causes the next iteration of the loop to be executed.break- The key word to get out of the loop.

Allows modification of array elements or their size in the loop. Here, we usefor...inThe formula for determining how many OHLCs of each K-line are greater than the SMA of the threshold of the k-close is given by a single parameter:

Examples

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

Here, we use the two parameters form of for...in to get ourisPosThe value of the array is set totrueAnd when they're in ourvaluesArrayThe corresponding value in the array is:

Examples

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

See you later for while array.sum array.min array.max

while

whileStatements allow for the condition iteration of local code blocks.

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

Explained:variable_declaration- Optional declaration of variables.return expressionAn initialization value can be provided for this variable.boolean_expression- If true, executewhileThe local block of the statement. If false, then inwhileAfter the sentence, continue to execute the script.continue - continueThe keyword causes the loop to branch to the next iteration.break - breakThe keyword causes the loop to terminate.whileThe sentence is restarted afterwards.return_expression- ProvidedwhileOptional lines for which statements return values.

Examples

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

NotesEarlywhileThe local code block after the line must be compressed into four spaces or a punctuation mark.whileThe circle.whileThe following Boolean expression must eventually become false, or it must be executed.break

switch

The switch operator transfers control to one of several statements based on the value of the condition and expression.

[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

It's the same with the switch with the expression:

Examples

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

It's not just the words that make up the name of the game.

Examples

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)

Returns the valueThe value of the last expression in the executed local statement block.

NotesCan only be executedlocal_blockExample ordefault_local_blockOne of them.default_local_blockOnly with=>Markers are introduced together, and are executed only when the previous block is not executed; ifswitchThe result of the statement is assigned to a variable and is not specifieddefault_local_blockIf not executedlocal_blockThe sentence is returned.naI will.switchWhen the result of the statement is assigned to a variable, alllocal_blockThe instance must return a value of the same type.

See you later if ?:

series

series is a keyword for the data series type.seriesKeywords are usually unnecessary.

The operator

=

Used to assign variables, but only when declaring variables (the first time used).

:=

An assignment operator, assigning a value to the left-hand variable. It is used to assign values to previously declared variables.

!=

It is not equal to..........

expr1 != expr2

Returns the valueA Boolean value, or a set of Boolean values.

%

Modes ((integer residuals) ⇒ are used for numerical expressions ⇒

expr1 % expr2

Returns the valueAn integer or floating-point value, or a series of values.

NotesIn the Pine script, when calculating the remainder of an integer, the dealer will be cut off; that is, its square fours into the lowest absolute value. The resulting value will have the same symbol as the dividend.

Example: -1 % 9 = -1 - 9 * truncate ((-1/9) = -1 - 9 * truncate ((-0.111) = -1 - 9 * 0 = -1.

%=

Modal designation. It is used for numerical expressions.

expr1 %= expr2

Examples

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

Returns the valueAn integer or floating-point value, or a series of values.

*

Multiplication. It is used for numerical expressions.

expr1 * expr2

Returns the valueAn integer or floating-point value, or a series of values.

*=

Multiplication assignment. It is used for numerical expressions.

expr1 *= expr2

Examples

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

Returns the valueAn integer or floating-point value, or a series of values.

+

Adding or uniting digits. Use for numeric expressions or strings.

expr1 + expr2
+ expr

Returns the valueString binary+Returns the sum of express1 and express2 A digit returns an integer or floating point value, or a series of values: The binomial r +'returns express1 plus express2. One-way + one-way returns express (adding nothing to the one-way operator symmetry).

NotesYou can use arithmetic operators with numbers as well as arrays of variables. In the case of arrays, the operator applies to elements.

+=

Additive notation. Useful for numerical expressions or strings.

expr1 += expr2

Examples

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

Returns the valueFor strings, returns a string of expres1 and expres2; for numbers, returns an integer or floating point value, or a series of values.

NotesYou can use arithmetic operators with numbers as well as arrays of variables. In the case of arrays, the operator applies to elements.

-

Subtraction law or unit negative number.

expr1 - expr2
- expr

Returns the valueReturns an integer or floating point value, or a series of values: The binomial r +'returns express1 minus express2. One dollar-Returns the negation of expr.

NotesYou can use arithmetic operators with numbers as well as arrays of variables. In the case of arrays, the operator applies to elements.

-=

Subtraction assignment ⇒ Useful for numerical expressions.

expr1 -= expr2

Examples

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

Returns the valueAn integer or floating-point value, or a series of values.

/

Except for the fact that it applies to numerical expressions.

expr1 / expr2

Returns the valueAn integer or floating-point value, or a series of values.

/=

Except assignment. It is used for numerical expressions.

expr1 /= expr2

Examples

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

Returns the valueAn integer or floating-point value, or a series of values.

<

Less than. Applies to numerical expressions.

expr1 < expr2

Returns the valueA Boolean value, or a set of Boolean values.

<=

Less than or equal to. Applies to numerical expressions.

expr1 <= expr2

Returns the valueA Boolean value, or a set of Boolean values.

==

Equivalent to ▽ applicable to any type of expression.

expr1 == expr2

Returns the valueA Boolean value, or a set of Boolean values.

=>

The '=>' operator is used for user-defined function declarations andswitchI'm not sure what you mean by that.

The syntax of the function declaration is:

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

One<local_block>It's zero or more Pine sentences.<function_result>A variable, an expression, or an elementary group.

Examples

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

NotesYou can learn more about user-defined functions on the declaration and script library pages of the user manual.

>

Greater than. Applies to numerical expressions.

expr1 > expr2

Returns the valueA Boolean value, or a set of Boolean values.

>=

greater than or equal to ≠ ≠ ≠ ≠ ≠ ≠

expr1 >= expr2

Returns the valueA Boolean value, or a set of Boolean values.

?:

The triangular conditional operator.

expr1 ? expr2 : expr3

Examples

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

Returns the valueIf express1 is evaluated as true, then express2 is evaluated as true, otherwise it is considered to be express3。 The zero value ((0 and NaN+, Infinity,-Infinity) is considered false, all other values are true。

NotesIf you don't need it, use na as a branch of the else. You can combine using two or more?: operators to implement statements similar to a switch button (see example above). You can use numeric arithmetic operators as well as arrays of variables. In the case of arrays, the operator applies to elements.

See you later na

[]

Series subtitles ─ providing access to previous values of the series express1 ─ expr2 is the number of lines past k and must be a value ─ floating will be omitted ─

expr1[expr2]

Examples

// [] 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)

Returns the valueA series of values.

See you later math.floor

and

Logical AND↑ is used for Boolean expressions↑

expr1 and expr2

Returns the valueA Boolean value, or a set of Boolean values.

or

Logical OR↑ is used for Boolean expressions↑

expr1 or expr2

Returns the valueA Boolean value, or a set of Boolean values.

not

The logical inverse ((NOT) ⇒ applies to Boolean expressions.

not expr1

Returns the valueA Boolean value, or a set of Boolean values.

Keyword for data type

bool

A keyword of the type "Bool" for explicitly declared variables or arguments. The value of the variable "Bool" can be true, false or na.

Examples

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

NotesIt is optional to explicitly mention a type in the variable declaration unless it is initialized with na. Learn more about the type type in the user manual page of the type system.

See you later var varip int float color string true false

int

Keyword of type int ((integer)) used to explicitly declare variables or parameters.

Examples

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

NotesIt is optional to explicitly mention a type in the variable declaration unless it is initialized with na. Learn more about the type type in the user manual page of the type system.

See you later var varip float bool color string

float

Keyword of type float float (floating point) used to explicitly declare variables or parameters.

Examples

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

NotesIt is optional to explicitly mention the type in the variable declaration, unless it is initialized with na.

See you later var varip int bool color string

string

A keyword of the "string" type used to explicitly declare a variable or parameter.

Examples

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

NotesIt is optional to explicitly mention a type in the variable declaration unless it is initialized with na. Learn more about the type type in the user manual page of the type system.

See you later var varip int float bool str.tostring str.format

color

Keyword for the type "color" used to explicitly declare variables or parameters.

Examples

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

NotesThe color character has the following format: #RRGGBB or #RRGGBBAA. The letter represents a sixteenth digit value from 00 to FF (0 to 255 in the decimal system), where RR, GG and BB are the values of the red, green and blue components of the color. AA is an optional value for color transparency (or alpha component), where 00 is invisible and FF is opaque. It is optional to explicitly mention a type in the variable declaration unless it is initialized with na. Learn more about the type type in the user manual page of the type system.

See you later var varip int float string color.rgb color.new

array

The keyword for the type of array array array that is explicitly declared as a variable or parameter.array.new<type>,array.fromThe function creates array objects (or IDs).

Examples

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

NotesArray objects are always in the form of arrays in a hierarchical array.

See you later var array.new array.from

Built-in functions

When calling a function, parameters can be passed, parameters can be named, variables can be passed directly at the corresponding parameter location, and mixed use is also supported. For example:

plot(close, title="test plot")     // 直接传参数 close ;指定参数 title ,赋值字符串"test plot"

Once the parameter name assignment is specified, the variable can no longer be passed directly as a parameter. All subsequent passwords must be written in the form of parameter name assignment.

// plot(close, title="test", color.red)    // 虽然plot第三个参数是颜色值,但是这样写就会报错
plot(close, title="test", color=color.red) // 正确写法
plot(close, "test", color.red)             // 正确写法

timeframe

timeframe.in_seconds

It will be forwarded totimeframeThe time period of the parameter is converted to seconds.

timeframe.in_seconds(timeframe)

Examples

// Get chart timeframe:
i_tf = input.timeframe("1D")

// Convert timeframe to the int value (number of seconds in 1 Day):
tf = timeframe.in_seconds(i_tf)

plot(tf)

Returns the value timeframeThe int of the number of seconds in a K-line is given by the form

Parameters

  • timeframe(simple string) Timeframe↑ Optional↑ The default is timeframe.period↑

NotesFor thetimeframe>= 1M function calculated from the number of seconds of 30.4167 (365/12) days in a month.

See you later input.timeframe timeframe.period

ticker

ticker.heikinashi

Create a code identifier requesting smooth average K-line value.

ticker.heikinashi(symbol)

Examples

heikinashi_close = request.security(ticker.heikinashi(syminfo.tickerid), timeframe.period, close)

heikinashi_aapl_60_close = request.security(ticker.heikinashi(syminfo.tickerid), "60", close)
plot(heikinashi_close)
plot(heikinashi_aapl_60_close)

Returns the value 股票代码的字符串值,可以提供给request.security函数。

Parameters

  • symbol(simple string) Commodity code identifier.

See you later syminfo.tickerid syminfo.ticker request.security

request

request.data

Request external data.

request.data(url, attribute)

Examples

/*backtest
start: 2022-01-26 09:00:00
end: 2024-02-01 15:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}]
*/

// 图表地址https://www.datadata.cn/queries/a10ea45c-1674-48ef-b414-cc17a7e4a548
var chart_data = "https://www.datadata.cn/api/v1/query/a10ea45c-1674-48ef-b414-cc17a7e4a548/data"
add_investor = request.data(chart_data, "$.add_investor")
idx_price = request.data(chart_data, "$.close_price")

plot(add_investor, "股市新增人口")
plot(idx_price, "股指价格")
// 反指交易
avg_investor = ta.ema(add_investor[1], 30)
if strategy.position_size == 0
    if add_investor > avg_investor*1.1
        runtime.log("新增人口:", add_investor, "近30天平均:", avg_investor, "#ff0000")
        strategy.entry("Enter Short", strategy.short)
    else if add_investor < avg_investor*0.9
        runtime.log("新增人口:", add_investor, "近30天平均:", avg_investor, "#ff0000")
        strategy.entry("Enter Long", strategy.long)

Returns the valueParametersattributeSpecified data series.

Parameters

  • url(simple string) The requested data source url, the data format of which the data source responds to, must meet the following requirements (including at least the time、data attributes):{"data": [], "schema": ["time", "data"]}The following data formats can be used in the example:
    {
        "data": [
            [1430438400000, "2015年04月", "{\"add_investor\" : 497.53, \"close_price\" : 4441.655}"],
            [1433116800000, "2015年05月", "{\"add_investor\" : 415.87, \"close_price\" : 4611.744}"]
            // ...
        ],
        "schema": ["time", "date", "data"]
    }  
    
  • attribute(simple string) Specifies the attribute name and returns the desired data. For example:"$.add_investor", use$.As a prefix, the attribute name matches the attribute in the data field in the data that was responded to when the requested data source was requested

request.security

This is the first time I have seen this video.

request.security(symbol, timeframe, expression, gaps, lookahead, ignore_invalid_symbol, currency) 

Examples

s = request.security(syminfo.tickerid, "D", close)   // 1 Day
plot(s)

expr = ta.sma(close, 10)
s1 = request.security(syminfo.tickerid, "240", expr) // 240 Minutes
plot(s1)

// To avoid difference in calculation on history/realtime you can request not latest values and use merge strategy flags as follows:
s2 = request.security(syminfo.tickerid, "D", close[1], barmerge.gaps_off, barmerge.lookahead_on)
plot(s2)
f() => [open, high]
[o, h] = request.security(syminfo.tickerid, "D", f())
[l, c] = request.security(syminfo.tickerid, "D", [low, close])
plot((o + h + l + c) / 4)

Returns the valueRequired series

Parameters

  • symbol(simple string) Commodity code.
  • timeframe(simple string) Time period. The empty string will be interpreted as the current time period of the graph.
  • expression(series int/float/bool/color) can be called from request.security and return an expression. It can be an array or an array containing elements that can be converted to a series.
  • gaps(barmerge_gaps) Policy for merging data requested ((requires data to be merged automatically with the main series of OHLC data)). Possible values: barmerge.gaps_on, barmerge.gaps_off。 barmerge.gaps_on - data requested is merged with possible gaps ((na value) ). barmerge.gaps_off - data requested is merged continuously without interruption, with all gaps filled with the previous most recent existing value。 The default is barmerge.gaps_off。
  • lookahead(barmerge_lookahead) gives the requested data merge policy. Possible values: barmerge.lookahead_on, barmerge.lookahead_off. Starting with version 3, the default is barmerge.lookahead_off. Note that the behavior is the same as in real time, only different in history.
  • ignore_invalid_symbol(const bool) An optional parameter. Determines the behavior of the function if the specified commodity is not found: if false, the script will stop and return an error at run time; if true, the function will return na and continue to execute.
  • currency(simple string) Converts the currency-related value (e.g. OHLC) of the commodity into the currency it is converted into. Then the conversion value is calculated based on the conversion value. The conversion rate used is based on the daily exchange rate of the previous day of the FX_IDC pair (relative to the K-line to be calculated). Optional. The default value is syminfo.currency. Possible value: a three-letter string or currency with an ISO 4217 format currency code (e.g. USD). One of the constants in the namespace, e.g. currency.USD.

NotesUsing this feature, the code in PineScript can perform different calculations on historical records and real-time data.If you want to specify additional parameters for the requested commodity, such as transaction time intervals or adjustment type, you can use the following command to specify the type of transaction.您可以使用ticker.newLet's see if we can do this. You can't pass a point error to this function using the ticker tick variable. You can use tick.ticker.newA string representation of a hash variable or stock code, such as hash AAPL+MSFT*TSLA hash.Currently, a script can have up to 40 request.security calls. Please note that using this variable/function may result in a redrawing of the indicator. The resolution parameter allows values of: 1S, 5S, 15S, 30S - second interval ((Chart cycle should be less than or equal to the requested cycle) From 1 to 1440 minutes From 1D to 365D days From 1W to 52W in a few weeks. From 1M to 12M in a few months

See you later syminfo.ticker syminfo.tickerid timeframe.period ta.correlation barmerge.lookahead_off barmerge.lookahead_on

str

str.contains

What ifsourceString containsstrIf a string is a substring, it returns true, otherwise it returns false.

str.contains(source, str)

Examples

// If the current chart is a continuous futures chart, e.g “BTC1!”, then the function will return true, false otherwise.
var isFutures = str.contains(syminfo.tickerid, "!")
plot(isFutures ? 1 : 0)

Returns the valueWhat ifsourceFind in the string.str, is true or false.

Parameters

  • source(series string) The source string
  • str(series string) The substring to be searched.

See you later str.pos str.match

str.endswith

What ifsourceString withstrThe end of the specified substring returns true or false.

str.endswith(source, str)

Returns the valueWhat ifsourceString withstrThe end of the specified substring is true or false.

Parameters

  • source(series string) The source string
  • str(series string) The substring to be searched.

See you later str.startswith

str.startswith

What ifsourceString withstrThe start of the specified substring in the middle returns true, otherwise false.

str.startswith(source, str)

Returns the valueWhat ifsourceString withstrThe start of the substring specified in the string is true, otherwise false.

Parameters

  • source(series string) The source string
  • str(series string) The substring to be searched.

See you later str.endswith

str.substring

So we're going to return a new string, which issourceA substring of a string.begin_posStart with the character in the specified index and extend tosourceThe end_pos of the string is end_pos - 1.

str.substring(source, begin_pos)
str.substring(source, begin_pos, end_pos)

Examples

sym= "EXCHANGE_NAME:SYMBOL_NAME"
pos = str.pos(sym, ":")        // Get position of ":" character
tkr= str.substring(sym, pos+1) // "SYMBOL_NAME"
if barstate.islastconfirmedhistory
    runtime.log(tkr)

Returns the valueA substring extracted from the source string.

Parameters

  • source(series string) Extract the source string of the substring.
  • begin_pos(series int) is the starting position of the extracted substring. It is exclusive (the extracted substring includes characters from that position).
  • end_pos(series int) end position. It is exclusive (extracted string does not include characters from that position). Optional.sourceString length.

NotesThe string index starts at 0; ifbegin_posis equal toend_pos, which returns an empty string.

See you later str.contains str.pos str.match

str.tonumber

str.tonumber(string)

Returns the valueIf it contains a valid number, it is the floating-point type of the string, otherwise it is na.

Parameters

  • string(series string) int or float string representation form.

str.format

Convert format strings and values to formatting strings. A format string can contain a placeholder in the text and a parenthesis {} in the parenthesis {} of each value to be formatted. Each placeholder includes an index that will replace its required parameter (starting from 0), and an optional format instruction. The index indicates the position of the parameter in the list of str.format parameters.

str.format(formatString, arg0, arg1, ...)

Examples

// The format specifier inside the curly braces accepts certain modifiers:
// - Specify the number of decimals to display:
s1 = str.format("{0,number,#.#}", 1.34) // returns: 1.3
runtime.log(s1)

// - Round a float value to an integer:
s2 = str.format("{0,number,integer}", 1.34) // returns: 1
runtime.log(s2)

// - Display a number in currency:
s3 = str.format("{0,number,currency}", 1.34) // returns: $1.34
runtime.log(s3)

// - Display a number as a percentage:
s4 = str.format("{0,number,percent}", 0.5) // returns: 50%
runtime.log(s4)

// EXAMPLES WITH SEVERAL ARGUMENTS
// returns: Number 1 is not equal to 4
s5 = str.format("Number {0} is not {1} to {2}", 1, "equal", 4)
runtime.log(s5)

// returns: 1.34 != 1.3
s6 = str.format("{0} != {0, number, #.#}", 1.34)
runtime.log(s6)

// returns: 1 is equal to 1, but 2 is equal to 2
s7 = str.format("{0, number, integer} is equal to 1, but {1, number, integer} is equal to 2", 1.34, 1.52)
runtime.log(s7)

// returns: The cash turnover amounted to $1,340,000.00
s8 = str.format("The cash turnover amounted to {0, number, currency}", 1340000)
runtime.log(s8)

// returns: Expected return is 10% - 20%
s9 = str.format("Expected return is {0, number, percent} - {1, number, percent}", 0.1, 0.2)
runtime.log(s9)

Returns the valueString formatted.

Parameters

  • formatString(series string) String in the format.
  • arg0, arg1, ...(series int/float/bool/string/na/int[]/float[]/bool[]/string[]) is the value to be formatted.

NotesAll parentheses in the unquoted style must be balanced. For example, ab {0} de" and "ab } de" are valid styles, but "ab {0} de, ab } de" and {" are not.

str.length

Returns the integer that corresponds to the number of characters in the string.

str.length(string)

Returns the valueThe number of characters in the source string.

Parameters

  • string(series string) The source string

str.lower

Returns a new string where all letters are converted to lower case.

str.lower(source)

Returns the valueAll the letters are converted into new lowercase strings.

Parameters

  • source(series string) The string to be converted.

See you later str.upper

str.upper

Returns a new string in which all letters are converted to capital letters.

str.upper(source)

Returns the valueAll the letters are converted into new strings in capital letters.

Parameters

  • source(series string) The string to be converted.

See you later str.lower

str.match

If matchedregexThe normal expression returnssourceThe new substring of the string, otherwise returns na.

str.match(source, regex) 

Examples

s = input.string("It's time to sell some EXCHANGE_NAME:SYMBOL_NAME!")

// finding first substring that matches regular expression "[\w]+:[\w]+"
var string tickerid = str.match(s, "[\\w]+:[\\w]+")

if barstate.islastconfirmedhistory
    runtime.log(tickerid) // "EXCHAN

More

wuhuoyanHow do you do it if you want to have multiple transactions running simultaneously?

Light cloudsPlease tell me, can pine do more transactions? Can it also go through transactions like JS? Thank you.

lisa20231Thank you for providing detailed documentation.

artistryWow! How does this pine script use the okex simulation on the platform?

artistryThis is equivalent to copying the tradingview platform's strategy directly to the inventor platform and using it!

The Little DreamThe PINE language can only do single-variety strategies, multi-variety strategies are best written in python, javascript, c++.

The Little DreamOh, yes, OKX is special, their analog environment and the real disk environment have the same address, only the difference is made elsewhere.

Light cloudsI can't use the okx analogue disc.

The Little DreamThis multi-variety architecture problem cannot be solved, because each exchange has a different interface, and the frequency limitation of the interface is not the same, which causes many problems.

The Little DreamWell, thank you for the suggestion, please report this request here.

Light cloudsIt feels better to be able to mix with JS and JS can be better adapted to different trading methods.

The trend hunterIn the future, will we consider more varieties?

The Little DreamI'm not being polite.

Light cloudsGood, thank you very much.

The Little DreamHello, the PINE language policy is currently only for single varieties.

The Little DreamThank you for your support. The documentation will continue to be improved.

The Little DreamYes, I did.

The Little DreamPINE template library, where parameters can be set to switch exchange base addresses.