[TOC]
The general structure of the code in Pine is:
<version>
<declaration_statement>
<code>
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')
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
。
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:
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.
if
,for
,while
orswitch
and so on.Sentences can be arranged in many ways.
空格
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.local block
A 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.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) // 调用一个内置函数输出日志 (全局范围)
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 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 variablesopen
For example,open
The built-in variable records the opening price of each K-line BAR, if thisopen
So this is the data for the five-minute K-line cycle.open
What is recorded in the variable is the opening price of the K-line BAR (column) every 5 minutes.open
This 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.
The built-in template for the PINE policy, "Pine language transaction library", has parametric settings.
定价货币精度
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.javascript
Calls in policySetMaxBarLen
The function works the same way.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) // 指定(较低的)价格,计划下买单订单,等待成交开仓,限价开仓
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%持仓
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).
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.entry
So we can specify that when we order a function, we can specifylimit
、stop
Parameters 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 paymentdirection
The parameter isstrategy.long
The order is triggered only when the current market price is below that price.
When the order is for sale (i.e.direction
The parameter isstrategy.short
The 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 simultaneouslylimit
、stop
Parameters, orders are triggered at the first price that meets the conditions.
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
The FMZ is divided into real-time price models, closing price models, and price comparisons.var
、varip
We 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.var
、varip
The declared variable i, ii will perform incremental operations every time the policy code is executed, becauseif true
So 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.var
、varip
The 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 + 1
andii := ii + 1
The 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.var
、varip
The declared variables are perfectly consistent in the incremental representation in the above example, with BAR incrementing by 1 for each K line.
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.
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
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
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
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 truethen
The logic of thevar_decl_then0
,var_decl_then1
etc) ⇒ If the condition is false, use the sentence blockelse if
Orelse
The logic of thevar_decl_else0
,var_decl_else1
I'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_then
andreturn_expression_else
Types. 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 omittedelse
blocks. 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
Examples
// if
x = if open > close
5
else if high > low
close
else
open
plot(x)
Can be ignoredif
The result value of the statement ((
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)
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
The 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_expression
The 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_element
In 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_declaration
The 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...in
The 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 ourisPos
The value of the array is set totrue
And when they're in ourvaluesArray
The 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
Statements 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 expression
An initialization value can be provided for this variable.boolean_expression
- If true, executewhile
The local block of the statement. If false, then inwhile
After the sentence, continue to execute the script.continue
- continue
The keyword causes the loop to branch to the next iteration.break
- break
The keyword causes the loop to terminate.while
The sentence is restarted afterwards.return_expression
- Providedwhile
Optional 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)
NotesEarlywhile
The local code block after the line must be compressed into four spaces or a punctuation mark.while
The circle.while
The following Boolean expression must eventually become false, or it must be executed.break
。
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_block
Example ordefault_local_block
One of them.default_local_block
Only with=>
Markers are introduced together, and are executed only when the previous block is not executed; ifswitch
The result of the statement is assigned to a variable and is not specifieddefault_local_block
If not executedlocal_block
The sentence is returned.na
I will.switch
When the result of the statement is assigned to a variable, alllocal_block
The instance must return a value of the same type.
See you later
if
?:
series is a keyword for the data series type.series
Keywords are usually unnecessary.
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 andswitch
I'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
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
Logical AND↑ is used for Boolean expressions↑
expr1 and expr2
Returns the valueA Boolean value, or a set of Boolean values.
Logical OR↑ is used for Boolean expressions↑
expr1 or expr2
Returns the valueA Boolean value, or a set of Boolean values.
The logical inverse ((NOT) ⇒ applies to Boolean expressions.
not expr1
Returns the valueA Boolean value, or a set of Boolean values.
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
Keyword of type
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
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
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
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
The keyword for the type of array array array that is explicitly declared as a variable or parameter.array.new<type>
,array.from
The 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
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) // 正确写法
It will be forwarded totimeframe
The 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
timeframe
The 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
>=
See you later
input.timeframe
timeframe.period
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 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 valueParametersattribute
Specified 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 requestedThis 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. 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
What ifsource
String containsstr
If 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 ifsource
Find in the string.str
, is true or false.
Parameters
source
(series string) The source stringstr
(series string) The substring to be searched.See you later
str.pos
str.match
What ifsource
String withstr
The end of the specified substring returns true or false.
str.endswith(source, str)
Returns the valueWhat ifsource
String withstr
The end of the specified substring is true or false.
Parameters
source
(series string) The source stringstr
(series string) The substring to be searched.See you later
str.startswith
What ifsource
String withstr
The start of the specified substring in the middle returns true, otherwise false.
str.startswith(source, str)
Returns the valueWhat ifsource
String withstr
The start of the substring specified in the string is true, otherwise false.
Parameters
source
(series string) The source stringstr
(series string) The substring to be searched.See you later
str.endswith
So we're going to return a new string, which issource
A substring of a string.begin_pos
Start with the character in the specified index and extend tosource
The end_pos of the string is
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.source
String length.NotesThe string index starts at 0; ifbegin_pos
is equal toend_pos
, which returns an empty string.
See you later
str.contains
str.pos
str.match
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.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,
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 stringReturns 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
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
If matchedregex
The normal expression returnssource
The new substring of the string, otherwise returns
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
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.