跳到主要内容

Pine Script 学习笔记(二)——基本特点

前言

这是Pine Script 学习笔记的第二篇,简单挑教程上重要的记录了一下。

Context switching and the security function

security 函数可以用于按照特定要求请求数据

//@version=4
study("Example security 1", overlay=true)
ibm_15 = security("NYSE:IBM", "15", close)
plot(ibm_15)

security(symbol, resolution, expression, gaps, lookahead)
  • symbol (string) 商品代码。

    商品代码可以包含数据提供商信息,也可以不含

    如 "NYSE:IBM","BATS:IBM","IBM"(如不提供,默认使用BATS)

    syminfo.ticker and syminfo.tickerid是表示当前图标上的商品代码,syminfo.ticker是不含数据供应商信息,syminfo.tickerid是包含供应商信息。Pine教程建议使用后者,为了避免数据的模糊性

  • resolution (string) 分辨率/ timeframe时间周期

    • 分钟级:1,5,10,21,60,120,等等
    • 日级: D,1D,2D 等等
    • 周级:W,1W,2W
    • 月级:M,1M,2M
    • timeframe.period 记录当前图标时间周期
  • expression (series) 计数并从 security调用返回的表达式。

    如果仅仅是获取收盘价数据,我们可以用security('EURUSD','D',close)

    但是,expression能给我们提供更加丰富的操作,比如,我们需要知道,EURUSD相对于GBPUSD 上涨的幅度

    //@version=4
    study(title = "Advance Decline Ratio", shorttitle="ADR")
    ratio(t1, t2, source) =>
    s1 = security(t1, timeframe.period, source)
    s2 = security(t2, timeframe.period, source)
    s1 / s2
    plot(ratio("GBPUSD", "EURUSD", close-open))

    如上图所以,GBPUSD上涨幅度/EURUSD 的上涨幅度我们可以很轻松的通过7行代码实现。在绝大多数情况下,两者是同比例变动,但是在某些特等情况下,变化是相反的。这对于研究这两种货币对的走势关系有很大的帮助。

在security数据应用到当前图表上的时候,有两个控制,一个是gaps,另一个是lookahead

  • gaps (const bool) 默认值为barmerge.gaps_off。可以理解为数据平滑的操作,因为数据中会存在空值(na),在gaps_off的情况下,na会被离它最近的非空值所替代,也就不会出现间隔(gap)的情况

  • lookahead (const bool) 默认值为barmerge.lookahead_off

    合并所请求数据位置的策略。 请求的条形图与当前的条形图按照k线开盘时间合并。 这种合并策略可能导致从“未来”获取数据计算历史的不良影响。 这在回溯测试策略中不被接受,但在指标中可使用。

    //@version=4
    study('My Script', overlay=true)
    a = security(syminfo.tickerid, '60', low, lookahead=barmerge.lookahead_off)
    plot(a, color=color.red)
    b = security(syminfo.tickerid, '60', low, lookahead=barmerge.lookahead_on)
    plot(b, color=color.lime)

    红色是lookahead_off,绿色是lookahead_on。 我们发现开启了lookahead功能后,所产生的最低价是整个时间段的最低价,而原先是开盘K点的最低价。

bar state.* 变量

  • barstate.isfirst 当前k线为k线组的第一条k线

  • barstate.islast 当前k线为k线组的最后一条k线

  • barstate.ishistory 当前k线为历史k线

  • batstate.isrealtime 当前k线为实时k线

  • barstate.isnew 新K线的第一次更新

  • batstate.isconfirmed =当前k线的最后(关闭)更新

    不建议在security表达式中使用barstate.isconfirmed

所有的历史柱线都曾被认为是新的柱线,因为脚本是依次执行的。当柱线第一更开盘价生成的时候,认为此柱线是新的。

会话和时间信息

Pine 提供方法来生成 交易区间,时间和日期的信息。

time(变量): 返回的是时间戳格式

time(函数):time(resolution, session) → series 返回的是按照session 格式返回的时间,如果不在session时间段的话便会返回na值

//@version=4
study("Time", overlay=true)
t1 = time(timeframe.period, "0000-0000")
bgcolor(t1 ? color.blue : na)

session = "0000-0000:23456" 即24h,去除周六日,运行结果如下

可以看到,周一至周五背景都变成了蓝色,因为t1 不在session的范围内的时候返回na值

交易区间的格式有

  • 0000-0000:1234567 24小时交易,时间从午夜0点开始

  • 0000-0000:23456 工作日24小时交易

  • 1700-1700:24小时交易,时间从17点开始

  • 0930-1700:146 交易时间为09:30~17:00,交易时间在周日(1),周三(4),周五(6)

  • 24x7 等价于 0000-0000:1234567

// 判断是否为30min的新柱线
//@version=4
study("new 30 min bar")
is_newbar(res) =>
t = time(res)
not na(t) and (na(t[1]) or t > t[1])
plot(is_newbar("30") ? 1 : 0)

用到的函数变量和类型

  • time:UNIX格式的当前k线时间
  • timenow:UNIX格式的当前时间
  • syminfo.timezone:时区

当前K线用到的变量

  • year/month/weekofyear
  • dayofmonth
  • dayofweek(sunday,monday 等)
  • hour/minute/second

创建时间

策略编写

backtesting & forwardtesting

strategy脚本是可以产生交易订单的Pine 脚本。利用strategy 可以做策略回测(backtesting)和 模拟交易(forwardtesting)

无论backtesting 还是forwardtesting,计算都是**默认**发生在K线收盘的时候,但是在forwardtesting 的时候,可以选择在每一个tick发生的时候,都运行一次。

做法一是调整strategy的 Setting/Properties,或者修改代码,添加strategy(... ,calc_on_every_tick=true ) ,此外还可以选择在每笔订单完成之后计算strategy(... , calc_on_order_fills=true)

经纪商模拟

仅仅只有OHLC数据的话,K线内数据的生成有一套逻辑,如果最高价更接近开盘价,生成顺序是 open->high->low->close,此外还假设价格是没有gaps的

订单生成命令

strategy.entry 订单生成函数

这是进入市场的命令。 如果具有相同ID的订单已经挂起,则可修改订单。 如果没有指定ID的订单,则会发出新的订单。

要取消/停用预挂单,应使用命令strategy.cancelstrategy.cancel_all

与函数strategy.order相比,strategy.entry功能受金字塔影响,可以正确反转市场位置。 如果“Limit”和“stop”参数均为“NaN”,则订单类型为市场订单。

strategy.entry(id, long, qty, limit, stop, oca_name, oca_type, comment, when) → void

strategy.exit 订单退出函数

strategy.exit(id, from_entry, qty, qty_percent, profit, limit, loss, stop, trail_price, trail_points, trail_offset, oca_name, comment, when) → void

这是一个退出指定进场或整个市场地位的命令,重点区分它和strategy.close 的不同

  • id(string): 订单的标识符。
  • from_entry(string): 这里填入要平仓的订单的标识符,默认为空。
  • qty: 平仓手数(弄清楚合约的大小)
  • qty_percent: 平台的比例
  • profit: 获利点数(一定搞清楚单位是点还是步)
  • limit: 与profit 相似,limit约定获利的价格
  • loss:止损点数
  • stop:与loss 相似,stop约定止损的价格
  • tail.*: 指明跟踪指数

strategy.order

这条命令可以生成开仓也可以生成平仓命令,但是它不受金字塔影响。它的作用就是弥补strategy.entry 和 strategy.exit 函数的不灵活星。

实例

下面是几个例子,可以帮助我们理解strategy函数

例1
//@version=4
strategy("revers demo")
if bar_index > 4000
strategy.entry("buy", strategy.long, 4, when=strategy.position_size <= 0)
strategy.entry("sell", strategy.short, 6, when=strategy.position_size > 0)
plot(strategy.equity)

当仓位为空头或者无头寸的话,买4。当仓位为多头的话,卖6。

我们可以看到entry中buy 或sell 在交易的时候,会自动平仓,平掉反向的仓位。仓位在+4 --> -6 变化。

例2
//@version=4
strategy("Partial exit demo")
if bar_index > 6500 and bar_index <6550
strategy.entry("buy", strategy.long, 40000, when=strategy.position_size <= 0)
strategy.exit("bracket1", "buy", 20000, profit = 3000,loss = 3000)
strategy.exit("bracket2", "buy", profit=2000, loss=2000)
plot(strategy.equity)

盈亏曲线

交易逻辑

  • buy:当空仓时候买入,40000笔合约(40000美金)
  • bracket1:设定平仓对象为buy标识的交易,平仓2000美金,止盈300点(单位为步,3000步=300点)。止损300点
  • bracket2:止盈止损200点

下面结合交易清单具体分析

  • 1:空仓买入4000美金
  • 2:止损200点,亏损20000 * 200 * 0.0001 = $ 400,从图中可以看到是bracket2 先止损
  • 3:价格继续向下,亏损300点,bracket1策略触发,亏损$ 600
  • 4,5,6:同上逻辑

风险管理

strategy.risk.* 一系列函数,可以帮助进行风险管理。当风险管理规则被激活的时候,没有订单会生成。

//@version=4
strategy("multi risk demo", overlay=true, pyramiding=10, calc_on_order_fills = true)
if year > 2014
strategy.entry("LE", strategy.long)
strategy.risk.max_intraday_filled_orders(5)
strategy.risk.max_intraday_filled_orders(2)
  • strategy.risk.max_intraday_filled_orders(2)

    限制一天成交的最大的交易单数,一旦达到,所有未成交订单全部取消,成交订单关闭。并且一直关闭交易直到本交易日结束。

    上图中,当第二笔交易生成的时候,同时也是两笔交易关闭的时间。

  • 其余的函数参考手册

指标重绘

历史数据仅仅包含OHLC,不包含线内的运动。这会导致的问题是,历史数据上的回测和实时数据不一致的情况。

另外一个担心是,未来函数的使用。这里尤其要关注security 函数,此函数可能会错误的引入未来的信息。

绘图

Pine V4 中存在两种绘图类型:label 和 line。

注:用户的绘图和 编程绘图是不一样的,编程得到的绘图是不能用鼠标修改的。

和指标绘图函数(plot,plotshape,plotchar) 不一样的是,绘图函数可以在图表右侧没有K线的地方。

label

label.new(x, y, text, xloc, yloc, color, style, textcolor, size) → series[label]
//@version=4
study("My Script", overlay=true)
label.new(bar_index, high, style=label.style_none,
text="x=" + tostring(bar_index) + "\ny=" + tostring(high))

  • x的位置是用bar_index 标识的,此时xloc 的默认值为xloc.barindex

  • y的位置是最高价

  • xloc取值:xloc.bar_index(默认) 和 xloc.bar_time

  • yloc取值:

    • yloc.price 传入此函数,需要输入y值

    • yloc.abovebar,yloc.belowbar 启动时,y值会失效。标签在图表上部或者下部

  • style: 很多种,可能用到比较多的有label.style_none,无底色

label.set_* 一系列函数可以用来对对象进一步的修改。

line

line.new(x1, y1, x2, y2, xloc, extend, color, style, width) → series[line]
  • extend: extend.none/extend.right/extend.left