Tradingview pine script 学习笔记

表达式、声明 (Expressions, declarations and statements)

:=表达式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
:=
这个表达方式在之前的python和JavaScript我都没看到过。但好像python3.8会引入这个运算符
在Python3.8中的介绍是这样的:
正式地,这运算符被叫做:assignment expression
非正式地:这运算符被称为:walrus operator。海象运算符,因为长得像海象,哈哈。
它用来赋值,同时也可以计算表达式。
我们回到pine script:
:= 必须用于给一个变量赋一个新的值,这个变量必须在你赋值之前声明
变量的类型在声明的时候就被定义了。类型要和声明的类型一致,不然的话会报错。
赋值例子:
//@version=4
study("My Script")
price = close
if hl2 > price
price := hl2
plot(price)

if statement

大致形势是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<var_declarationX> = if <condition>
<var_decl_then0>
<var_decl_then1>
...
<var_decl_thenN>
else if [optional block]
<var_decl_else0>
<var_decl_else1>
...
<var_decl_elseN>
else
<var_decl_else0>
<var_decl_else1>
...
<var_decl_elseN>
<return_expression_else>
例子:
// This code compiles
x = if close > open
close
else
open
// This code doesn't compile
x = if close > open
close
else
"open"

运算符

总的来说和Python以及JavaScript的语法都有些类似,我这里之说下不一样的。

三元条件运算符 Ternary conditional operator.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
expr1 ? expr2 : expr3
// Draw circles at the bars where open crosses close
s2 = cross(open, close) ? 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)
如果expr1 成立的话,返回expr2,否则返回expr3.
0被认为是false
注意的是:
如果你不用else branch的话,在else branch里使用na

For循环

To have access to and use the for statement, one should specify the version >= 2 of Pine Script language in the very first line of code, for example: //@version=4
var_declarationX = for counter = from_num to to_num [by step_num]
  var_decl0
  var_decl1
  …
  continue
  …
  break
  …
  var_declN
  return_expression
where:
counter - a variable, loop counter.
from_num - start value of the counter
to_num - end value of the counter. When the counter becomes greater than to_num (or less than to_num in case from_num > to_num) the loop is broken.
step_num - loop step. Can be omitted (in the case loop step = 1).
If from_num is greater than to_num loop step will change direction automatically, no need to specify negative numbers.
var_decl0, … var_declN, return_expression - body of the loop. It must be shifted by 4 spaces or 1 tab.
return_expression - returning value. When a loop is finished or broken, the returning value is given to the var_declarationX.
continue - a keyword. Can be used only in loops. It switches the loop to next iteration.
break - a keyword. Can be used only in loops. It breaks the loop.

var

var是用在赋值和一次性初始化变量的关键字
通常,一个不包括var关键字的变量赋值语法会导致变量值被一次更新都会被重写。相反,用var关键字赋值的话就可以保留状态

内置variable

bar_index

就是bar的序号。比如上市第一天为1,第二天的为2.

1
2
3
//plot(bar_index)
//打印出500天后的收盘价
plot(bar_index > 500 ? close : 0)

close

当前收盘价

high

最高价

strategy.equity

当前资产

strategy.position_size

当前仓位信息, 该变量等于0.0,说明空仓,大于0.0多头仓位,小于0.0空头仓位。

内置方法

array.new_float

The function creates a new array object of float type elements.
方法创建一个float类型的数组

1
2
3
4
5
//@version=4
study("array.new_float example")
length = 5
a = array.new_float(length, close)
plot(array.sum(a) / length)

array.pop

1
2
3
4
5
6
//@version=4
study("array.pop example")
a = array.new_float(5,high)
removedEl = array.pop(a)
plot(array.size(a))
plot(removedEl)

array.push

1
2
3
4
5
//@version=4
study("array.push example")
a = array.new_float(5, 0)
array.push(a, open)
plot(array.get(a, 5))

array.range

The function returns the difference between the min and max values from a given array.
方法返回数组中最大和最小数值的差值

1
2
3
4
5
6
//@version=4
study("array.range example")
a = array.new_float(0)
for i = 0 to 9
array.push(a, close[i])
plot(array.range(a))

array.sort

1
2
3
4
5
6
7
8
//@version=4
study("array.sort example")
a = array.new_float(0,0)
for i = 0 to 5
array.push(a, high[i])
array.sort(a, order.descending)
if barstate.islast
label.new(bar_index, close, tostring(a))

offset

Shifts series x on the y bars to the right.
ARGUMENTS
source (series) Series of values to process.
offset (integer) Number of bars to offset, must be a positive number. Negative offsets are not supported.

rsi

Relative strength index

1
2
3
4
5
6
7
8
9
10
11
plot(rsi(close, 7))
// same on pine, but less efficient
pine_rsi(x, y) =>
u = max(x - x[1], 0) // upward change
d = max(x[1] - x, 0) // downward change
rs = rma(u, y) / rma(d, y)
res = 100 - 100 / (1 + rs)
res
plot(pine_rsi(close, 7))

crossover

黄金交叉

crossunder

死亡交叉

input

给你的代码指标添加输入。Script input和内置的技术分析指标input完全式样的。

当我们策略写好之后,需要调试一些参数,那么就需要让这些参数暴露出来,这样我们就可以直接在配置里面改参数,然后查看对应的策略回测数据。

  • 参数解析
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    defval,类型必须符合type参数定义的类型
    defval决定了在scripts里"settings/inputs"标签里的input变量
    title 标题,没啥好说的
    type (const string) Input type.
    可能选项是
    input.bool, input.integer, input.float, input.string, input.symbol, input.resolution, input.session, input.source, input.color, input.time.
    minval (const integer, float)
    input变量最小的可能值。这个参数只有在input 类型为input.integer or input.float.才有效
    maxval (const integer, float)
    input变量最大的可能值。这个参数只有在input 类型为input.integer or input.float.才有效
    confirm (const bool)
    如果true,用户在指标在添加到图表之前会被询问确认。默认为false。
    step (const integer, float)
    Step value to use for incrementing/decrementing input from format dialog. Default value is 1. This argument is used only for input types input.integer and input.float.
    用于增量或减量input,只在input type为input.integer and input.float.时候有效。默认为1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
b = input(title="On/Off", type=input.bool, defval=true)
plot(b ? open : na)
i = input(title="Offset", type=input.integer, defval=7, minval=-10, maxval=10)
plot(offset(close, i))
f = input(title="Angle", type=input.float, defval=-0.5, minval=-3.14, maxval=3.14, step=0.02)
plot(sin(f) > 0 ? close : open)
sym = input(title="Symbol", type=input.symbol, defval="DELL")
res = input(title="Resolution", type=input.resolution, defval="60")
c = input(title="Plot Color", type=input.color, defval=color.red)
plot(close, color=c)
plot(security(sym, res, close), color=color.green)
s = input(title="Session", defval="24x7", options=["24x7", "0900-1300", "1300-1700", "1700-2100"])
plot(time(timeframe.period, s))
src = input(title="Source", type=input.source, defval=close)
plot(src)
date1 = input(title="Date", type=input.time, defval=timestamp("20 Feb 2020 00:00 +0300"))
plot(date1)
date2 = input(title="Date", type=input.time, defval=timestamp("2020-02-20T00:00+03:00"))
plot(date2)

security

Request another symbol/resolution

1
2
3
4
5
6
7
8
9
10
11
12
13
14
s = security("MSFT", "D", close) // 1 Day
plot(s)
expr = sma(close, 10)
s1 = security("AAPL", "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=security(syminfo.tickerid, "D", close[1], barmerge.gaps_off, barmerge.lookahead_on)
plot(s2)
f() => [open, high]
[o, h] = security(syminfo.tickerid, "D", f())
[l, c] = security(syminfo.tickerid, "D", [low, close])
plot((o + h + l + c) / 4)

strategy

strategy是关于策略的方法,这个是非常重要的,一定要学会
The function sets a number of strategy properties.

参数解析:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
这个方法参数特多
strategy(title, shorttitle, overlay, format, precision, scale, pyramiding, calc_on_order_fills, calc_on_every_tick, max_bars_back, backtest_fill_limits_assumption, default_qty_type, default_qty_value, initial_capital, currency, max_lines_count, max_labels_count, slippage, commission_type, commission_value, process_orders_on_close, close_entries_rule, margin_long, margin_short, max_boxes_count) → void
EXAMPLE
strategy(title='MyStrategy')
strategy(title="MyStrategy", shorttitle="MS", pyramiding = 10)
ARGUMENTS
title (const string) 没啥好说的
shorttitle (const string) 也没啥好说的,会显示在chart legend上。study short title that would be seen in the chart legend.
overlay (const bool) 如果true的话,会在主series中(也就就是主K线图)增加一个覆盖(叠在一起)。如果false的话,只会在一个另外独立的chart面板上增加。默认为false
precision (const integer) 小数点精度
scale (const integer) 价格范围
pyramiding (const integer) 最大允许的在同一个方向上的entry数,如果设置为0的话,只有一个entry在同一个方向上下单。默认value为0.
calc_on_order_fills (const bool) 如果设置为true的话,策略会在下单后重新计算一次intrabar。默认值为false
calc_on_every_tick (const bool) 额外的intrabar策略计算。如果设置为true的话,策略会计算每一个实时tick,而不是bars的收盘价。参数不会影响策略对历史数据的计算。
max_bars_back (const integer) 历史引用中,一个策略可用bars的最大数量。
backtest_fill_limits_assumption (const integer) 限价订单执行假设。仅当市场价格超过限额订单水平指定的ticks数时,限额订单才在栏内填写。
margin_long (const integer) 多头保证金 percentage
margin_short (const integer) 空头保证金 percentage
default_qty_type (const string) Parameter to determine the number of contracts/shares/lots/units to trade, if the 'qty' = 'NaN'. The allowed values are: strategy.fixed (fixed quantity by default), strategy.cash (specified in currency of the symbol and the amount is converted into quantity), strategy.percent_of_equity (% of currently available equity).
default_qty_value (const float) Number of contracts/shares/lots/units if 'default_qty_type'=strategy.fixed is used; or amount of cash in currency of the symbol if 'default_qty_type'=strategy.cash is used; or number of percents of currently available equity if 'default_qty_type'=strategy.percent_of_equity is used.
currency (const string) Account currency for this strategy. Possible values are: NONE, USD, EUR, AUD, GBP, NZD, CAD, CHF, HKD, JPY, NOK, SEK, SGD, TRY, ZAR
linktoseries (const bool) if true then the study will be always on the same pane and same price scale as the main series. Should be used only in combination with 'overlay=true'. Default is false.
slippage (const integer) Slippage in ticks to be added to/subtracted from the fill price of buy/sell market or stop orders. If mintick=0.01 and slippage=5, the amount of slippage will be 5*0.01=0.05.
commission_type (const string) Commission type for an order. The allowed values are: strategy.commission.percent (a percentage of the cash volume of order), strategy.commission.cash_per_contract (money displayed in the account currency per contract), strategy.commission.cash_per_order (money displayed in the account currency per order).
commission_value (const float) Commission value for an order. Depending on the type selected (commission_type) includes percentage or money.
process_orders_on_close (const bool) When set to `true`, generates an additional attempt to execute orders after a bar closes and strategy calculations are completed. If the orders are market orders, the broker emulator executes them before the next bar's open. If the orders are conditional on price, they will only be filled if the price conditions are met. This option is useful if you wish to close positions on the current bar. The default value is 'false'.
close_entries_rule (const string) Determines the order in which orders are closed. Allowed values are: 'FIFO' or 'ANY'. FIFO (First-In, First-Out) means that when several trades are open, the earliest trades must be closed first. This rule applies to stocks, futures and US forex (NFA Compliance Rule 2-43b). 'ANY' means that trades may be closed in any order; this is allowed in non-US forex. The default value is 'FIFO'.
max_lines_count (const integer) The number of last line drawings displayed. The default value is 50 and the maximum allowed is 500.
max_labels_count (const integer) The number of last label drawings displayed. The default value is 50 and the maximum allowed is 500.
max_boxes_count (const integer) The number of last box drawings displayed. The default value is 50 and the maximum allowed is 500.
REMARKS
Every strategy script must have one strategy call.
PineScript code that uses argument calc_on_every_tick=true could calculate differently on history and real-time data.
When using non-standard types of chart as a basis for strategy, you need to realize that the result will be different. The orders will be executed at the prices of this chart (e.g.for Heikin Ashi it’ll take Heikin Ashi prices (the average ones) not the real market prices). Therefore we highly recommend you to use standard chart type for strategies.

strategy.entry

这是进入市场的命令。
如果具有相同ID的订单已经挂起,则可修改订单。 如果没有指定ID的订单,则会发出新的订单。
要停用进场指令,应使用命令strategy.cancel或strategy.cancel_all。 与函数strategy.order相比,strategy.entry功能受金字塔影响,可以正确反转市场位置。
如果“Limit”和“stop”参数均为“NaN”,则订单类型为市场订单。

strategy.exit

这是一个退出指定进场或整个市场地位的命令。如果函数strategy.exit被调用一次,则只会退出一次。 如果要退出多次,应该多次调用命令strategy.exit。

参数
id (series[string]) 必要参数。 订单标识符。 可以通过引用其标识来取消或修改订单。
from_entry (series[string]) 可选参数。以指定进场指令标识符退出。 要退出所有头寸,应使用空字符串。 默认值为空字符串。
qty (float) 可选参数。退出交易的合约/股数/手数/单位的数量。默认值为’NaN’。
qty_percent (float) 可选参数。定义退出交易的已输入的合约/股数/手数/单位的百分比。当其值不是NaN时,其优先级高于’qty’参数。其值的范围可以从0到100。如果’qty’是NaN,则默认值’qty_percent’是100。
profit (float) 可选参数。 利润目标(以点表示)。 如果已指定,当达到指定的利润额(点)时,则以限价订单退出市场头寸。 默认值为“NaN”。
limit (float) 可选参数。 利润目标(需指定价格)。 若已指定,则以指定价格(或更好)退出市场头寸。 参数’limit’的优先级高于参数’profit’的优先级(若值非’NaN’,则’limit’取代’profit’)。 默认值为“NaN”。
loss (float) 可选参数。 止损(以点表示)。 如果已指定,当达到指定的亏损额(点)时,则以停损单退出市场头寸。 默认值为“NaN”。
stop (float) 可选参数。 止损(需指定价格)。 如果已指定,则将以指定价格(或更差)退出市场头寸。 参数’止损’的优先级高于参数’损失’的优先级(若值非’NaN’,则’止损’代替’损失’)。 默认值为“NaN”。
trail_price (float) 可选参数。跟踪止损激活水平(需指定价格)。如果已指定,当达到指定价格水平时,将放置跟踪止损单。在“trail_offset”参数中指定用于确定跟踪止损单初始价格的偏移量(以点计):X 点低于激活水平以退出多头; X点高于激活水平以退出空头。默认值为“NaN”。
trail_points (float) 可选参数。跟踪止损激活水平(利润以点表示)。如果已指定,当达到已计算价格水平(指定利润金额)时,将放置跟踪止损单。在“trail_offset”参数中指定用于确定跟踪止损单初始价格的偏移量(以点计):X 点低于激活水平以退出多头; X点高于激活水平以退出空头。默认值为“NaN”。
trail_offset (float) 可选参数。跟踪止损激活水平(以点表示)。以点计的偏移量用于确定跟踪止损单的初始价格:X 点低于’trail_price’ or ‘trail_points’以退出多头; X点高于 ‘trail_price’ or ‘trail_points’以退出空头。默认值为“NaN”。
oca_name (string) 可选参数。OCA group的名称 (oca_type = strategy.oca.reduce) 获利目标,止损/跟踪止损。如果未指定名称,将自动生成该名称。
comment (string) 可选参数。订单的其他说明。
when (bool) 可选参数。订单的状况。若为”true”,订单被放置。若为”false”,则没有任何事情发生(之前放置的相同 ID 的订单没有被撤销)。默认值为”true”。
alert_message (string) 当在“创建警报”对话框的“消息”字段中使用占位符时,一个可选参数。

strategy.close

退出entry
如果有多个entry 订单都是同一个ID的话,所有都会一次性退出。
如果没有open的带有指定ID的entry触发的话,这个命令将不会生效。

strategy.close_all

退出你的所有仓位。

strategy.order

加仓

问题与思考

strategy.close 与 strategy.exit的区别

  • close
    Is a command to exit from the entry with the specified ID.
    退出某个ID的entry

If there were multiple entry orders with the same ID, all of them are exited at once.
如果有多个同样ID的订单,所有的订单都会一次性退出。

  • exit
    It is a command to exit either a specific entry or whole market position.
    退出某个entry或者退出整个时长仓位

If an order with the same ID is already pending, it is possible to modify the order.
如果一个相同ID的订单是pending的话,有可能修改这个订单。