Deepwick Script 参考
Deepwick Script 是 Deepwick 图表和回测所用的语言。它运行 Pine Script 的一个子集:ta.*、math.*、str.*、input.*、plot* 和 strategy.* 的多数函数都与 Pine 中完全一致,不支持的代码行会标出行号和列号。这一页列出了引擎目前支持的一切,以及它不支持什么。
第一次用 Deepwick?先看这份分步指南: 如何免费回测一个 Pine Script 策略.
在做一个会写 Deepwick Script 的 AI 助手? 把这份参考当成一份 Markdown 文档.
更新时间:
语言
Deepwick Script 运行 Pine Script 的一个子集,包括枚举、用户自定义类型、方法和 map;//@version 这一行不会被强制校验。脚本按 K 线逐根运行,从最老的一根到最新的一根,每个变量都保留自己的历史。
| 语法 | 作用 |
|---|---|
x = expr / x := expr | 声明一个变量,然后用 := 重新赋值。名字前面可以加一个可选的类型(int、float、bool、string、color、series、simple、const、line、label)。 |
var / varip | 在第一根 K 线上初始化一次,之后各根 K 线沿用这个值。由于脚本运行在已收盘的 K 线上,varip 的行为和 var 一样。 |
x[n] | 历史运算符:n 根之前 x 的值(第一根之前为 na)。 |
if / else | 条件块,缩进四个空格。if 也可以当作表达式使用。 |
cond ? a : b | 三元运算符。 |
switch | 多路分支,可以带一个用于比较的值,也可以不带。 |
for i = a to b [by step] | 计数循环。支持 break 和 continue。 |
while cond | 条件成立时持续循环。 |
f(x, y) => expr | 用户自定义函数,可以写在一行,也可以写成缩进块并返回最后一个表达式。和 Pine 一样,每个调用位置各自保留 ta.* 的状态。 |
[a, b] = f() | 元组:函数可以返回多个值,ta.macd() 和 ta.bb() 这类内置函数就是这样。 |
and / or / not | 逻辑运算符。算术:+ - * / %;比较:== != < <= > >=。 |
声明
| 语法 | 作用 |
|---|---|
indicator(title, shorttitle, overlay, precision) | 声明一个指标:它在图上绘制,没有可回测的对象。study() 作为别名也可以。 |
strategy(title, overlay, initial_capital, default_qty_type, default_qty_value, commission_type, commission_value, slippage, pyramiding) | 声明一个策略。默认值:initial_capital 100000、每单 1 张合约、手续费 0、滑点 0 个 tick、金字塔加仓 1。process_orders_on_close 等其他参数会被忽略。 |
输入
输入会显示在编辑器旁边和指标的设置里,这样不用改代码就能调整它们。
| 语法 | 作用 |
|---|---|
input.int(defval, title, minval, maxval, step) | 整数。 |
input.float(defval, title, minval, maxval, step) | 小数。 |
input.bool(defval, title) | 复选框。 |
input.string(defval, title, options) | 文本,或者一组选项。 |
input.session(defval, title) | 一个交易时段,比如 "0930-1600",或者一组星期,比如 "23456"。把它传给 session.ismarket() 和其它 session.* 判断。 |
input.source(defval, title) | 一个价格来源:open、high、low、close、hl2、hlc3、ohlc4 或 hlcc4。 |
input.color(defval, title) | 取色器。 |
input(defval, title) | 通用输入,类型由默认值决定。 |
K 线数据与时间
时间是 UTC 毫秒。hour() 和其它时间函数可以传入一个时间;hour() 还可以传入一个时区,取自固定的偏移量列表,不含夏令时。
| 语法 | 作用 |
|---|---|
open, high, low, close, volume | 当前 K 线的价格和成交量。 |
hl2, hlc3, ohlc4, hlcc4 | 常用的价格均值。 |
bar_index, last_bar_index | 当前 K 线的序号(0 是最老的一根)和最后一根的序号。 |
time, time_close | K 线的开盘和收盘时间。作为函数 —— time("D")、time(timeframe.period, "0000-0900:23456", "UTC") —— 返回包含当前这根的高周期 K 线的开始(或结束)时间;如果这根 K 线在时段之外,则返回 na。时段写法:"HHMM-HHMM",也可以跨夜,逗号分隔多个窗口,冒号后可跟星期(1 = 周日 … 7 = 周六),以及 "24x7"。 |
timeframe.change(timeframe) | 在每个新周期的第一根 K 线上为真,例如 timeframe.change("D") 在每天的第一根上为真(每周从周一开始)。 |
timestamp(timezone?, year, month, day, hour, minute, second) | 由各部分组成毫秒时间,或由日期字符串得到:timestamp("2026-01-05T09:30:00Z")。 |
dayofweek.sunday … dayofweek.saturday | 用来和 dayofweek(1 … 7)比较的星期常量。 |
session.ismarket, isfirstbar, islastbar, ispremarket, ispostmarket | 时段状态。这里的市场几乎全天交易,所以每根 K 线都在交易时段内;isfirstbar / islastbar 标出每个 UTC 日的第一根和最后一根。 |
year, month, weekofyear, dayofmonth, dayofweek, hour, minute, second | K 线时间的日历字段;也可以传入一个时间来调用,例如 hour(time, "America/New_York")。dayofweek:1 = 周日 … 7 = 周六。 |
barstate.isfirst, islast, isnew, isconfirmed, ishistory, isrealtime | 脚本在 K 线历史中的位置。 |
timeframe.period, multiplier, isintraday, isdaily, isweekly, ismonthly | 图表的周期。 |
syminfo.ticker, tickerid, mintick, pointvalue | 图表的品种、最小价格变动和一个点的价值。 |
技术分析(ta.*)
和 Pine 一样,每个调用位置各自保留状态:写在两行里的两次 ta.ema() 调用是两个互不相干的平均值。K 线不够多之前,结果是 na。
| 语法 | 作用 |
|---|---|
ta.sma(source, length) | 简单移动平均。 |
ta.ema(source, length) | 指数移动平均。 |
ta.rma(source, length) | Wilder 移动平均,RSI 和 ATR 用的是它。 |
ta.wma(source, length) | 加权移动平均。 |
ta.vwma(source, length) | 成交量加权移动平均。 |
ta.hma(source, length) | Hull 移动平均。 |
ta.linreg(source, length, offset) | 线性回归线的数值。 |
ta.vwap(source) | 成交量加权平均价,每天 00:00 UTC 重新开始。 |
ta.rsi(source, length) | 相对强弱指数,0 到 100。 |
ta.macd(source, fastlen, slowlen, siglen) | 返回 [macd, signal, histogram]。 |
ta.stoch(source, high, low, length) | 随机指标 %K,0 到 100。 |
ta.cci(source, length) | 商品通道指数。 |
ta.mfi(series, length) | 资金流量指数。 |
ta.wpr(length) | 威廉指标 %R,-100 到 0。 |
ta.dmi(diLength, adxSmoothing) | 返回 [+DI, -DI, ADX]。 |
ta.supertrend(factor, atrPeriod) | 返回 [supertrend, direction];上涨趋势中 direction 为 -1,下跌趋势中为 1。 |
ta.sar(start, inc, max) | 抛物线 SAR。 |
ta.mom(source, length) | 动量:source 减去 length 根之前的 source。 |
ta.roc(source, length) | 变动率,以百分比表示。 |
ta.change(source, length) | 与 length 根之前的差值(默认为 1)。 |
ta.tr / ta.tr(handle_na) | 真实波幅。 |
ta.atr(length) | 平均真实波幅(Wilder)。 |
ta.bb(series, length, mult) | 布林带:返回 [middle, upper, lower]。 |
ta.bbw(series, length, mult) | 布林带宽度:(upper - lower) / middle。 |
ta.kc(series, length, mult) | 肯特纳通道:返回 [middle, upper, lower],使用真实波幅的 EMA。 |
ta.stdev(source, length, biased) | 标准差。 |
ta.variance(source, length, biased) | 方差。 |
ta.dev(source, length) | 平均绝对偏差。 |
ta.median(source, length) | 中位数。 |
ta.highest(source, length) / ta.highest(length) | 最近 length 根里的最高值(默认为 high)。 |
ta.lowest(source, length) / ta.lowest(length) | 最近 length 根里的最低值(默认为 low)。 |
ta.highestbars(source, length) | 相对最高值的偏移:0 或负数。 |
ta.lowestbars(source, length) | 相对最低值的偏移:0 或负数。 |
ta.rising(source, length) | 如果 source 高于它之前 length 个值中的每一个,则为真。 |
ta.falling(source, length) | 如果 source 低于它之前 length 个值中的每一个,则为真。 |
ta.crossover(source1, source2) | 在 source1 上穿 source2 的那根 K 线上为真。 |
ta.crossunder(source1, source2) | 在 source1 下穿 source2 的那根 K 线上为真。 |
ta.cross(source1, source2) | 任意方向的交叉都为真。 |
ta.pivothigh(source, leftbars, rightbars) | 枢轴高点的价格,要等枢轴之后 rightbars 根才能确定,在此之前是 na。source 可选(默认为 high)。 |
ta.pivotlow(source, leftbars, rightbars) | 枢轴低点的价格,要等枢轴之后 rightbars 根才能确定,在此之前是 na。source 可选(默认为 low)。 |
ta.valuewhen(condition, source, occurrence) | 在最近第 occurrence 根满足 condition 的 K 线上,source 的取值。 |
ta.barssince(condition) | 自 condition 上一次为真以来经过的 K 线数。 |
ta.cum(source) | 从第一根 K 线开始的累计值。 |
其他周期(request.*)
高周期是用图表自己的 K 线拼出来的,所以它不需要引擎手里没有的数据。高周期一根 K 线的值,要等它收盘之后的图表 K 线上才看得见:一根 4 小时 K 线永远无法从自己内部读到,这正是回测保持诚实的原因。
| 语法 | 作用 |
|---|---|
request.security(symbol, timeframe, expression) | 在同一个品种的高周期上运行 expression,返回最后一个已收盘的值。它只对图表自己的品种有效(也可以是 syminfo.tickerid 或空品种);换成别的品种会返回 na,因为引擎手里始终只有图表的 K 线。周期写法接受 Pine 的("60"、"240"、"D"、"W"、"M")和 Deepwick 的("1h"、"4h"、"1d")。expression 可以是一次 ta.* 调用,这时会在高周期序列上求值。在这样一根 K 线收盘之前,返回 na。 |
request.security(..., lookahead) | 接受但忽略。打开 lookahead_on 会让回测读到正在形成的高周期 K 线,那就是偷看未来;引擎从不偷看。gaps 只影响 K 线内部的绘制,这里用不上。 |
策略(strategy.*)
市价单在下一根 K 线开盘时成交。止损单和限价单沿着这根 K 线成交:开盘价,然后是离开盘更近的那个极值,再是另一个极值,最后是收盘价。如果价格跳空越过订单,就按开盘价成交。每次成交都收手续费;滑点适用于市价单和止损单。
| 语法 | 作用 |
|---|---|
strategy.entry(id, direction, qty, limit, stop, comment) | 开仓或加仓;没有指定 limit 或 stop 时就是市价单。 |
strategy.order(id, direction, qty, limit, stop, comment) | 参数和 strategy.entry() 相同。 |
strategy.exit(id, from_entry, qty_percent, profit, limit, loss, stop, trail_points, trail_offset, comment) | 针对某次入场的止盈、止损和移动止损:止盈和止损以 tick 计,limit 和 stop 用价格。trail_points 是距已到过的最好价格的距离(以 tick 计),trail_offset 是移动止损生效之前需要先走出的盈利(以 tick 计)。止损只会向对你有利的方向移动,而且只在已收盘的 K 线上移动,所以任何一根 K 线都不可能触发它自己的最高价所设下的止损。 |
strategy.close(id, comment, qty_percent) | 在下一根 K 线以市价平掉一次入场。 |
strategy.close_all(comment) | 平掉所有持仓。 |
strategy.cancel(id) / strategy.cancel_all() | 撤掉未成交的订单。 |
strategy.position_size, position_avg_price | 当前持仓(多头为正,空头为负)及其均价。 |
strategy.opentrades.entry_bar_index(n), entry_price, entry_time, entry_id, size, profit, commission, max_runup, max_drawdown | 第 n 笔未平仓交易的详情(0 为最老的一笔);没有则为 na。空头的 size 为负数。例如持有 10 根 K 线后平仓:bar_index - strategy.opentrades.entry_bar_index(0) >= 10。 |
strategy.closedtrades.entry_bar_index(n), exit_bar_index, entry_price, exit_price, entry_time, exit_time, entry_id, size, profit, commission, max_runup, max_drawdown | 第 n 笔已平仓交易的详情(0 为最老的一笔;最后一笔是 strategy.closedtrades - 1)。 |
strategy.equity, netprofit, openprofit, grossprofit, grossloss, initial_capital | 账户数值。 |
strategy.closedtrades, opentrades, wintrades, losstrades | 交易笔数。 |
strategy.long, strategy.short | 方向。 |
strategy.fixed, strategy.cash, strategy.percent_of_equity | default_qty_type 的取值。 |
strategy.commission.percent, cash_per_order, cash_per_contract | commission_type 的取值。 |
绘图与提醒
| 语法 | 作用 |
|---|---|
plot(series, title, color, linewidth, style) | 在图表上或独立窗格中绘制一条序列。 |
plotshape(series, title, style, location, color, text) | 在 series 为真的那些 K 线上绘制图形。 |
plotchar(series, title, char, location, color) | 在 series 为真的那些 K 线上绘制字符。 |
hline(price, title, color, linestyle) | 固定水平上的水平线。 |
fill(plot1, plot2, color) | 在两条绘图线或两条 hline 之间填充。 |
bgcolor(color) | 给 K 线背景上色。 |
barcolor(color) | 给 K 线本身上色。 |
alertcondition(condition, title, message) | 声明一个条件,可以把它变成邮件、Telegram、Discord 或 webhook 提醒。 |
plot.style_* | line、linebr、stepline、histogram、columns、circles、cross、area。 |
hline.style_* | solid、dashed、dotted。 |
shape.* | triangleup, triangledown, arrowup, arrowdown, circle, xcross, cross, diamond, square, flag, labelup, labeldown. |
location.* | abovebar、belowbar、top、bottom、absolute。 |
size.* | auto、tiny、small、normal、large、huge。可以接受,但图形只按一种大小绘制。 |
线与方框
| 语法 | 作用 |
|---|---|
line.new(x1, y1, x2, y2, extend, color, style, width) | 在两个 K 线序号和两个价格之间画一条线,返回它的 id。 |
line.set_x1, set_y1, set_x2, set_y2, set_xy1, set_xy2, set_color, set_style, set_width | 修改一条线。 |
line.delete(id) | 删除一条线。 |
box.new(left, top, right, bottom, border_color, bgcolor, extend) | 画一个矩形,返回它的 id。 |
box.set_left, set_top, set_right, set_bottom, set_bgcolor, set_border_color, set_extend | 修改一个方框。 |
box.delete(id) | 删除一个方框。 |
line.style_*, box.style_* | solid、dashed、dotted。 |
extend.* | none、left、right、both。 |
数学、字符串与颜色
| 语法 | 作用 |
|---|---|
math.abs, ceil, floor, round(number, precision), sign, sqrt, exp, log, log10, pow(base, exponent) | 算术。 |
math.max(...), math.min(...), math.avg(...) | 对任意多个值。 |
math.sum(source, length) | 最近 length 根 K 线的总和。 |
math.pi, math.e | 常量。 |
na, na(x), nz(x, replacement), fixnan(x) | 缺失值、对它的判断、对它的替换,以及最后一个非 na 的值。 |
int(x), float(x), bool(x) | 类型转换。 |
str.tostring(value, format), str.format(text, ...), str.length(s), str.contains(s, part) | 字符串。str.format 用参数替换 {0}、{1}…。 |
color.new(color, transp), color.rgb(red, green, blue, transp) | 构造一种颜色;透明度从 0 到 100。 |
color.* | red, green, blue, orange, yellow, purple, aqua, lime, fuchsia, teal, maroon, navy, olive, gray, silver, white, black. |
数组(array.*)
| 语法 | 作用 |
|---|---|
array.new_float, new_int, new_bool, new_string, new_color, new_line, new_box, new_label, new_table(size) | 创建一个数组。 |
array.get, set, insert, push, pop, shift, unshift | 读取和修改元素。 |
array.size, first, last, sum, avg, min, max, stdev | 长度与统计。 |
Map 与用户自定义类型
支持用户自定义类型和 `map.<fn>` 集合。两者都是顶层声明;作用于某个值的方法用 `obj.method(args...)` 的写法。
| 语法 | 作用 |
|---|---|
enum Name
Member
Member = N
... | 顶层枚举声明。没有写值的成员从 0 开始自动递增;显式值可以是数字或字符串。在任何表达式位置都可以用 `Name.Member` 访问。枚举值就是普通的数字(或字符串),所以可以直接和比较运算符配合,也可以不转换就传给 `int()`。 |
type Name
field1
field2: int
field3 = default | 顶层用户自定义类型。字段一行一个;`: type` 和 `= default` 这两部分为了向前兼容被接受,但目前还没有校验。用 `Type.new(arg1, arg2, ...)` 构造,用 `instance.field` 读取字段。 |
m = map.new<int, float>() | 创建一个空的 map。类型参数 `<K, V>` 会被接受,但运行时忽略。 |
m = map.put(m, key, value) | 设置一个键。返回这个 map,所以调用可以链式书写或重新赋值。 |
v = map.get(m, key) | 读取一个值。键不存在时返回 na。 |
n = map.size(m) | 条目数量。 |
keys = map.keys(m), values = map.values(m) | 以 Pine 数组返回键或值(按插入顺序)。 |
map.contains(m, key), map.remove(m, key) | 成员判断和删除。两者都返回这个 map。 |
还不支持
调用引擎不认识的函数时,脚本会带着「Unknown function」以及行号和列号停下来。
| 语法 | 作用 |
|---|---|
label.new(), table.new() | 还不可用。线和方框可以。 |
import, matrix.*, array.new<type>() | 库、矩阵和带类型的数组构造函数还没有实现。 |
strategy.risk.* | 风控规则(max_position_size、max_intraday_loss、max_drawdown、allow_entry_in)还不支持。strategy.exit() 里的移动止损支持:用 trail_points 和 trail_offset。 |
常见问题
Deepwick Script 和 Pine Script 是一样的吗?
不是。它是 Deepwick 自己的引擎,运行 Pine Script 的一个子集:就是这一页上的函数。ta.*、math.*、str.*、input.*、plot* 和 strategy.* 的大部分调用都能照常运行;不支持的代码行会标出行号和列号。Deepwick 与 TradingView 无隶属关系;Pine Script 是 TradingView, Inc. 的商标。
Deepwick Script 支持 Pine Script 的哪些功能?
Deepwick Script 运行 Pine Script 的一个子集,包括枚举、用户自定义类型(`type`)、方法声明和 `map.*` 集合。还没有实现的有:库(`import`)、`matrix.*` 以及带类型的 `array.new<type>()` 构造函数;编辑器会用准确的行号和列号指出来。//@version 这一行不会被强制校验。把脚本粘进编辑器就能看到哪些行会运行。
Deepwick 支持 request.security() 吗?
支持,但只针对图表自己品种的高周期。request.security(syminfo.tickerid, "240", close) 返回最近一根已收盘的 4 小时 K 线的收盘价,expression 也可以是一次 ta.* 调用。换成别的品种仍然返回 na:引擎手里始终只有图表的 K 线,一个看起来合理但错误的数字比没有数字更糟。
为什么 request.security() 在最开始的几根 K 线上返回 na?
因为还没有任何高周期 K 线收盘。4 小时 K 线只有在它收盘之后的那根图表 K 线上才读得到,而这正是让回测读不到正在形成的 K 线的机制。一旦有一根收盘,这个值就会一直重复到下一根收盘为止。
回测里策略订单是怎么成交的?
市价单在下一根 K 线开盘时成交。止损单和限价单沿着这根 K 线成交(开盘价、离开盘更近的极值、更远的极值、收盘价),价格跳空越过订单时按开盘价成交。每次成交都收手续费,市价单和止损单还会计入滑点,都由 strategy() 设定,默认都是 0。
脚本在哪里运行?
在图表上,在你的浏览器里,基于图表已加载的 K 线运行。保存的回测在 Deepwick 的服务器上运行,最多 5,000 根 K 线。