В процессе загрузки ресурсов... загрузка...

Изобретатели количественного введения языка PINE

Автор:Изобретатели количественного измерения - мечты, Создано: 2022-05-30 16:23:43, Обновлено: 2022-09-28 17:10:21

Вот пример:

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)

Примечание: выражение для суждения, возвращающее значение Бура; обратите внимание на сжатие; может иметь только одну ветвьelse; все выражения с ветвями не являются истинными, и не имеют ветвейelse, возвращают na;

x = if close > open
    close
plot(x, title="x")

Поскольку, когда строка K BAR является стеной, то есть когда close < open, выражение после if-заявления false, то локальный блок if не выполняется. В этом случае также нет подразделенияelse, и if-заявление возвращает na. x присвоено на.

Смены

switch - это также разветвленная структура, предназначенная для проектирования различных путей выполнения в зависимости от определенных условий.

1, как и if, может возвращать значения. В отличие от других языков, в которых выполняется только один локальный блок в своем коде, не требуется заявление break (т. е. не нужно писать ключевые слова, такие как break). Каждый отрасль Switch может писать локальный блок кода, последний ряд которого возвращает значение (это может быть элементарная группа значений). Если не выполнено ни одного отраслью, возвращается na. 4, определение местоположения выражения в структуре переключателя, записывание строк, переменных, выражений или вызовов функций. 5. Switch позволяет указать возвращаемое значение, которое используется как значение по умолчанию при выполнении других условий в структуре.

В этой статье мы рассмотрим примеры, чтобы понять, как их использовать.

1 с выражениемswitchНапример:

// input.string: defval, title, options, tooltip
func = input.string("EMA", title="指标名称", tooltip="选择要使用的指标函数名称", options=["EMA", "SMA", "RMA", "WMA"])

// input.int: defval, title, options, tooltip
// param1 = input.int(10, title="周期参数")
fastPeriod = input.int(10, title="快线周期参数", options=[5, 10, 20])
slowPeriod = input.int(20, title="慢线周期参数", options=[20, 25, 30])

data = input(close, title="数据", tooltip="选择使用收盘价、开盘价、最高价...")
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.stringinput.intФункция.input.stringВ конце концов, мы можем использовать это для того, чтобы вернуть строки.input.intФункция возвращает целые числа. В этом примере добавляется один.optionsВ этом случае мы должны использовать параметры.optionsПараметры могут быть переданы в массив, состоящий из выборных значений.options=["EMA", "SMA", "RMA", "WMA"]иoptions=[5, 10, 20](Обратите внимание, что один из них - тип строки, а другой - тип числа) ‒ таким образом, контроллеры в интерфейсе политики не требуют ввода конкретных чисел, а становятся спускаемыми окнами, которые выбирают опции, предоставленные в параметре options.

Значение переменной func используется в качестве строки для определения того, какая ветвь выполняется. Если переменная func не может совпадать с выражением на любом из ветвей, выполняется блок кода по умолчанию.runtime.error("error")Функция заставляет политику бросать исключительную остановку.

В нашем тестовом коде выше после последнего строка runtime.error в блоке кода разделения по умолчанию в Switch мы не добавляем такой код, как [na, na] для совместимости возвращаемого значения, в торговом виде это нужно учитывать, если тип несовместим, то ошибка будет возвращена. Но в 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 ошибки не возвращаются, а в торговом просмотре - нет.

2, без выражения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 должны быть взаимно противоречивыми. То есть, в примере up и down не могут быть одновременно истинными. Поскольку switch может выполнять только один локальный блок раздела, можно использовать следующие строки:up = close > open // up = close < openВместо того, чтобы заменять содержание в комментариях, проверьте результаты наблюдений. Вы обнаружите, что отрасль Switch может выполнять только первую отрасль. Кроме того, необходимо быть осторожным, чтобы не писать вызовы функций в отрасль Switch, которая не может быть вызвана на каждом BAR, что может вызвать некоторые проблемы с вычислением данных.switchВ примере "выполнение ветви определено и не будет изменено в ходе реализации стратегии")

Циклическая структура

фраза "for"

返回值 = for 计数 = 起始计数 to 最终计数 by 步长
    语句                                            // 注释:语句里可以有break,continue
    语句                                            // 注释:最后一条语句为返回值

Использование for очень просто, цикл for может возвращать одно значение в конечном итоге ((или возвращать несколько значений, в виде [a, b, c]); как в том же pseudo-коде выше, ассигнования на место "возвращения" переменных. После заказа for следует переменная "счет" для управления количеством циклов, ссылки на другие значения и т. д. Переменные "счет" ассигнованы на "первоначальное счисление" до начала цикла, а затем переданы в соответствии с настройкой "расти", а цикл останавливается, когда количество "счетов" больше, чем число "конечных" переменных.

for используется в циклеbreakКлючевое слово: когда выполненоbreakПосле этого цикл прекращается. for используется в циклеcontinueКлючевое слово: когда выполненоcontinueПосле слов цикл игнорируется.continueПоследующий код, который выполняет следующий цикл прямо; for возвращает значение, которое было возвращено при последнем выполнении цикла; если не выполнено никакого кода, возвращает пустое значение.

Вот вам простой пример:

ret = for i = 0 to 10       // 可以增加by关键字修改步长,暂时FMZ不支持 i = 10 to 0 这样的反向循环
    // 可以增加条件设置,使用continue跳过,break跳出
    runtime.log("i:", i)
    i                       // 如果这行不写,就返回空值,因为没有可返回的变量
    
runtime.log("ret:", ret)
runtime.error("stop")

for... in предложения

for ... inПо словам одного из авторов статьи, "это неправда, что мы говорим о том, что мы не знаем, что это такое".

返回值 = for 数组元素 in 数组 
    语句                        // 注释:语句里可以有break,continue
    语句                        // 注释:最后一条语句为返回值
返回值 = for [索引变量, 索引变量对应的数组元素] in 数组
    语句                        // 注释:语句里可以有break,continue
    语句                        // 注释:最后一条语句为返回值 

Основное отличие двух форм заключается в том, что следует за ключевым словом for, одна из которых использует переменную как переменную, ссылаясь на элемент матрицы. Другая использует структуру, содержащую переменную индекса, переменную элемента матрицы.

testArray = array.from(10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
for ele in testArray            // 修改成 [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Я не знаю, как это написать.

for циркулятивные приложения

Когда можно выполнить некоторые циклические расчеты с помощью встроенных функций, предоставленных языком Pine, можно написать их напрямую с помощью циклических структур, или же можно использовать встроенные функции для обработки. Вот два примера.

1, расчетная средняя

При использовании циркулярных конструкций:

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При расчете показателей уравнения, очевидно, проще для расчета уравнения использовать встроенные функции. На графике можно увидеть, что результаты расчёта полностью совпадают.

2 и

Например, если вы хотите, чтобы ваш ребенок был здоровым, вы можете использовать пример выше.

При использовании циркулярных конструкций:

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)

Вы можете увидеть, что вычисленные данные полностью совпадают с графиком с помощью графического рисунка.

Если эти задачи выполняются с помощью встроенных функций, зачем создавать циклы? 1, некоторые операции для матриц, вычисления. 2, просматривая историю, например, выясняя, насколько прошлые высоты выше высоты текущего BAR. Поскольку высоты текущего BAR известны только на BAR, где выполняется сценарий, требуется цикл, чтобы вернуться вовремя и проанализировать прошлые BAR. В случае, когда встроенная функция с использованием языка Pine не может выполнить вычисления на прошедшем BAR.

while

whileСтроки позволяют коду циркулирующей части выполняться до тех пор, пока условие определения в структуре while не будет ложным.

返回值 = while 判断条件
    语句                    // 注释:语句里可以有break,continue
    语句                    // 注释:最后一条语句为返回值

Другие правила 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 loop также очень просто, и можно спроектировать некоторые вычислительные логики, которые не могут быть заменены на встроенные функции, например, вычислить степень умножения:

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("当前BAR上的a值:", a, ", 上1根BAR上的a,即a[1]值:", a[1])
else if bar_index == 1 
    array.push(a, bar_index)
    runtime.log("当前BAR上的a值:", a, ", 上1根BAR上的a,即a[1]值:", a[1])
else if bar_index == 2
    array.push(a, bar_index)
    runtime.log("当前BAR上的a值:", a, ", 上1根BAR上的a,即a[1]值:", a[1], ", 向前数2根BAR上的a,即a[2]值:", a[2])
else if bar_index == 3 
    array.push(a, bar_index)
    runtime.log("当前BAR上的a值:", a, ", 上1根BAR上的a,即a[1]值:", a[1], ", 向前数2根BAR上的a,即a[2]值:", a[2], ", 向前数3根BAR上的a,即a[3]值:", a[3])
else if bar_index == 4 
    // 使用array.get 按索引获取元素,使用array.set按索引修改元素
    runtime.log("数组修改前:", array.get(a, 0), array.get(a, 1), array.get(a, 2), array.get(a, 3))
    array.set(a, 1, 999)
    runtime.log("数组修改后:", array.get(a, 0), array.get(a, 1), array.get(a, 2), array.get(a, 3))

Декларируемые матрицы

Использованиеarray<int> afloat[] 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函数。Pine语言中还有很多和类型相关的与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 циклов просмотра. Чем ближе максимальное значение высокого в течение последних 100 циклов просмотра, тем выше уровень, тем глубже соответствующее цветное значение (низкая прозрачность).

Пройдите через элементы матрицы

Как перейти через матрицу, мы можем сделать это с помощью предложения for/for in/while, которое мы изучали ранее.

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)

Добавление матриц, удаление операционных функций

1, функции, связанные с увеличением матриц:

array.unshift()array.insert()array.push()

2, Функции, связанные с операциями по удалению матриц:

array.remove()array.shift()array.pop()array.clear()

Мы используем следующие примеры для проверки функций добавления и удаления этих матриц.

a = array.from("A", "B", "C")
ret = array.unshift(a, "X")
runtime.log("数组a:", a, ", ret:", ret)

ret := array.insert(a, 1, "Y")
runtime.log("数组a:", a, ", ret:", ret)

ret := array.push(a, "D")
runtime.log("数组a:", a, ", ret:", ret)

ret := array.remove(a, 2)
runtime.log("数组a:", a, ", ret:", ret)

ret := array.shift(a)
runtime.log("数组a:", a, ", ret:", ret)

ret := array.pop(a)
runtime.log("数组a:", a, ", ret:", ret)

ret := array.clear(a)
runtime.log("数组a:", a, ", ret:", ret)

runtime.error("stop")

Применение добавления и удаления: матрицы как очереди

Используя матрицы, а также некоторые функции добавления и удаления матриц, мы можем создать структуру данных "колонки". Колонки могут быть использованы для расчета скользящих средних цен на тики.

Квартира - это структура, часто используемая в области программирования, которая характеризуется следующими характеристиками:

Первый элемент в очереди, первый элемент в очереди.

Это гарантирует, что данные, которые есть в очереди, являются новейшими данными, и длина очереди не будет бесконечно расширяться (код с бесконечной расширенностью может быть написан только в полдень, так как это может привести к проблемам рано или поздно).

В следующем примере мы используем строку, которая записывает цены на каждый тик, вычисляет движущуюся среднюю цену на уровне тика, а затем сравниваем ее с движущейся средней на уровне линии K в 1 минуту.

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.varip│ Таким образом, каждое изменение цены записывается в матрице a│

Часто используемые арифметические вычисления, операционные функции

Вычислить соответствующие функции:

array.avg()Укажите средние значения всех элементов в матрице.array.min()Это наименьший элемент в матрице.array.max()Это означает, что мы можем найти наиболее важный элемент в матрице.array.stdev()Стандартная погрешность всех элементов в матрицеarray.sum()Сумма всех элементов в матрице.

Функции, связанные с операцией:array.concat()Объединяет или соединяет две матрицы.array.copy()Написать матрицу.array.joinСоединяет все элементы в матрице в одну строку.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("数组a的算数平均:", array.avg(a))
runtime.log("数组a中的最小元素:", array.min(a))
runtime.log("数组a中的最大元素:", array.max(a))
runtime.log("数组a中的标准差:", array.stdev(a))
runtime.log("数组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("数组a:", a, ", 数组b:", b)
runtime.log("数组a,数组b连接在一起:", array.concat(a, b))
c = array.copy(b)

runtime.log("复制一个数组b,赋值给变量c,变量c:", c)

runtime.log("使用array.join处理数组c,给每个元素中间增加符号+,连接所有元素结果为字符串:", array.join(c, "+"))
runtime.log("排序数组b,按从小到大顺序,使用参数order.ascending:", array.sort(b, order.ascending))     // array.sort函数修改原数组
runtime.log("排序数组b,按从大到小顺序,使用参数order.descending:", array.sort(b, order.descending))   // array.sort函数修改原数组

runtime.log("数组a:", a, ", 数组b:", b)
array.reverse(a)   // 此函数修改原数组
runtime.log("反转数组a中的所有元素顺序,反转之后数组a为:", a)    

runtime.log("截取数组a,索引0 ~ 索引3,遵循左闭右开区间规则:", array.slice(a, 0, 3))
runtime.log("在数组b中搜索元素11:", array.includes(b, 11))
runtime.log("在数组a中搜索元素100:", array.includes(a, 100))
runtime.log("将数组a和数组b连接,搜索其中第一次出现元素2的索引位置:", array.indexof(array.concat(a, b), 2), " , 参考观察 array.concat(a, b):", array.concat(a, b))
runtime.log("将数组a和数组b连接,搜索其中最后一次出现元素6的索引位置:", array.lastindexof(array.concat(a, b), 6), " , 参考观察 array.concat(a, b):", array.concat(a, b))

runtime.error("stop")

Функции

Функции настройки

Язык Pine может проектировать настройки, и в целом настройки в языке Pine имеют следующие правила:

1, все функции определены в глобальном пределе сценария. Невозможно объявить одну функцию в другой функции. 2, не допускает функций к вызову себя в своем коде. 3, в принципе, все языки PINE имеют встроенную функцию рисункаbarcolor()、 fill()、 hline()、plot()、 plotbar()、 plotcandle()) не может быть вызвано в пределах пользовательских функций. 4, функция может быть написана как однострочная, так и многострочная. Вернутое значение последнего предложения является текущим функцией, которая может возвращать элементарный формат.

В предыдущих уроках мы также много раз использовали пользовательские функции, например, создание пользовательских функций в виде одной строки:

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 Script документацияСреди запросов.

Встроенные функции в языке Pine:

1, функция обработки строкstr.Сериал. 2, функция обработки цветаcolor.Сериал. 3, параметровые функции вводаinput.Сериал. 4, показатель вычислительной функцииta.Сериал. 5, функция рисункаplot.Сериал. 6, арифметическая обработкаarray.Сериал. 7. Функции, связанные с транзакциейstrategy.Сериал. 8 Математические операции, связанные с функциямиmath.Сериал. 9, Другие функции ((время обработки, неплотные серии рисунков,request.Среди них есть: серийные функции, типы обработки функций и т.д.).

Функции транзакций

strategy.Серийные функции - это функции, которые мы часто используем в дизайнерской стратегии, и они тесно связаны с выполнением операций, когда стратегия конкретно работает.


1、strategy.entry

strategy.entryФункция является важнейшей функцией, когда мы пишем стратегию, и имеет несколько важных параметров:id, direction, qty, whenИ так далее.

Параметры:

  • id: может быть понято как ссылка на название определенной торговой позиции.
  • direction: если направление заказа больше ((покупать) этот параметр передаетсяstrategy.longЭта встроенная переменная передается, если мы хотим сделать её пустой.strategy.shortЭта переменная.
  • qty: Укажите количество заказов, если этот параметр не будет передан, то будет использоваться количество заказов по умолчанию.
  • when: условие выполнения, можно указать этот параметр, чтобы контролировать, будет ли задействована текущая подзагрузка.
  • limitНапример: указать предельную цену заказа.
  • stopСнижение цены: Стоп-лосс.

strategy.entryКонкретные детали выполнения функцииstrategyПараметры, на которые можно настроить функции при вызове, также могут быть установлены с помощью"Параметры шаблонов для языковой библиотеки "Pine"Более подробную информацию о контроле настройки, параметры шаблона библиотеки сделок языка Pine можно найти в документации по ссылке.

В этом случае мы не можем сказать, что это было.strategyВ этой функцииpyramidingdefault_qty_valueПараметры. Используйте следующий код для тестирования:

/*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 мы установили, что мы можем торговать в одном направлении не более трех раз.strategy.entryОдин из следующих операций не был выполнен.default_qty_valueПараметры 0.1, так что ID обозначается как long 1.strategy.entryПо умолчанию количество подстроек для подстрочных операций установлено на 0.1.strategy.entryЭто то, что мы указываем при вызове функции.directionВсе равноstrategy.longВ этом случае, если вы не хотите, чтобы ваш рецензент был некомпетентным, вы должны заплатить за него.

Обратите внимание на код.strategy.entry("long3", ...Следующая операция вызвана дважды, для одного и того же ID: long3.strategy.entryВторой вызов не выполнен.strategy.entryФункция изменяет заказ на этот ID (данные, отображенные при повторном тестировании, также показывают, что количество заказов на этот ограничительный заказ изменено на 0.3). В другом случае, например, если при первом ID заказ на long3 был оформлен, продолжать использовать его в соответствии с этим оформленным ID long3.strategy.entryФункция ставит заказ, тогда все позиции будут накапливаться на ID-код-long3.


2、strategy.close

strategy.closeФункция используется для определения идентификатора позиции вхождения в баланс. Основные параметры:idwhenqtyqty_percent

Параметры:

  • idМы используем ID-адрес, который требует прокладки.strategy.entryИдентификатор, указанный при открытии позиции.
  • whenУсловия выполнения:
  • qtyНапример: количество позиций.
  • qty_percentПроцент свертываемости.

Для того, чтобы ознакомиться с подробностями использования этой функции, приведем пример: В коде/*backtest ... */是FMZ.COM国际站回测时的配置信息,可以删掉,设置自己需要测试的市场、品种、时间范围等信息。

/*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")                   // 多个入场订单,不指定qty参数,全部平仓
    // strategy.close()                          // 不指定id参数,会平掉当前的持仓
    // strategy.close("long2")                   // 如果指定一个不存在的id则什么都不操作
    // strategy.close("long1", qty=0.15)         // 指定qty参数平仓
    // strategy.close("long1", qty_percent=50)   // qty_percent设置50即为平掉long1标识仓位的50%持仓
    // strategy.close("long1", qty_percent=80, when=close<open)  // 指定when参数,修改为close>open就不触发了
    enableStop := true

Тестирующая стратегия показывает, что нужно начинать с трех последовательных многопроходных входов, каждый из которых имеет идентификатор входа в длину 1, а затем использоватьstrategy.closeРазличные результаты, полученные при установке различных параметров функции на равновесие.strategy.closeФункция не имеет параметров, позволяющих указывать цены на покупку, и в основном используется для немедленной покупки на текущей рыночной цене.


3、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И это действительно так, так что выполните ID только в случае, если when параметр выполняет условия, установленные в параграфе when.strategy.entryВходная функция. После хранения множества позиций.strategy.position_sizeВ случае, когда ID больше 0, то входная функция для х-шорта может быть выполнена. Поскольку в настоящее время удерживается многоголовая позиция, этот сигнал обратного замыкания, возникающий в это время, приводит к разрыву многоголовой позиции и обратному открытию.strategy.position_size < 0В случае, когда удерживается пустой холдинг, все позиции в текущем направлении удерживания выровняются.enableStop := trueНапример, если вы хотите, чтобы ваш блог был доступным для просмотра, вы можете перейти к следующему разделу.

Вы можете найтиstrategy.close_allФункция не имеет параметров, позволяющих указывать цены на покупку, и в основном используется для немедленной покупки на текущей рыночной цене.


4、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")          // 如果仅仅指定一个id参数,则该退场订单无效,参数profit, limit, loss, stop等出场条件也至少需要设置一个,否则也无效
    strategy.exit("exit1", "long1", profit=50)                    // 由于long1入场订单没有成交,因此ID为exit1的出场订单也处于暂待状态,直到对应的入场订单成交才会放置exit1
    strategy.exit("exit2", "long2", qty=0.1, profit=100)          // 指定参数qty,平掉ID为long2的持仓中0.1个持仓
    strategy.exit("exit3", "long3", qty_percent=50, limit=strategy.opentrades.entry_price(findOrderIdx("long3")) + 1000)   // 指定参数qty_percent,平掉ID为long3的持仓中50%的持仓
    isExit := true 

if bar_index == 0 
    runtime.log("每点价格为:", syminfo.mintick)    // 每点价格和Pine语言模板参数上「定价货币精度」参数设置有关

Используя ретро-тестирование модели цены в режиме реального времени, эта стратегия тестирования начинается с выполнения трех входных операций.strategy.entryФункция), на которую настроили "long1" специальноlimitПараметры, цена заказа 1 делает его невозможным. Затем проверьте условия выхода функции.strategy.exit; используется стоп-офис по количеству точек; стоп-офис по цене; используется стап-офис по количеству позиций; используется стоп-офис по проценту; учитывая, что в этом примере демонстрируется только стоп-офис; стоп-офис по цене также является симметричным;strategy.exitФункция также имеет более сложные параметры отслеживания:trail_pricetrail_pointstrail_offsetТакже можно попробовать узнать, как их использовать в этом примере.


5、strategy.cancel

strategy.cancelФункции, используемые для отмены / отмены всех предварительно вывешенных команд; эти функцииstrategy.order, strategy.entry , strategy.exitМожно создавать входный ID. Основные параметры функции:idwhen

Параметры:

  • 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.3, limit=3)

if not barstate.ishistory and close < open 
    strategy.cancel("long1")
    strategy.cancel("long2")
    strategy.cancel("long3")
    isStop := true 

6、strategy.cancel_all

strategy.cancel_allФункции иstrategy.cancelФункции похожие на "отменить/отменить все предварительно заказанные команды".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("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.3, limit=3)

if not barstate.ishistory and close < open 
    strategy.cancel_all()
    isStop := true 

7、strategy.order

strategy.orderФункции, параметры и т.д.strategy.entryВ результате,strategy.orderФункция не может бытьstrategyФункцииpyramidingПараметры влияют на настройки, не ограничивая количество повторений.

Параметры:

  • id: может быть понято как ссылка на название определенной торговой позиции.
  • direction: если направление заказа больше ((покупать) этот параметр передаетсяstrategy.longЭта встроенная переменная передается, если мы хотим сделать её пустой.strategy.shortЭта переменная.
  • qty: Укажите количество заказов, если этот параметр не будет передан, то будет использоваться количество заказов по умолчанию.
  • when: условие выполнения, можно указать этот параметр, чтобы контролировать, будет ли задействована текущая подзагрузка.
  • limitНапример: указать предельную цену заказа.
  • stopСнижение цены: Стоп-лосс.

Мы используемstrategy.orderЭто не ограничивается следующим числом единиц.strategy.exitУсловное выходная функция ─ создание сценария, похожий на сетевую сделку ─ пример очень простой, только для обучения:

/*backtest
start: 2021-03-01 00:00:00
end: 2022-08-30 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"ETH_USDT"}]
args: [["ZPrecision",0,358374]]
*/

varip beginPrice = -1

if not barstate.ishistory
    if beginPrice == -1 or (math.abs(close - beginPrice) > 1000 and strategy.opentrades == 0) 
        beginPrice := close
    
    for i = 0 to 20
        strategy.order("buy"+i, strategy.long, 0.01, limit=beginPrice-i*200, when=(beginPrice-i*200)<close)
        strategy.exit("coverBuy"+i, "buy"+i, qty=0.01, profit=200)
        
        strategy.order("sell"+i, strategy.short, 0.01, limit=beginPrice+i*200, when=(beginPrice+i*200)>close)
        strategy.exit("coverSell"+i, "sell"+i, qty=0.01, profit=200)

Примеры стратегии

Примеры стратегии в этом учебном пособии используются только для обучения стратегии, для руководства идеями по разработке стратегии и не являются какими-либо торговыми рекомендациями, рекомендациями.

Стратегия сверхтенденционных индикаторов

strategy("supertrend", overlay=true)

[supertrend, direction] = ta.supertrend(input(5, "factor"), input.int(10, "atrPeriod"))

plot(direction < 0 ? supertrend : na, "Up direction", color = color.green, style=plot.style_linebr)
plot(direction > 0 ? supertrend : na, "Down direction", color = color.red, style=plot.style_linebr)

if direction < 0
    if supertrend > supertrend[2]
        strategy.entry("entry long", strategy.long)
    else if strategy.position_size < 0
        strategy.close_all()
else if direction > 0
    if supertrend < supertrend[3]
        strategy.entry("entry short", strategy.short)
    else if strategy.position_size > 0
        strategy.close_all()

Написать стратегию тренда с помощью языка Pine очень просто. Здесь мы разработаем простую стратегию отслеживания тренда с помощью супер-показателя тренда. Давайте вместе проанализируем исходный код этой стратегии.

Сначала используйте стратегический код.strategyФункция выполняет несколько простых настроек:strategy("supertrend", overlay=true), просто настроить стратегию, название которой - Supertrend.overlayПараметры:trueЕсли мы создаем стратегию или изучаем сценарий стратегии, то первое, что мы должны посмотреть, это дизайн параметров интерфейса стратегии. Мы смотрим на исходный код стратегии супертенденционных индикаторов, в котором есть то, что мы изучали в предыдущих уроках.inputФункции

[supertrend, direction] = ta.supertrend ((input ((5, factor),input.int(10, atrPeriod))

inputВызов функции используется непосредственно дляta.supertrendПараметры индикаторной функции используются для вычисления сверхтенденционных индикаторов; среди них:

  • ввод ((5, фактор)
  • input.int(10, trPeriod)

Функция по умолчанию устанавливает два параметровых контроля в интерфейсе политики языка Pine, как показано ниже:

img

И вы видите, что по умолчанию на контролеinputФункции иinputФункция серии (((input.intПервые параметры, которые также описаны в предыдущих главах. С помощью этих двух функций мы можем настроить на стратегическом интерфейсеta.supertrendПараметры функции. Функция сверхтенденционного индикатора вычисляет данные о ценах.supertrendИ данные в одном направлении.direction‒ А потом используйте.plotФункциональный график, обратите внимание, когда график рисуется в соответствии с направлением индикаторов сверхтенденции, рисуется только в текущем направлении.directionНа данный момент рынок движется вверх, когда -1.directionНа 1 час текущий рынок имеет тенденцию к снижению.plotОпределение при рисованииdirectionБольший, меньший, чем 0.

Следующая статьяif ... else ifЛогика заключается в том, что мы можем судить о сигнале, когда мы используем выражениеdirection < 0Это означает, что рынок находится на верхней стадии, и если данные о ценах в сверхтенденционном индикаторе не соответствуют действительности, то рынок не может быть уверенным.supertrendСупертензивный показатель цены выше двух предыдущих BAR (т.е.supertrend[2],还记得历史操作符引用某个变量历史数据吧Если в данный момент имеется позиция, то призыв к обратному снижению функции будет сначала выровнять предыдущую позицию, а затем открыть позицию в соответствии с текущим направлением торговли.supertrend > supertrend[2]Если условия не будут соблюдены, то только на данный момент.strategy.position_size < 0Именно поэтому мы и предлагаем вам использовать эту возможность.strategy.close_all()Исполнение функций, выполнение всех выровненных.

direction > 0Если вы находитесь на стадии нисходящего тренда, то это также имеет сходство. Если у вас есть несколько позиций, все они будут выровнены, и вы соответствуете условиям.supertrend < supertrend[3]Если вы хотите, чтобы ваш телефон не работал, вы должны выключить сигнал "Отключите".[3]Может быть, это было преднамеренно, поскольку в некоторых рынках, например, на рынке контрактных торгов, риск делать пустое немного больше, чем риск делать много.

Дляta.supertrendИндекс, который интересует некоторых из ваших одноклассников, как вы можете определить, является ли текущая тенденция повышающейся или понижающейся?

На самом деле, этот показатель также может быть реализован в виде пользовательских функций в языке Pine:

pine_supertrend(factor, atrPeriod) =>
	src = hl2
	atr = ta.atr(atrPeriod)
	upperBand = src + factor * atr
	lowerBand = src - factor * atr
	prevLowerBand = nz(lowerBand[1])
	prevUpperBand = nz(upperBand[1])

	lowerBand := lowerBand > prevLowerBand or close[1] < prevLowerBand ? lowerBand : prevLowerBand
	upperBand := upperBand < prevUpperBand or close[1] > prevUpperBand ? upperBand : prevUpperBand
	int direction = na
	float superTrend = na
	prevSuperTrend = superTrend[1]
	if na(atr[1])
		direction := 1
	else if prevSuperTrend == prevUpperBand
		direction := close > upperBand ? -1 : 1
	else
		direction := close < lowerBand ? 1 : -1
	superTrend := direction == -1 ? lowerBand : upperBand
	[superTrend, direction]

Эта функция, как правило, выполняется с помощью встроенных функций.ta.supertrendИменно такой же алгоритм, и, конечно же, то же самое количество данных по показателям, которые вычисляются. Из этого алгоритма настройки функции мы можем увидеть, что встроенный сверхтенденционный индикатор Pine использует для вычисленияhl2Встроенные переменные (самые высокие цены, самые низкие цены, добавленные и разделенные на 2, то есть средние цены на самые низкие цены) затем вычисляются в соответствии с параметромatrPeriod.

Обновление в соответствии с трехзначными выражениями в кодеlowerBandиupperBand

    lowerBand := lowerBand > prevLowerBand or close[1] < prevLowerBand ? lowerBand : prevLowerBand
    upperBand := upperBand < prevUpperBand or close[1] > prevUpperBand ? upperBand : prevUpperBand

lowerBand: нижний тракт, используемый для определения изменения тенденции к росту. upperBand: верхний тракт, используемый для определения изменения тенденции к росту. both lowerBand and upperBand are always being calculated, only in this custom function to finally determine the current trend direction.

    else if prevSuperTrend == prevUpperBand
        direction := close > upperBand ? -1 : 1
    else
        direction := close < lowerBand ? 1 : -1

Здесь можно судить, если цена супертенденции на последнем бар-prevUpperBandЕсли в данный момент мы находимся на пересечении, то мы можем сказать, что мы находимся на пересечении, то это означает, что мы находимся на пересечении.closeБольшеupperBandВ то время как в Китае цены продолжают расти и снижаться, цены продолжают расти и снижаться.directionПо направлению переменная установлена на -1 (высокий тренд); иначе она остается на 1 (низкий тренд); так что вы увидите это в стратегии супертенденции.if direction < 0В то же время, если вы хотите, чтобы ваш сигнал был услышан, вы должны сделать больше, когда сигнальные условия активируются.direction > 0В то же время, если вы не хотите, чтобы ваш телефон был закрыт, вы должны сделать это.

    superTrend := direction == -1 ? lowerBand : upperBand
    [superTrend, direction]

Наконец, в зависимости от направления выбор возвращает конкретные данные о цене и направлении индикаторов сверхтенденции.

Стратегия динамического баланса

/*backtest
start: 2021-03-01 00:00:00
end: 2022-09-08 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Binance","currency":"ETH_USDT"}]
args: [["v_input_1",4374],["v_input_2",3],["v_input_3",300],["ZPrecision",0,358374]]
*/

varip balance = input(50000, "balance")
varip stocks = input(0, "stocks")

maxDiffValue = input(1000, "maxDiffValue")


if balance - close * stocks > maxDiffValue and not barstate.ishistory
    // more balance , open long 
    tradeAmount = (balance - close * stocks) / 2 / close
    strategy.order("long", strategy.long, tradeAmount)
    balance := balance - tradeAmount * close
    stocks := stocks + tradeAmount
    runtime.log("balance:", balance, ", stocks:", stocks, ", tradeAmount:", tradeAmount)

else if close * stocks - balance > maxDiffValue and not barstate.ishistory
    // more stocks , open short 
    tradeAmount = (close * stocks - balance) / 2 / close
    strategy.order("short", strategy.short, tradeAmount)
    balance := balance + tradeAmount * close
    stocks := stocks - tradeAmount
    runtime.log("balance:", balance, ", stocks:", stocks, ", tradeAmount:", tradeAmount)

plot(balance, title="balance value(quoteCurrency)", color=color.red)
plot(stocks*close, title="stocks value(quoteCurrency)", color=color.blue)

img

img

Мы продолжаем изучать некоторые модели дизайна стратегии языка Пайн, и на этот раз мы рассмотрим стратегию динамического балансирования.BaseCurrencyсумма (разновидность сделки) иQuoteCurrencyСуммы всегда балансируются; рост относительной цены какого-либо актива, увеличение стоимости акций, находящихся в счете, зависит от продажи какого-либо актива. Если относительная цена какого-либо актива снижается, а стоимость акций, находящихся в счете, снижается, то этот актив покупается. Это так называемая стратегия динамического балансирования.

Недостатком этой стратегии является то, что, как показано на графике обратного отсчета, она имеет более высокий уровень недвижимости на этапах большого тренда. Таким образом, эта стратегия хороша для текущей стратегии, а использование ее на фьючерсах требует контроля риска.

В этом контексте мы должны быть готовы к тому, что в будущем мы сможем использовать все возможности, чтобы создать новые технологии.

Мы использовали упрощенный дизайн, который имитировал стратегиюbalance(т.е. количество активов в котировке) иstocksМы не читаем количество реальных активов в счетах, мы просто используем имитируемые суммы, чтобы рассчитать подходящие покупки и продажи.maxDiffValueЭтот параметр является критерием для сбалансированного суждения.BaseCurrencyиQuoteCurrencyСверхотклоненияmaxDiffValueВ то время, когда мы пытаемся балансировать, мы продаем более дорогие активы и покупаем более дешевые, чтобы балансировать активы.

Триггеры стратегических торговых сигналов должны иметь смысл только на стадии BAR в режиме реального времени, поэтому стратегические торговые условия устанавливаются в суждениях if.not barstate.ishistoryНапример, в Китае, в Китае, в Китае, в Китае, в Китае, в Китае, в Китае, в Китае.balanceСтоимость превышаетstocksПокупка при цене; продажа наоборот; обновление после выполнения транзакции.balanceиstocksВ этом случае вы можете переместить переменную, а затем подождать, пока следующий баланс не будет задействован.

Выше приведенная информация о цене на разновидность, с которой началась эта стратегия, - это 1458, так что я специально установил параметры.balanceПараметры: 4374 ((1458*3)stocksДля: 3. Постарайтесь, чтобы актив был в балансе с самого начала.

Супер-тренд-стратегия с отслеживанием стоп-потери и сдерживанием падений

В предыдущих уроках мы узнали,strategy.exitФункции выхода из позиции, в которых прослеживается функция остановки убытков, мы не рассказываем в примерах.strategy.exitФункция отслеживания стоп-лосс-стоп-дюймов для оптимизации стратегии супертенденции.

Сначала давайте посмотрим.strategy.exitПараметры отслеживания функций:

1、trail_priceПараметры: запускать размещение слежения стоп-стоп-потери на балансовой позиции (с указанием цены)


Больше