Расчет среднего и стандартного отклонения с данными, которые соответствуют условию - PullRequest
0 голосов
/ 17 января 2020

У меня есть индикатор, который колеблется между 1 и -1 в зависимости от значения одной переменной, назовем его M. Я хотел бы взять среднее значение и sDev для M за определенный промежуток времени, но я хочу сделать что отдельно для положительных значений и отрицательных значений M.

Другими словами, я хочу иметь возможность получить среднее значение M при M> 0 за временной ряд, игнорируя при этом любые значения, когда M <0 в временной ряд. Аналогично для sDev и наоборот для отрицательных значений. </p>

Я не уверен, как отфильтровать данные, которые мне не нужны, в коде или возможно ли это. Спасибо за помощь!

Обновление

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

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

Функция stdev () была другим вопросом. Он не действует как функция sma (), считающая каждую сторону. Вместо этого он будет считать только sdev ряда, когда период просмотра был больше или равен непрерывной последовательности значений pos или neg. поэтому, если бы я установил период обратного просмотра равным 60, который является длинным, никогда не было временных рядов, которые бы все положили или отрицали для этой длины, поэтому sdev будет читать как na. Я надеялся, что он просто включит sdev предыдущих частей серии, но, похоже, это не так. Вот упомянутые экраны и код, чтобы помочь проиллюстрировать

Upper = Spread > 0 ? Spread : na
Lower = Spread < 0 ? Spread : na

lbp = 60  //avg and sdev look back periods
sDevLbp = 7  

UpperSdev = stdev(Upper,sDevLbp)
LowerSdev = stdev(Lower,sDevLbp)


UpperTreshold = sma(Upper,lbp)
LowerTreshold = sma(Lower,lbp)


plot(msaSpread, title='MSA Spread', style=columns)
plot(UpperS, title='Upper S', style=line, color=orange)
plot(UpperTreshold, title='Upper Band', style=line, color=purple)

Этот первый снимок экрана с выводом показывает, что я выделяю раннюю полосу в импульсе вверх. Не то, чтобы в окне данных sdev было na, а среднее - нет.

Image1 Link

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

Изображение 2 Ссылка

Теперь проблема в том, что из-за того, как действует функция stdev (), я не могу рассчитать более длительный срок sdev. Я не смог найти обходной путь, чтобы добраться до более ранних записей в серии. Я только сейчас читаю этот новый ответ, поэтому я сделаю это.

Обновление 2

Я получил работу на 95%, используя добрый совет Густаво Карделл ниже. У меня есть одна крошечная проблема, которую я еще не разобрал, но я вернусь к этому чуть позже. Что я сделал, так это оглянулся на большой диапазон и построил значения avg и sDev, используя фиксированное количество хороших значений. Поэтому, если я хочу просмотреть период времени, в котором средние значения и средние значения превышают 15 не-баров, я посмотрю более 100 баров, возьму последние 15 хороших и вычислю их. Код и экраны ниже. У меня есть проблема в том, что, хотя верхняя граница выглядит правильно, то есть она движется, когда значения положительные, и ровная, если значения отрицательные, нижняя граница кажется покачивающейся, а значения положительными. Я не уверен, почему это так.

lbp = 15
Range = 100

lbpCount = 1
UpperAVG = 0.0
for i = 0 to Range+1
    if(na(Upper[i]))
        continue
    if(lbpCount<=lbp)
        UpperAVG := UpperAVG+Upper[i]
        lbpCount := lbpCount+1
    if(lbpCount>lbp)
        UpperAVG := UpperAVG/lbp
        break

lbpCount2 = 1
holder = 0.0
UpperSTDEV = 0.0
for i = 0 to Range+1
    if(na(Upper[i]))
        continue
    if(lbpCount2<=lbp)
        holder := Upper[i] - UpperAVG
        holder := holder*holder
        UpperSTDEV := UpperSTDEV + holder
        lbpCount2 := lbpCount2+1
    if(lbpCount2>lbp)
        UpperSTDEV := UpperSTDEV/lbp
        UpperSTDEV := sqrt(UpperSTDEV)
        break

plot(UpperSTDEV+UpperAVG, title='UpperBOUND', color=orange )        


lbpCount3 = 1
LowerAVG = 0.0
for i = 0 to Range+1
    if(na(Lower[i]))
        continue
    if(lbpCount3<=lbp)
        LowerAVG := LowerAVG+Lower[i]
        lbpCount3 := lbpCount3+1
    if(lbpCount3>lbp)
        LowerAVG := LowerAVG/lbp
        break

lbpCount4 = 1
holder4 = 0.0
LowerSTDEV = 0.0
for i = 0 to Range+1
    if(na(Lower[i]))
        continue
    if(lbpCount4<=lbp)
        holder4 := Lower[i] - LowerAVG
        holder4 := holder4*holder4
        LowerSTDEV := LowerSTDEV + holder4
        lbpCount4 := lbpCount4+1
    if(lbpCount4>lbp)
        LowerSTDEV := LowerSTDEV/lbp
        LowerSTDEV := sqrt(LowerSTDEV)
        break

plot(LowerAVG-LowerSTDEV, title='LowerBOUND', color=orange )

вот пи c вывода:

Выходное изображение Link

Так как вы можете видеть, нижняя граница немного странная, так как она перемещается даже тогда, когда значения не являются отрицательными (следовательно, ничего не меняется). Я думал, что это как-то связано с отрицательными значениями в расчете sdev, но я думаю, что моя математика верна. Возможно, я смотрел на это слишком долго, или это может быть правильно, и я не понимаю, почему. Вот оно! Просто нужно проработать последнюю деталь. Спасибо за вашу помощь!

Обновление 3

понял последний бит и обновил код выше. Работает как задумано!

Ответы [ 2 ]

1 голос
/ 19 января 2020

Ваша идея противоречит некоторым ограничениям.

Давайте сначала обсудим, почему sma() делает это хорошо, а stdev() - нет: когда вы вычисляете среднее значение, а значение отсутствует, вы просто замените отсутствующее значение на последнее известное среднее, и ваш средний расчет от этого не пострадает. Однако стандартное отклонение нелинейно зависит от количества выборок, и угадывание того, какое значение использовать для замены начальных значений, чтобы конечный результат не изменился, является сложным итеративным процессом для того, что сосна НЕ (редактировать) означало.

С учетом сказанного и учитывая смещенное выражение стандартного отклонения, как в:

Biased standard deviation

Я бы предложил следующий обходной путь:

1) создайте for l oop, где вы просматриваете N баров назад во времени и вычисляете среднее значение интересующих вас значений (либо только положительное, либо только отрицательное) , Воспользуйтесь возможностью вычислить N, то есть количество действительных значений, которые вы усредняете

2) сделать еще один for l oop, где вы снова посмотрите на те же N столбцов во времени и вычислите Суммирование квадратов разности каждой действительной точки данных по сравнению со средним значением, вычисленным на первом этапе. Это SIGMA [(xi-x_avg) ^ 2] часть формулы)

3) разделите результат шага 2 на N, полученный на шаге 1

4), получите желаемое stdev путем квадратного корня значения, полученного на шаге 3

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

0 голосов
/ 17 января 2020

Вы можете использовать Тернарный условный оператор и создать две переменные (положительную и отрицательную)

Что-то в этом роде

ema_M = ema(M, length)
ema_M_Pos = M > 0 ? ema_M : na
ema_M_Neg = M < 0 ? ema_M : na
plot (ema_M_Pos)
plot (ema_M_Neg)
...