Организация циклов в ThinkScript

»

Циклы – выполнение одного и того же кода указанное количество раз с использованием счетчика. Именно так можно описать циклы. Обычно сначала описывается счетчик, который будет увеличиваться на единицу, потом идет код, который и будет выполняться много раз, но в этом коде будет использоваться счетчик, он будет с каждым ходом увеличен на единицу, а значит и формула измениться.

Синтаксис цикла:

def <result> = fold <index> = <start> to <end> [ with <variable> [ = <init> ] ] [ while <condition> ] do <expression>;

Код получился длинный и не совсем понятный на первый взгляд, ну ничего разберемся.

<result> — Это всего лишь имя переменной, в нее вернется результат работы цикла.

fold – зарезервированное слово, означает что будет организован цикл.

<index> — Имя переменной счетчика.

<start> — Стартовая позиция счетчика.

<end> — Конечная позиция счетчика.

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

with – Объявить промежуточную переменную для работы внутри цикла.

<variable> — Имя переменное которая будет участвовать внутри цикла.

<init> — Присвоить значение объявленной переменной перед началом цикла.

while – Использовать условие для выхода из цикла.

<condition> — условие для выхода из цикла раньше его завершения.

do – выражение внутри цикла.

<expression> — формула внутри цикла.

Сложно? Не беда, упростим и разберемся.

def fc = fold i = 1 to 10 with p = 1 do p + i;

Вот простой пример. Что бы понять, как все работает нужно пройти по шагам.

Итак, поехали:

  1. i = 1 — Объявили переменную-счетчик i и присвоили ей 1.
  2. to 10 – Сообщаем что счетчик будет считать от 1 до 10, а потом цикл закончится.
  3. with p = 1 – объявили переменную для работы внутри цикла и присвоили ей 1 как начальное значение.
  4. do p + i – Это формула внутри цикла и будет выполнена 9 раз. Нет, это не ошибка, именно 9 раз, а не 10. Дело в том, что, когда мы указали до 10 это означает что 10 не включается, так что последнее значение, которое примет переменная i это как раз 9.

Что касается переменной p, эта переменная доступна только внутри цикла и обращаться из вне к ней нельзя.

Так что же вернет наш цикл? Что бы это узнать нужно выполнить расчет вручную и пройти по всем итерациям (итерация – одинарное выполнение кода внутри цикла).

Снова распишем шаги:

  1. Перед тем как цикл начнется, все переменные должны содержать значения. У нас они следующие: i = 1, p = 1.
  2. После каждой итерации значение записывается во внутреннюю переменную p. p = p + i. Подставим значения p = 1 + 1. После первой итерации переменная p = 2.
  3. Вторая итерация: p = p + i. p = 2 + 2. Когда итерация проходит наш счетчик увеличился на единицу и теперь i = 2. p = 4
  4. Третья итерация: p = 4 + 3. i = 3, p = 7
  5. Четвертая итерация: p = 7 + 4
  6. Пятая итерация: p = 11 + 5
  7. Шестая итерация: p = 16 + 6
  8. Седьмая итерация: p = 22 + 7
  9. Восьмая итерация: p = 29 + 8
  10. Девятая итерация: p = 37 + 9
  11. Вот и была последняя итерация, теперь последнее значение которое получила внутренняя переменная p возвращается и присваивается переменной fc. p = 46, а значит и fc = 46.

Вот и разобрались со всем циклом. Не так и сложно.

Теперь будем дальше изучать и добавим параметр while.

def fc = fold i = 1 to 10 with p = 1 while i <= 5 do p + i;

Мы установили условие, пока условие выполняется цикл работает, как только условие перестанет выполняться, цикл завершится. Пройдемся теперь по шагам.

1.     Объявили переменные i = 1, p = 1.

2.     Проверяем условие. i <= 5 ? или 1 <= 5 ? – Да, цикл продолжается.

3.     Первая итерация p = p + i или p = 1 + 1. p = 2.

4.     Проверяем условие. i <= 5 ? или 2 <= 5 ? – Да, цикл продолжается.

5.     Вторя итерация p = p + i или p = 2 + 2. p = 4.

6.     Проверяем условие. i <= 5 ? или 3 <= 5 ? – Да, цикл продолжается.

7.     Третья итерация p = p + i или p = 4 + 3. p = 7.

8.     Проверяем условие. i <= 5 ? или 4 <= 5 ? – Да, цикл продолжается.

9.     Четвертая итерация p = p + i или p = 7 + 4. p = 11.

10. Проверяем условие. i <= 5 ? или 5 <= 5 ? – Да, цикл продолжается.

11. Пятая итерация p = p + i или p = 11 + 5. p = 16.

12. Проверяем условие. i <= 5 ? или 6 <= 5 ? – Нет, цикл завершился.

13. Последнее значение p присваиваем переменной fc. p = 16. fc = 16.

Вот и вся работа цикла.

К сожалению этот цикл очень ограничен и не дает много делать, но хоть такой есть.

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

Синтаксис функции GetValue.

GetValue(IDataHolder data, IDataHolder dynamic offset, int max offset);

data – Данные которые нужно получить.

dynamic offset – динамическое смещение.

max offset – максимальное смещение. (по умолчанию 0)

Напишем пример

def price1 = close[10];
def price2 = GetValue(close, 10);

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

def fc = fold i = 1 to 10 with p = 1 do close + close[i+1];

Попробуйте добавить эту строку в редактор thinkScript и получите ошибку. В описании ошибки предложат использовать функцию GetValue.

Заменим наш код с использованием данной функции.

def fc = fold i = 1 to 10 with p = 1 do close + GetValue(close, i+1);

Теперь код принят. Все хорошо.

Вот и все, что касается циклов.

Постоянная ссылка на это сообщение: https://k-pavel.ru/organizacija-ciklov-v-thinkscript/

avatar
1 Цепочка комментария
2 Ответы по цепочке
1 Последователи
 
Популярнейший комментарий
Цепочка актуального комментария
2 Авторы комментариев
SergeyПавел Кашинский Авторы недавних комментариев

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.

  Subscribe  
Новые Старые Популярные
Подписаться на
Sergey
Гость
Sergey

Неделю не могу закодить простейшый цикл. TOS не дает внутри цикла использовать переменные. Хотя бы направление можете подсказать
Вот пример на Java
// Bisection Method - Solves: x^2 - 3 = 0

public class Bisection01
{
public static void main(String[] args)
{
final double epsilon = 0.00001;
double a, b, m, y_m, y_a;

a = 0; b = 4;

while ( (b-a) > epsilon )
{
m = (a+b)/2; // Mid point

y_m = m*m - 3.0; // y_m = f(m)
y_a = a*a - 3.0; // y_a = f(a)

if ( (y_m > 0 && y_a < 0) || (y_m < 0 && y_a > 0) )
{ // f(a) and f(m) have different signs: move b
b = m;
}
else
{ // f(a) and f(m) have same signs: move a
a = m;
}
System.out.println("New interval: [" + a + " .. " + b + "]");
// Print progress
}

System.out.println("Approximate solution = " + (a+b)/2 );
}
}

А вот попытка написать на thinkscript
script func { # simple fuction
input x = 0;
plot f = x - 2.035;
}
script Bisec {
input a = 1.0001;
input b = 2.31;
def e = 0.00001;
def mn = a;
def mx = b;
plot ret = fold i = 0 to 100 with mid=(a +b) / 2 while mx - mn > e do {
if func(mn) * func(mid) < 0 then mx == mid else mn == mid;
mid=(mn + mx) / 2;
}
}

def res = Bisec().ret;
AddLabel(yes, "Res = " + res);

Sergey
Гость
Sergey

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