Итак, мы видим, что на трех выведенных линиях a, b и c линия b на один бар медленнее линии a, а линия c на один бар медленнее линии b.
Мы можем перетащить диаграмму в крайнее левое и наблюдать, что на первой K-линии оба значения b и c являются нулевыми (na). Это потому, что когда скрипт выполняется на первой K-линии BAR, он не существует при ссылке на историческое значение одного или двух периодов вперед, которое не существует. Поэтому нам нужно быть осторожными при написании стратегий, чтобы проверить, приведет ли ссылка на исторические данные к нулевым значениям. Если использовать нулевое значение небрежно, это вызовет ряд расчетных различий и может даже повлиять на BAR в режиме реального времени. Обычно мы будем использовать встроенные функцииna
, nz
чтобы судить в кодексе (на самом деле, мы также столкнулисьnz
, ```na `` в наших предыдущих видеороликах, помните, какая глава это?) занимаются случаем нулевых значений, например:
close > nz(close[1], open) // When referencing the historical value of the previous BAR of the close built-in variable, if it does not exist, the open built-in variable is used
Это способ обработки возможных ссылок на нулевые значения (na).
Мы выучили много операторов в языке Пайн. Эти операторы формируют выражения через различные комбинации с операндами. Итак, каков приоритет этих операций при оценке в выражениях? Точно так же, как арифметика, которую мы изучали в школе, умножение и деление вычисляются сначала, а затем добавление и вычитание. То же самое относится к выражениям в языке Пайн.
Приоритетность | Операторы |
---|---|
9 | [] |
8 | + 、- иnot в униарном операторе |
7 | * 、/ 、% |
6 | + 、- в бинарном операторе |
5 | > 、< 、>= 、<= |
4 | == 、!= |
3 | and |
2 | or |
1 | ?: |
Высокоприоритетные выражения вычисляются первыми, и если приоритеты одинаковы, он оценивается слева направо.()
чтобы завершить выражение, чтобы заставить часть оцениваться первой.
Мы уже изучали понятие
Режим декларирования:
Первое, что нужно написать при декларировании переменной, это
var
.varip
.Вvar
иvarip
Ключевые слова были изучены в нашей предыдущей главеAssignment Operators
, поэтому мы не будем вдаваться в детали здесь. Если ничего не написано для режима декларации переменной, например, утверждение:i = 1
, как мы также упоминали ранее, такая переменная, объявленная и назначенная, выполняется на каждой K-линии BAR.
Тип Язык Pine на FMZ не является строгим в отношении типов, и его обычно можно опустить.
int i = 0
float f = 1.1
Требования к типу в Trading View достаточно строги, и будет сообщена ошибка, если в Trading View используется следующий код:
baseLine0 = na // compile time error!
Маркер Маркеры - это имена переменных.https://www.fmz.com/bbs-topic/9637#markers
Подводя итог, объявление переменной может быть написано так:
// [<declaration_mode>] [<type>] <marker> = value
declaration mode type marker = value
Оператор назначения используется здесь:=
При присвоении значения может быть строка, число, выражение, вызов функции,if
, for
, while
, илиswitch
и другие структуры (эти структурные ключевые слова и использование заявления будут подробно объяснены в последующих курсах.
Здесь мы сосредоточимся на функции ввода, которая является функцией, которую мы будем часто использовать при разработке и написании стратегий.
функция ввода:
input function, parameters: defval、title、tooltip、inline、group
Функция ввода на FMZ несколько отличается от той, что на Trading View, но эта функция используется в качестве ввода назначения параметров стратегии.
param1 = input(10, title="name of param1", tooltip="description for param1", group="group name A")
param2 = input("close", title="name of param2", tooltip="description for param2", group="group name A")
param3 = input(color.red, title="name of param3", tooltip="description for param3", group="group name B")
param4 = input(close, title="name of param4", tooltip="description for param4", group="group name B")
param5 = input(true, title="name of param5", tooltip="description for param5", group="group name C")
ma = ta.ema(param4, param1)
plot(ma, title=param2, color=param3, overlay=param5)
Функция ввода часто используется для присвоения значений переменным при их декларировании. Функция ввода на FMZ автоматически набирает элементы управления для настройки параметров стратегии в интерфейсе стратегии FMZ. В настоящее время в FMZ поддерживаются элементы управления, включающие цифровые поля ввода, текстовые поля ввода, выпадающие ящики и булевые контрольные ящики.
Мы представляем несколько основных параметров входной функции:
В дополнение к декларированию и назначению отдельных переменных, существует также способ декларирования группы переменных и назначения их на языке Pine:
[Variable A, Variable B, Variable C] = function or structure, such as ```if```, ```for```, ```while``` or ```switch```
Наиболее распространенным является когда мы используемta.macd
Поскольку индикатор MACD представляет собой многолинейный индикатор, рассчитываются три набора данных.
[dif,dea,column] = ta.macd(close, 12, 26, 9)
plot(dif, title="dif")
plot(dea, title="dea")
plot(column, title="column", style=plot.style_histogram)
Мы можем легко нарисовать график MACD с помощью вышеперечисленного кода. Не только встроенные функции могут возвращать несколько переменных, но и написанные пользовательские функции могут возвращать несколько данных.
twoEMA(data, fastPeriod, slowPeriod) =>
fast = ta.ema(data, fastPeriod)
slow = ta.ema(data, slowPeriod)
[fast, slow]
[ema10, ema20] = twoEMA(close, 10, 20)
plot(ema10, title="ema10", overlay=true)
plot(ema20, title="ema20", overlay=true)
Метод написания использования if и других структур в качестве заданий множественных переменных также похож на вышеуказанную пользовательскую функцию, и вы можете попробовать ее, если вы заинтересованы.
[ema10, ema20] = if true
fast = ta.ema(close, 10)
slow = ta.ema(close, 20)
[fast, slow]
plot(ema10, title="ema10", color=color.fuchsia, overlay=true)
plot(ema20, title="ema20", color=color.aqua, overlay=true)
Некоторые функции не могут быть написаны в локальном кодовом блоке условной ветви, в основном включая следующие функции:
barcolor ((), fill ((), hline ((), indicator ((), plot ((), plotcandle ((), plotchar ((), plotshape (())
Trading View будет компилировать с ошибками, FMZ не так ограничивает, но рекомендуется следовать спецификациям Trading View.
strategy("test", overlay=true)
if close > open
plot(close, title="close")
else
plot(open, title="open")
Пример объяснения:
var lineColor = na
n = if bar_index > 10 and bar_index <= 20
lineColor := color.green
else if bar_index > 20 and bar_index <= 30
lineColor := color.blue
else if bar_index > 30 and bar_index <= 40
lineColor := color.orange
else if bar_index > 40
lineColor := color.black
else
lineColor := color.red
plot(close, title="close", color=n, linewidth=5, overlay=true)
plotchar(true, title="bar_index", char=str.tostring(bar_index), location=location.abovebar, color=color.red, overlay=true)
Ключевой момент: выражения, используемые для суждений, которые возвращают булевые значения. Обратите внимание на отступление. Может быть максимум еще одна ветвь. Если все выражения ветвей не соответствуют действительности и нет другой ветви, верните na.
x = if close > open
close
plot(x, title="x")
Указание switch также является структурным указанием, которое используется для проектирования различных путей, которые должны быть выполнены в соответствии с определенными условиями.
Есть две формы переключения, давайте посмотрим на примеры один за другим, чтобы понять их использование.
switch
с выражениями - пример объяснения:// input.string: defval, title, options, tooltip
func = input.string("EMA", title="indicator name", tooltip="select the name of the indicator function to be used", options=["EMA", "SMA", "RMA", "WMA"])
// input.int: defval, title, options, tooltip
// param1 = input.int(10, title="period parameter")
fastPeriod = input.int(10, title="fastPeriod parameter", options=[5, 10, 20])
slowPeriod = input.int(20, title="slowPeriod parameter", options=[20, 25, 30])
data = input(close, title="data", tooltip="select the closing price, opening price, highest price...")
fastColor = color.red
slowColor = color.red
[fast, slow] = switch func
"EMA" =>
fastLine = ta.ema(data, fastPeriod)
slowLine = ta.ema(data, slowPeriod)
fastColor := color.red
slowColor := color.red
[fastLine, slowLine]
"SMA" =>
fastLine = ta.sma(data, fastPeriod)
slowLine = ta.sma(data, slowPeriod)
fastColor := color.green
slowColor := color.green
[fastLine, slowLine]
"RMA" =>
fastLine = ta.rma(data, fastPeriod)
slowLine = ta.rma(data, slowPeriod)
fastColor := color.blue
slowColor := color.blue
[fastLine, slowLine]
=>
runtime.error("error")
plot(fast, title="fast" + fastPeriod, color=fastColor, overlay=true)
plot(slow, title="slow" + slowPeriod, color=slowColor, overlay=true)
Мы изучали входную функцию раньше, здесь мы продолжаем изучать две функции, похожие на вход:input.string
, input.int
functions.
input.string
используется для возвращения строки, иinput.int
В примере, есть новое использованиеoptions
параметр.options
параметр может быть передан массив необязательных значений, таких какoptions=["EMA", "SMA", "RMA", "WMA"]
иoptions=[5, 10, 20]
в примере (заметьте, что один из них - тип строки, другой - числовой тип). Таким образом, элементам управления на интерфейсе стратегии не нужно вводить конкретные значения, но элементы управления становятся выпадающими окнами для выбора этих опций, предоставленных в параметре опций.
Значение переменной func представляет собой строку, и переменная func используется в качестве выражения для переключения (которое может быть переменной, вызовом функции или выражением), чтобы определить, какая ветвь в переключателе выполняется.runtime.error("error")
Функция будет выполнена, что заставляет стратегию бросить исключение и остановиться.
В нашем тестовом коде выше, после последней строки runtime.error в блоке кода раздела по умолчанию переключателя, мы не добавили код вроде [na, na] для совместимости с возвращаемым значением. Эта проблема должна быть рассмотрена в Trading View. Если тип несовместим, будет сообщена ошибка. Но на FMZ, поскольку тип не является строго необходимым, этот код совместимости может быть пропущен. Поэтому нет необходимости рассматривать совместимость типа возвращаемого значения if и switch branches на FMZ.
strategy("test", overlay=true)
x = if close > open
close
else
"open"
plotchar(true, title="x", char=str.tostring(x), location=location.abovebar, color=color.red)
Ошибки не будут сообщаться на FMZ, но ошибка будет сообщаться на торговом виде.
switch
без выраженийДалее, давайте посмотрим на другой способ использованияswitch
, то есть без выражений.
up = close > open // up = close < open
down = close < open
var upOfCount = 0
var downOfCount = 0
msgColor = switch
up =>
upOfCount += 1
color.green
down =>
downOfCount += 1
color.red
plotchar(up, title="up", char=str.tostring(upOfCount), location=location.abovebar, color=msgColor, overlay=true)
plotchar(down, title="down", char=str.tostring(downOfCount), location=location.belowbar, color=msgColor, overlay=true)
Как мы можем видеть из примера тестового кода, switch будет соответствовать выполнению локального кодового блока, который является истинным при условии ветви. В целом, условия ветви, следующие за инструкцией switch, должны быть взаимоисключающими. То есть, вверх и вниз в примере не могут быть истинными одновременно. Поскольку switch может выполнять только локальный кодовый блок одной ветви, если вы заинтересованы, вы можете заменить эту строку в коде:up = close > open // up = close < open
Вы обнаружите, что ветвь переключателя может выполнять только первую ветвь. Кроме того, необходимо обратить внимание на то, чтобы не писать вызовы функций в ветви переключателя, насколько это возможно, функция не может быть вызвана на каждом BAR, что может вызвать некоторые проблемы с расчетом данных (если только в примере "switch
с выражениями", ветвь исполнения является детерминированной и не будет изменена во время операции стратегии).
return value = for count = start count to final count by step length
statement // Note: There can be break and continue in the statement
statement // Note: The last statement is the return value
Заявление for очень простое в использовании, петля for может в конечном итоге вернуть значение (или несколько значений, в виде [a, b, c]). Как и переменная, присвоенная позиции
Вbreak
Ключевое слово, используемое в цикле for: цикл прекращается, когдаbreak
Заявление выполнено.
Вcontinue
Ключевое слово, используемое в цикле "for":continue
когда выполняется заявление, петля будет игнорировать код послеcontinue
и выполнять следующий раунд петли напрямую. Заявление for возвращает значение от последнего выполнения петли. и возвращает null, если код не выполнен.
Затем мы покажем с помощью простого примера:
ret = for i = 0 to 10 // We can increase the keyword by to modify the step length, FMZ does not support reverse loops such as i = 10 to 0 for now
// We can add condition settings, use continue to skip, use break to jump out
runtime.log("i:", i)
i // If this line is not written, it will return null because there is no variable to return
runtime.log("ret:", ret)
runtime.error("stop")
Вfor ... in
Заявление имеет две формы, мы покажем их в следующем псевдокоде.
return value = for array element in array
statement // Note: There can be break and continue in the statement
statement // Note: The last statement is the return value
Return value = for [index variable, array element corresponding to index variable] in array
statement // Note: There can be break and continue in the statement
statement // Note: The last statement is the return value
Мы можем видеть, что основное различие между двумя формами заключается в содержании, которое следует за ключевым словом for, одна из них - использование переменной в качестве переменной, которая относится к элементам массива, другая - использование структуры, содержащей индексные переменные, тупли переменных элементов массива в качестве ссылок. Для других правил возвращения значений, таких как использование перерыва, продолжения и т. Д., Соответствуют для петль.
testArray = array.from(10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
for ele in testArray // Modify it to the form of [i, ele]: for [i, ele] in testArray, runtime.log("ele:", ele, ", i:", i)
runtime.log("ele:", ele)
runtime.error("stop")
Когда нужно использовать индекс, используйте грамматикуfor [i, ele] in testArray
.
Применение для циклов
Мы можем использовать встроенные функции, предоставленные в языке Pine, для выполнения некоторых логических вычислений петли, либо написанных с использованием структуры петли напрямую, либо обработанных с использованием встроенных функций.
При проектировании с конструкцией петли:
length = 5
var a = array.new(length)
array.push(a, close)
if array.size(a) >= length
array.remove(a, 0)
sum = 0
for ele in a
sum += ele
avg = sum / length
plot(avg, title="avg", overlay=true)
В примере используется петля for для расчета суммы, а затем вычислить среднее значение.
Расчет скользящей средней напрямую с помощью встроенной функции:
plot(ta.sma(close, length), title="ta.sma", overlay=true)
Использовать встроенную функциюta.sma
Для расчета скользящей средней, очевидно, проще использовать встроенную функцию. Сравнивая на графике, можно увидеть, что рассчитанные результаты точно одинаковы.
Мы все еще используем приведенный выше пример для иллюстрации.
При проектировании с конструкцией петли:
length = 5
var a = array.new(length)
array.push(a, close)
if array.size(a) >= length
array.remove(a, 0)
sum = 0
for ele in a
sum += ele
avg = sum / length
plot(avg, title="avg", overlay=true)
plot(ta.sma(close, length), title="ta.sma", overlay=true)
Для вычисления суммы всех элементов в массиве, мы можем использовать петлю, чтобы обработать его, или использовать встроенную функциюarray.sum
чтобы рассчитать.
Вычислить сумму непосредственно с помощью встроенной функции:
length = 5
var a = array.new(length)
array.push(a, close)
if array.size(a) >= length
array.remove(a, 0)
plot(array.sum(a) / length, title="avg", overlay=true)
plot(ta.sma(close, length), title="ta.sma", overlay=true)
Мы можем видеть, что рассчитанные данные точно такие же, как и те, которые отображаются на графике с использованием графиков.
Так зачем создавать петли, когда мы можем делать все это с встроенными функциями?
Вwhile
Заявление сохраняет код в секции петли, выполняющейся до тех пор, пока условие суждения в структуре while не будет ложным.
return value = while judgment condition
statement // Note: There can be break and continue in the statement
statement // Note: The last statement is the return value
Другие правила while аналогичны правилам цикла for. Последней строкой локального кодового блока тела цикла является значение возврата, которое может возвращать несколько значений. Выполнить цикл, когда условие
Мы все равно будем использовать пример вычисления скользящих средних для демонстрации:
length = 10
sma(data, length) =>
i = 0
sum = 0
while i < 10
sum += data[i]
i += 1
sum / length
plot(sma(close, length), title="sma", overlay=true)
plot(ta.sma(close, length), title="ta.sma", overlay=true)
Мы можем видеть, что петля while также очень проста в использовании, и также возможно разработать некоторую логику вычисления, которую нельзя заменить встроенными функциями, такими как вычисление фактора:
counter = 5
fact = 1
ret = while counter > 0
fact := fact * counter
counter := counter - 1
fact
plot(ret, title="ret") // ret = 5 * 4 * 3 * 2 * 1
Определение массивов в языке Pine похоже на определение массивов в других языках программирования. Массивы Pine[]
чтобы ссылаться на элемент в массиве, мы должны использовать функцииarray.get()
иarray.set()
Индексовый порядок элементов в массиве заключается в том, что индекс первого элемента массива равен 0, а индекс следующего элемента увеличивается на 1.
Мы проиллюстрируем это простым кодом:
var a = array.from(0)
if bar_index == 0
runtime.log("current value a on BAR:", a, ", a on the last BAR, i.e. the value of a[1]:", a[1])
else if bar_index == 1
array.push(a, bar_index)
runtime.log("current value a on BAR:", a, ", a on the last BAR, i.e. the value of a[1]:", a[1])
else if bar_index == 2
array.push(a, bar_index)
runtime.log("current value a on BAR:", a, ", a on the last BAR, i.e. the value of a[1]:", a[1], ", a on the last second BAR, i.e. the value of a[2]:", a[2])
else if bar_index == 3
array.push(a, bar_index)
runtime.log("current value a on BAR:", a, ", a on the last BAR, i.e. the value of a[1]:", a[1], ", a on the last second BAR, i.e. the value of a[2]:", a[2], ", a on the last third BAR, i.e. the value of a[3]:", a[3])
else if bar_index == 4
// Obtain elements by index using array.get, modify elements by index using array.set
runtime.log("Before array modification:", array.get(a, 0), array.get(a, 1), array.get(a, 2), array.get(a, 3))
array.set(a, 1, 999)
runtime.log("After array modification:", array.get(a, 0), array.get(a, 1), array.get(a, 2), array.get(a, 3))
Использованиеarray<int> a
, float[] b
чтобы объявить массив или просто объявить переменную, которая может быть присвоена массиву, например:
array<int> a = array.new(3, bar_index)
float[] b = array.new(3, close)
c = array.from("hello", "fmz", "!")
runtime.log("a:", a)
runtime.log("b:", b)
runtime.log("c:", c)
runtime.error("stop")
Переменные массива инициируются с помощьюarray.new
иarray.from
Существует также множество типовых функций, похожих наarray.newна языке соснового:array.new_int()
, array.new_bool()
, array.new_color()
, array.new_string()
, и т.д.
Ключевое слово var также работает с режимом декларирования массива. Массивы, декларируемые с ключевым словом var, инициируются только на первом BAR. Давайте посмотрим на пример:
var a = array.from(0)
b = array.from(0)
if bar_index == 1
array.push(a, bar_index)
array.push(b, bar_index)
else if bar_index == 2
array.push(a, bar_index)
array.push(b, bar_index)
else if barstate.islast
runtime.log("a:", a)
runtime.log("b:", b)
runtime.error("stop")
Можно увидеть, что изменения массива a были непрерывно определены и не были сброшены. массив b инициируется на каждом BAR. Наконец, когдаbarstate.islast
Это правда, есть только один элемент, напечатанный с значением 0.
Используйте array.get, чтобы получить элемент в указанном индексе в массиве, и используйте array.set, чтобы изменить элемент в указанном индексе в массиве.
Первый параметр array.get - это массив, который должен быть обработан, а второй параметр - указанный индекс. Первый параметр array.set - это массив, который должен быть обработан, второй параметр - указанный индекс, а третий параметр - элемент, который должен быть записан.
Мы используем следующий простой пример для иллюстрации:
lookbackInput = input.int(100)
FILL_COLOR = color.green
var fillColors = array.new(5)
if barstate.isfirst
array.set(fillColors, 0, color.new(FILL_COLOR, 70))
array.set(fillColors, 1, color.new(FILL_COLOR, 75))
array.set(fillColors, 2, color.new(FILL_COLOR, 80))
array.set(fillColors, 3, color.new(FILL_COLOR, 85))
array.set(fillColors, 4, color.new(FILL_COLOR, 90))
lastHiBar = - ta.highestbars(high, lookbackInput)
fillNo = math.min(lastHiBar / (lookbackInput / 5), 4)
bgcolor(array.get(fillColors, int(fillNo)), overlay=true)
plot(lastHiBar, title="lastHiBar")
plot(fillNo, title="fillNo")
Пример инициализирует базовый цвет зеленый, объявляет и инициализирует массив для хранения цветов, а затем присваивает различные значения прозрачности цветам (используяcolor.newУровень цвета рассчитывается путем расчета расстояния текущего BAR от максимального значения высокого в 100 периодов просмотра. Чем ближе расстояние к максимальному значению HIGH в последних 100 циклах просмотра, тем выше рейтинг и тем темнее (ниже прозрачность) соответствующее цветовое значение.
Как итерации через массив, мы можем использовать для / для в / в то время как заявления, которые мы узнали раньше.
a = array.from(1, 2, 3, 4, 5, 6)
for i = 0 to (array.size(a) == 0 ? na : array.size(a) - 1)
array.set(a, i, i)
runtime.log(a)
runtime.error("stop")
a = array.from(1, 2, 3, 4, 5, 6)
i = 0
while i < array.size(a)
array.set(a, i, i)
i += 1
runtime.log(a)
runtime.error("stop")
a = array.from(1, 2, 3, 4, 5, 6)
for [i, ele] in a
array.set(a, i, i)
runtime.log(a)
runtime.error("stop")
Эти три метода прохождения имеют одинаковые результаты выполнения.
Массивы могут быть объявлены в глобальном масштабе скрипта или в локальном масштабе функции или if-отдела.
Для использования элементов в массивах следующие способы эквивалентны. Мы можем увидеть на следующем примере, что на графике нарисованы два набора линий, по два в каждом наборе, и две линии в каждом наборе имеют точно одно и то же значение.
a = array.new_float(1)
array.set(a, 0, close)
closeA1 = array.get(a, 0)[1]
closeB1 = close[1]
plot(closeA1, "closeA1", color.red, 6)
plot(closeB1, "closeB1", color.black, 2)
ma1 = ta.sma(array.get(a, 0), 20)
ma2 = ta.sma(close, 20)
plot(ma1, "ma1", color.aqua, 6)
plot(ma2, "ma2", color.black, 2)
array.unshift()
, array.insert()
, array.push()
.
array.remove()
, array.shift()
, array.pop()
, array.clear()
.
Мы используем следующий пример для проверки этих функций добавления и удаления массива.
a = array.from("A", "B", "C")
ret = array.unshift(a, "X")
runtime.log("array a:", a, ", ret:", ret)
ret := array.insert(a, 1, "Y")
runtime.log("array a:", a, ", ret:", ret)
ret := array.push(a, "D")
runtime.log("array a:", a, ", ret:", ret)
ret := array.remove(a, 2)
runtime.log("array a:", a, ", ret:", ret)
ret := array.shift(a)
runtime.log("array a:", a, ", ret:", ret)
ret := array.pop(a)
runtime.log("array a:", a, ", ret:", ret)
ret := array.clear(a)
runtime.log("array a:", a, ", ret:", ret)
runtime.error("stop")
Применение добавлений, удалений: массивы как очереди
Мы можем построить структуру данных
Очередь - это структура, которая часто используется в области программирования, характеристиками очереди являются:
Элемент, который входит в очередь первым, выходит из очереди первым.
Таким образом, он гарантирует, что данные в очереди являются последними данными, и что длина очереди не будет расширяться бесконечно.
В следующем примере мы используем структуру очереди для записи цены каждого тика, вычисляем среднемобильную цену на уровне тика, а затем сравниваем ее с скользящей средней на уровне 1-минутной линии K.
strategy("test", overlay=true)
varip a = array.new_float(0)
var length = 10
if not barstate.ishistory
array.push(a, close)
if array.size(a) > length
array.shift(a)
sum = 0.0
for [index, ele] in a
sum += ele
avgPrice = array.size(a) == length ? sum / length : na
plot(avgPrice, title="avgPrice")
plot(ta.sma(close, length), title="ta.sma")
Обратите внимание, что при декларировании массива a, мы указываем режим декларирования и используем ключевое словоvariant
Таким образом, каждое изменение цены будет записываться в массиве a.
Расчет корреляционных функций:
array.avg()
вычисляет среднее значение всех элементов массива,array.min()
вычисляет самый маленький элемент в массиве,array.max()
вычисляет самый маленький элемент в массиве,array.stdev()
вычисляет стандартное отклонение всех элементов массива,array.sum()
вычисляет стандартное отклонение всех элементов в массиве.
Функции, связанные с эксплуатацией:array.concat()
чтобы объединить или соединить два массива.array.copy()
чтобы скопировать массив.array.join
to соединяет все элементы массива в строку.array.sort()
отсортировать по восходящему или нисходящему порядку.array.reverse()
чтобы перевернуть массив.array.slice()
чтобы разрезать массив.array.includes()
чтобы судить элемент.array.indexof()
Если значение не найдено, возвращается -1.array.lastindexof()
чтобы найти последнее происхождение значения.
Примеры испытаний функций, связанных с расчетом массива:
a = array.from(3, 2, 1, 4, 5, 6, 7, 8, 9)
runtime.log("Arithmetic average of the array a:", array.avg(a))
runtime.log("The minimum element in the array a:", array.min(a))
runtime.log("The maximum element in the array a:", array.max(a))
runtime.log("Standard deviation in array a:", array.stdev(a))
runtime.log("Sum of all elements of the array a:", array.sum(a))
runtime.error("stop")
Это обычно используемые функции расчета массива.
Примеры операционных функций:
a = array.from(1, 2, 3, 4, 5, 6)
b = array.from(11, 2, 13, 4, 15, 6)
runtime.log("array a: ", a, ", array b: ", b)
runtime.log("array a, array b is concatenated with:", array.concat(a, b))
c = array.copy(b)
runtime.log("Copy an array b and assign it to the variable c, variable c:", c)
runtime.log("use array.join to process the array c, add the symbol + to the middle of each element, concatenating all elements results in a string:", array.join(c, "+"))
runtime.log("Sort the array b, in order from smallest to largest, using the parameter order.ascending:", array.sort(b, order.ascending)) // array.sort function modifies the original array
runtime.log("Sort the array b, in order from largest to smallest, using the parameter order.descending:", array.sort(b, order.descending)) // array.sort function modifies the original array
runtime.log("array a:", a, ", array b:", b)
array.reverse(a) // This function modifies the original array
runtime.log("reverse the order of all elements in the array a, after reversing, the array a is:", a)
runtime.log("Intercept array a, index 0~index 3, and follow the rule of left-closed and right-open interval:", array.slice(a, 0, 3))
runtime.log("Search for element 11 in array b:", array.includes(b, 11))
runtime.log("Search for element 100 in array a:", array.includes(a, 100))
runtime.log("Connect array a and array b, and search the index position of the first occurrence of element 2:", array.indexof(array.concat(a, b), 2), " , observe array.concat(a, b):", array.concat(a, b))
runtime.log("Connect array a and array b, and search the index position of the last occurrence of element 6:", array.lastindexof(array.concat(a, b), 6), " , observe array.concat(a, b):", array.concat(a, b))
runtime.error("stop")
Язык Pine может быть разработан с помощью пользовательских функций.
barcolor(), fill(), hline(), plot(), plotbar(), plotcandle()
) не может быть вызвано в пользовательских функциях.Мы также использовали пользовательские функции много раз в наших предыдущих учебниках, такие как те, которые разработаны как одна строка:
barIsUp() => close > open
является ли текущая BAR положительной прямой, когда функция возвращается.
Специальные функции, предназначенные для множественных линий:
sma(data, length) =>
i = 0
sum = 0
while i < 10
sum += data[i]
i += 1
sum / length
plot(sma(close, length), title="sma", overlay=true)
plot(ta.sma(close, length), title="ta.sma", overlay=true)
Мы используем пользовательскую функцию, чтобы реализовать функцию среднего расчета.
Кроме того, два примера пользовательских функций, которые мы можем вернуть:
twoEMA(data, fastPeriod, slowPeriod) =>
fast = ta.ema(data, fastPeriod)
slow = ta.ema(data, slowPeriod)
[fast, slow]
[ema10, ema20] = twoEMA(close, 10, 20)
plot(ema10, title="ema10", overlay=true)
plot(ema20, title="ema20", overlay=true)
Одна функция может вычислить быструю линию, медленную линию и два средних показателя EMA.
Встроенные функции можно легко найти вСкрипт FMZ PINE.
Классификация встроенных функций на языке Pine:
str.
series.color.
series.input.
series.ta.
series.plot.
series.array.
series.strategy.
series.math.
series.request.
серийные функции, функции обработки типов и т.д.)Вstrategy.
серии функций - это функции, которые мы часто используем при разработке стратегий, и эти функции тесно связаны с выполнением торговых операций, когда стратегия выполняется конкретно.
strategy.entry
strategy.entry
функция является более важной функцией, когда мы пишем стратегию размещения заказа, несколько важных параметров для функции:id
, direction
, qty
, when
, и т.д.
Параметры:
id
: Это может быть понято как присвоение названия торговой позиции для ссылки.direction
: Если направление ордера длинное (купить), вставьте встроенную переменнуюstrategy.long
, и если вы хотите пойти короткий (продать), пройти в переменнойstrategy.short
.qty
: Укажите сумму заказов, которые должны быть размещены, если этот параметр не будет передан, будет использоваться сумма заказов по умолчанию.when
: Условие выполнения, вы можете указать этот параметр для контроля того, будет ли задействована текущая операция заказа или нет.limit
: Укажите предельную цену заказа.stop
Стоп-лосс.Конкретные подробности исполненияstrategy.entry
Функции контролируются параметром, когдаstrategy
функция называется, и она также может контролироваться с помощью [
Мы сосредоточены наpyramiding
, default_qty_value
параметры вstrategy
Мы используем следующий код для тестирования:
/*backtest
start: 2022-07-03 00:00:00
end: 2022-07-09 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/
strategy(title = "open long example", pyramiding = 3, default_qty_value=0.1, overlay=true)
ema10 = ta.ema(close, 10)
findOrderIdx(idx) =>
if strategy.opentrades == 0
false
else
ret = false
for i = 0 to strategy.opentrades - 1
if strategy.opentrades.entry_id(i) == idx
ret := true
break
ret
if not findOrderIdx("long1")
strategy.entry("long1", strategy.long)
if not findOrderIdx("long2")
strategy.entry("long2", strategy.long, 0.2, when = close > ema10)
if not findOrderIdx("long3")
strategy.entry("long3", strategy.long, 0.2, limit = low[1])
strategy.entry("long3", strategy.long, 0.3, limit = low[1])
if not findOrderIdx("long4")
strategy.entry("long4", strategy.long, 0.2)
plot(ema10, title="ema10", color=color.red)
Часть в начале кода/* backtest... */
является настройкой обратного теста, которая используется для записи времени настройки обратного теста и другой информации в это время для отладки, а не кода запуска.
В коде:strategy(title = "open long example", pyramiding = 3, default_qty_value=0.1, overlay=true)
, когда мы указываемpyramiding
Параметр 3, мы устанавливаем максимальное количество сделок в том же направлении 3.strategy.entry
Поскольку мы также указалиdefault_qty_value
параметр будет 0,1, этоstrategy.entry
Операция с ИДlong1
имеет размер заказа по умолчанию 0,1.strategy.entry
Функция вызов, когда мы указываемdirection
какstrategy.long
, так что все тестовые заказы являются заказчиками.
Обратите внимание, что операция заказаstrategy.entry("long3", ...
в коде называется дважды для одного и того же идентификатора:long3
, первыйstrategy.entry
Операция заказа не была заполнена, и второй вызовstrategy.entry
В другом случае, например, если первый порядок с ID strategy.entry
функция размещения заказов в соответствии с ID
strategy.close
Вstrategy.close
Функция используется для закрытия позиции входа с указанным идентификационным идентификатором. Основными параметрами являются:id
, when
, qty
, qty_percent
.
Параметры:
id
: Идентификатор входа, который необходимо закрыть, - это идентификатор, который мы указываем, когда открываем позицию с помощью функции входа, например:strategy.entry
.when
: условия исполнения.qty
: Количество закрытых позиций.qty_percent
: Процент закрытых позиций.Давайте ознакомимся с деталями использования этой функции на примере:
В/*backtest ... */
в коде указана информация о конфигурации дляFMZ.COMмеждународный веб-сайт backtest, вы можете удалить его и установить рынок, сорт, временной диапазон и другую информацию, которую вам нужно протестировать.
/*backtest
start: 2022-07-03 00:00:00
end: 2022-07-09 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/
strategy("close Demo", pyramiding=3)
var enableStop = false
if enableStop
runtime.error("stop")
strategy.entry("long1", strategy.long, 0.2)
if strategy.opentrades >= 3
strategy.close("long1") // Multiple entry orders, no qty parameters specified, close all
// strategy.close() // Without specifying the id parameter, the current position will be closed
// strategy.close("long2") // If a non-existent id is specified then nothing is done
// strategy.close("long1", qty=0.15) // Specify qty parameters to close a position
// strategy.close("long1", qty_percent=50) // qty_percent is set to 50 to close 50% of the positions marked by long1
// strategy.close("long1", qty_percent=80, when=close<open) // Specify the parameter when, change it to close>open and it won't trigger
enableStop := true
Стратегия тестирования показывает три последовательных длинных записи с идентификатором записи strategy.close
Функция для установки различных результатов обратного теста при закрытии позиции.strategy.close
функция не имеет параметров для указания цены ордера на закрытие позиции, эта функция в основном используется для закрытия позиции сразу по текущей рыночной цене.
strategy.close_all
Функцияstrategy.close_all
используется для закрытия всех текущих позиций, потому что язык Пина сценарий позиций может иметь только направление, то есть, если есть сигнал, вызванный в противоположном направлении текущей позиции будет закрыть текущую позицию, а затем открыть его в соответствии с сигналом триггера.strategy.close_all
будет закрывать все позиции в текущем направлении, когда он вызван.strategy.close_all
Функция:when
.
Параметры:
when
: условия исполнения.Давайте посмотрим на следующий пример:
/*backtest
start: 2022-07-03 00:00:00
end: 2022-07-09 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/
strategy("closeAll Demo")
var enableStop = false
if enableStop
runtime.error("stop")
strategy.entry("long", strategy.long, 0.2, when=strategy.position_size==0 and close>open)
strategy.entry("short", strategy.short, 0.3, when=strategy.position_size>0 and close<open)
if strategy.position_size < 0
strategy.close_all()
enableStop := true
Код испытания начинается с номера позиции 0 (т.е.strategy.position_size==0
является истинным), так что когда условия, установленные параметром когда выполнены, толькоstrategy.entry
функция входа с ID strategy.position_size
Если длина позиции больше 0, то функция входа с ID strategy.position_size < 0
, т.е. при удержании короткой позиции все позиции в текущем направлении удержания будут закрыты.enableStop := true
. Прекращает выполнение стратегии, чтобы можно было наблюдать за журналом.
Можно обнаружить, что функцияstrategy.close_all
не имеет параметров для указания цены закрытия ордера, эта функция в основном используется для немедленного закрытия позиции по текущей рыночной цене.
strategy.exit
Вstrategy.exit
В отличие от этой функции,strategy.close
иstrategy.close_all
Функции закрывают позицию немедленно по текущей рыночной цене.strategy.exit
Функция будет закрывать позицию в соответствии с параметрами.
Параметры:
id
: Идентификатор ордера текущего ордера с условием закрытия.from_entry
: Используется для указания идентификатора входа позиции, которая должна быть закрыта.qty
: Количество закрытых позиций.qty_percent
: Процент закрытых позиций, диапазон: 0 ~ 100.profit
: Целевая прибыль, выраженная в пунктах.loss
: Цель стоп-лосса, выраженная в пунктах.limit
: Целевая прибыль, определяемая ценой.stop
: Цель стоп-лосса, определенная ценой.when
: условия исполнения.Используйте стратегию тестирования для понимания использования параметров.
/*backtest
start: 2022-07-03 00:00:00
end: 2022-07-09 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
args: [["RunMode",1,358374],["ZPrecision",0,358374]]
*/
strategy("strategy.exit Demo", pyramiding=3)
varip isExit = false
findOrderIdx(idx) =>
ret = -1
if strategy.opentrades == 0
ret
else
for i = 0 to strategy.opentrades - 1
if strategy.opentrades.entry_id(i) == idx
ret := i
break
ret
strategy.entry("long1", strategy.long, 0.1, limit=1, when=findOrderIdx("long1") < 0)
strategy.entry("long2", strategy.long, 0.2, when=findOrderIdx("long2") < 0)
strategy.entry("long3", strategy.long, 0.3, when=findOrderIdx("long3") < 0)
if not isExit and strategy.opentrades > 0
// strategy.exit("exitAll") // If only one id parameter is specified, the exit order is invalid, and the parameters profit, limit, loss, stop and other exit conditions also need to be set at least one, otherwise it is also invalid
strategy.exit("exit1", "long1", profit=50) // Since the long1 entry order is not filled, the exit order with ID exit1 is also on hold until the corresponding entry order is filled before exit1 is placed
strategy.exit("exit2", "long2", qty=0.1, profit=100) // Specify the parameter qty to close 0.1 positions in the position with ID long2
strategy.exit("exit3", "long3", qty_percent=50, limit=strategy.opentrades.entry_price(findOrderIdx("long3")) + 1000) // Specify the parameter qty_percent to close 50% of the positions in the position with ID long3
isExit := true
if bar_index == 0
runtime.log("The price per point:", syminfo.mintick) // The price per point is related to the "Pricing Currency Precision" parameter setting on the Pine language template parameters
Мы используем модель цены в реальном времени для обратного тестирования, стратегия тестирования начинается с 3 входных операций (strategy.entry
функцию), иlong1
преднамеренно устанавливаетсяlimit
параметр с ожидаемой ценой ордера 1, так что он не может быть заполнен.strategy.exit
Мы использовали strategy.exit
Функция также имеет более сложные параметры остановки:trail_price
, trail_points
, trail_offset
также могут быть проверены в этом примере, чтобы узнать их использование.
strategy.cancel
Вstrategy.cancel
функции используются для отмены/остановки всех предварительных ожидаемых заказов.strategy.order
, strategy.entry
, strategy.exit
Основными параметрами этой функции являются:id
, when
.
Параметры:
id
: Идентификатор допуска отменяется.when
: условия исполнения.Эта функция легко понятна, и она используется для отмены заказов, которые не выполнены.
/*backtest
start: 2022-07-03 00:00:00
end: 2022-07-09 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/
strategy("strategy.cancel Demo", pyramiding=3)
var isStop = false
if isStop
runtime.error("stop")
strategy.entry("long1", strategy.long, 0.1, limit=1)
strategy.entry("long2", strategy.long, 0.2, limit=2)
strategy.entry("long3", strategy.long, 0