Как создать переменную, которая сохраняет свое значение - PullRequest
0 голосов
/ 10 июня 2019

В диаграммах и сканировании thinkcript любой скрипт выполняется многократно по одному разу для каждой панели. Состояние программы между такими выполнениями хранится в переменных массива, доступ к которым осуществляется напрямую или посредством смещения через [] или GetValue(). Многие сценарии, использующие какое-либо распознавание образов, должны инициализировать такие переменные на первой панели, присваивая им начальные значения. При выполнении на последующих барах скрипт либо копирует предыдущее значение, либо создает новые значения. Затем, в зависимости от какого-либо другого условия, скрипт может проверить, равна ли текущая запись массива первой записи массива, чтобы выяснить, произошло ли что-то интересное в данных.

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

При сканировании выполняется один оператор графика на последнем баре. Скрипт имеет единственный критерий того, что проверяемая переменная сохраняет свое значение и не изменяется чем-то другим. Изменение переменных или записей массива переменных в thinkcript недопустимо и никогда не должно происходить. Однако этот скрипт показывает, что первая запись переменной перезаписывается. Как это происходит и как этого избежать?

def index;
def myVar;
if (BarNumber() == 1) {
    index = -1;
    myVar = close;
} else {
    if (close > myVar[1]) {
        myVar = close;
        index = index[1];
    } else {
        if (close <= myVar[1]) {
            index = 1;
        } else {
            index = index[1];
        }
        myVar = myVar[1];
    }
}
plot scan = GetValue(index, BarNumber() -1) == -1;

1 Ответ

0 голосов
/ 13 июня 2019

Невозможно избежать этого, потому что это дефект, ошибка в модуле сканирования по состоянию на 2019-06-13. Позвольте мне в нескольких простых шагах представить подтверждение всего кода, выполняемого модулем сканирования для всех символов, чтобы получить максимальное покрытие.

def myLowest = LowestAll(BarNumber());
plot scan = myLowest == 1;

Возвращает весь набор и доказывает, что в первом столбце для всех отсканированных символов указано BarNumber() == 1; Всегда.

Опять же, мы начинаем для всех символов с

def myHighest = HighestAll(BarNumber());
plot scan = BarNumber() == myHighest;

Возвращает весь набор.

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

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

Теперь мы используем эти знания для проверки успешного выполнения пользователем написанного оператора if в модуле сканирования.

def index;
if (BarNumber() == 1) {
    index = -1;
} else {
   index = 3;
}

plot scan = GetValue(index, BarNumber() -1) == -1;

Функция GetValue() позволяет нам использовать переменное смещение для индексации в зависимости от количества баров, которые есть у каждого символа. Мы ожидаем сравнить первую запись в index, где мы можем проверить содержимое как число -1, и оно будет работать, как и ожидалось, потому что сканирование возвращает все символы в наборе.

В качестве последнего шага мы расширяем код оператора if, чтобы показать сбой модуля сканирования. Мы все еще выполняем тот же тест в утверждении заговора. Однако теперь механизм сканирования повреждает первую запись index как побочный эффект нового кода. Тест сейчас не проходит. Модуль сканирования устанавливает значение index при BarNumber() == 1 равным 0. Нет кода пользователя, который делает это - код пользователя устанавливает его в -1.

def index;
def myVar;
if (BarNumber() == 1) {
    index = -1;
    myVar = close;
} else {
    if (close > myVar[1]) {
        myVar = close;
        index = index[1];
    } else {
        if (close <= myVar[1]) {
            index = 1;
        } else {
            index = index[1];
        }
        myVar = myVar[1];
    }
}
plot scan = GetValue(index, BarNumber() -1) == -1;

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

Ниже приведен еще один пример:

def sum;
if (BarNumber() == 1) {
    sum = 1;
} else {
    if (BarNumber() < 5) {
        sum = sum[1] + 1;
    } else {
        sum = sum[1]; # This causes the problem.
        #sum = Double.NaN;# alternative: does not corrupt previous value but useless.
    }
}
plot scan = GetValue(sum, BarNumber() -1) == 1;
...