|
@@ -1,5989 +0,0 @@
|
|
|
-package talib
|
|
|
-
|
|
|
-/*
|
|
|
-Copyright 2016 Mark Chenoweth
|
|
|
-Licensed under terms of MIT license (see LICENSE)
|
|
|
-*/
|
|
|
-
|
|
|
-import (
|
|
|
- "errors"
|
|
|
- "math"
|
|
|
-)
|
|
|
-
|
|
|
-// MaType - Moving average type
|
|
|
-type MaType int
|
|
|
-
|
|
|
-type moneyFlow struct {
|
|
|
- positive float64
|
|
|
- negative float64
|
|
|
-}
|
|
|
-
|
|
|
-// Kinds of moving averages
|
|
|
-const (
|
|
|
- SMA MaType = iota
|
|
|
- EMA
|
|
|
- WMA
|
|
|
- DEMA
|
|
|
- TEMA
|
|
|
- TRIMA
|
|
|
- KAMA
|
|
|
- MAMA
|
|
|
- T3MA
|
|
|
-)
|
|
|
-
|
|
|
-/* Overlap Studies */
|
|
|
-
|
|
|
-// BBands - Bollinger Bands
|
|
|
-// upperband, middleband, lowerband = BBands(close, timeperiod=5, nbdevup=2, nbdevdn=2, matype=0)
|
|
|
-func BBands(inReal []float64, inTimePeriod int, inNbDevUp float64, inNbDevDn float64, inMAType MaType) ([]float64, []float64, []float64) {
|
|
|
-
|
|
|
- outRealUpperBand := make([]float64, len(inReal))
|
|
|
- outRealMiddleBand := Ma(inReal, inTimePeriod, inMAType)
|
|
|
- outRealLowerBand := make([]float64, len(inReal))
|
|
|
-
|
|
|
- tempBuffer2 := StdDev(inReal, inTimePeriod, 1.0)
|
|
|
-
|
|
|
- if inNbDevUp == inNbDevDn {
|
|
|
-
|
|
|
- if inNbDevUp == 1.0 {
|
|
|
- for i := 0; i < len(inReal); i++ {
|
|
|
- tempReal := tempBuffer2[i]
|
|
|
- tempReal2 := outRealMiddleBand[i]
|
|
|
- outRealUpperBand[i] = tempReal2 + tempReal
|
|
|
- outRealLowerBand[i] = tempReal2 - tempReal
|
|
|
- }
|
|
|
- } else {
|
|
|
- for i := 0; i < len(inReal); i++ {
|
|
|
- tempReal := tempBuffer2[i] * inNbDevUp
|
|
|
- tempReal2 := outRealMiddleBand[i]
|
|
|
- outRealUpperBand[i] = tempReal2 + tempReal
|
|
|
- outRealLowerBand[i] = tempReal2 - tempReal
|
|
|
- }
|
|
|
- }
|
|
|
- } else if inNbDevUp == 1.0 {
|
|
|
- for i := 0; i < len(inReal); i++ {
|
|
|
- tempReal := tempBuffer2[i]
|
|
|
- tempReal2 := outRealMiddleBand[i]
|
|
|
- outRealUpperBand[i] = tempReal2 + tempReal
|
|
|
- outRealLowerBand[i] = tempReal2 - (tempReal * inNbDevDn)
|
|
|
- }
|
|
|
- } else if inNbDevDn == 1.0 {
|
|
|
- for i := 0; i < len(inReal); i++ {
|
|
|
- tempReal := tempBuffer2[i]
|
|
|
- tempReal2 := outRealMiddleBand[i]
|
|
|
- outRealLowerBand[i] = tempReal2 - tempReal
|
|
|
- outRealUpperBand[i] = tempReal2 + (tempReal * inNbDevUp)
|
|
|
- }
|
|
|
- } else {
|
|
|
- for i := 0; i < len(inReal); i++ {
|
|
|
- tempReal := tempBuffer2[i]
|
|
|
- tempReal2 := outRealMiddleBand[i]
|
|
|
- outRealUpperBand[i] = tempReal2 + (tempReal * inNbDevUp)
|
|
|
- outRealLowerBand[i] = tempReal2 - (tempReal * inNbDevDn)
|
|
|
- }
|
|
|
- }
|
|
|
- return outRealUpperBand, outRealMiddleBand, outRealLowerBand
|
|
|
-}
|
|
|
-
|
|
|
-// Dema - Double Exponential Moving Average
|
|
|
-func Dema(inReal []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
- firstEMA := Ema(inReal, inTimePeriod)
|
|
|
- secondEMA := Ema(firstEMA[inTimePeriod-1:], inTimePeriod)
|
|
|
-
|
|
|
- for outIdx, secondEMAIdx := (inTimePeriod*2)-2, inTimePeriod-1; outIdx < len(inReal); outIdx, secondEMAIdx = outIdx+1, secondEMAIdx+1 {
|
|
|
- outReal[outIdx] = (2.0 * firstEMA[outIdx]) - secondEMA[secondEMAIdx]
|
|
|
- }
|
|
|
-
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Ema - Exponential Moving Average
|
|
|
-func ema(inReal []float64, inTimePeriod int, k1 float64) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
-
|
|
|
- lookbackTotal := inTimePeriod - 1
|
|
|
- startIdx := lookbackTotal
|
|
|
- today := startIdx - lookbackTotal
|
|
|
- i := inTimePeriod
|
|
|
- tempReal := 0.0
|
|
|
- for i > 0 {
|
|
|
- tempReal += inReal[today]
|
|
|
- today++
|
|
|
- i--
|
|
|
- }
|
|
|
-
|
|
|
- prevMA := tempReal / float64(inTimePeriod)
|
|
|
-
|
|
|
- for today <= startIdx {
|
|
|
- prevMA = ((inReal[today] - prevMA) * k1) + prevMA
|
|
|
- today++
|
|
|
- }
|
|
|
- outReal[startIdx] = prevMA
|
|
|
- outIdx := startIdx + 1
|
|
|
- for today < len(inReal) {
|
|
|
- prevMA = ((inReal[today] - prevMA) * k1) + prevMA
|
|
|
- outReal[outIdx] = prevMA
|
|
|
- today++
|
|
|
- outIdx++
|
|
|
- }
|
|
|
-
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Ema - Exponential Moving Average
|
|
|
-func Ema(inReal []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- k := 2.0 / float64(inTimePeriod+1)
|
|
|
- outReal := ema(inReal, inTimePeriod, k)
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// HtTrendline - Hilbert Transform - Instantaneous Trendline (lookback=63)
|
|
|
-func HtTrendline(inReal []float64) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
- a := 0.0962
|
|
|
- b := 0.5769
|
|
|
- detrenderOdd := make([]float64, 3)
|
|
|
- detrenderEven := make([]float64, 3)
|
|
|
- q1Odd := make([]float64, 3)
|
|
|
- q1Even := make([]float64, 3)
|
|
|
- jIOdd := make([]float64, 3)
|
|
|
- jIEven := make([]float64, 3)
|
|
|
- jQOdd := make([]float64, 3)
|
|
|
- jQEven := make([]float64, 3)
|
|
|
- smoothPriceIdx := 0
|
|
|
- maxIdxSmoothPrice := (50 - 1)
|
|
|
- smoothPrice := make([]float64, maxIdxSmoothPrice+1)
|
|
|
- iTrend1 := 0.0
|
|
|
- iTrend2 := 0.0
|
|
|
- iTrend3 := 0.0
|
|
|
- tempReal := math.Atan(1)
|
|
|
- rad2Deg := 45.0 / tempReal
|
|
|
- lookbackTotal := 63
|
|
|
- startIdx := lookbackTotal
|
|
|
- trailingWMAIdx := startIdx - lookbackTotal
|
|
|
- today := trailingWMAIdx
|
|
|
- tempReal = inReal[today]
|
|
|
- today++
|
|
|
- periodWMASub := tempReal
|
|
|
- periodWMASum := tempReal
|
|
|
- tempReal = inReal[today]
|
|
|
- today++
|
|
|
- periodWMASub += tempReal
|
|
|
- periodWMASum += tempReal * 2.0
|
|
|
- tempReal = inReal[today]
|
|
|
- today++
|
|
|
- periodWMASub += tempReal
|
|
|
- periodWMASum += tempReal * 3.0
|
|
|
- trailingWMAValue := 0.0
|
|
|
- i := 34
|
|
|
- for ok := true; ok; {
|
|
|
- tempReal = inReal[today]
|
|
|
- today++
|
|
|
- periodWMASub += tempReal
|
|
|
- periodWMASub -= trailingWMAValue
|
|
|
- periodWMASum += tempReal * 4.0
|
|
|
- trailingWMAValue = inReal[trailingWMAIdx]
|
|
|
- trailingWMAIdx++
|
|
|
- //smoothedValue := periodWMASum * 0.1
|
|
|
- periodWMASum -= periodWMASub
|
|
|
- i--
|
|
|
- ok = i != 0
|
|
|
- }
|
|
|
- hilbertIdx := 0
|
|
|
- detrender := 0.0
|
|
|
- prevDetrenderOdd := 0.0
|
|
|
- prevDetrenderEven := 0.0
|
|
|
- prevDetrenderInputOdd := 0.0
|
|
|
- prevDetrenderInputEven := 0.0
|
|
|
- q1 := 0.0
|
|
|
- prevq1Odd := 0.0
|
|
|
- prevq1Even := 0.0
|
|
|
- prevq1InputOdd := 0.0
|
|
|
- prevq1InputEven := 0.0
|
|
|
- jI := 0.0
|
|
|
- prevJIOdd := 0.0
|
|
|
- prevJIEven := 0.0
|
|
|
- prevJIInputOdd := 0.0
|
|
|
- prevJIInputEven := 0.0
|
|
|
- jQ := 0.0
|
|
|
- prevJQOdd := 0.0
|
|
|
- prevJQEven := 0.0
|
|
|
- prevJQInputOdd := 0.0
|
|
|
- prevJQInputEven := 0.0
|
|
|
- period := 0.0
|
|
|
- outIdx := 63
|
|
|
- previ2 := 0.0
|
|
|
- prevq2 := 0.0
|
|
|
- Re := 0.0
|
|
|
- Im := 0.0
|
|
|
- i1ForOddPrev3 := 0.0
|
|
|
- i1ForEvenPrev3 := 0.0
|
|
|
- i1ForOddPrev2 := 0.0
|
|
|
- i1ForEvenPrev2 := 0.0
|
|
|
- smoothPeriod := 0.0
|
|
|
- q2 := 0.0
|
|
|
- i2 := 0.0
|
|
|
- for today < len(inReal) {
|
|
|
- adjustedPrevPeriod := (0.075 * period) + 0.54
|
|
|
- todayValue := inReal[today]
|
|
|
- periodWMASub += todayValue
|
|
|
- periodWMASub -= trailingWMAValue
|
|
|
- periodWMASum += todayValue * 4.0
|
|
|
- trailingWMAValue = inReal[trailingWMAIdx]
|
|
|
- trailingWMAIdx++
|
|
|
- smoothedValue := periodWMASum * 0.1
|
|
|
- periodWMASum -= periodWMASub
|
|
|
- smoothPrice[smoothPriceIdx] = smoothedValue
|
|
|
- if (today % 2) == 0 {
|
|
|
- hilbertTempReal := a * smoothedValue
|
|
|
- detrender = -detrenderEven[hilbertIdx]
|
|
|
- detrenderEven[hilbertIdx] = hilbertTempReal
|
|
|
- detrender += hilbertTempReal
|
|
|
- detrender -= prevDetrenderEven
|
|
|
- prevDetrenderEven = b * prevDetrenderInputEven
|
|
|
- detrender += prevDetrenderEven
|
|
|
- prevDetrenderInputEven = smoothedValue
|
|
|
- detrender *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * detrender
|
|
|
- q1 = -q1Even[hilbertIdx]
|
|
|
- q1Even[hilbertIdx] = hilbertTempReal
|
|
|
- q1 += hilbertTempReal
|
|
|
- q1 -= prevq1Even
|
|
|
- prevq1Even = b * prevq1InputEven
|
|
|
- q1 += prevq1Even
|
|
|
- prevq1InputEven = detrender
|
|
|
- q1 *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * i1ForEvenPrev3
|
|
|
- jI = -jIEven[hilbertIdx]
|
|
|
- jIEven[hilbertIdx] = hilbertTempReal
|
|
|
- jI += hilbertTempReal
|
|
|
- jI -= prevJIEven
|
|
|
- prevJIEven = b * prevJIInputEven
|
|
|
- jI += prevJIEven
|
|
|
- prevJIInputEven = i1ForEvenPrev3
|
|
|
- jI *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * q1
|
|
|
- jQ = -jQEven[hilbertIdx]
|
|
|
- jQEven[hilbertIdx] = hilbertTempReal
|
|
|
- jQ += hilbertTempReal
|
|
|
- jQ -= prevJQEven
|
|
|
- prevJQEven = b * prevJQInputEven
|
|
|
- jQ += prevJQEven
|
|
|
- prevJQInputEven = q1
|
|
|
- jQ *= adjustedPrevPeriod
|
|
|
- hilbertIdx++
|
|
|
- if hilbertIdx == 3 {
|
|
|
- hilbertIdx = 0
|
|
|
- }
|
|
|
- q2 = (0.2 * (q1 + jI)) + (0.8 * prevq2)
|
|
|
- i2 = (0.2 * (i1ForEvenPrev3 - jQ)) + (0.8 * previ2)
|
|
|
- i1ForOddPrev3 = i1ForOddPrev2
|
|
|
- i1ForOddPrev2 = detrender
|
|
|
- } else {
|
|
|
- hilbertTempReal := a * smoothedValue
|
|
|
- detrender = -detrenderOdd[hilbertIdx]
|
|
|
- detrenderOdd[hilbertIdx] = hilbertTempReal
|
|
|
- detrender += hilbertTempReal
|
|
|
- detrender -= prevDetrenderOdd
|
|
|
- prevDetrenderOdd = b * prevDetrenderInputOdd
|
|
|
- detrender += prevDetrenderOdd
|
|
|
- prevDetrenderInputOdd = smoothedValue
|
|
|
- detrender *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * detrender
|
|
|
- q1 = -q1Odd[hilbertIdx]
|
|
|
- q1Odd[hilbertIdx] = hilbertTempReal
|
|
|
- q1 += hilbertTempReal
|
|
|
- q1 -= prevq1Odd
|
|
|
- prevq1Odd = b * prevq1InputOdd
|
|
|
- q1 += prevq1Odd
|
|
|
- prevq1InputOdd = detrender
|
|
|
- q1 *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * i1ForOddPrev3
|
|
|
- jI = -jIOdd[hilbertIdx]
|
|
|
- jIOdd[hilbertIdx] = hilbertTempReal
|
|
|
- jI += hilbertTempReal
|
|
|
- jI -= prevJIOdd
|
|
|
- prevJIOdd = b * prevJIInputOdd
|
|
|
- jI += prevJIOdd
|
|
|
- prevJIInputOdd = i1ForOddPrev3
|
|
|
- jI *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * q1
|
|
|
- jQ = -jQOdd[hilbertIdx]
|
|
|
- jQOdd[hilbertIdx] = hilbertTempReal
|
|
|
- jQ += hilbertTempReal
|
|
|
- jQ -= prevJQOdd
|
|
|
- prevJQOdd = b * prevJQInputOdd
|
|
|
- jQ += prevJQOdd
|
|
|
- prevJQInputOdd = q1
|
|
|
- jQ *= adjustedPrevPeriod
|
|
|
- q2 = (0.2 * (q1 + jI)) + (0.8 * prevq2)
|
|
|
- i2 = (0.2 * (i1ForOddPrev3 - jQ)) + (0.8 * previ2)
|
|
|
- i1ForEvenPrev3 = i1ForEvenPrev2
|
|
|
- i1ForEvenPrev2 = detrender
|
|
|
- }
|
|
|
- Re = (0.2 * ((i2 * previ2) + (q2 * prevq2))) + (0.8 * Re)
|
|
|
- Im = (0.2 * ((i2 * prevq2) - (q2 * previ2))) + (0.8 * Im)
|
|
|
- prevq2 = q2
|
|
|
- previ2 = i2
|
|
|
- tempReal = period
|
|
|
- if (Im != 0.0) && (Re != 0.0) {
|
|
|
- period = 360.0 / (math.Atan(Im/Re) * rad2Deg)
|
|
|
- }
|
|
|
- tempReal2 := 1.5 * tempReal
|
|
|
- if period > tempReal2 {
|
|
|
- period = tempReal2
|
|
|
- }
|
|
|
- tempReal2 = 0.67 * tempReal
|
|
|
- if period < tempReal2 {
|
|
|
- period = tempReal2
|
|
|
- }
|
|
|
- if period < 6 {
|
|
|
- period = 6
|
|
|
- } else if period > 50 {
|
|
|
- period = 50
|
|
|
- }
|
|
|
- period = (0.2 * period) + (0.8 * tempReal)
|
|
|
- smoothPeriod = (0.33 * period) + (0.67 * smoothPeriod)
|
|
|
- DCPeriod := smoothPeriod + 0.5
|
|
|
- DCPeriodInt := math.Floor(DCPeriod)
|
|
|
- idx := today
|
|
|
- tempReal = 0.0
|
|
|
- for i := 0; i < int(DCPeriodInt); i++ {
|
|
|
- tempReal += inReal[idx]
|
|
|
- idx--
|
|
|
- }
|
|
|
- if DCPeriodInt > 0 {
|
|
|
- tempReal = tempReal / (DCPeriodInt * 1.0)
|
|
|
- }
|
|
|
- tempReal2 = (4.0*tempReal + 3.0*iTrend1 + 2.0*iTrend2 + iTrend3) / 10.0
|
|
|
- iTrend3 = iTrend2
|
|
|
- iTrend2 = iTrend1
|
|
|
- iTrend1 = tempReal
|
|
|
- if today >= startIdx {
|
|
|
- outReal[outIdx] = tempReal2
|
|
|
- outIdx++
|
|
|
- }
|
|
|
- smoothPriceIdx++
|
|
|
- if smoothPriceIdx > maxIdxSmoothPrice {
|
|
|
- smoothPriceIdx = 0
|
|
|
- }
|
|
|
-
|
|
|
- today++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Kama - Kaufman Adaptive Moving Average
|
|
|
-func Kama(inReal []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
-
|
|
|
- constMax := 2.0 / (30.0 + 1.0)
|
|
|
- constDiff := 2.0/(2.0+1.0) - constMax
|
|
|
- lookbackTotal := inTimePeriod
|
|
|
- startIdx := lookbackTotal
|
|
|
- sumROC1 := 0.0
|
|
|
- today := startIdx - lookbackTotal
|
|
|
- trailingIdx := today
|
|
|
- i := inTimePeriod
|
|
|
- for i > 0 {
|
|
|
- tempReal := inReal[today]
|
|
|
- today++
|
|
|
- tempReal -= inReal[today]
|
|
|
- sumROC1 += math.Abs(tempReal)
|
|
|
- i--
|
|
|
- }
|
|
|
- prevKAMA := inReal[today-1]
|
|
|
- tempReal := inReal[today]
|
|
|
- tempReal2 := inReal[trailingIdx]
|
|
|
- trailingIdx++
|
|
|
- periodROC := tempReal - tempReal2
|
|
|
- trailingValue := tempReal2
|
|
|
- if (sumROC1 <= periodROC) || (((-(0.00000000000001)) < sumROC1) && (sumROC1 < (0.00000000000001))) {
|
|
|
- tempReal = 1.0
|
|
|
- } else {
|
|
|
- tempReal = math.Abs(periodROC / sumROC1)
|
|
|
- }
|
|
|
- tempReal = (tempReal * constDiff) + constMax
|
|
|
- tempReal *= tempReal
|
|
|
- prevKAMA = ((inReal[today] - prevKAMA) * tempReal) + prevKAMA
|
|
|
- today++
|
|
|
- for today <= startIdx {
|
|
|
- tempReal = inReal[today]
|
|
|
- tempReal2 = inReal[trailingIdx]
|
|
|
- trailingIdx++
|
|
|
- periodROC = tempReal - tempReal2
|
|
|
- sumROC1 -= math.Abs(trailingValue - tempReal2)
|
|
|
- sumROC1 += math.Abs(tempReal - inReal[today-1])
|
|
|
- trailingValue = tempReal2
|
|
|
- if (sumROC1 <= periodROC) || (((-(0.00000000000001)) < sumROC1) && (sumROC1 < (0.00000000000001))) {
|
|
|
- tempReal = 1.0
|
|
|
- } else {
|
|
|
- tempReal = math.Abs(periodROC / sumROC1)
|
|
|
- }
|
|
|
- tempReal = (tempReal * constDiff) + constMax
|
|
|
- tempReal *= tempReal
|
|
|
- prevKAMA = ((inReal[today] - prevKAMA) * tempReal) + prevKAMA
|
|
|
- today++
|
|
|
- }
|
|
|
- outReal[inTimePeriod] = prevKAMA
|
|
|
- outIdx := inTimePeriod + 1
|
|
|
- for today < len(inReal) {
|
|
|
- tempReal = inReal[today]
|
|
|
- tempReal2 = inReal[trailingIdx]
|
|
|
- trailingIdx++
|
|
|
- periodROC = tempReal - tempReal2
|
|
|
- sumROC1 -= math.Abs(trailingValue - tempReal2)
|
|
|
- sumROC1 += math.Abs(tempReal - inReal[today-1])
|
|
|
- trailingValue = tempReal2
|
|
|
- if (sumROC1 <= periodROC) || (((-(0.00000000000001)) < sumROC1) && (sumROC1 < (0.00000000000001))) {
|
|
|
- tempReal = 1.0
|
|
|
- } else {
|
|
|
- tempReal = math.Abs(periodROC / sumROC1)
|
|
|
- }
|
|
|
- tempReal = (tempReal * constDiff) + constMax
|
|
|
- tempReal *= tempReal
|
|
|
- prevKAMA = ((inReal[today] - prevKAMA) * tempReal) + prevKAMA
|
|
|
- today++
|
|
|
- outReal[outIdx] = prevKAMA
|
|
|
- outIdx++
|
|
|
- }
|
|
|
-
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Ma - Moving average
|
|
|
-func Ma(inReal []float64, inTimePeriod int, inMAType MaType) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
-
|
|
|
- if inTimePeriod == 1 {
|
|
|
- copy(outReal, inReal)
|
|
|
- return outReal
|
|
|
- }
|
|
|
-
|
|
|
- switch inMAType {
|
|
|
- case SMA:
|
|
|
- outReal = Sma(inReal, inTimePeriod)
|
|
|
- case EMA:
|
|
|
- outReal = Ema(inReal, inTimePeriod)
|
|
|
- case WMA:
|
|
|
- outReal = Wma(inReal, inTimePeriod)
|
|
|
- case DEMA:
|
|
|
- outReal = Dema(inReal, inTimePeriod)
|
|
|
- case TEMA:
|
|
|
- outReal = Tema(inReal, inTimePeriod)
|
|
|
- case TRIMA:
|
|
|
- outReal = Trima(inReal, inTimePeriod)
|
|
|
- case KAMA:
|
|
|
- outReal = Kama(inReal, inTimePeriod)
|
|
|
- case MAMA:
|
|
|
- outReal, _ = Mama(inReal, 0.5, 0.05)
|
|
|
- case T3MA:
|
|
|
- outReal = T3(inReal, inTimePeriod, 0.7)
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Mama - MESA Adaptive Moving Average (lookback=32)
|
|
|
-func Mama(inReal []float64, inFastLimit float64, inSlowLimit float64) ([]float64, []float64) {
|
|
|
-
|
|
|
- outMAMA := make([]float64, len(inReal))
|
|
|
- outFAMA := make([]float64, len(inReal))
|
|
|
-
|
|
|
- a := 0.0962
|
|
|
- b := 0.5769
|
|
|
- detrenderOdd := make([]float64, 3)
|
|
|
- detrenderEven := make([]float64, 3)
|
|
|
- q1Odd := make([]float64, 3)
|
|
|
- q1Even := make([]float64, 3)
|
|
|
- jIOdd := make([]float64, 3)
|
|
|
- jIEven := make([]float64, 3)
|
|
|
- jQOdd := make([]float64, 3)
|
|
|
- jQEven := make([]float64, 3)
|
|
|
- rad2Deg := 180.0 / (4.0 * math.Atan(1))
|
|
|
- lookbackTotal := 32
|
|
|
- startIdx := lookbackTotal
|
|
|
- trailingWMAIdx := startIdx - lookbackTotal
|
|
|
- today := trailingWMAIdx
|
|
|
- tempReal := inReal[today]
|
|
|
- today++
|
|
|
- periodWMASub := tempReal
|
|
|
- periodWMASum := tempReal
|
|
|
- tempReal = inReal[today]
|
|
|
- today++
|
|
|
- periodWMASub += tempReal
|
|
|
- periodWMASum += tempReal * 2.0
|
|
|
- tempReal = inReal[today]
|
|
|
- today++
|
|
|
- periodWMASub += tempReal
|
|
|
- periodWMASum += tempReal * 3.0
|
|
|
- trailingWMAValue := 0.0
|
|
|
- i := 9
|
|
|
- smoothedValue := 0.0
|
|
|
- for ok := true; ok; {
|
|
|
- tempReal = inReal[today]
|
|
|
- today++
|
|
|
- periodWMASub += tempReal
|
|
|
- periodWMASub -= trailingWMAValue
|
|
|
- periodWMASum += tempReal * 4.0
|
|
|
- trailingWMAValue = inReal[trailingWMAIdx]
|
|
|
- trailingWMAIdx++
|
|
|
- smoothedValue = periodWMASum * 0.1
|
|
|
- periodWMASum -= periodWMASub
|
|
|
- i--
|
|
|
- ok = i != 0
|
|
|
- }
|
|
|
- hilbertIdx := 0
|
|
|
- detrenderOdd[0] = 0.0
|
|
|
- detrenderOdd[1] = 0.0
|
|
|
- detrenderOdd[2] = 0.0
|
|
|
- detrenderEven[0] = 0.0
|
|
|
- detrenderEven[1] = 0.0
|
|
|
- detrenderEven[2] = 0.0
|
|
|
- detrender := 0.0
|
|
|
- prevDetrenderOdd := 0.0
|
|
|
- prevDetrenderEven := 0.0
|
|
|
- prevDetrenderInputOdd := 0.0
|
|
|
- prevDetrenderInputEven := 0.0
|
|
|
-
|
|
|
- q1Odd[0] = 0.0
|
|
|
- q1Odd[1] = 0.0
|
|
|
- q1Odd[2] = 0.0
|
|
|
- q1Even[0] = 0.0
|
|
|
- q1Even[1] = 0.0
|
|
|
- q1Even[2] = 0.0
|
|
|
- q1 := 0.0
|
|
|
- prevq1Odd := 0.0
|
|
|
- prevq1Even := 0.0
|
|
|
- prevq1InputOdd := 0.0
|
|
|
- prevq1InputEven := 0.0
|
|
|
-
|
|
|
- jIOdd[0] = 0.0
|
|
|
- jIOdd[1] = 0.0
|
|
|
- jIOdd[2] = 0.0
|
|
|
- jIEven[0] = 0.0
|
|
|
- jIEven[1] = 0.0
|
|
|
- jIEven[2] = 0.0
|
|
|
- jI := 0.0
|
|
|
- prevjIOdd := 0.0
|
|
|
- prevjIEven := 0.0
|
|
|
- prevjIInputOdd := 0.0
|
|
|
- prevjIInputEven := 0.0
|
|
|
-
|
|
|
- jQOdd[0] = 0.0
|
|
|
- jQOdd[1] = 0.0
|
|
|
- jQOdd[2] = 0.0
|
|
|
- jQEven[0] = 0.0
|
|
|
- jQEven[1] = 0.0
|
|
|
- jQEven[2] = 0.0
|
|
|
- jQ := 0.0
|
|
|
- prevjQOdd := 0.0
|
|
|
- prevjQEven := 0.0
|
|
|
- prevjQInputOdd := 0.0
|
|
|
- prevjQInputEven := 0.0
|
|
|
-
|
|
|
- period := 0.0
|
|
|
- outIdx := startIdx
|
|
|
- previ2, prevq2 := 0.0, 0.0
|
|
|
- Re, Im := 0.0, 0.0
|
|
|
- mama, fama := 0.0, 0.0
|
|
|
- i1ForOddPrev3, i1ForEvenPrev3 := 0.0, 0.0
|
|
|
- i1ForOddPrev2, i1ForEvenPrev2 := 0.0, 0.0
|
|
|
- prevPhase := 0.0
|
|
|
- adjustedPrevPeriod := 0.0
|
|
|
- todayValue := 0.0
|
|
|
- hilbertTempReal := 0.0
|
|
|
- for today < len(inReal) {
|
|
|
- adjustedPrevPeriod = (0.075 * period) + 0.54
|
|
|
- todayValue = inReal[today]
|
|
|
-
|
|
|
- periodWMASub += todayValue
|
|
|
- periodWMASub -= trailingWMAValue
|
|
|
- periodWMASum += todayValue * 4.0
|
|
|
- trailingWMAValue = inReal[trailingWMAIdx]
|
|
|
- trailingWMAIdx++
|
|
|
- smoothedValue = periodWMASum * 0.1
|
|
|
- periodWMASum -= periodWMASub
|
|
|
- q2, i2 := 0.0, 0.0
|
|
|
- tempReal2 := 0.0
|
|
|
- if (today % 2) == 0 {
|
|
|
-
|
|
|
- hilbertTempReal = a * smoothedValue
|
|
|
- detrender = -detrenderEven[hilbertIdx]
|
|
|
- detrenderEven[hilbertIdx] = hilbertTempReal
|
|
|
- detrender += hilbertTempReal
|
|
|
- detrender -= prevDetrenderEven
|
|
|
- prevDetrenderEven = b * prevDetrenderInputEven
|
|
|
- detrender += prevDetrenderEven
|
|
|
- prevDetrenderInputEven = smoothedValue
|
|
|
- detrender *= adjustedPrevPeriod
|
|
|
-
|
|
|
- hilbertTempReal = a * detrender
|
|
|
- q1 = -q1Even[hilbertIdx]
|
|
|
- q1Even[hilbertIdx] = hilbertTempReal
|
|
|
- q1 += hilbertTempReal
|
|
|
- q1 -= prevq1Even
|
|
|
- prevq1Even = b * prevq1InputEven
|
|
|
- q1 += prevq1Even
|
|
|
- prevq1InputEven = detrender
|
|
|
- q1 *= adjustedPrevPeriod
|
|
|
-
|
|
|
- hilbertTempReal = a * i1ForEvenPrev3
|
|
|
- jI = -jIEven[hilbertIdx]
|
|
|
- jIEven[hilbertIdx] = hilbertTempReal
|
|
|
- jI += hilbertTempReal
|
|
|
- jI -= prevjIEven
|
|
|
- prevjIEven = b * prevjIInputEven
|
|
|
- jI += prevjIEven
|
|
|
- prevjIInputEven = i1ForEvenPrev3
|
|
|
- jI *= adjustedPrevPeriod
|
|
|
-
|
|
|
- hilbertTempReal = a * q1
|
|
|
- jQ = -jQEven[hilbertIdx]
|
|
|
- jQEven[hilbertIdx] = hilbertTempReal
|
|
|
- jQ += hilbertTempReal
|
|
|
- jQ -= prevjQEven
|
|
|
- prevjQEven = b * prevjQInputEven
|
|
|
- jQ += prevjQEven
|
|
|
- prevjQInputEven = q1
|
|
|
- jQ *= adjustedPrevPeriod
|
|
|
- hilbertIdx++
|
|
|
- if hilbertIdx == 3 {
|
|
|
- hilbertIdx = 0
|
|
|
- }
|
|
|
- q2 = (0.2 * (q1 + jI)) + (0.8 * prevq2)
|
|
|
- i2 = (0.2 * (i1ForEvenPrev3 - jQ)) + (0.8 * previ2)
|
|
|
- i1ForOddPrev3 = i1ForOddPrev2
|
|
|
- i1ForOddPrev2 = detrender
|
|
|
- if i1ForEvenPrev3 != 0.0 {
|
|
|
- tempReal2 = (math.Atan(q1/i1ForEvenPrev3) * rad2Deg)
|
|
|
- } else {
|
|
|
- tempReal2 = 0.0
|
|
|
- }
|
|
|
- } else {
|
|
|
-
|
|
|
- hilbertTempReal = a * smoothedValue
|
|
|
- detrender = -detrenderOdd[hilbertIdx]
|
|
|
- detrenderOdd[hilbertIdx] = hilbertTempReal
|
|
|
- detrender += hilbertTempReal
|
|
|
- detrender -= prevDetrenderOdd
|
|
|
- prevDetrenderOdd = b * prevDetrenderInputOdd
|
|
|
- detrender += prevDetrenderOdd
|
|
|
- prevDetrenderInputOdd = smoothedValue
|
|
|
- detrender *= adjustedPrevPeriod
|
|
|
-
|
|
|
- hilbertTempReal = a * detrender
|
|
|
- q1 = -q1Odd[hilbertIdx]
|
|
|
- q1Odd[hilbertIdx] = hilbertTempReal
|
|
|
- q1 += hilbertTempReal
|
|
|
- q1 -= prevq1Odd
|
|
|
- prevq1Odd = b * prevq1InputOdd
|
|
|
- q1 += prevq1Odd
|
|
|
- prevq1InputOdd = detrender
|
|
|
- q1 *= adjustedPrevPeriod
|
|
|
-
|
|
|
- hilbertTempReal = a * i1ForOddPrev3
|
|
|
- jI = -jIOdd[hilbertIdx]
|
|
|
- jIOdd[hilbertIdx] = hilbertTempReal
|
|
|
- jI += hilbertTempReal
|
|
|
- jI -= prevjIOdd
|
|
|
- prevjIOdd = b * prevjIInputOdd
|
|
|
- jI += prevjIOdd
|
|
|
- prevjIInputOdd = i1ForOddPrev3
|
|
|
- jI *= adjustedPrevPeriod
|
|
|
-
|
|
|
- hilbertTempReal = a * q1
|
|
|
- jQ = -jQOdd[hilbertIdx]
|
|
|
- jQOdd[hilbertIdx] = hilbertTempReal
|
|
|
- jQ += hilbertTempReal
|
|
|
- jQ -= prevjQOdd
|
|
|
- prevjQOdd = b * prevjQInputOdd
|
|
|
- jQ += prevjQOdd
|
|
|
- prevjQInputOdd = q1
|
|
|
- jQ *= adjustedPrevPeriod
|
|
|
-
|
|
|
- q2 = (0.2 * (q1 + jI)) + (0.8 * prevq2)
|
|
|
- i2 = (0.2 * (i1ForOddPrev3 - jQ)) + (0.8 * previ2)
|
|
|
- i1ForEvenPrev3 = i1ForEvenPrev2
|
|
|
- i1ForEvenPrev2 = detrender
|
|
|
- if i1ForOddPrev3 != 0.0 {
|
|
|
- tempReal2 = (math.Atan(q1/i1ForOddPrev3) * rad2Deg)
|
|
|
- } else {
|
|
|
- tempReal2 = 0.0
|
|
|
- }
|
|
|
- }
|
|
|
- tempReal = prevPhase - tempReal2
|
|
|
- prevPhase = tempReal2
|
|
|
- if tempReal < 1.0 {
|
|
|
- tempReal = 1.0
|
|
|
- }
|
|
|
- if tempReal > 1.0 {
|
|
|
- tempReal = inFastLimit / tempReal
|
|
|
- if tempReal < inSlowLimit {
|
|
|
- tempReal = inSlowLimit
|
|
|
- }
|
|
|
- } else {
|
|
|
- tempReal = inFastLimit
|
|
|
- }
|
|
|
- mama = (tempReal * todayValue) + ((1 - tempReal) * mama)
|
|
|
- tempReal *= 0.5
|
|
|
- fama = (tempReal * mama) + ((1 - tempReal) * fama)
|
|
|
- if today >= startIdx {
|
|
|
- outMAMA[outIdx] = mama
|
|
|
- outFAMA[outIdx] = fama
|
|
|
- outIdx++
|
|
|
- }
|
|
|
- Re = (0.2 * ((i2 * previ2) + (q2 * prevq2))) + (0.8 * Re)
|
|
|
- Im = (0.2 * ((i2 * prevq2) - (q2 * previ2))) + (0.8 * Im)
|
|
|
- prevq2 = q2
|
|
|
- previ2 = i2
|
|
|
- tempReal = period
|
|
|
- if (Im != 0.0) && (Re != 0.0) {
|
|
|
- period = 360.0 / (math.Atan(Im/Re) * rad2Deg)
|
|
|
- }
|
|
|
- tempReal2 = 1.5 * tempReal
|
|
|
- if period > tempReal2 {
|
|
|
- period = tempReal2
|
|
|
- }
|
|
|
- tempReal2 = 0.67 * tempReal
|
|
|
- if period < tempReal2 {
|
|
|
- period = tempReal2
|
|
|
- }
|
|
|
- if period < 6 {
|
|
|
- period = 6
|
|
|
- } else if period > 50 {
|
|
|
- period = 50
|
|
|
- }
|
|
|
- period = (0.2 * period) + (0.8 * tempReal)
|
|
|
- today++
|
|
|
- }
|
|
|
- return outMAMA, outFAMA
|
|
|
-}
|
|
|
-
|
|
|
-// MaVp - Moving average with variable period
|
|
|
-func MaVp(inReal []float64, inPeriods []float64, inMinPeriod int, inMaxPeriod int, inMAType MaType) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
- startIdx := inMaxPeriod - 1
|
|
|
- outputSize := len(inReal)
|
|
|
-
|
|
|
- localPeriodArray := make([]float64, outputSize)
|
|
|
- for i := startIdx; i < outputSize; i++ {
|
|
|
- tempInt := int(inPeriods[i])
|
|
|
- if tempInt < inMinPeriod {
|
|
|
- tempInt = inMinPeriod
|
|
|
- } else if tempInt > inMaxPeriod {
|
|
|
- tempInt = inMaxPeriod
|
|
|
- }
|
|
|
- localPeriodArray[i] = float64(tempInt)
|
|
|
- }
|
|
|
-
|
|
|
- for i := startIdx; i < outputSize; i++ {
|
|
|
- curPeriod := int(localPeriodArray[i])
|
|
|
- if curPeriod != 0 {
|
|
|
- localOutputArray := Ma(inReal, curPeriod, inMAType)
|
|
|
- outReal[i] = localOutputArray[i]
|
|
|
- for j := i + 1; j < outputSize; j++ {
|
|
|
- if localPeriodArray[j] == float64(curPeriod) {
|
|
|
- localPeriodArray[j] = 0
|
|
|
- outReal[j] = localOutputArray[j]
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// MidPoint - MidPoint over period
|
|
|
-func MidPoint(inReal []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
- nbInitialElementNeeded := inTimePeriod - 1
|
|
|
- startIdx := nbInitialElementNeeded
|
|
|
- outIdx := inTimePeriod - 1
|
|
|
- today := startIdx
|
|
|
- trailingIdx := startIdx - nbInitialElementNeeded
|
|
|
-
|
|
|
- for today < len(inReal) {
|
|
|
- lowest := inReal[trailingIdx]
|
|
|
- trailingIdx++
|
|
|
- highest := lowest
|
|
|
- for i := trailingIdx; i <= today; i++ {
|
|
|
- tmp := inReal[i]
|
|
|
- if tmp < lowest {
|
|
|
- lowest = tmp
|
|
|
- } else if tmp > highest {
|
|
|
- highest = tmp
|
|
|
- }
|
|
|
- }
|
|
|
- outReal[outIdx] = (highest + lowest) / 2.0
|
|
|
- outIdx++
|
|
|
- today++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// MidPrice - Midpoint Price over period
|
|
|
-func MidPrice(inHigh []float64, inLow []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inHigh))
|
|
|
-
|
|
|
- nbInitialElementNeeded := inTimePeriod - 1
|
|
|
- startIdx := nbInitialElementNeeded
|
|
|
- outIdx := inTimePeriod - 1
|
|
|
- today := startIdx
|
|
|
- trailingIdx := startIdx - nbInitialElementNeeded
|
|
|
- for today < len(inHigh) {
|
|
|
- lowest := inLow[trailingIdx]
|
|
|
- highest := inHigh[trailingIdx]
|
|
|
- trailingIdx++
|
|
|
- for i := trailingIdx; i <= today; i++ {
|
|
|
- tmp := inLow[i]
|
|
|
- if tmp < lowest {
|
|
|
- lowest = tmp
|
|
|
- }
|
|
|
- tmp = inHigh[i]
|
|
|
- if tmp > highest {
|
|
|
- highest = tmp
|
|
|
- }
|
|
|
- }
|
|
|
- outReal[outIdx] = (highest + lowest) / 2.0
|
|
|
- outIdx++
|
|
|
- today++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Sar - Parabolic SAR
|
|
|
-// real = Sar(high, low, acceleration=0, maximum=0)
|
|
|
-func Sar(inHigh []float64, inLow []float64, inAcceleration float64, inMaximum float64) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inHigh))
|
|
|
-
|
|
|
- af := inAcceleration
|
|
|
- if af > inMaximum {
|
|
|
- af, inAcceleration = inMaximum, inMaximum
|
|
|
- }
|
|
|
-
|
|
|
- epTemp := MinusDM(inHigh, inLow, 1)
|
|
|
- isLong := 1
|
|
|
- if epTemp[1] > 0 {
|
|
|
- isLong = 0
|
|
|
- }
|
|
|
- startIdx := 1
|
|
|
- outIdx := startIdx
|
|
|
- todayIdx := startIdx
|
|
|
- newHigh := inHigh[todayIdx-1]
|
|
|
- newLow := inLow[todayIdx-1]
|
|
|
- sar, ep := 0.0, 0.0
|
|
|
- if isLong == 1 {
|
|
|
- ep = inHigh[todayIdx]
|
|
|
- sar = newLow
|
|
|
- } else {
|
|
|
- ep = inLow[todayIdx]
|
|
|
- sar = newHigh
|
|
|
- }
|
|
|
- newLow = inLow[todayIdx]
|
|
|
- newHigh = inHigh[todayIdx]
|
|
|
- prevLow := 0.0
|
|
|
- prevHigh := 0.0
|
|
|
- for todayIdx < len(inHigh) {
|
|
|
- prevLow = newLow
|
|
|
- prevHigh = newHigh
|
|
|
- newLow = inLow[todayIdx]
|
|
|
- newHigh = inHigh[todayIdx]
|
|
|
- todayIdx++
|
|
|
- if isLong == 1 {
|
|
|
- if newLow <= sar {
|
|
|
- isLong = 0
|
|
|
- sar = ep
|
|
|
- if sar < prevHigh {
|
|
|
- sar = prevHigh
|
|
|
- }
|
|
|
- if sar < newHigh {
|
|
|
- sar = newHigh
|
|
|
- }
|
|
|
- outReal[outIdx] = sar
|
|
|
- outIdx++
|
|
|
- af = inAcceleration
|
|
|
- ep = newLow
|
|
|
- sar = sar + af*(ep-sar)
|
|
|
- if sar < prevHigh {
|
|
|
- sar = prevHigh
|
|
|
- }
|
|
|
- if sar < newHigh {
|
|
|
- sar = newHigh
|
|
|
- }
|
|
|
- } else {
|
|
|
- outReal[outIdx] = sar
|
|
|
- outIdx++
|
|
|
- if newHigh > ep {
|
|
|
- ep = newHigh
|
|
|
- af += inAcceleration
|
|
|
- if af > inMaximum {
|
|
|
- af = inMaximum
|
|
|
- }
|
|
|
- }
|
|
|
- sar = sar + af*(ep-sar)
|
|
|
- if sar > prevLow {
|
|
|
- sar = prevLow
|
|
|
- }
|
|
|
- if sar > newLow {
|
|
|
- sar = newLow
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- if newHigh >= sar {
|
|
|
- isLong = 1
|
|
|
- sar = ep
|
|
|
- if sar > prevLow {
|
|
|
- sar = prevLow
|
|
|
- }
|
|
|
- if sar > newLow {
|
|
|
- sar = newLow
|
|
|
- }
|
|
|
- outReal[outIdx] = sar
|
|
|
- outIdx++
|
|
|
- af = inAcceleration
|
|
|
- ep = newHigh
|
|
|
- sar = sar + af*(ep-sar)
|
|
|
- if sar > prevLow {
|
|
|
- sar = prevLow
|
|
|
- }
|
|
|
- if sar > newLow {
|
|
|
- sar = newLow
|
|
|
- }
|
|
|
- } else {
|
|
|
- outReal[outIdx] = sar
|
|
|
- outIdx++
|
|
|
- if newLow < ep {
|
|
|
- ep = newLow
|
|
|
- af += inAcceleration
|
|
|
- if af > inMaximum {
|
|
|
- af = inMaximum
|
|
|
- }
|
|
|
- }
|
|
|
- sar = sar + af*(ep-sar)
|
|
|
- if sar < prevHigh {
|
|
|
- sar = prevHigh
|
|
|
- }
|
|
|
- if sar < newHigh {
|
|
|
- sar = newHigh
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// SarExt - Parabolic SAR - Extended
|
|
|
-// real = SAREXT(high, low, startvalue=0, offsetonreverse=0, accelerationinitlong=0, accelerationlong=0, accelerationmaxlong=0, accelerationinitshort=0, accelerationshort=0, accelerationmaxshort=0)
|
|
|
-func SarExt(inHigh []float64, inLow []float64,
|
|
|
- inStartValue float64,
|
|
|
- inOffsetOnReverse float64,
|
|
|
- inAccelerationInitLong float64,
|
|
|
- inAccelerationLong float64,
|
|
|
- inAccelerationMaxLong float64,
|
|
|
- inAccelerationInitShort float64,
|
|
|
- inAccelerationShort float64,
|
|
|
- inAccelerationMaxShort float64) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inHigh))
|
|
|
-
|
|
|
- startIdx := 1
|
|
|
- afLong := inAccelerationInitLong
|
|
|
- afShort := inAccelerationInitShort
|
|
|
- if afLong > inAccelerationMaxLong {
|
|
|
- afLong, inAccelerationInitLong = inAccelerationMaxLong, inAccelerationMaxLong
|
|
|
- }
|
|
|
-
|
|
|
- if inAccelerationLong > inAccelerationMaxLong {
|
|
|
- inAccelerationLong = inAccelerationMaxLong
|
|
|
- }
|
|
|
-
|
|
|
- if afShort > inAccelerationMaxShort {
|
|
|
- afShort, inAccelerationInitShort = inAccelerationMaxShort, inAccelerationMaxShort
|
|
|
- }
|
|
|
-
|
|
|
- if inAccelerationShort > inAccelerationMaxShort {
|
|
|
- inAccelerationShort = inAccelerationMaxShort
|
|
|
- }
|
|
|
-
|
|
|
- isLong := 0
|
|
|
- if inStartValue == 0 {
|
|
|
- epTemp := MinusDM(inHigh, inLow, 1)
|
|
|
- if epTemp[1] > 0 {
|
|
|
- isLong = 0
|
|
|
- } else {
|
|
|
- isLong = 1
|
|
|
- }
|
|
|
- } else if inStartValue > 0 {
|
|
|
- isLong = 1
|
|
|
- }
|
|
|
- outIdx := startIdx
|
|
|
- todayIdx := startIdx
|
|
|
- newHigh := inHigh[todayIdx-1]
|
|
|
- newLow := inLow[todayIdx-1]
|
|
|
- ep := 0.0
|
|
|
- sar := 0.0
|
|
|
- if inStartValue == 0 {
|
|
|
- if isLong == 1 {
|
|
|
- ep = inHigh[todayIdx]
|
|
|
- sar = newLow
|
|
|
- } else {
|
|
|
- ep = inLow[todayIdx]
|
|
|
- sar = newHigh
|
|
|
- }
|
|
|
- } else if inStartValue > 0 {
|
|
|
- ep = inHigh[todayIdx]
|
|
|
- sar = inStartValue
|
|
|
- } else {
|
|
|
- ep = inLow[todayIdx]
|
|
|
- sar = math.Abs(inStartValue)
|
|
|
- }
|
|
|
- newLow = inLow[todayIdx]
|
|
|
- newHigh = inHigh[todayIdx]
|
|
|
- prevLow := 0.0
|
|
|
- prevHigh := 0.0
|
|
|
- for todayIdx < len(inHigh) {
|
|
|
- prevLow = newLow
|
|
|
- prevHigh = newHigh
|
|
|
- newLow = inLow[todayIdx]
|
|
|
- newHigh = inHigh[todayIdx]
|
|
|
- todayIdx++
|
|
|
- if isLong == 1 {
|
|
|
- if newLow <= sar {
|
|
|
- isLong = 0
|
|
|
- sar = ep
|
|
|
- if sar < prevHigh {
|
|
|
- sar = prevHigh
|
|
|
- }
|
|
|
- if sar < newHigh {
|
|
|
- sar = newHigh
|
|
|
- }
|
|
|
- if inOffsetOnReverse != 0.0 {
|
|
|
- sar += sar * inOffsetOnReverse
|
|
|
- }
|
|
|
- outReal[outIdx] = -sar
|
|
|
- outIdx++
|
|
|
- afShort = inAccelerationInitShort
|
|
|
- ep = newLow
|
|
|
- sar = sar + afShort*(ep-sar)
|
|
|
- if sar < prevHigh {
|
|
|
- sar = prevHigh
|
|
|
- }
|
|
|
- if sar < newHigh {
|
|
|
- sar = newHigh
|
|
|
- }
|
|
|
- } else {
|
|
|
- outReal[outIdx] = sar
|
|
|
- outIdx++
|
|
|
- if newHigh > ep {
|
|
|
- ep = newHigh
|
|
|
- afLong += inAccelerationLong
|
|
|
- if afLong > inAccelerationMaxLong {
|
|
|
- afLong = inAccelerationMaxLong
|
|
|
- }
|
|
|
- }
|
|
|
- sar = sar + afLong*(ep-sar)
|
|
|
- if sar > prevLow {
|
|
|
- sar = prevLow
|
|
|
- }
|
|
|
- if sar > newLow {
|
|
|
- sar = newLow
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- if newHigh >= sar {
|
|
|
- isLong = 1
|
|
|
- sar = ep
|
|
|
- if sar > prevLow {
|
|
|
- sar = prevLow
|
|
|
- }
|
|
|
- if sar > newLow {
|
|
|
- sar = newLow
|
|
|
- }
|
|
|
- if inOffsetOnReverse != 0.0 {
|
|
|
- sar -= sar * inOffsetOnReverse
|
|
|
- }
|
|
|
- outReal[outIdx] = sar
|
|
|
- outIdx++
|
|
|
- afLong = inAccelerationInitLong
|
|
|
- ep = newHigh
|
|
|
- sar = sar + afLong*(ep-sar)
|
|
|
- if sar > prevLow {
|
|
|
- sar = prevLow
|
|
|
- }
|
|
|
- if sar > newLow {
|
|
|
- sar = newLow
|
|
|
- }
|
|
|
- } else {
|
|
|
- outReal[outIdx] = -sar
|
|
|
- outIdx++
|
|
|
- if newLow < ep {
|
|
|
- ep = newLow
|
|
|
- afShort += inAccelerationShort
|
|
|
- if afShort > inAccelerationMaxShort {
|
|
|
- afShort = inAccelerationMaxShort
|
|
|
- }
|
|
|
- }
|
|
|
- sar = sar + afShort*(ep-sar)
|
|
|
- if sar < prevHigh {
|
|
|
- sar = prevHigh
|
|
|
- }
|
|
|
- if sar < newHigh {
|
|
|
- sar = newHigh
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Sma - Simple Moving Average
|
|
|
-func Sma(inReal []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
-
|
|
|
- lookbackTotal := inTimePeriod - 1
|
|
|
- startIdx := lookbackTotal
|
|
|
- periodTotal := 0.0
|
|
|
- trailingIdx := startIdx - lookbackTotal
|
|
|
- i := trailingIdx
|
|
|
- if inTimePeriod > 1 {
|
|
|
- for i < startIdx {
|
|
|
- periodTotal += inReal[i]
|
|
|
- i++
|
|
|
- }
|
|
|
- }
|
|
|
- outIdx := startIdx
|
|
|
- for ok := true; ok; {
|
|
|
- periodTotal += inReal[i]
|
|
|
- tempReal := periodTotal
|
|
|
- periodTotal -= inReal[trailingIdx]
|
|
|
- outReal[outIdx] = tempReal / float64(inTimePeriod)
|
|
|
- trailingIdx++
|
|
|
- i++
|
|
|
- outIdx++
|
|
|
- ok = i < len(outReal)
|
|
|
- }
|
|
|
-
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// T3 - Triple Exponential Moving Average (T3) (lookback=6*inTimePeriod)
|
|
|
-func T3(inReal []float64, inTimePeriod int, inVFactor float64) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
-
|
|
|
- lookbackTotal := 6 * (inTimePeriod - 1)
|
|
|
- startIdx := lookbackTotal
|
|
|
- today := startIdx - lookbackTotal
|
|
|
- k := 2.0 / (float64(inTimePeriod) + 1.0)
|
|
|
- oneMinusK := 1.0 - k
|
|
|
- tempReal := inReal[today]
|
|
|
- today++
|
|
|
- for i := inTimePeriod - 1; i > 0; i-- {
|
|
|
- tempReal += inReal[today]
|
|
|
- today++
|
|
|
- }
|
|
|
- e1 := tempReal / float64(inTimePeriod)
|
|
|
- tempReal = e1
|
|
|
- for i := inTimePeriod - 1; i > 0; i-- {
|
|
|
- e1 = (k * inReal[today]) + (oneMinusK * e1)
|
|
|
- tempReal += e1
|
|
|
- today++
|
|
|
- }
|
|
|
- e2 := tempReal / float64(inTimePeriod)
|
|
|
- tempReal = e2
|
|
|
- for i := inTimePeriod - 1; i > 0; i-- {
|
|
|
- e1 = (k * inReal[today]) + (oneMinusK * e1)
|
|
|
- e2 = (k * e1) + (oneMinusK * e2)
|
|
|
- tempReal += e2
|
|
|
- today++
|
|
|
- }
|
|
|
- e3 := tempReal / float64(inTimePeriod)
|
|
|
- tempReal = e3
|
|
|
- for i := inTimePeriod - 1; i > 0; i-- {
|
|
|
- e1 = (k * inReal[today]) + (oneMinusK * e1)
|
|
|
- e2 = (k * e1) + (oneMinusK * e2)
|
|
|
- e3 = (k * e2) + (oneMinusK * e3)
|
|
|
- tempReal += e3
|
|
|
- today++
|
|
|
- }
|
|
|
- e4 := tempReal / float64(inTimePeriod)
|
|
|
- tempReal = e4
|
|
|
- for i := inTimePeriod - 1; i > 0; i-- {
|
|
|
- e1 = (k * inReal[today]) + (oneMinusK * e1)
|
|
|
- e2 = (k * e1) + (oneMinusK * e2)
|
|
|
- e3 = (k * e2) + (oneMinusK * e3)
|
|
|
- e4 = (k * e3) + (oneMinusK * e4)
|
|
|
- tempReal += e4
|
|
|
- today++
|
|
|
- }
|
|
|
- e5 := tempReal / float64(inTimePeriod)
|
|
|
- tempReal = e5
|
|
|
- for i := inTimePeriod - 1; i > 0; i-- {
|
|
|
- e1 = (k * inReal[today]) + (oneMinusK * e1)
|
|
|
- e2 = (k * e1) + (oneMinusK * e2)
|
|
|
- e3 = (k * e2) + (oneMinusK * e3)
|
|
|
- e4 = (k * e3) + (oneMinusK * e4)
|
|
|
- e5 = (k * e4) + (oneMinusK * e5)
|
|
|
- tempReal += e5
|
|
|
- today++
|
|
|
- }
|
|
|
- e6 := tempReal / float64(inTimePeriod)
|
|
|
- for today <= startIdx {
|
|
|
- e1 = (k * inReal[today]) + (oneMinusK * e1)
|
|
|
- e2 = (k * e1) + (oneMinusK * e2)
|
|
|
- e3 = (k * e2) + (oneMinusK * e3)
|
|
|
- e4 = (k * e3) + (oneMinusK * e4)
|
|
|
- e5 = (k * e4) + (oneMinusK * e5)
|
|
|
- e6 = (k * e5) + (oneMinusK * e6)
|
|
|
- today++
|
|
|
- }
|
|
|
- tempReal = inVFactor * inVFactor
|
|
|
- c1 := -(tempReal * inVFactor)
|
|
|
- c2 := 3.0 * (tempReal - c1)
|
|
|
- c3 := -6.0*tempReal - 3.0*(inVFactor-c1)
|
|
|
- c4 := 1.0 + 3.0*inVFactor - c1 + 3.0*tempReal
|
|
|
- outIdx := lookbackTotal
|
|
|
- outReal[outIdx] = c1*e6 + c2*e5 + c3*e4 + c4*e3
|
|
|
- outIdx++
|
|
|
- for today < len(inReal) {
|
|
|
- e1 = (k * inReal[today]) + (oneMinusK * e1)
|
|
|
- e2 = (k * e1) + (oneMinusK * e2)
|
|
|
- e3 = (k * e2) + (oneMinusK * e3)
|
|
|
- e4 = (k * e3) + (oneMinusK * e4)
|
|
|
- e5 = (k * e4) + (oneMinusK * e5)
|
|
|
- e6 = (k * e5) + (oneMinusK * e6)
|
|
|
- outReal[outIdx] = c1*e6 + c2*e5 + c3*e4 + c4*e3
|
|
|
- outIdx++
|
|
|
- today++
|
|
|
- }
|
|
|
-
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Tema - Triple Exponential Moving Average
|
|
|
-func Tema(inReal []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
- firstEMA := Ema(inReal, inTimePeriod)
|
|
|
- secondEMA := Ema(firstEMA[inTimePeriod-1:], inTimePeriod)
|
|
|
- thirdEMA := Ema(secondEMA[inTimePeriod-1:], inTimePeriod)
|
|
|
-
|
|
|
- outIdx := (inTimePeriod * 3) - 3
|
|
|
- secondEMAIdx := (inTimePeriod * 2) - 2
|
|
|
- thirdEMAIdx := inTimePeriod - 1
|
|
|
-
|
|
|
- for outIdx < len(inReal) {
|
|
|
- outReal[outIdx] = thirdEMA[thirdEMAIdx] + ((3.0 * firstEMA[outIdx]) - (3.0 * secondEMA[secondEMAIdx]))
|
|
|
- outIdx++
|
|
|
- secondEMAIdx++
|
|
|
- thirdEMAIdx++
|
|
|
- }
|
|
|
-
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Trima - Triangular Moving Average
|
|
|
-func Trima(inReal []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
-
|
|
|
- lookbackTotal := inTimePeriod - 1
|
|
|
- startIdx := lookbackTotal
|
|
|
- outIdx := inTimePeriod - 1
|
|
|
- var factor float64
|
|
|
-
|
|
|
- if inTimePeriod%2 == 1 {
|
|
|
- i := inTimePeriod >> 1
|
|
|
- factor = (float64(i) + 1.0) * (float64(i) + 1.0)
|
|
|
- factor = 1.0 / factor
|
|
|
- trailingIdx := startIdx - lookbackTotal
|
|
|
- middleIdx := trailingIdx + i
|
|
|
- todayIdx := middleIdx + i
|
|
|
- numerator := 0.0
|
|
|
- numeratorSub := 0.0
|
|
|
- for i := middleIdx; i >= trailingIdx; i-- {
|
|
|
- tempReal := inReal[i]
|
|
|
- numeratorSub += tempReal
|
|
|
- numerator += numeratorSub
|
|
|
- }
|
|
|
- numeratorAdd := 0.0
|
|
|
- middleIdx++
|
|
|
- for i := middleIdx; i <= todayIdx; i++ {
|
|
|
- tempReal := inReal[i]
|
|
|
- numeratorAdd += tempReal
|
|
|
- numerator += numeratorAdd
|
|
|
- }
|
|
|
- outIdx = inTimePeriod - 1
|
|
|
- tempReal := inReal[trailingIdx]
|
|
|
- trailingIdx++
|
|
|
- outReal[outIdx] = numerator * factor
|
|
|
- outIdx++
|
|
|
- todayIdx++
|
|
|
- for todayIdx < len(inReal) {
|
|
|
- numerator -= numeratorSub
|
|
|
- numeratorSub -= tempReal
|
|
|
- tempReal = inReal[middleIdx]
|
|
|
- middleIdx++
|
|
|
- numeratorSub += tempReal
|
|
|
- numerator += numeratorAdd
|
|
|
- numeratorAdd -= tempReal
|
|
|
- tempReal = inReal[todayIdx]
|
|
|
- todayIdx++
|
|
|
- numeratorAdd += tempReal
|
|
|
- numerator += tempReal
|
|
|
- tempReal = inReal[trailingIdx]
|
|
|
- trailingIdx++
|
|
|
- outReal[outIdx] = numerator * factor
|
|
|
- outIdx++
|
|
|
- }
|
|
|
-
|
|
|
- } else {
|
|
|
-
|
|
|
- i := (inTimePeriod >> 1)
|
|
|
- factor = float64(i) * (float64(i) + 1)
|
|
|
- factor = 1.0 / factor
|
|
|
- trailingIdx := startIdx - lookbackTotal
|
|
|
- middleIdx := trailingIdx + i - 1
|
|
|
- todayIdx := middleIdx + i
|
|
|
- numerator := 0.0
|
|
|
- numeratorSub := 0.0
|
|
|
- for i := middleIdx; i >= trailingIdx; i-- {
|
|
|
- tempReal := inReal[i]
|
|
|
- numeratorSub += tempReal
|
|
|
- numerator += numeratorSub
|
|
|
- }
|
|
|
- numeratorAdd := 0.0
|
|
|
- middleIdx++
|
|
|
- for i := middleIdx; i <= todayIdx; i++ {
|
|
|
- tempReal := inReal[i]
|
|
|
- numeratorAdd += tempReal
|
|
|
- numerator += numeratorAdd
|
|
|
- }
|
|
|
- outIdx = inTimePeriod - 1
|
|
|
- tempReal := inReal[trailingIdx]
|
|
|
- trailingIdx++
|
|
|
- outReal[outIdx] = numerator * factor
|
|
|
- outIdx++
|
|
|
- todayIdx++
|
|
|
-
|
|
|
- for todayIdx < len(inReal) {
|
|
|
- numerator -= numeratorSub
|
|
|
- numeratorSub -= tempReal
|
|
|
- tempReal = inReal[middleIdx]
|
|
|
- middleIdx++
|
|
|
- numeratorSub += tempReal
|
|
|
- numeratorAdd -= tempReal
|
|
|
- numerator += numeratorAdd
|
|
|
- tempReal = inReal[todayIdx]
|
|
|
- todayIdx++
|
|
|
- numeratorAdd += tempReal
|
|
|
- numerator += tempReal
|
|
|
- tempReal = inReal[trailingIdx]
|
|
|
- trailingIdx++
|
|
|
- outReal[outIdx] = numerator * factor
|
|
|
- outIdx++
|
|
|
- }
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Wma - Weighted Moving Average
|
|
|
-func Wma(inReal []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
-
|
|
|
- lookbackTotal := inTimePeriod - 1
|
|
|
- startIdx := lookbackTotal
|
|
|
-
|
|
|
- if inTimePeriod == 1 {
|
|
|
- copy(outReal, inReal)
|
|
|
- return outReal
|
|
|
- }
|
|
|
- divider := (inTimePeriod * (inTimePeriod + 1)) >> 1
|
|
|
- outIdx := inTimePeriod - 1
|
|
|
- trailingIdx := startIdx - lookbackTotal
|
|
|
- periodSum, periodSub := 0.0, 0.0
|
|
|
- inIdx := trailingIdx
|
|
|
- i := 1
|
|
|
- for inIdx < startIdx {
|
|
|
- tempReal := inReal[inIdx]
|
|
|
- periodSub += tempReal
|
|
|
- periodSum += tempReal * float64(i)
|
|
|
- inIdx++
|
|
|
- i++
|
|
|
- }
|
|
|
- trailingValue := 0.0
|
|
|
- for inIdx < len(inReal) {
|
|
|
- tempReal := inReal[inIdx]
|
|
|
- periodSub += tempReal
|
|
|
- periodSub -= trailingValue
|
|
|
- periodSum += tempReal * float64(inTimePeriod)
|
|
|
- trailingValue = inReal[trailingIdx]
|
|
|
- outReal[outIdx] = periodSum / float64(divider)
|
|
|
- periodSum -= periodSub
|
|
|
- inIdx++
|
|
|
- trailingIdx++
|
|
|
- outIdx++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-/* Momentum Indicators */
|
|
|
-
|
|
|
-// Adx - Average Directional Movement Index
|
|
|
-func Adx(inHigh []float64, inLow []float64, inClose []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inClose))
|
|
|
-
|
|
|
- inTimePeriodF := float64(inTimePeriod)
|
|
|
- lookbackTotal := (2 * inTimePeriod) - 1
|
|
|
- startIdx := lookbackTotal
|
|
|
- outIdx := inTimePeriod
|
|
|
- prevMinusDM := 0.0
|
|
|
- prevPlusDM := 0.0
|
|
|
- prevTR := 0.0
|
|
|
- today := startIdx - lookbackTotal
|
|
|
- prevHigh := inHigh[today]
|
|
|
- prevLow := inLow[today]
|
|
|
- prevClose := inClose[today]
|
|
|
- for i := inTimePeriod - 1; i > 0; i-- {
|
|
|
- today++
|
|
|
- tempReal := inHigh[today]
|
|
|
- diffP := tempReal - prevHigh
|
|
|
- prevHigh = tempReal
|
|
|
- tempReal = inLow[today]
|
|
|
- diffM := prevLow - tempReal
|
|
|
- prevLow = tempReal
|
|
|
- if (diffM > 0) && (diffP < diffM) {
|
|
|
- prevMinusDM += diffM
|
|
|
- } else if (diffP > 0) && (diffP > diffM) {
|
|
|
- prevPlusDM += diffP
|
|
|
- }
|
|
|
- tempReal = prevHigh - prevLow
|
|
|
- tempReal2 := math.Abs(prevHigh - prevClose)
|
|
|
- if tempReal2 > tempReal {
|
|
|
- tempReal = tempReal2
|
|
|
- }
|
|
|
- tempReal2 = math.Abs(prevLow - prevClose)
|
|
|
- if tempReal2 > tempReal {
|
|
|
- tempReal = tempReal2
|
|
|
- }
|
|
|
-
|
|
|
- prevTR += tempReal
|
|
|
- prevClose = inClose[today]
|
|
|
- }
|
|
|
- sumDX := 0.0
|
|
|
- for i := inTimePeriod; i > 0; i-- {
|
|
|
- today++
|
|
|
- tempReal := inHigh[today]
|
|
|
- diffP := tempReal - prevHigh
|
|
|
- prevHigh = tempReal
|
|
|
- tempReal = inLow[today]
|
|
|
- diffM := prevLow - tempReal
|
|
|
- prevLow = tempReal
|
|
|
- prevMinusDM -= prevMinusDM / inTimePeriodF
|
|
|
- prevPlusDM -= prevPlusDM / inTimePeriodF
|
|
|
- if (diffM > 0) && (diffP < diffM) {
|
|
|
- prevMinusDM += diffM
|
|
|
- } else if (diffP > 0) && (diffP > diffM) {
|
|
|
- prevPlusDM += diffP
|
|
|
- }
|
|
|
- tempReal = prevHigh - prevLow
|
|
|
- tempReal2 := math.Abs(prevHigh - prevClose)
|
|
|
- if tempReal2 > tempReal {
|
|
|
- tempReal = tempReal2
|
|
|
- }
|
|
|
- tempReal2 = math.Abs(prevLow - prevClose)
|
|
|
- if tempReal2 > tempReal {
|
|
|
- tempReal = tempReal2
|
|
|
- }
|
|
|
-
|
|
|
- prevTR = prevTR - (prevTR / inTimePeriodF) + tempReal
|
|
|
- prevClose = inClose[today]
|
|
|
- if !(((-(0.00000000000001)) < prevTR) && (prevTR < (0.00000000000001))) {
|
|
|
- minusDI := (100.0 * (prevMinusDM / prevTR))
|
|
|
- plusDI := (100.0 * (prevPlusDM / prevTR))
|
|
|
- tempReal = minusDI + plusDI
|
|
|
- if !(((-(0.00000000000001)) < tempReal) && (tempReal < (0.00000000000001))) {
|
|
|
- sumDX += (100.0 * (math.Abs(minusDI-plusDI) / tempReal))
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- prevADX := (sumDX / inTimePeriodF)
|
|
|
-
|
|
|
- outReal[startIdx] = prevADX
|
|
|
- outIdx = startIdx + 1
|
|
|
- today++
|
|
|
- for today < len(inClose) {
|
|
|
- tempReal := inHigh[today]
|
|
|
- diffP := tempReal - prevHigh
|
|
|
- prevHigh = tempReal
|
|
|
- tempReal = inLow[today]
|
|
|
- diffM := prevLow - tempReal
|
|
|
- prevLow = tempReal
|
|
|
- prevMinusDM -= prevMinusDM / inTimePeriodF
|
|
|
- prevPlusDM -= prevPlusDM / inTimePeriodF
|
|
|
- if (diffM > 0) && (diffP < diffM) {
|
|
|
- prevMinusDM += diffM
|
|
|
- } else if (diffP > 0) && (diffP > diffM) {
|
|
|
- prevPlusDM += diffP
|
|
|
- }
|
|
|
- tempReal = prevHigh - prevLow
|
|
|
- tempReal2 := math.Abs(prevHigh - prevClose)
|
|
|
- if tempReal2 > tempReal {
|
|
|
- tempReal = tempReal2
|
|
|
- }
|
|
|
- tempReal2 = math.Abs(prevLow - prevClose)
|
|
|
- if tempReal2 > tempReal {
|
|
|
- tempReal = tempReal2
|
|
|
- }
|
|
|
-
|
|
|
- prevTR = prevTR - (prevTR / inTimePeriodF) + tempReal
|
|
|
- prevClose = inClose[today]
|
|
|
- if !(((-(0.00000000000001)) < prevTR) && (prevTR < (0.00000000000001))) {
|
|
|
- minusDI := (100.0 * (prevMinusDM / prevTR))
|
|
|
- plusDI := (100.0 * (prevPlusDM / prevTR))
|
|
|
- tempReal = minusDI + plusDI
|
|
|
- if !(((-(0.00000000000001)) < tempReal) && (tempReal < (0.00000000000001))) {
|
|
|
- tempReal = (100.0 * (math.Abs(minusDI-plusDI) / tempReal))
|
|
|
- prevADX = (((prevADX * (inTimePeriodF - 1)) + tempReal) / inTimePeriodF)
|
|
|
- }
|
|
|
- }
|
|
|
- outReal[outIdx] = prevADX
|
|
|
- outIdx++
|
|
|
- today++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// AdxR - Average Directional Movement Index Rating
|
|
|
-func AdxR(inHigh []float64, inLow []float64, inClose []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inClose))
|
|
|
- startIdx := (2 * inTimePeriod) - 1
|
|
|
- tmpadx := Adx(inHigh, inLow, inClose, inTimePeriod)
|
|
|
- i := startIdx
|
|
|
- j := startIdx + inTimePeriod - 1
|
|
|
- for outIdx := startIdx + inTimePeriod - 1; outIdx < len(inClose); outIdx, i, j = outIdx+1, i+1, j+1 {
|
|
|
- outReal[outIdx] = ((tmpadx[i] + tmpadx[j]) / 2.0)
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Apo - Absolute Price Oscillator
|
|
|
-func Apo(inReal []float64, inFastPeriod int, inSlowPeriod int, inMAType MaType) []float64 {
|
|
|
-
|
|
|
- if inSlowPeriod < inFastPeriod {
|
|
|
- inSlowPeriod, inFastPeriod = inFastPeriod, inSlowPeriod
|
|
|
- }
|
|
|
- tempBuffer := Ma(inReal, inFastPeriod, inMAType)
|
|
|
- outReal := Ma(inReal, inSlowPeriod, inMAType)
|
|
|
- for i := inSlowPeriod - 1; i < len(inReal); i++ {
|
|
|
- outReal[i] = tempBuffer[i] - outReal[i]
|
|
|
- }
|
|
|
-
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Aroon - Aroon
|
|
|
-// aroondown, aroonup = AROON(high, low, timeperiod=14)
|
|
|
-func Aroon(inHigh []float64, inLow []float64, inTimePeriod int) ([]float64, []float64) {
|
|
|
-
|
|
|
- outAroonUp := make([]float64, len(inHigh))
|
|
|
- outAroonDown := make([]float64, len(inHigh))
|
|
|
-
|
|
|
- startIdx := inTimePeriod
|
|
|
- outIdx := startIdx
|
|
|
- today := startIdx
|
|
|
- trailingIdx := startIdx - inTimePeriod
|
|
|
- lowestIdx := -1
|
|
|
- highestIdx := -1
|
|
|
- lowest := 0.0
|
|
|
- highest := 0.0
|
|
|
- factor := 100.0 / float64(inTimePeriod)
|
|
|
- for today < len(inHigh) {
|
|
|
- tmp := inLow[today]
|
|
|
- if lowestIdx < trailingIdx {
|
|
|
- lowestIdx = trailingIdx
|
|
|
- lowest = inLow[lowestIdx]
|
|
|
- i := lowestIdx
|
|
|
- i++
|
|
|
- for i <= today {
|
|
|
- tmp = inLow[i]
|
|
|
- if tmp <= lowest {
|
|
|
- lowestIdx = i
|
|
|
- lowest = tmp
|
|
|
- }
|
|
|
- i++
|
|
|
- }
|
|
|
- } else if tmp <= lowest {
|
|
|
- lowestIdx = today
|
|
|
- lowest = tmp
|
|
|
- }
|
|
|
- tmp = inHigh[today]
|
|
|
- if highestIdx < trailingIdx {
|
|
|
- highestIdx = trailingIdx
|
|
|
- highest = inHigh[highestIdx]
|
|
|
- i := highestIdx
|
|
|
- i++
|
|
|
- for i <= today {
|
|
|
- tmp = inHigh[i]
|
|
|
- if tmp >= highest {
|
|
|
- highestIdx = i
|
|
|
- highest = tmp
|
|
|
- }
|
|
|
- i++
|
|
|
- }
|
|
|
- } else if tmp >= highest {
|
|
|
- highestIdx = today
|
|
|
- highest = tmp
|
|
|
- }
|
|
|
- outAroonUp[outIdx] = factor * float64(inTimePeriod-(today-highestIdx))
|
|
|
- outAroonDown[outIdx] = factor * float64(inTimePeriod-(today-lowestIdx))
|
|
|
- outIdx++
|
|
|
- trailingIdx++
|
|
|
- today++
|
|
|
- }
|
|
|
- return outAroonDown, outAroonUp
|
|
|
-}
|
|
|
-
|
|
|
-// AroonOsc - Aroon Oscillator
|
|
|
-func AroonOsc(inHigh []float64, inLow []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inHigh))
|
|
|
-
|
|
|
- startIdx := inTimePeriod
|
|
|
- outIdx := startIdx
|
|
|
- today := startIdx
|
|
|
- trailingIdx := startIdx - inTimePeriod
|
|
|
- lowestIdx := -1
|
|
|
- highestIdx := -1
|
|
|
- lowest := 0.0
|
|
|
- highest := 0.0
|
|
|
- factor := 100.0 / float64(inTimePeriod)
|
|
|
- for today < len(inHigh) {
|
|
|
- tmp := inLow[today]
|
|
|
- if lowestIdx < trailingIdx {
|
|
|
- lowestIdx = trailingIdx
|
|
|
- lowest = inLow[lowestIdx]
|
|
|
- i := lowestIdx
|
|
|
- i++
|
|
|
- for i <= today {
|
|
|
- tmp = inLow[i]
|
|
|
- if tmp <= lowest {
|
|
|
- lowestIdx = i
|
|
|
- lowest = tmp
|
|
|
- }
|
|
|
- i++
|
|
|
- }
|
|
|
- } else if tmp <= lowest {
|
|
|
- lowestIdx = today
|
|
|
- lowest = tmp
|
|
|
- }
|
|
|
- tmp = inHigh[today]
|
|
|
- if highestIdx < trailingIdx {
|
|
|
- highestIdx = trailingIdx
|
|
|
- highest = inHigh[highestIdx]
|
|
|
- i := highestIdx
|
|
|
- i++
|
|
|
- for i <= today {
|
|
|
- tmp = inHigh[i]
|
|
|
- if tmp >= highest {
|
|
|
- highestIdx = i
|
|
|
- highest = tmp
|
|
|
- }
|
|
|
- i++
|
|
|
- }
|
|
|
- } else if tmp >= highest {
|
|
|
- highestIdx = today
|
|
|
- highest = tmp
|
|
|
- }
|
|
|
- aroon := factor * float64(highestIdx-lowestIdx)
|
|
|
- outReal[outIdx] = aroon
|
|
|
- outIdx++
|
|
|
- trailingIdx++
|
|
|
- today++
|
|
|
- }
|
|
|
-
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Bop - Balance Of Power
|
|
|
-func Bop(inOpen []float64, inHigh []float64, inLow []float64, inClose []float64) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inClose))
|
|
|
-
|
|
|
- for i := 0; i < len(inClose); i++ {
|
|
|
- tempReal := inHigh[i] - inLow[i]
|
|
|
- if tempReal < (0.00000000000001) {
|
|
|
- outReal[i] = 0.0
|
|
|
- } else {
|
|
|
- outReal[i] = (inClose[i] - inOpen[i]) / tempReal
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Cmo - Chande Momentum Oscillator
|
|
|
-func Cmo(inReal []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
-
|
|
|
- lookbackTotal := inTimePeriod
|
|
|
- startIdx := lookbackTotal
|
|
|
- outIdx := startIdx
|
|
|
- if inTimePeriod == 1 {
|
|
|
- copy(outReal, inReal)
|
|
|
- return outReal
|
|
|
- }
|
|
|
- today := startIdx - lookbackTotal
|
|
|
- prevValue := inReal[today]
|
|
|
- prevGain := 0.0
|
|
|
- prevLoss := 0.0
|
|
|
- today++
|
|
|
- for i := inTimePeriod; i > 0; i-- {
|
|
|
- tempValue1 := inReal[today]
|
|
|
- tempValue2 := tempValue1 - prevValue
|
|
|
- prevValue = tempValue1
|
|
|
- if tempValue2 < 0 {
|
|
|
- prevLoss -= tempValue2
|
|
|
- } else {
|
|
|
- prevGain += tempValue2
|
|
|
- }
|
|
|
- today++
|
|
|
- }
|
|
|
- prevLoss /= float64(inTimePeriod)
|
|
|
- prevGain /= float64(inTimePeriod)
|
|
|
- if today > startIdx {
|
|
|
- tempValue1 := prevGain + prevLoss
|
|
|
- if !(((-(0.00000000000001)) < tempValue1) && (tempValue1 < (0.00000000000001))) {
|
|
|
- outReal[outIdx] = 100.0 * ((prevGain - prevLoss) / tempValue1)
|
|
|
- } else {
|
|
|
- outReal[outIdx] = 0.0
|
|
|
- }
|
|
|
- outIdx++
|
|
|
- } else {
|
|
|
- for today < startIdx {
|
|
|
- tempValue1 := inReal[today]
|
|
|
- tempValue2 := tempValue1 - prevValue
|
|
|
- prevValue = tempValue1
|
|
|
- prevLoss *= float64(inTimePeriod - 1)
|
|
|
- prevGain *= float64(inTimePeriod - 1)
|
|
|
- if tempValue2 < 0 {
|
|
|
- prevLoss -= tempValue2
|
|
|
- } else {
|
|
|
- prevGain += tempValue2
|
|
|
- }
|
|
|
- prevLoss /= float64(inTimePeriod)
|
|
|
- prevGain /= float64(inTimePeriod)
|
|
|
- today++
|
|
|
- }
|
|
|
- }
|
|
|
- for today < len(inReal) {
|
|
|
- tempValue1 := inReal[today]
|
|
|
- today++
|
|
|
- tempValue2 := tempValue1 - prevValue
|
|
|
- prevValue = tempValue1
|
|
|
- prevLoss *= float64(inTimePeriod - 1)
|
|
|
- prevGain *= float64(inTimePeriod - 1)
|
|
|
- if tempValue2 < 0 {
|
|
|
- prevLoss -= tempValue2
|
|
|
- } else {
|
|
|
- prevGain += tempValue2
|
|
|
- }
|
|
|
- prevLoss /= float64(inTimePeriod)
|
|
|
- prevGain /= float64(inTimePeriod)
|
|
|
- tempValue1 = prevGain + prevLoss
|
|
|
- if !(((-(0.00000000000001)) < tempValue1) && (tempValue1 < (0.00000000000001))) {
|
|
|
- outReal[outIdx] = 100.0 * ((prevGain - prevLoss) / tempValue1)
|
|
|
- } else {
|
|
|
- outReal[outIdx] = 0.0
|
|
|
- }
|
|
|
- outIdx++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Cci - Commodity Channel Index
|
|
|
-func Cci(inHigh []float64, inLow []float64, inClose []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inClose))
|
|
|
-
|
|
|
- circBufferIdx := 0
|
|
|
- lookbackTotal := inTimePeriod - 1
|
|
|
- startIdx := lookbackTotal
|
|
|
- circBuffer := make([]float64, inTimePeriod)
|
|
|
- maxIdxCircBuffer := (inTimePeriod - 1)
|
|
|
- i := startIdx - lookbackTotal
|
|
|
- if inTimePeriod > 1 {
|
|
|
- for i < startIdx {
|
|
|
- circBuffer[circBufferIdx] = (inHigh[i] + inLow[i] + inClose[i]) / 3
|
|
|
- i++
|
|
|
- circBufferIdx++
|
|
|
- if circBufferIdx > maxIdxCircBuffer {
|
|
|
- circBufferIdx = 0
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- }
|
|
|
- outIdx := inTimePeriod - 1
|
|
|
- for i < len(inClose) {
|
|
|
- lastValue := (inHigh[i] + inLow[i] + inClose[i]) / 3
|
|
|
- circBuffer[circBufferIdx] = lastValue
|
|
|
- theAverage := 0.0
|
|
|
- for j := 0; j < inTimePeriod; j++ {
|
|
|
- theAverage += circBuffer[j]
|
|
|
- }
|
|
|
-
|
|
|
- theAverage /= float64(inTimePeriod)
|
|
|
- tempReal2 := 0.0
|
|
|
- for j := 0; j < inTimePeriod; j++ {
|
|
|
- tempReal2 += math.Abs(circBuffer[j] - theAverage)
|
|
|
- }
|
|
|
- tempReal := lastValue - theAverage
|
|
|
- if (tempReal != 0.0) && (tempReal2 != 0.0) {
|
|
|
- outReal[outIdx] = tempReal / (0.015 * (tempReal2 / float64(inTimePeriod)))
|
|
|
- } else {
|
|
|
- outReal[outIdx] = 0.0
|
|
|
- }
|
|
|
- {
|
|
|
- circBufferIdx++
|
|
|
- if circBufferIdx > maxIdxCircBuffer {
|
|
|
- circBufferIdx = 0
|
|
|
- }
|
|
|
- }
|
|
|
- outIdx++
|
|
|
- i++
|
|
|
- }
|
|
|
-
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Dx - Directional Movement Index
|
|
|
-func Dx(inHigh []float64, inLow []float64, inClose []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inClose))
|
|
|
-
|
|
|
- lookbackTotal := 2
|
|
|
- if inTimePeriod > 1 {
|
|
|
- lookbackTotal = inTimePeriod
|
|
|
- }
|
|
|
- startIdx := lookbackTotal
|
|
|
- outIdx := startIdx
|
|
|
- prevMinusDM := 0.0
|
|
|
- prevPlusDM := 0.0
|
|
|
- prevTR := 0.0
|
|
|
- today := startIdx - lookbackTotal
|
|
|
- prevHigh := inHigh[today]
|
|
|
- prevLow := inLow[today]
|
|
|
- prevClose := inClose[today]
|
|
|
- i := inTimePeriod - 1
|
|
|
- for i > 0 {
|
|
|
- i--
|
|
|
- today++
|
|
|
- tempReal := inHigh[today]
|
|
|
- diffP := tempReal - prevHigh
|
|
|
- prevHigh = tempReal
|
|
|
- tempReal = inLow[today]
|
|
|
- diffM := prevLow - tempReal
|
|
|
- prevLow = tempReal
|
|
|
- if (diffM > 0) && (diffP < diffM) {
|
|
|
- prevMinusDM += diffM
|
|
|
- } else if (diffP > 0) && (diffP > diffM) {
|
|
|
- prevPlusDM += diffP
|
|
|
- }
|
|
|
- tempReal = prevHigh - prevLow
|
|
|
- tempReal2 := math.Abs(prevHigh - prevClose)
|
|
|
- if tempReal2 > tempReal {
|
|
|
- tempReal = tempReal2
|
|
|
- }
|
|
|
- tempReal2 = math.Abs(prevLow - prevClose)
|
|
|
- if tempReal2 > tempReal {
|
|
|
- tempReal = tempReal2
|
|
|
- }
|
|
|
-
|
|
|
- prevTR += tempReal
|
|
|
- prevClose = inClose[today]
|
|
|
- }
|
|
|
-
|
|
|
- if !(((-(0.00000000000001)) < prevTR) && (prevTR < (0.00000000000001))) {
|
|
|
- minusDI := (100.0 * (prevMinusDM / prevTR))
|
|
|
- plusDI := (100.0 * (prevPlusDM / prevTR))
|
|
|
- tempReal := minusDI + plusDI
|
|
|
- if !(((-(0.00000000000001)) < tempReal) && (tempReal < (0.00000000000001))) {
|
|
|
- outReal[outIdx] = (100.0 * (math.Abs(minusDI-plusDI) / tempReal))
|
|
|
- } else {
|
|
|
- outReal[outIdx] = 0.0
|
|
|
- }
|
|
|
- } else {
|
|
|
- outReal[outIdx] = 0.0
|
|
|
- }
|
|
|
-
|
|
|
- outIdx = startIdx
|
|
|
- for today < len(inClose)-1 {
|
|
|
- today++
|
|
|
- tempReal := inHigh[today]
|
|
|
- diffP := tempReal - prevHigh
|
|
|
- prevHigh = tempReal
|
|
|
- tempReal = inLow[today]
|
|
|
- diffM := prevLow - tempReal
|
|
|
- prevLow = tempReal
|
|
|
- prevMinusDM -= prevMinusDM / float64(inTimePeriod)
|
|
|
- prevPlusDM -= prevPlusDM / float64(inTimePeriod)
|
|
|
- if (diffM > 0) && (diffP < diffM) {
|
|
|
- prevMinusDM += diffM
|
|
|
- } else if (diffP > 0) && (diffP > diffM) {
|
|
|
- prevPlusDM += diffP
|
|
|
- }
|
|
|
- tempReal = prevHigh - prevLow
|
|
|
- tempReal2 := math.Abs(prevHigh - prevClose)
|
|
|
- if tempReal2 > tempReal {
|
|
|
- tempReal = tempReal2
|
|
|
- }
|
|
|
- tempReal2 = math.Abs(prevLow - prevClose)
|
|
|
- if tempReal2 > tempReal {
|
|
|
- tempReal = tempReal2
|
|
|
- }
|
|
|
-
|
|
|
- prevTR = prevTR - (prevTR / float64(inTimePeriod)) + tempReal
|
|
|
- prevClose = inClose[today]
|
|
|
- if !(((-(0.00000000000001)) < prevTR) && (prevTR < (0.00000000000001))) {
|
|
|
- minusDI := (100.0 * (prevMinusDM / prevTR))
|
|
|
- plusDI := (100.0 * (prevPlusDM / prevTR))
|
|
|
- tempReal = minusDI + plusDI
|
|
|
- if !(((-(0.00000000000001)) < tempReal) && (tempReal < (0.00000000000001))) {
|
|
|
- outReal[outIdx] = (100.0 * (math.Abs(minusDI-plusDI) / tempReal))
|
|
|
- } else {
|
|
|
- outReal[outIdx] = outReal[outIdx-1]
|
|
|
- }
|
|
|
- } else {
|
|
|
- outReal[outIdx] = outReal[outIdx-1]
|
|
|
- }
|
|
|
- outIdx++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Macd - Moving Average Convergence/Divergence
|
|
|
-// unstable period ~= 100
|
|
|
-func Macd(inReal []float64, inFastPeriod int, inSlowPeriod int, inSignalPeriod int) ([]float64, []float64, []float64) {
|
|
|
-
|
|
|
- if inSlowPeriod < inFastPeriod {
|
|
|
- inSlowPeriod, inFastPeriod = inFastPeriod, inSlowPeriod
|
|
|
- }
|
|
|
-
|
|
|
- k1 := 0.0
|
|
|
- k2 := 0.0
|
|
|
- if inSlowPeriod != 0 {
|
|
|
- k1 = 2.0 / float64(inSlowPeriod+1)
|
|
|
- } else {
|
|
|
- inSlowPeriod = 26
|
|
|
- k1 = 0.075
|
|
|
- }
|
|
|
- if inFastPeriod != 0 {
|
|
|
- k2 = 2.0 / float64(inFastPeriod+1)
|
|
|
- } else {
|
|
|
- inFastPeriod = 12
|
|
|
- k2 = 0.15
|
|
|
- }
|
|
|
-
|
|
|
- lookbackSignal := inSignalPeriod - 1
|
|
|
- lookbackTotal := lookbackSignal
|
|
|
- lookbackTotal += (inSlowPeriod - 1)
|
|
|
-
|
|
|
- fastEMABuffer := ema(inReal, inFastPeriod, k2)
|
|
|
- slowEMABuffer := ema(inReal, inSlowPeriod, k1)
|
|
|
- for i := 0; i < len(fastEMABuffer); i++ {
|
|
|
- fastEMABuffer[i] = fastEMABuffer[i] - slowEMABuffer[i]
|
|
|
- }
|
|
|
-
|
|
|
- outMACD := make([]float64, len(inReal))
|
|
|
- for i := lookbackTotal - 1; i < len(fastEMABuffer); i++ {
|
|
|
- outMACD[i] = fastEMABuffer[i]
|
|
|
- }
|
|
|
- outMACDSignal := ema(outMACD, inSignalPeriod, (2.0 / float64(inSignalPeriod+1)))
|
|
|
-
|
|
|
- outMACDHist := make([]float64, len(inReal))
|
|
|
- for i := lookbackTotal; i < len(outMACDHist); i++ {
|
|
|
- outMACDHist[i] = outMACD[i] - outMACDSignal[i]
|
|
|
- }
|
|
|
-
|
|
|
- return outMACD, outMACDSignal, outMACDHist
|
|
|
-}
|
|
|
-
|
|
|
-// MacdExt - MACD with controllable MA type
|
|
|
-// unstable period ~= 100
|
|
|
-func MacdExt(inReal []float64, inFastPeriod int, inFastMAType MaType, inSlowPeriod int, inSlowMAType MaType, inSignalPeriod int, inSignalMAType MaType) ([]float64, []float64, []float64) {
|
|
|
-
|
|
|
- lookbackLargest := 0
|
|
|
- if inFastPeriod < inSlowPeriod {
|
|
|
- lookbackLargest = inSlowPeriod
|
|
|
- } else {
|
|
|
- lookbackLargest = inFastPeriod
|
|
|
- }
|
|
|
- lookbackTotal := (inSignalPeriod - 1) + (lookbackLargest - 1)
|
|
|
-
|
|
|
- outMACD := make([]float64, len(inReal))
|
|
|
- outMACDSignal := make([]float64, len(inReal))
|
|
|
- outMACDHist := make([]float64, len(inReal))
|
|
|
-
|
|
|
- slowMABuffer := Ma(inReal, inSlowPeriod, inSlowMAType)
|
|
|
- fastMABuffer := Ma(inReal, inFastPeriod, inFastMAType)
|
|
|
- tempBuffer1 := make([]float64, len(inReal))
|
|
|
-
|
|
|
- for i := 0; i < len(slowMABuffer); i++ {
|
|
|
- tempBuffer1[i] = fastMABuffer[i] - slowMABuffer[i]
|
|
|
- }
|
|
|
- tempBuffer2 := Ma(tempBuffer1, inSignalPeriod, inSignalMAType)
|
|
|
-
|
|
|
- for i := lookbackTotal; i < len(outMACDHist); i++ {
|
|
|
- outMACD[i] = tempBuffer1[i]
|
|
|
- outMACDSignal[i] = tempBuffer2[i]
|
|
|
- outMACDHist[i] = outMACD[i] - outMACDSignal[i]
|
|
|
- }
|
|
|
-
|
|
|
- return outMACD, outMACDSignal, outMACDHist
|
|
|
-}
|
|
|
-
|
|
|
-// MacdFix - MACD Fix 12/26
|
|
|
-// unstable period ~= 100
|
|
|
-func MacdFix(inReal []float64, inSignalPeriod int) ([]float64, []float64, []float64) {
|
|
|
- return Macd(inReal, 0, 0, inSignalPeriod)
|
|
|
-}
|
|
|
-
|
|
|
-// MinusDI - Minus Directional Indicator
|
|
|
-func MinusDI(inHigh []float64, inLow []float64, inClose []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inClose))
|
|
|
-
|
|
|
- lookbackTotal := 1
|
|
|
- if inTimePeriod > 1 {
|
|
|
- lookbackTotal = inTimePeriod
|
|
|
- }
|
|
|
- startIdx := lookbackTotal
|
|
|
- outIdx := startIdx
|
|
|
-
|
|
|
- prevHigh := 0.0
|
|
|
- prevLow := 0.0
|
|
|
- prevClose := 0.0
|
|
|
- if inTimePeriod <= 1 {
|
|
|
- today := startIdx - 1
|
|
|
- prevHigh = inHigh[today]
|
|
|
- prevLow = inLow[today]
|
|
|
- prevClose = inClose[today]
|
|
|
- for today < len(inClose)-1 {
|
|
|
- today++
|
|
|
- tempReal := inHigh[today]
|
|
|
- diffP := tempReal - prevHigh
|
|
|
- prevHigh = tempReal
|
|
|
- tempReal = inLow[today]
|
|
|
- diffM := prevLow - tempReal
|
|
|
- prevLow = tempReal
|
|
|
- if (diffM > 0) && (diffP < diffM) {
|
|
|
-
|
|
|
- tempReal = prevHigh - prevLow
|
|
|
- tempReal2 := math.Abs(prevHigh - prevClose)
|
|
|
- if tempReal2 > tempReal {
|
|
|
- tempReal = tempReal2
|
|
|
- }
|
|
|
- tempReal2 = math.Abs(prevLow - prevClose)
|
|
|
- if tempReal2 > tempReal {
|
|
|
- tempReal = tempReal2
|
|
|
- }
|
|
|
-
|
|
|
- if ((-(0.00000000000001)) < tempReal) && (tempReal < (0.00000000000001)) {
|
|
|
- outReal[outIdx] = 0.0
|
|
|
- } else {
|
|
|
- outReal[outIdx] = diffM / tempReal
|
|
|
- }
|
|
|
- outIdx++
|
|
|
- } else {
|
|
|
- outReal[outIdx] = 0.0
|
|
|
- outIdx++
|
|
|
- }
|
|
|
- prevClose = inClose[today]
|
|
|
- }
|
|
|
- return outReal
|
|
|
- }
|
|
|
- prevMinusDM := 0.0
|
|
|
- prevTR := 0.0
|
|
|
- today := startIdx - lookbackTotal
|
|
|
- prevHigh = inHigh[today]
|
|
|
- prevLow = inLow[today]
|
|
|
- prevClose = inClose[today]
|
|
|
- i := inTimePeriod - 1
|
|
|
-
|
|
|
- for i > 0 {
|
|
|
- i--
|
|
|
- today++
|
|
|
- tempReal := inHigh[today]
|
|
|
- diffP := tempReal - prevHigh
|
|
|
- prevHigh = tempReal
|
|
|
- tempReal = inLow[today]
|
|
|
- diffM := prevLow - tempReal
|
|
|
- prevLow = tempReal
|
|
|
- if (diffM > 0) && (diffP < diffM) {
|
|
|
- prevMinusDM += diffM
|
|
|
- }
|
|
|
- tempReal = prevHigh - prevLow
|
|
|
- tempReal2 := math.Abs(prevHigh - prevClose)
|
|
|
- if tempReal2 > tempReal {
|
|
|
- tempReal = tempReal2
|
|
|
- }
|
|
|
- tempReal2 = math.Abs(prevLow - prevClose)
|
|
|
- if tempReal2 > tempReal {
|
|
|
- tempReal = tempReal2
|
|
|
- }
|
|
|
-
|
|
|
- prevTR += tempReal
|
|
|
- prevClose = inClose[today]
|
|
|
- }
|
|
|
- i = 1
|
|
|
- for i != 0 {
|
|
|
- i--
|
|
|
- today++
|
|
|
- tempReal := inHigh[today]
|
|
|
- diffP := tempReal - prevHigh
|
|
|
- prevHigh = tempReal
|
|
|
- tempReal = inLow[today]
|
|
|
- diffM := prevLow - tempReal
|
|
|
- prevLow = tempReal
|
|
|
- if (diffM > 0) && (diffP < diffM) {
|
|
|
- prevMinusDM = prevMinusDM - (prevMinusDM / float64(inTimePeriod)) + diffM
|
|
|
- } else {
|
|
|
- prevMinusDM = prevMinusDM - (prevMinusDM / float64(inTimePeriod))
|
|
|
- }
|
|
|
- tempReal = prevHigh - prevLow
|
|
|
- tempReal2 := math.Abs(prevHigh - prevClose)
|
|
|
- if tempReal2 > tempReal {
|
|
|
- tempReal = tempReal2
|
|
|
- }
|
|
|
- tempReal2 = math.Abs(prevLow - prevClose)
|
|
|
- if tempReal2 > tempReal {
|
|
|
- tempReal = tempReal2
|
|
|
- }
|
|
|
-
|
|
|
- prevTR = prevTR - (prevTR / float64(inTimePeriod)) + tempReal
|
|
|
- prevClose = inClose[today]
|
|
|
- }
|
|
|
- if !(((-(0.00000000000001)) < prevTR) && (prevTR < (0.00000000000001))) {
|
|
|
- outReal[startIdx] = (100.0 * (prevMinusDM / prevTR))
|
|
|
- } else {
|
|
|
- outReal[startIdx] = 0.0
|
|
|
- }
|
|
|
- outIdx = startIdx + 1
|
|
|
- for today < len(inClose)-1 {
|
|
|
- today++
|
|
|
- tempReal := inHigh[today]
|
|
|
- diffP := tempReal - prevHigh
|
|
|
- prevHigh = tempReal
|
|
|
- tempReal = inLow[today]
|
|
|
- diffM := prevLow - tempReal
|
|
|
- prevLow = tempReal
|
|
|
- if (diffM > 0) && (diffP < diffM) {
|
|
|
- prevMinusDM = prevMinusDM - (prevMinusDM / float64(inTimePeriod)) + diffM
|
|
|
- } else {
|
|
|
- prevMinusDM = prevMinusDM - (prevMinusDM / float64(inTimePeriod))
|
|
|
- }
|
|
|
- tempReal = prevHigh - prevLow
|
|
|
- tempReal2 := math.Abs(prevHigh - prevClose)
|
|
|
- if tempReal2 > tempReal {
|
|
|
- tempReal = tempReal2
|
|
|
- }
|
|
|
- tempReal2 = math.Abs(prevLow - prevClose)
|
|
|
- if tempReal2 > tempReal {
|
|
|
- tempReal = tempReal2
|
|
|
- }
|
|
|
-
|
|
|
- prevTR = prevTR - (prevTR / float64(inTimePeriod)) + tempReal
|
|
|
- prevClose = inClose[today]
|
|
|
- if !(((-(0.00000000000001)) < prevTR) && (prevTR < (0.00000000000001))) {
|
|
|
- outReal[outIdx] = (100.0 * (prevMinusDM / prevTR))
|
|
|
- } else {
|
|
|
- outReal[outIdx] = 0.0
|
|
|
- }
|
|
|
- outIdx++
|
|
|
- }
|
|
|
-
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// MinusDM - Minus Directional Movement
|
|
|
-func MinusDM(inHigh []float64, inLow []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inHigh))
|
|
|
-
|
|
|
- lookbackTotal := 1
|
|
|
- if inTimePeriod > 1 {
|
|
|
- lookbackTotal = inTimePeriod - 1
|
|
|
- }
|
|
|
- startIdx := lookbackTotal
|
|
|
- outIdx := startIdx
|
|
|
- today := startIdx
|
|
|
- prevHigh := 0.0
|
|
|
- prevLow := 0.0
|
|
|
- if inTimePeriod <= 1 {
|
|
|
- today = startIdx - 1
|
|
|
- prevHigh = inHigh[today]
|
|
|
- prevLow = inLow[today]
|
|
|
- for today < len(inHigh)-1 {
|
|
|
- today++
|
|
|
- tempReal := inHigh[today]
|
|
|
- diffP := tempReal - prevHigh
|
|
|
- prevHigh = tempReal
|
|
|
- tempReal = inLow[today]
|
|
|
- diffM := prevLow - tempReal
|
|
|
- prevLow = tempReal
|
|
|
- if (diffM > 0) && (diffP < diffM) {
|
|
|
- outReal[outIdx] = diffM
|
|
|
- } else {
|
|
|
- outReal[outIdx] = 0
|
|
|
- }
|
|
|
- outIdx++
|
|
|
- }
|
|
|
- return outReal
|
|
|
- }
|
|
|
- prevMinusDM := 0.0
|
|
|
- today = startIdx - lookbackTotal
|
|
|
- prevHigh = inHigh[today]
|
|
|
- prevLow = inLow[today]
|
|
|
- i := inTimePeriod - 1
|
|
|
- for i > 0 {
|
|
|
- i--
|
|
|
- today++
|
|
|
- tempReal := inHigh[today]
|
|
|
- diffP := tempReal - prevHigh
|
|
|
- prevHigh = tempReal
|
|
|
- tempReal = inLow[today]
|
|
|
- diffM := prevLow - tempReal
|
|
|
- prevLow = tempReal
|
|
|
- if (diffM > 0) && (diffP < diffM) {
|
|
|
- prevMinusDM += diffM
|
|
|
- }
|
|
|
- }
|
|
|
- i = 0
|
|
|
- for i != 0 {
|
|
|
- i--
|
|
|
- today++
|
|
|
- tempReal := inHigh[today]
|
|
|
- diffP := tempReal - prevHigh
|
|
|
- prevHigh = tempReal
|
|
|
- tempReal = inLow[today]
|
|
|
- diffM := prevLow - tempReal
|
|
|
- prevLow = tempReal
|
|
|
- if (diffM > 0) && (diffP < diffM) {
|
|
|
- prevMinusDM = prevMinusDM - (prevMinusDM / float64(inTimePeriod)) + diffM
|
|
|
- } else {
|
|
|
- prevMinusDM = prevMinusDM - (prevMinusDM / float64(inTimePeriod))
|
|
|
- }
|
|
|
- }
|
|
|
- outReal[startIdx] = prevMinusDM
|
|
|
- outIdx = startIdx + 1
|
|
|
- for today < len(inHigh)-1 {
|
|
|
- today++
|
|
|
- tempReal := inHigh[today]
|
|
|
- diffP := tempReal - prevHigh
|
|
|
- prevHigh = tempReal
|
|
|
- tempReal = inLow[today]
|
|
|
- diffM := prevLow - tempReal
|
|
|
- prevLow = tempReal
|
|
|
- if (diffM > 0) && (diffP < diffM) {
|
|
|
- prevMinusDM = prevMinusDM - (prevMinusDM / float64(inTimePeriod)) + diffM
|
|
|
- } else {
|
|
|
- prevMinusDM = prevMinusDM - (prevMinusDM / float64(inTimePeriod))
|
|
|
- }
|
|
|
- outReal[outIdx] = prevMinusDM
|
|
|
- outIdx++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Mfi - Money Flow Index
|
|
|
-func Mfi(inHigh []float64, inLow []float64, inClose []float64, inVolume []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inClose))
|
|
|
- mflowIdx := 0
|
|
|
- maxIdxMflow := (50 - 1)
|
|
|
- mflow := make([]moneyFlow, inTimePeriod)
|
|
|
- maxIdxMflow = inTimePeriod - 1
|
|
|
- lookbackTotal := inTimePeriod
|
|
|
- startIdx := lookbackTotal
|
|
|
- outIdx := startIdx
|
|
|
- today := startIdx - lookbackTotal
|
|
|
- prevValue := (inHigh[today] + inLow[today] + inClose[today]) / 3.0
|
|
|
- posSumMF := 0.0
|
|
|
- negSumMF := 0.0
|
|
|
- today++
|
|
|
- for i := inTimePeriod; i > 0; i-- {
|
|
|
- tempValue1 := (inHigh[today] + inLow[today] + inClose[today]) / 3.0
|
|
|
- tempValue2 := tempValue1 - prevValue
|
|
|
- prevValue = tempValue1
|
|
|
- tempValue1 *= inVolume[today]
|
|
|
- today++
|
|
|
- if tempValue2 < 0 {
|
|
|
- (mflow[mflowIdx]).negative = tempValue1
|
|
|
- negSumMF += tempValue1
|
|
|
- (mflow[mflowIdx]).positive = 0.0
|
|
|
- } else if tempValue2 > 0 {
|
|
|
- (mflow[mflowIdx]).positive = tempValue1
|
|
|
- posSumMF += tempValue1
|
|
|
- (mflow[mflowIdx]).negative = 0.0
|
|
|
- } else {
|
|
|
- (mflow[mflowIdx]).positive = 0.0
|
|
|
- (mflow[mflowIdx]).negative = 0.0
|
|
|
- }
|
|
|
- mflowIdx++
|
|
|
- if mflowIdx > maxIdxMflow {
|
|
|
- mflowIdx = 0
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- if today > startIdx {
|
|
|
- tempValue1 := posSumMF + negSumMF
|
|
|
- if tempValue1 < 1.0 {
|
|
|
- } else {
|
|
|
- outReal[outIdx] = 100.0 * (posSumMF / tempValue1)
|
|
|
- outIdx++
|
|
|
- }
|
|
|
- } else {
|
|
|
- for today < startIdx {
|
|
|
- posSumMF -= mflow[mflowIdx].positive
|
|
|
- negSumMF -= mflow[mflowIdx].negative
|
|
|
- tempValue1 := (inHigh[today] + inLow[today] + inClose[today]) / 3.0
|
|
|
- tempValue2 := tempValue1 - prevValue
|
|
|
- prevValue = tempValue1
|
|
|
- tempValue1 *= inVolume[today]
|
|
|
- today++
|
|
|
- if tempValue2 < 0 {
|
|
|
- (mflow[mflowIdx]).negative = tempValue1
|
|
|
- negSumMF += tempValue1
|
|
|
- (mflow[mflowIdx]).positive = 0.0
|
|
|
- } else if tempValue2 > 0 {
|
|
|
- (mflow[mflowIdx]).positive = tempValue1
|
|
|
- posSumMF += tempValue1
|
|
|
- (mflow[mflowIdx]).negative = 0.0
|
|
|
- } else {
|
|
|
- (mflow[mflowIdx]).positive = 0.0
|
|
|
- (mflow[mflowIdx]).negative = 0.0
|
|
|
- }
|
|
|
- mflowIdx++
|
|
|
- if mflowIdx > maxIdxMflow {
|
|
|
- mflowIdx = 0
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- }
|
|
|
- for today < len(inClose) {
|
|
|
- posSumMF -= (mflow[mflowIdx]).positive
|
|
|
- negSumMF -= (mflow[mflowIdx]).negative
|
|
|
- tempValue1 := (inHigh[today] + inLow[today] + inClose[today]) / 3.0
|
|
|
- tempValue2 := tempValue1 - prevValue
|
|
|
- prevValue = tempValue1
|
|
|
- tempValue1 *= inVolume[today]
|
|
|
- today++
|
|
|
- if tempValue2 < 0 {
|
|
|
- (mflow[mflowIdx]).negative = tempValue1
|
|
|
- negSumMF += tempValue1
|
|
|
- (mflow[mflowIdx]).positive = 0.0
|
|
|
- } else if tempValue2 > 0 {
|
|
|
- (mflow[mflowIdx]).positive = tempValue1
|
|
|
- posSumMF += tempValue1
|
|
|
- (mflow[mflowIdx]).negative = 0.0
|
|
|
- } else {
|
|
|
- (mflow[mflowIdx]).positive = 0.0
|
|
|
- (mflow[mflowIdx]).negative = 0.0
|
|
|
- }
|
|
|
- tempValue1 = posSumMF + negSumMF
|
|
|
- if tempValue1 < 1.0 {
|
|
|
- outReal[outIdx] = 0.0
|
|
|
- } else {
|
|
|
- outReal[outIdx] = 100.0 * (posSumMF / tempValue1)
|
|
|
- }
|
|
|
- outIdx++
|
|
|
- mflowIdx++
|
|
|
- if mflowIdx > maxIdxMflow {
|
|
|
- mflowIdx = 0
|
|
|
- }
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Mom - Momentum
|
|
|
-func Mom(inReal []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
-
|
|
|
- inIdx, outIdx, trailingIdx := inTimePeriod, inTimePeriod, 0
|
|
|
- for inIdx < len(inReal) {
|
|
|
- outReal[outIdx] = inReal[inIdx] - inReal[trailingIdx]
|
|
|
- inIdx, outIdx, trailingIdx = inIdx+1, outIdx+1, trailingIdx+1
|
|
|
- }
|
|
|
-
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// PlusDI - Plus Directional Indicator
|
|
|
-func PlusDI(inHigh []float64, inLow []float64, inClose []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inClose))
|
|
|
-
|
|
|
- lookbackTotal := 1
|
|
|
- if inTimePeriod > 1 {
|
|
|
- lookbackTotal = inTimePeriod
|
|
|
- }
|
|
|
- startIdx := lookbackTotal
|
|
|
- outIdx := startIdx
|
|
|
-
|
|
|
- prevHigh := 0.0
|
|
|
- prevLow := 0.0
|
|
|
- prevClose := 0.0
|
|
|
- if inTimePeriod <= 1 {
|
|
|
- today := startIdx - 1
|
|
|
- prevHigh = inHigh[today]
|
|
|
- prevLow = inLow[today]
|
|
|
- prevClose = inClose[today]
|
|
|
- for today < len(inClose)-1 {
|
|
|
- today++
|
|
|
- tempReal := inHigh[today]
|
|
|
- diffP := tempReal - prevHigh
|
|
|
- prevHigh = tempReal
|
|
|
- tempReal = inLow[today]
|
|
|
- diffM := prevLow - tempReal
|
|
|
- prevLow = tempReal
|
|
|
- if (diffP > 0) && (diffP > diffM) {
|
|
|
-
|
|
|
- tempReal = prevHigh - prevLow
|
|
|
- tempReal2 := math.Abs(prevHigh - prevClose)
|
|
|
- if tempReal2 > tempReal {
|
|
|
- tempReal = tempReal2
|
|
|
- }
|
|
|
- tempReal2 = math.Abs(prevLow - prevClose)
|
|
|
- if tempReal2 > tempReal {
|
|
|
- tempReal = tempReal2
|
|
|
- }
|
|
|
-
|
|
|
- if ((-(0.00000000000001)) < tempReal) && (tempReal < (0.00000000000001)) {
|
|
|
- outReal[outIdx] = 0.0
|
|
|
- } else {
|
|
|
- outReal[outIdx] = diffP / tempReal
|
|
|
- }
|
|
|
- outIdx++
|
|
|
- } else {
|
|
|
- outReal[outIdx] = 0.0
|
|
|
- outIdx++
|
|
|
- }
|
|
|
- prevClose = inClose[today]
|
|
|
- }
|
|
|
- return outReal
|
|
|
- }
|
|
|
- prevPlusDM := 0.0
|
|
|
- prevTR := 0.0
|
|
|
- today := startIdx - lookbackTotal
|
|
|
- prevHigh = inHigh[today]
|
|
|
- prevLow = inLow[today]
|
|
|
- prevClose = inClose[today]
|
|
|
- i := inTimePeriod - 1
|
|
|
-
|
|
|
- for i > 0 {
|
|
|
- i--
|
|
|
- today++
|
|
|
- tempReal := inHigh[today]
|
|
|
- diffP := tempReal - prevHigh
|
|
|
- prevHigh = tempReal
|
|
|
- tempReal = inLow[today]
|
|
|
- diffM := prevLow - tempReal
|
|
|
- prevLow = tempReal
|
|
|
- if (diffP > 0) && (diffP > diffM) {
|
|
|
- prevPlusDM += diffP
|
|
|
- }
|
|
|
- tempReal = prevHigh - prevLow
|
|
|
- tempReal2 := math.Abs(prevHigh - prevClose)
|
|
|
- if tempReal2 > tempReal {
|
|
|
- tempReal = tempReal2
|
|
|
- }
|
|
|
- tempReal2 = math.Abs(prevLow - prevClose)
|
|
|
- if tempReal2 > tempReal {
|
|
|
- tempReal = tempReal2
|
|
|
- }
|
|
|
-
|
|
|
- prevTR += tempReal
|
|
|
- prevClose = inClose[today]
|
|
|
- }
|
|
|
- i = 1
|
|
|
- for i != 0 {
|
|
|
- i--
|
|
|
- today++
|
|
|
- tempReal := inHigh[today]
|
|
|
- diffP := tempReal - prevHigh
|
|
|
- prevHigh = tempReal
|
|
|
- tempReal = inLow[today]
|
|
|
- diffM := prevLow - tempReal
|
|
|
- prevLow = tempReal
|
|
|
- if (diffP > 0) && (diffP > diffM) {
|
|
|
- prevPlusDM = prevPlusDM - (prevPlusDM / float64(inTimePeriod)) + diffP
|
|
|
- } else {
|
|
|
- prevPlusDM = prevPlusDM - (prevPlusDM / float64(inTimePeriod))
|
|
|
- }
|
|
|
- tempReal = prevHigh - prevLow
|
|
|
- tempReal2 := math.Abs(prevHigh - prevClose)
|
|
|
- if tempReal2 > tempReal {
|
|
|
- tempReal = tempReal2
|
|
|
- }
|
|
|
- tempReal2 = math.Abs(prevLow - prevClose)
|
|
|
- if tempReal2 > tempReal {
|
|
|
- tempReal = tempReal2
|
|
|
- }
|
|
|
-
|
|
|
- prevTR = prevTR - (prevTR / float64(inTimePeriod)) + tempReal
|
|
|
- prevClose = inClose[today]
|
|
|
- }
|
|
|
- if !(((-(0.00000000000001)) < prevTR) && (prevTR < (0.00000000000001))) {
|
|
|
- outReal[startIdx] = (100.0 * (prevPlusDM / prevTR))
|
|
|
- } else {
|
|
|
- outReal[startIdx] = 0.0
|
|
|
- }
|
|
|
- outIdx = startIdx + 1
|
|
|
- for today < len(inClose)-1 {
|
|
|
- today++
|
|
|
- tempReal := inHigh[today]
|
|
|
- diffP := tempReal - prevHigh
|
|
|
- prevHigh = tempReal
|
|
|
- tempReal = inLow[today]
|
|
|
- diffM := prevLow - tempReal
|
|
|
- prevLow = tempReal
|
|
|
- if (diffP > 0) && (diffP > diffM) {
|
|
|
- prevPlusDM = prevPlusDM - (prevPlusDM / float64(inTimePeriod)) + diffP
|
|
|
- } else {
|
|
|
- prevPlusDM = prevPlusDM - (prevPlusDM / float64(inTimePeriod))
|
|
|
- }
|
|
|
- tempReal = prevHigh - prevLow
|
|
|
- tempReal2 := math.Abs(prevHigh - prevClose)
|
|
|
- if tempReal2 > tempReal {
|
|
|
- tempReal = tempReal2
|
|
|
- }
|
|
|
- tempReal2 = math.Abs(prevLow - prevClose)
|
|
|
- if tempReal2 > tempReal {
|
|
|
- tempReal = tempReal2
|
|
|
- }
|
|
|
-
|
|
|
- prevTR = prevTR - (prevTR / float64(inTimePeriod)) + tempReal
|
|
|
- prevClose = inClose[today]
|
|
|
- if !(((-(0.00000000000001)) < prevTR) && (prevTR < (0.00000000000001))) {
|
|
|
- outReal[outIdx] = (100.0 * (prevPlusDM / prevTR))
|
|
|
- } else {
|
|
|
- outReal[outIdx] = 0.0
|
|
|
- }
|
|
|
- outIdx++
|
|
|
- }
|
|
|
-
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// PlusDM - Plus Directional Movement
|
|
|
-func PlusDM(inHigh []float64, inLow []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inHigh))
|
|
|
-
|
|
|
- lookbackTotal := 1
|
|
|
- if inTimePeriod > 1 {
|
|
|
- lookbackTotal = inTimePeriod - 1
|
|
|
- }
|
|
|
- startIdx := lookbackTotal
|
|
|
- outIdx := startIdx
|
|
|
- today := startIdx
|
|
|
- prevHigh := 0.0
|
|
|
- prevLow := 0.0
|
|
|
- if inTimePeriod <= 1 {
|
|
|
- today = startIdx - 1
|
|
|
- prevHigh = inHigh[today]
|
|
|
- prevLow = inLow[today]
|
|
|
- for today < len(inHigh)-1 {
|
|
|
- today++
|
|
|
- tempReal := inHigh[today]
|
|
|
- diffP := tempReal - prevHigh
|
|
|
- prevHigh = tempReal
|
|
|
- tempReal = inLow[today]
|
|
|
- diffM := prevLow - tempReal
|
|
|
- prevLow = tempReal
|
|
|
- if (diffP > 0) && (diffP > diffM) {
|
|
|
- outReal[outIdx] = diffP
|
|
|
- } else {
|
|
|
- outReal[outIdx] = 0
|
|
|
- }
|
|
|
- outIdx++
|
|
|
- }
|
|
|
- return outReal
|
|
|
- }
|
|
|
- prevPlusDM := 0.0
|
|
|
- today = startIdx - lookbackTotal
|
|
|
- prevHigh = inHigh[today]
|
|
|
- prevLow = inLow[today]
|
|
|
- i := inTimePeriod - 1
|
|
|
- for i > 0 {
|
|
|
- i--
|
|
|
- today++
|
|
|
- tempReal := inHigh[today]
|
|
|
- diffP := tempReal - prevHigh
|
|
|
- prevHigh = tempReal
|
|
|
- tempReal = inLow[today]
|
|
|
- diffM := prevLow - tempReal
|
|
|
- prevLow = tempReal
|
|
|
- if (diffP > 0) && (diffP > diffM) {
|
|
|
- prevPlusDM += diffP
|
|
|
- }
|
|
|
- }
|
|
|
- i = 0
|
|
|
- for i != 0 {
|
|
|
- i--
|
|
|
- today++
|
|
|
- tempReal := inHigh[today]
|
|
|
- diffP := tempReal - prevHigh
|
|
|
- prevHigh = tempReal
|
|
|
- tempReal = inLow[today]
|
|
|
- diffM := prevLow - tempReal
|
|
|
- prevLow = tempReal
|
|
|
- if (diffP > 0) && (diffP > diffM) {
|
|
|
- prevPlusDM = prevPlusDM - (prevPlusDM / float64(inTimePeriod)) + diffP
|
|
|
- } else {
|
|
|
- prevPlusDM = prevPlusDM - (prevPlusDM / float64(inTimePeriod))
|
|
|
- }
|
|
|
- }
|
|
|
- outReal[startIdx] = prevPlusDM
|
|
|
- outIdx = startIdx + 1
|
|
|
- for today < len(inHigh)-1 {
|
|
|
- today++
|
|
|
- tempReal := inHigh[today]
|
|
|
- diffP := tempReal - prevHigh
|
|
|
- prevHigh = tempReal
|
|
|
- tempReal = inLow[today]
|
|
|
- diffM := prevLow - tempReal
|
|
|
- prevLow = tempReal
|
|
|
- if (diffP > 0) && (diffP > diffM) {
|
|
|
- prevPlusDM = prevPlusDM - (prevPlusDM / float64(inTimePeriod)) + diffP
|
|
|
- } else {
|
|
|
- prevPlusDM = prevPlusDM - (prevPlusDM / float64(inTimePeriod))
|
|
|
- }
|
|
|
- outReal[outIdx] = prevPlusDM
|
|
|
- outIdx++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Ppo - Percentage Price Oscillator
|
|
|
-func Ppo(inReal []float64, inFastPeriod int, inSlowPeriod int, inMAType MaType) []float64 {
|
|
|
-
|
|
|
- if inSlowPeriod < inFastPeriod {
|
|
|
- inSlowPeriod, inFastPeriod = inFastPeriod, inSlowPeriod
|
|
|
- }
|
|
|
- tempBuffer := Ma(inReal, inFastPeriod, inMAType)
|
|
|
- outReal := Ma(inReal, inSlowPeriod, inMAType)
|
|
|
-
|
|
|
- for i := inSlowPeriod - 1; i < len(inReal); i++ {
|
|
|
- tempReal := outReal[i]
|
|
|
- if !(((-(0.00000000000001)) < tempReal) && (tempReal < (0.00000000000001))) {
|
|
|
- outReal[i] = ((tempBuffer[i] - tempReal) / tempReal) * 100.0
|
|
|
- } else {
|
|
|
- outReal[i] = 0.0
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Rocp - Rate of change Percentage: (price-prevPrice)/prevPrice
|
|
|
-func Rocp(inReal []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
-
|
|
|
- if inTimePeriod < 1 {
|
|
|
- return outReal
|
|
|
- }
|
|
|
-
|
|
|
- startIdx := inTimePeriod
|
|
|
- outIdx := startIdx
|
|
|
- inIdx := startIdx
|
|
|
- trailingIdx := startIdx - inTimePeriod
|
|
|
- for inIdx < len(outReal) {
|
|
|
- tempReal := inReal[trailingIdx]
|
|
|
- if tempReal != 0.0 {
|
|
|
- outReal[outIdx] = (inReal[inIdx] - tempReal) / tempReal
|
|
|
- } else {
|
|
|
- outReal[outIdx] = 0.0
|
|
|
- }
|
|
|
- trailingIdx++
|
|
|
- outIdx++
|
|
|
- inIdx++
|
|
|
- }
|
|
|
-
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Roc - Rate of change : ((price/prevPrice)-1)*100
|
|
|
-func Roc(inReal []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
-
|
|
|
- startIdx := inTimePeriod
|
|
|
- outIdx := inTimePeriod
|
|
|
- inIdx := startIdx
|
|
|
- trailingIdx := startIdx - inTimePeriod
|
|
|
-
|
|
|
- for inIdx < len(inReal) {
|
|
|
- tempReal := inReal[trailingIdx]
|
|
|
- if tempReal != 0.0 {
|
|
|
- outReal[outIdx] = ((inReal[inIdx] / tempReal) - 1.0) * 100.0
|
|
|
- } else {
|
|
|
- outReal[outIdx] = 0.0
|
|
|
- }
|
|
|
- trailingIdx++
|
|
|
- outIdx++
|
|
|
- inIdx++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Rocr - Rate of change ratio: (price/prevPrice)
|
|
|
-func Rocr(inReal []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
-
|
|
|
- startIdx := inTimePeriod
|
|
|
- outIdx := inTimePeriod
|
|
|
- inIdx := startIdx
|
|
|
- trailingIdx := startIdx - inTimePeriod
|
|
|
-
|
|
|
- for inIdx < len(inReal) {
|
|
|
- tempReal := inReal[trailingIdx]
|
|
|
- if tempReal != 0.0 {
|
|
|
- outReal[outIdx] = (inReal[inIdx] / tempReal)
|
|
|
- } else {
|
|
|
- outReal[outIdx] = 0.0
|
|
|
- }
|
|
|
- trailingIdx++
|
|
|
- outIdx++
|
|
|
- inIdx++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Rocr100 - Rate of change ratio 100 scale: (price/prevPrice)*100
|
|
|
-func Rocr100(inReal []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
-
|
|
|
- startIdx := inTimePeriod
|
|
|
- outIdx := inTimePeriod
|
|
|
- inIdx := startIdx
|
|
|
- trailingIdx := startIdx - inTimePeriod
|
|
|
-
|
|
|
- for inIdx < len(inReal) {
|
|
|
- tempReal := inReal[trailingIdx]
|
|
|
- if tempReal != 0.0 {
|
|
|
- outReal[outIdx] = (inReal[inIdx] / tempReal) * 100.0
|
|
|
- } else {
|
|
|
- outReal[outIdx] = 0.0
|
|
|
- }
|
|
|
- trailingIdx++
|
|
|
- outIdx++
|
|
|
- inIdx++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Rsi - Relative strength index
|
|
|
-func Rsi(inReal []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
-
|
|
|
- if inTimePeriod < 2 {
|
|
|
- return outReal
|
|
|
- }
|
|
|
-
|
|
|
- // variable declarations
|
|
|
- tempValue1 := 0.0
|
|
|
- tempValue2 := 0.0
|
|
|
- outIdx := inTimePeriod
|
|
|
- today := 0
|
|
|
- prevValue := inReal[today]
|
|
|
- prevGain := 0.0
|
|
|
- prevLoss := 0.0
|
|
|
- today++
|
|
|
-
|
|
|
- for i := inTimePeriod; i > 0; i-- {
|
|
|
- tempValue1 = inReal[today]
|
|
|
- today++
|
|
|
- tempValue2 = tempValue1 - prevValue
|
|
|
- prevValue = tempValue1
|
|
|
- if tempValue2 < 0 {
|
|
|
- prevLoss -= tempValue2
|
|
|
- } else {
|
|
|
- prevGain += tempValue2
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- prevLoss /= float64(inTimePeriod)
|
|
|
- prevGain /= float64(inTimePeriod)
|
|
|
-
|
|
|
- if today > 0 {
|
|
|
-
|
|
|
- tempValue1 = prevGain + prevLoss
|
|
|
- if !((-0.00000000000001 < tempValue1) && (tempValue1 < 0.00000000000001)) {
|
|
|
- outReal[outIdx] = 100.0 * (prevGain / tempValue1)
|
|
|
- } else {
|
|
|
- outReal[outIdx] = 0.0
|
|
|
- }
|
|
|
- outIdx++
|
|
|
-
|
|
|
- } else {
|
|
|
-
|
|
|
- for today < 0 {
|
|
|
- tempValue1 = inReal[today]
|
|
|
- tempValue2 = tempValue1 - prevValue
|
|
|
- prevValue = tempValue1
|
|
|
- prevLoss *= float64(inTimePeriod - 1)
|
|
|
- prevGain *= float64(inTimePeriod - 1)
|
|
|
- if tempValue2 < 0 {
|
|
|
- prevLoss -= tempValue2
|
|
|
- } else {
|
|
|
- prevGain += tempValue2
|
|
|
- }
|
|
|
- prevLoss /= float64(inTimePeriod)
|
|
|
- prevGain /= float64(inTimePeriod)
|
|
|
- today++
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- for today < len(inReal) {
|
|
|
-
|
|
|
- tempValue1 = inReal[today]
|
|
|
- today++
|
|
|
- tempValue2 = tempValue1 - prevValue
|
|
|
- prevValue = tempValue1
|
|
|
- prevLoss *= float64(inTimePeriod - 1)
|
|
|
- prevGain *= float64(inTimePeriod - 1)
|
|
|
- if tempValue2 < 0 {
|
|
|
- prevLoss -= tempValue2
|
|
|
- } else {
|
|
|
- prevGain += tempValue2
|
|
|
- }
|
|
|
- prevLoss /= float64(inTimePeriod)
|
|
|
- prevGain /= float64(inTimePeriod)
|
|
|
- tempValue1 = prevGain + prevLoss
|
|
|
- if !((-0.00000000000001 < tempValue1) && (tempValue1 < 0.00000000000001)) {
|
|
|
- outReal[outIdx] = 100.0 * (prevGain / tempValue1)
|
|
|
- } else {
|
|
|
- outReal[outIdx] = 0.0
|
|
|
- }
|
|
|
- outIdx++
|
|
|
- }
|
|
|
-
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Stoch - Stochastic
|
|
|
-func Stoch(inHigh []float64, inLow []float64, inClose []float64, inFastKPeriod int, inSlowKPeriod int, inSlowKMAType MaType, inSlowDPeriod int, inSlowDMAType MaType) ([]float64, []float64) {
|
|
|
-
|
|
|
- outSlowK := make([]float64, len(inClose))
|
|
|
- outSlowD := make([]float64, len(inClose))
|
|
|
-
|
|
|
- lookbackK := inFastKPeriod - 1
|
|
|
- lookbackKSlow := inSlowKPeriod - 1
|
|
|
- lookbackDSlow := inSlowDPeriod - 1
|
|
|
- lookbackTotal := lookbackK + lookbackDSlow + lookbackKSlow
|
|
|
- startIdx := lookbackTotal
|
|
|
- outIdx := 0
|
|
|
- trailingIdx := startIdx - lookbackTotal
|
|
|
- today := trailingIdx + lookbackK
|
|
|
- lowestIdx, highestIdx := -1, -1
|
|
|
- diff, highest, lowest := 0.0, 0.0, 0.0
|
|
|
- tempBuffer := make([]float64, len(inClose)-today+1)
|
|
|
- for today < len(inClose) {
|
|
|
- tmp := inLow[today]
|
|
|
- if lowestIdx < trailingIdx {
|
|
|
- lowestIdx = trailingIdx
|
|
|
- lowest = inLow[lowestIdx]
|
|
|
- i := lowestIdx + 1
|
|
|
- for i <= today {
|
|
|
-
|
|
|
- tmp := inLow[i]
|
|
|
- if tmp < lowest {
|
|
|
- lowestIdx = i
|
|
|
- lowest = tmp
|
|
|
- }
|
|
|
- i++
|
|
|
- }
|
|
|
- diff = (highest - lowest) / 100.0
|
|
|
- } else if tmp <= lowest {
|
|
|
- lowestIdx = today
|
|
|
- lowest = tmp
|
|
|
- diff = (highest - lowest) / 100.0
|
|
|
- }
|
|
|
- tmp = inHigh[today]
|
|
|
- if highestIdx < trailingIdx {
|
|
|
- highestIdx = trailingIdx
|
|
|
- highest = inHigh[highestIdx]
|
|
|
- i := highestIdx + 1
|
|
|
- for i <= today {
|
|
|
- tmp := inHigh[i]
|
|
|
- if tmp > highest {
|
|
|
- highestIdx = i
|
|
|
- highest = tmp
|
|
|
- }
|
|
|
- i++
|
|
|
- }
|
|
|
- diff = (highest - lowest) / 100.0
|
|
|
- } else if tmp >= highest {
|
|
|
- highestIdx = today
|
|
|
- highest = tmp
|
|
|
- diff = (highest - lowest) / 100.0
|
|
|
- }
|
|
|
- if diff != 0.0 {
|
|
|
- tempBuffer[outIdx] = (inClose[today] - lowest) / diff
|
|
|
- } else {
|
|
|
- tempBuffer[outIdx] = 0.0
|
|
|
- }
|
|
|
- outIdx++
|
|
|
- trailingIdx++
|
|
|
- today++
|
|
|
- }
|
|
|
-
|
|
|
- tempBuffer1 := Ma(tempBuffer, inSlowKPeriod, inSlowKMAType)
|
|
|
- tempBuffer2 := Ma(tempBuffer1, inSlowDPeriod, inSlowDMAType)
|
|
|
- //for i, j := lookbackK, lookbackTotal; j < len(inClose); i, j = i+1, j+1 {
|
|
|
- for i, j := lookbackDSlow+lookbackKSlow, lookbackTotal; j < len(inClose); i, j = i+1, j+1 {
|
|
|
- outSlowK[j] = tempBuffer1[i]
|
|
|
- outSlowD[j] = tempBuffer2[i]
|
|
|
- }
|
|
|
-
|
|
|
- return outSlowK, outSlowD
|
|
|
-}
|
|
|
-
|
|
|
-// StochF - Stochastic Fast
|
|
|
-func StochF(inHigh []float64, inLow []float64, inClose []float64, inFastKPeriod int, inFastDPeriod int, inFastDMAType MaType) ([]float64, []float64) {
|
|
|
-
|
|
|
- outFastK := make([]float64, len(inClose))
|
|
|
- outFastD := make([]float64, len(inClose))
|
|
|
-
|
|
|
- lookbackK := inFastKPeriod - 1
|
|
|
- lookbackFastD := inFastDPeriod - 1
|
|
|
- lookbackTotal := lookbackK + lookbackFastD
|
|
|
- startIdx := lookbackTotal
|
|
|
- outIdx := 0
|
|
|
- trailingIdx := startIdx - lookbackTotal
|
|
|
- today := trailingIdx + lookbackK
|
|
|
- lowestIdx, highestIdx := -1, -1
|
|
|
- diff, highest, lowest := 0.0, 0.0, 0.0
|
|
|
- tempBuffer := make([]float64, (len(inClose) - today + 1))
|
|
|
-
|
|
|
- for today < len(inClose) {
|
|
|
- tmp := inLow[today]
|
|
|
- if lowestIdx < trailingIdx {
|
|
|
- lowestIdx = trailingIdx
|
|
|
- lowest = inLow[lowestIdx]
|
|
|
- i := lowestIdx
|
|
|
- i++
|
|
|
- for i <= today {
|
|
|
- tmp = inLow[i]
|
|
|
- if tmp < lowest {
|
|
|
- lowestIdx = i
|
|
|
- lowest = tmp
|
|
|
- }
|
|
|
- i++
|
|
|
- }
|
|
|
- diff = (highest - lowest) / 100.0
|
|
|
- } else if tmp <= lowest {
|
|
|
- lowestIdx = today
|
|
|
- lowest = tmp
|
|
|
- diff = (highest - lowest) / 100.0
|
|
|
- }
|
|
|
- tmp = inHigh[today]
|
|
|
- if highestIdx < trailingIdx {
|
|
|
- highestIdx = trailingIdx
|
|
|
- highest = inHigh[highestIdx]
|
|
|
- i := highestIdx
|
|
|
- i++
|
|
|
- for i <= today {
|
|
|
- tmp = inHigh[i]
|
|
|
- if tmp > highest {
|
|
|
- highestIdx = i
|
|
|
- highest = tmp
|
|
|
- }
|
|
|
- i++
|
|
|
- }
|
|
|
- diff = (highest - lowest) / 100.0
|
|
|
- } else if tmp >= highest {
|
|
|
- highestIdx = today
|
|
|
- highest = tmp
|
|
|
- diff = (highest - lowest) / 100.0
|
|
|
- }
|
|
|
- if diff != 0.0 {
|
|
|
- tempBuffer[outIdx] = (inClose[today] - lowest) / diff
|
|
|
-
|
|
|
- } else {
|
|
|
- tempBuffer[outIdx] = 0.0
|
|
|
- }
|
|
|
- outIdx++
|
|
|
- trailingIdx++
|
|
|
- today++
|
|
|
- }
|
|
|
-
|
|
|
- tempBuffer1 := Ma(tempBuffer, inFastDPeriod, inFastDMAType)
|
|
|
- for i, j := lookbackFastD, lookbackTotal; j < len(inClose); i, j = i+1, j+1 {
|
|
|
- outFastK[j] = tempBuffer[i]
|
|
|
- outFastD[j] = tempBuffer1[i]
|
|
|
- }
|
|
|
-
|
|
|
- return outFastK, outFastD
|
|
|
-}
|
|
|
-
|
|
|
-// StochRsi - Stochastic Relative Strength Index
|
|
|
-func StochRsi(inReal []float64, inTimePeriod int, inFastKPeriod int, inFastDPeriod int, inFastDMAType MaType) ([]float64, []float64) {
|
|
|
-
|
|
|
- outFastK := make([]float64, len(inReal))
|
|
|
- outFastD := make([]float64, len(inReal))
|
|
|
-
|
|
|
- lookbackSTOCHF := (inFastKPeriod - 1) + (inFastDPeriod - 1)
|
|
|
- lookbackTotal := inTimePeriod + lookbackSTOCHF
|
|
|
- startIdx := lookbackTotal
|
|
|
- tempRSIBuffer := Rsi(inReal, inTimePeriod)
|
|
|
- tempk, tempd := StochF(tempRSIBuffer, tempRSIBuffer, tempRSIBuffer, inFastKPeriod, inFastDPeriod, inFastDMAType)
|
|
|
-
|
|
|
- for i := startIdx; i < len(inReal); i++ {
|
|
|
- outFastK[i] = tempk[i]
|
|
|
- outFastD[i] = tempd[i]
|
|
|
- }
|
|
|
-
|
|
|
- return outFastK, outFastD
|
|
|
-}
|
|
|
-
|
|
|
-// Trix - 1-day Rate-Of-Change (ROC) of a Triple Smooth EMA
|
|
|
-func Trix(inReal []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- tmpReal := Ema(inReal, inTimePeriod)
|
|
|
- tmpReal = Ema(tmpReal[inTimePeriod-1:], inTimePeriod)
|
|
|
- tmpReal = Ema(tmpReal[inTimePeriod-1:], inTimePeriod)
|
|
|
- tmpReal = Roc(tmpReal, 1)
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
- for i, j := inTimePeriod, ((inTimePeriod-1)*3)+1; j < len(outReal); i, j = i+1, j+1 {
|
|
|
- outReal[j] = tmpReal[i]
|
|
|
- }
|
|
|
-
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// UltOsc - Ultimate Oscillator
|
|
|
-func UltOsc(inHigh []float64, inLow []float64, inClose []float64, inTimePeriod1 int, inTimePeriod2 int, inTimePeriod3 int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inClose))
|
|
|
-
|
|
|
- usedFlag := make([]int, 3)
|
|
|
- periods := make([]int, 3)
|
|
|
- sortedPeriods := make([]int, 3)
|
|
|
-
|
|
|
- periods[0] = inTimePeriod1
|
|
|
- periods[1] = inTimePeriod2
|
|
|
- periods[2] = inTimePeriod3
|
|
|
-
|
|
|
- for i := 0; i < 3; i++ {
|
|
|
- longestPeriod := 0
|
|
|
- longestIndex := 0
|
|
|
- for j := 0; j < 3; j++ {
|
|
|
- if (usedFlag[j] == 0) && (periods[j] > longestPeriod) {
|
|
|
- longestPeriod = periods[j]
|
|
|
- longestIndex = j
|
|
|
- }
|
|
|
- }
|
|
|
- usedFlag[longestIndex] = 1
|
|
|
- sortedPeriods[i] = longestPeriod
|
|
|
- }
|
|
|
- inTimePeriod1 = sortedPeriods[2]
|
|
|
- inTimePeriod2 = sortedPeriods[1]
|
|
|
- inTimePeriod3 = sortedPeriods[0]
|
|
|
-
|
|
|
- lookbackTotal := 0
|
|
|
- if inTimePeriod1 > inTimePeriod2 {
|
|
|
- lookbackTotal = inTimePeriod1
|
|
|
- }
|
|
|
- if inTimePeriod3 > lookbackTotal {
|
|
|
- lookbackTotal = inTimePeriod3
|
|
|
- }
|
|
|
- lookbackTotal++
|
|
|
-
|
|
|
- startIdx := lookbackTotal - 1
|
|
|
-
|
|
|
- a1Total := 0.0
|
|
|
- b1Total := 0.0
|
|
|
- for i := startIdx - inTimePeriod1 + 1; i < startIdx; i++ {
|
|
|
-
|
|
|
- tempLT := inLow[i]
|
|
|
- tempHT := inHigh[i]
|
|
|
- tempCY := inClose[i-1]
|
|
|
- trueLow := 0.0
|
|
|
- if tempLT < tempCY {
|
|
|
- trueLow = tempLT
|
|
|
- } else {
|
|
|
- trueLow = tempCY
|
|
|
- }
|
|
|
- closeMinusTrueLow := inClose[i] - trueLow
|
|
|
- trueRange := tempHT - tempLT
|
|
|
- tempDouble := math.Abs(tempCY - tempHT)
|
|
|
- if tempDouble > trueRange {
|
|
|
- trueRange = tempDouble
|
|
|
- }
|
|
|
- tempDouble = math.Abs(tempCY - tempLT)
|
|
|
- if tempDouble > trueRange {
|
|
|
- trueRange = tempDouble
|
|
|
- }
|
|
|
-
|
|
|
- a1Total += closeMinusTrueLow
|
|
|
- b1Total += trueRange
|
|
|
- }
|
|
|
-
|
|
|
- a2Total := 0.0
|
|
|
- b2Total := 0.0
|
|
|
- for i := startIdx - inTimePeriod2 + 1; i < startIdx; i++ {
|
|
|
-
|
|
|
- tempLT := inLow[i]
|
|
|
- tempHT := inHigh[i]
|
|
|
- tempCY := inClose[i-1]
|
|
|
- trueLow := 0.0
|
|
|
- if tempLT < tempCY {
|
|
|
- trueLow = tempLT
|
|
|
- } else {
|
|
|
- trueLow = tempCY
|
|
|
- }
|
|
|
- closeMinusTrueLow := inClose[i] - trueLow
|
|
|
- trueRange := tempHT - tempLT
|
|
|
- tempDouble := math.Abs(tempCY - tempHT)
|
|
|
- if tempDouble > trueRange {
|
|
|
- trueRange = tempDouble
|
|
|
- }
|
|
|
- tempDouble = math.Abs(tempCY - tempLT)
|
|
|
- if tempDouble > trueRange {
|
|
|
- trueRange = tempDouble
|
|
|
- }
|
|
|
-
|
|
|
- a2Total += closeMinusTrueLow
|
|
|
- b2Total += trueRange
|
|
|
- }
|
|
|
-
|
|
|
- a3Total := 0.0
|
|
|
- b3Total := 0.0
|
|
|
- for i := startIdx - inTimePeriod3 + 1; i < startIdx; i++ {
|
|
|
-
|
|
|
- tempLT := inLow[i]
|
|
|
- tempHT := inHigh[i]
|
|
|
- tempCY := inClose[i-1]
|
|
|
- trueLow := 0.0
|
|
|
- if tempLT < tempCY {
|
|
|
- trueLow = tempLT
|
|
|
- } else {
|
|
|
- trueLow = tempCY
|
|
|
- }
|
|
|
- closeMinusTrueLow := inClose[i] - trueLow
|
|
|
- trueRange := tempHT - tempLT
|
|
|
- tempDouble := math.Abs(tempCY - tempHT)
|
|
|
- if tempDouble > trueRange {
|
|
|
- trueRange = tempDouble
|
|
|
- }
|
|
|
- tempDouble = math.Abs(tempCY - tempLT)
|
|
|
- if tempDouble > trueRange {
|
|
|
- trueRange = tempDouble
|
|
|
- }
|
|
|
-
|
|
|
- a3Total += closeMinusTrueLow
|
|
|
- b3Total += trueRange
|
|
|
- }
|
|
|
-
|
|
|
- //today := startIdx
|
|
|
- //outIdx := startIdx
|
|
|
- //trailingIdx1 := today - inTimePeriod1 + 1
|
|
|
- //trailingIdx2 := today - inTimePeriod2 + 1
|
|
|
- //trailingIdx3 := today - inTimePeriod3 + 1
|
|
|
-
|
|
|
- today := startIdx
|
|
|
- outIdx := startIdx
|
|
|
- trailingIdx1 := today - inTimePeriod1 + 1
|
|
|
- trailingIdx2 := today - inTimePeriod2 + 1
|
|
|
- trailingIdx3 := today - inTimePeriod3 + 1
|
|
|
-
|
|
|
- for today < len(inClose) {
|
|
|
-
|
|
|
- tempLT := inLow[today]
|
|
|
- tempHT := inHigh[today]
|
|
|
- tempCY := inClose[today-1]
|
|
|
- trueLow := 0.0
|
|
|
- if tempLT < tempCY {
|
|
|
- trueLow = tempLT
|
|
|
- } else {
|
|
|
- trueLow = tempCY
|
|
|
- }
|
|
|
- closeMinusTrueLow := inClose[today] - trueLow
|
|
|
- trueRange := tempHT - tempLT
|
|
|
- tempDouble := math.Abs(tempCY - tempHT)
|
|
|
- if tempDouble > trueRange {
|
|
|
- trueRange = tempDouble
|
|
|
- }
|
|
|
- tempDouble = math.Abs(tempCY - tempLT)
|
|
|
- if tempDouble > trueRange {
|
|
|
- trueRange = tempDouble
|
|
|
- }
|
|
|
-
|
|
|
- a1Total += closeMinusTrueLow
|
|
|
- a2Total += closeMinusTrueLow
|
|
|
- a3Total += closeMinusTrueLow
|
|
|
- b1Total += trueRange
|
|
|
- b2Total += trueRange
|
|
|
- b3Total += trueRange
|
|
|
- output := 0.0
|
|
|
- if !(((-(0.00000000000001)) < b1Total) && (b1Total < (0.00000000000001))) {
|
|
|
- output += 4.0 * (a1Total / b1Total)
|
|
|
- }
|
|
|
- if !(((-(0.00000000000001)) < b2Total) && (b2Total < (0.00000000000001))) {
|
|
|
- output += 2.0 * (a2Total / b2Total)
|
|
|
- }
|
|
|
- if !(((-(0.00000000000001)) < b3Total) && (b3Total < (0.00000000000001))) {
|
|
|
- output += a3Total / b3Total
|
|
|
- }
|
|
|
- tempLT = inLow[trailingIdx1]
|
|
|
- tempHT = inHigh[trailingIdx1]
|
|
|
- tempCY = inClose[trailingIdx1-1]
|
|
|
- trueLow = 0.0
|
|
|
- if tempLT < tempCY {
|
|
|
- trueLow = tempLT
|
|
|
- } else {
|
|
|
- trueLow = tempCY
|
|
|
- }
|
|
|
- closeMinusTrueLow = inClose[trailingIdx1] - trueLow
|
|
|
- trueRange = tempHT - tempLT
|
|
|
- tempDouble = math.Abs(tempCY - tempHT)
|
|
|
- if tempDouble > trueRange {
|
|
|
- trueRange = tempDouble
|
|
|
- }
|
|
|
- tempDouble = math.Abs(tempCY - tempLT)
|
|
|
- if tempDouble > trueRange {
|
|
|
- trueRange = tempDouble
|
|
|
- }
|
|
|
-
|
|
|
- a1Total -= closeMinusTrueLow
|
|
|
- b1Total -= trueRange
|
|
|
- tempLT = inLow[trailingIdx2]
|
|
|
- tempHT = inHigh[trailingIdx2]
|
|
|
- tempCY = inClose[trailingIdx2-1]
|
|
|
- trueLow = 0.0
|
|
|
- if tempLT < tempCY {
|
|
|
- trueLow = tempLT
|
|
|
- } else {
|
|
|
- trueLow = tempCY
|
|
|
- }
|
|
|
- closeMinusTrueLow = inClose[trailingIdx2] - trueLow
|
|
|
- trueRange = tempHT - tempLT
|
|
|
- tempDouble = math.Abs(tempCY - tempHT)
|
|
|
- if tempDouble > trueRange {
|
|
|
- trueRange = tempDouble
|
|
|
- }
|
|
|
- tempDouble = math.Abs(tempCY - tempLT)
|
|
|
- if tempDouble > trueRange {
|
|
|
- trueRange = tempDouble
|
|
|
- }
|
|
|
-
|
|
|
- a2Total -= closeMinusTrueLow
|
|
|
- b2Total -= trueRange
|
|
|
- tempLT = inLow[trailingIdx3]
|
|
|
- tempHT = inHigh[trailingIdx3]
|
|
|
- tempCY = inClose[trailingIdx3-1]
|
|
|
- trueLow = 0.0
|
|
|
- if tempLT < tempCY {
|
|
|
- trueLow = tempLT
|
|
|
- } else {
|
|
|
- trueLow = tempCY
|
|
|
- }
|
|
|
- closeMinusTrueLow = inClose[trailingIdx3] - trueLow
|
|
|
- trueRange = tempHT - tempLT
|
|
|
- tempDouble = math.Abs(tempCY - tempHT)
|
|
|
- if tempDouble > trueRange {
|
|
|
- trueRange = tempDouble
|
|
|
- }
|
|
|
- tempDouble = math.Abs(tempCY - tempLT)
|
|
|
- if tempDouble > trueRange {
|
|
|
- trueRange = tempDouble
|
|
|
- }
|
|
|
-
|
|
|
- a3Total -= closeMinusTrueLow
|
|
|
- b3Total -= trueRange
|
|
|
- outReal[outIdx] = 100.0 * (output / 7.0)
|
|
|
- outIdx++
|
|
|
- today++
|
|
|
- trailingIdx1++
|
|
|
- trailingIdx2++
|
|
|
- trailingIdx3++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// WillR - Williams' %R
|
|
|
-func WillR(inHigh []float64, inLow []float64, inClose []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inClose))
|
|
|
- nbInitialElementNeeded := (inTimePeriod - 1)
|
|
|
- diff := 0.0
|
|
|
- outIdx := inTimePeriod - 1
|
|
|
- startIdx := inTimePeriod - 1
|
|
|
- today := startIdx
|
|
|
- trailingIdx := startIdx - nbInitialElementNeeded
|
|
|
- highestIdx := -1
|
|
|
- lowestIdx := -1
|
|
|
- highest := 0.0
|
|
|
- lowest := 0.0
|
|
|
- i := 0
|
|
|
- for today < len(inClose) {
|
|
|
- tmp := inLow[today]
|
|
|
- if lowestIdx < trailingIdx {
|
|
|
- lowestIdx = trailingIdx
|
|
|
- lowest = inLow[lowestIdx]
|
|
|
- i = lowestIdx
|
|
|
- i++
|
|
|
- for i <= today {
|
|
|
- tmp = inLow[i]
|
|
|
- if tmp < lowest {
|
|
|
- lowestIdx = i
|
|
|
- lowest = tmp
|
|
|
- }
|
|
|
- i++
|
|
|
- }
|
|
|
- diff = (highest - lowest) / (-100.0)
|
|
|
- } else if tmp <= lowest {
|
|
|
- lowestIdx = today
|
|
|
- lowest = tmp
|
|
|
- diff = (highest - lowest) / (-100.0)
|
|
|
- }
|
|
|
- tmp = inHigh[today]
|
|
|
- if highestIdx < trailingIdx {
|
|
|
- highestIdx = trailingIdx
|
|
|
- highest = inHigh[highestIdx]
|
|
|
- i = highestIdx
|
|
|
- i++
|
|
|
- for i <= today {
|
|
|
- tmp = inHigh[i]
|
|
|
- if tmp > highest {
|
|
|
- highestIdx = i
|
|
|
- highest = tmp
|
|
|
- }
|
|
|
- i++
|
|
|
- }
|
|
|
- diff = (highest - lowest) / (-100.0)
|
|
|
- } else if tmp >= highest {
|
|
|
- highestIdx = today
|
|
|
- highest = tmp
|
|
|
- diff = (highest - lowest) / (-100.0)
|
|
|
- }
|
|
|
- if diff != 0.0 {
|
|
|
- outReal[outIdx] = (highest - inClose[today]) / diff
|
|
|
- } else {
|
|
|
- outReal[outIdx] = 0.0
|
|
|
- }
|
|
|
- outIdx++
|
|
|
- trailingIdx++
|
|
|
- today++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-/* Volume Indicators */
|
|
|
-
|
|
|
-// Ad - Chaikin A/D Line
|
|
|
-func Ad(inHigh []float64, inLow []float64, inClose []float64, inVolume []float64) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inClose))
|
|
|
-
|
|
|
- startIdx := 0
|
|
|
- nbBar := len(inClose) - startIdx
|
|
|
- currentBar := startIdx
|
|
|
- outIdx := 0
|
|
|
- ad := 0.0
|
|
|
- for nbBar != 0 {
|
|
|
- high := inHigh[currentBar]
|
|
|
- low := inLow[currentBar]
|
|
|
- tmp := high - low
|
|
|
- close := inClose[currentBar]
|
|
|
- if tmp > 0.0 {
|
|
|
- ad += (((close - low) - (high - close)) / tmp) * (inVolume[currentBar])
|
|
|
- }
|
|
|
- outReal[outIdx] = ad
|
|
|
- outIdx++
|
|
|
- currentBar++
|
|
|
- nbBar--
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// AdOsc - Chaikin A/D Oscillator
|
|
|
-func AdOsc(inHigh []float64, inLow []float64, inClose []float64, inVolume []float64, inFastPeriod int, inSlowPeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inClose))
|
|
|
-
|
|
|
- if (inFastPeriod < 2) || (inSlowPeriod < 2) {
|
|
|
- return outReal
|
|
|
- }
|
|
|
-
|
|
|
- slowestPeriod := 0
|
|
|
- if inFastPeriod < inSlowPeriod {
|
|
|
- slowestPeriod = inSlowPeriod
|
|
|
- } else {
|
|
|
- slowestPeriod = inFastPeriod
|
|
|
- }
|
|
|
- lookbackTotal := slowestPeriod - 1
|
|
|
- startIdx := lookbackTotal
|
|
|
- today := startIdx - lookbackTotal
|
|
|
- ad := 0.0
|
|
|
- fastk := (2.0 / (float64(inFastPeriod) + 1.0))
|
|
|
- oneMinusfastk := 1.0 - fastk
|
|
|
- slowk := (2.0 / (float64(inSlowPeriod) + 1.0))
|
|
|
- oneMinusslowk := 1.0 - slowk
|
|
|
- high := inHigh[today]
|
|
|
- low := inLow[today]
|
|
|
- tmp := high - low
|
|
|
- close := inClose[today]
|
|
|
- if tmp > 0.0 {
|
|
|
- ad += (((close - low) - (high - close)) / tmp) * (inVolume[today])
|
|
|
- }
|
|
|
- today++
|
|
|
- fastEMA := ad
|
|
|
- slowEMA := ad
|
|
|
-
|
|
|
- for today < startIdx {
|
|
|
- high = inHigh[today]
|
|
|
- low = inLow[today]
|
|
|
- tmp = high - low
|
|
|
- close = inClose[today]
|
|
|
- if tmp > 0.0 {
|
|
|
- ad += (((close - low) - (high - close)) / tmp) * (inVolume[today])
|
|
|
- }
|
|
|
- today++
|
|
|
-
|
|
|
- fastEMA = (fastk * ad) + (oneMinusfastk * fastEMA)
|
|
|
- slowEMA = (slowk * ad) + (oneMinusslowk * slowEMA)
|
|
|
- }
|
|
|
- outIdx := lookbackTotal
|
|
|
- for today < len(inClose) {
|
|
|
- high = inHigh[today]
|
|
|
- low = inLow[today]
|
|
|
- tmp = high - low
|
|
|
- close = inClose[today]
|
|
|
- if tmp > 0.0 {
|
|
|
- ad += (((close - low) - (high - close)) / tmp) * (inVolume[today])
|
|
|
- }
|
|
|
- today++
|
|
|
- fastEMA = (fastk * ad) + (oneMinusfastk * fastEMA)
|
|
|
- slowEMA = (slowk * ad) + (oneMinusslowk * slowEMA)
|
|
|
- outReal[outIdx] = fastEMA - slowEMA
|
|
|
- outIdx++
|
|
|
- }
|
|
|
-
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Obv - On Balance Volume
|
|
|
-func Obv(inReal []float64, inVolume []float64) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
- startIdx := 0
|
|
|
- prevOBV := inVolume[startIdx]
|
|
|
- prevReal := inReal[startIdx]
|
|
|
- outIdx := 0
|
|
|
- for i := startIdx; i < len(inReal); i++ {
|
|
|
- tempReal := inReal[i]
|
|
|
- if tempReal > prevReal {
|
|
|
- prevOBV += inVolume[i]
|
|
|
- } else if tempReal < prevReal {
|
|
|
- prevOBV -= inVolume[i]
|
|
|
- }
|
|
|
- outReal[outIdx] = prevOBV
|
|
|
- prevReal = tempReal
|
|
|
- outIdx++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-/* Volatility Indicators */
|
|
|
-
|
|
|
-// Atr - Average True Range
|
|
|
-func Atr(inHigh []float64, inLow []float64, inClose []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inClose))
|
|
|
-
|
|
|
- inTimePeriodF := float64(inTimePeriod)
|
|
|
-
|
|
|
- if inTimePeriod < 1 {
|
|
|
- return outReal
|
|
|
- }
|
|
|
-
|
|
|
- if inTimePeriod <= 1 {
|
|
|
- return TRange(inHigh, inLow, inClose)
|
|
|
- }
|
|
|
-
|
|
|
- outIdx := inTimePeriod
|
|
|
- today := inTimePeriod + 1
|
|
|
-
|
|
|
- tr := TRange(inHigh, inLow, inClose)
|
|
|
- prevATRTemp := Sma(tr, inTimePeriod)
|
|
|
- prevATR := prevATRTemp[inTimePeriod]
|
|
|
- outReal[inTimePeriod] = prevATR
|
|
|
-
|
|
|
- for outIdx = inTimePeriod + 1; outIdx < len(inClose); outIdx++ {
|
|
|
- prevATR *= inTimePeriodF - 1.0
|
|
|
- prevATR += tr[today]
|
|
|
- prevATR /= inTimePeriodF
|
|
|
- outReal[outIdx] = prevATR
|
|
|
- today++
|
|
|
- }
|
|
|
-
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Natr - Normalized Average True Range
|
|
|
-func Natr(inHigh []float64, inLow []float64, inClose []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inClose))
|
|
|
-
|
|
|
- if inTimePeriod < 1 {
|
|
|
- return outReal
|
|
|
- }
|
|
|
-
|
|
|
- if inTimePeriod <= 1 {
|
|
|
- return TRange(inHigh, inLow, inClose)
|
|
|
- }
|
|
|
-
|
|
|
- inTimePeriodF := float64(inTimePeriod)
|
|
|
- outIdx := inTimePeriod
|
|
|
- today := inTimePeriod
|
|
|
-
|
|
|
- tr := TRange(inHigh, inLow, inClose)
|
|
|
- prevATRTemp := Sma(tr, inTimePeriod)
|
|
|
- prevATR := prevATRTemp[inTimePeriod]
|
|
|
-
|
|
|
- tempValue := inClose[today]
|
|
|
- if tempValue != 0.0 {
|
|
|
- outReal[outIdx] = (prevATR / tempValue) * 100.0
|
|
|
- } else {
|
|
|
- outReal[outIdx] = 0.0
|
|
|
- }
|
|
|
-
|
|
|
- for outIdx = inTimePeriod + 1; outIdx < len(inClose); outIdx++ {
|
|
|
- today++
|
|
|
- prevATR *= inTimePeriodF - 1.0
|
|
|
- prevATR += tr[today]
|
|
|
- prevATR /= inTimePeriodF
|
|
|
- tempValue = inClose[today]
|
|
|
- if tempValue != 0.0 {
|
|
|
- outReal[outIdx] = (prevATR / tempValue) * 100.0
|
|
|
- } else {
|
|
|
- outReal[0] = 0.0
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// TRange - True Range
|
|
|
-func TRange(inHigh []float64, inLow []float64, inClose []float64) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inClose))
|
|
|
-
|
|
|
- startIdx := 1
|
|
|
- outIdx := startIdx
|
|
|
- today := startIdx
|
|
|
- for today < len(inClose) {
|
|
|
- tempLT := inLow[today]
|
|
|
- tempHT := inHigh[today]
|
|
|
- tempCY := inClose[today-1]
|
|
|
- greatest := tempHT - tempLT
|
|
|
- val2 := math.Abs(tempCY - tempHT)
|
|
|
- if val2 > greatest {
|
|
|
- greatest = val2
|
|
|
- }
|
|
|
- val3 := math.Abs(tempCY - tempLT)
|
|
|
- if val3 > greatest {
|
|
|
- greatest = val3
|
|
|
- }
|
|
|
- outReal[outIdx] = greatest
|
|
|
- outIdx++
|
|
|
- today++
|
|
|
- }
|
|
|
-
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-/* Price Transform */
|
|
|
-
|
|
|
-// AvgPrice - Average Price (o+h+l+c)/4
|
|
|
-func AvgPrice(inOpen []float64, inHigh []float64, inLow []float64, inClose []float64) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inClose))
|
|
|
- outIdx := 0
|
|
|
- startIdx := 0
|
|
|
-
|
|
|
- for i := startIdx; i < len(inClose); i++ {
|
|
|
- outReal[outIdx] = (inHigh[i] + inLow[i] + inClose[i] + inOpen[i]) / 4
|
|
|
- outIdx++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// MedPrice - Median Price (h+l)/2
|
|
|
-func MedPrice(inHigh []float64, inLow []float64) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inHigh))
|
|
|
- outIdx := 0
|
|
|
- startIdx := 0
|
|
|
-
|
|
|
- for i := startIdx; i < len(inHigh); i++ {
|
|
|
- outReal[outIdx] = (inHigh[i] + inLow[i]) / 2.0
|
|
|
- outIdx++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// TypPrice - Typical Price (h+l+c)/3
|
|
|
-func TypPrice(inHigh []float64, inLow []float64, inClose []float64) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inClose))
|
|
|
- outIdx := 0
|
|
|
- startIdx := 0
|
|
|
-
|
|
|
- for i := startIdx; i < len(inClose); i++ {
|
|
|
- outReal[outIdx] = (inHigh[i] + inLow[i] + inClose[i]) / 3.0
|
|
|
- outIdx++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// WclPrice - Weighted Close Price
|
|
|
-func WclPrice(inHigh []float64, inLow []float64, inClose []float64) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inClose))
|
|
|
- outIdx := 0
|
|
|
- startIdx := 0
|
|
|
-
|
|
|
- for i := startIdx; i < len(inClose); i++ {
|
|
|
- outReal[outIdx] = (inHigh[i] + inLow[i] + (inClose[i] * 2.0)) / 4.0
|
|
|
- outIdx++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-/* Cycle Indicators */
|
|
|
-
|
|
|
-// HtDcPeriod - Hilbert Transform - Dominant Cycle Period (lookback=32)
|
|
|
-func HtDcPeriod(inReal []float64) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
-
|
|
|
- a := 0.0962
|
|
|
- b := 0.5769
|
|
|
- detrenderOdd := make([]float64, 3)
|
|
|
- detrenderEven := make([]float64, 3)
|
|
|
- q1Odd := make([]float64, 3)
|
|
|
- q1Even := make([]float64, 3)
|
|
|
- jIOdd := make([]float64, 3)
|
|
|
- jIEven := make([]float64, 3)
|
|
|
- jQOdd := make([]float64, 3)
|
|
|
- jQEven := make([]float64, 3)
|
|
|
- rad2Deg := 180.0 / (4.0 * math.Atan(1))
|
|
|
- lookbackTotal := 32
|
|
|
- startIdx := lookbackTotal
|
|
|
- trailingWMAIdx := startIdx - lookbackTotal
|
|
|
- today := trailingWMAIdx
|
|
|
- tempReal := inReal[today]
|
|
|
- today++
|
|
|
- periodWMASub := tempReal
|
|
|
- periodWMASum := tempReal
|
|
|
- tempReal = inReal[today]
|
|
|
- today++
|
|
|
- periodWMASub += tempReal
|
|
|
- periodWMASum += tempReal * 2.0
|
|
|
- tempReal = inReal[today]
|
|
|
- today++
|
|
|
- periodWMASub += tempReal
|
|
|
- periodWMASum += tempReal * 3.0
|
|
|
- trailingWMAValue := 0.0
|
|
|
- i := 9
|
|
|
- smoothedValue := 0.0
|
|
|
- for ok := true; ok; {
|
|
|
- tempReal = inReal[today]
|
|
|
- today++
|
|
|
- periodWMASub += tempReal
|
|
|
- periodWMASub -= trailingWMAValue
|
|
|
- periodWMASum += tempReal * 4.0
|
|
|
- trailingWMAValue = inReal[trailingWMAIdx]
|
|
|
- trailingWMAIdx++
|
|
|
- smoothedValue = periodWMASum * 0.1
|
|
|
- periodWMASum -= periodWMASub
|
|
|
- i--
|
|
|
- ok = i != 0
|
|
|
- }
|
|
|
-
|
|
|
- hilbertIdx := 0
|
|
|
- detrender := 0.0
|
|
|
- prevDetrenderOdd := 0.0
|
|
|
- prevDetrenderEven := 0.0
|
|
|
- prevDetrenderInputOdd := 0.0
|
|
|
- prevDetrenderInputEven := 0.0
|
|
|
- q1 := 0.0
|
|
|
- prevq1Odd := 0.0
|
|
|
- prevq1Even := 0.0
|
|
|
- prevq1InputOdd := 0.0
|
|
|
- prevq1InputEven := 0.0
|
|
|
- jI := 0.0
|
|
|
- prevJIOdd := 0.0
|
|
|
- prevJIEven := 0.0
|
|
|
- prevJIInputOdd := 0.0
|
|
|
- prevJIInputEven := 0.0
|
|
|
- jQ := 0.0
|
|
|
- prevJQOdd := 0.0
|
|
|
- prevJQEven := 0.0
|
|
|
- prevJQInputOdd := 0.0
|
|
|
- prevJQInputEven := 0.0
|
|
|
- period := 0.0
|
|
|
- outIdx := 32
|
|
|
- previ2 := 0.0
|
|
|
- prevq2 := 0.0
|
|
|
- Re := 0.0
|
|
|
- Im := 0.0
|
|
|
- i2 := 0.0
|
|
|
- q2 := 0.0
|
|
|
- i1ForOddPrev3 := 0.0
|
|
|
- i1ForEvenPrev3 := 0.0
|
|
|
- i1ForOddPrev2 := 0.0
|
|
|
- i1ForEvenPrev2 := 0.0
|
|
|
- smoothPeriod := 0.0
|
|
|
- for today < len(inReal) {
|
|
|
- adjustedPrevPeriod := (0.075 * period) + 0.54
|
|
|
- todayValue := inReal[today]
|
|
|
- periodWMASub += todayValue
|
|
|
- periodWMASub -= trailingWMAValue
|
|
|
- periodWMASum += todayValue * 4.0
|
|
|
- trailingWMAValue = inReal[trailingWMAIdx]
|
|
|
- trailingWMAIdx++
|
|
|
- smoothedValue = periodWMASum * 0.1
|
|
|
- periodWMASum -= periodWMASub
|
|
|
- hilbertTempReal := 0.0
|
|
|
- if (today % 2) == 0 {
|
|
|
- hilbertTempReal = a * smoothedValue
|
|
|
- detrender = -detrenderEven[hilbertIdx]
|
|
|
- detrenderEven[hilbertIdx] = hilbertTempReal
|
|
|
- detrender += hilbertTempReal
|
|
|
- detrender -= prevDetrenderEven
|
|
|
- prevDetrenderEven = b * prevDetrenderInputEven
|
|
|
- detrender += prevDetrenderEven
|
|
|
- prevDetrenderInputEven = smoothedValue
|
|
|
- detrender *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * detrender
|
|
|
- q1 = -q1Even[hilbertIdx]
|
|
|
- q1Even[hilbertIdx] = hilbertTempReal
|
|
|
- q1 += hilbertTempReal
|
|
|
- q1 -= prevq1Even
|
|
|
- prevq1Even = b * prevq1InputEven
|
|
|
- q1 += prevq1Even
|
|
|
- prevq1InputEven = detrender
|
|
|
- q1 *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * i1ForEvenPrev3
|
|
|
- jI = -jIEven[hilbertIdx]
|
|
|
- jIEven[hilbertIdx] = hilbertTempReal
|
|
|
- jI += hilbertTempReal
|
|
|
- jI -= prevJIEven
|
|
|
- prevJIEven = b * prevJIInputEven
|
|
|
- jI += prevJIEven
|
|
|
- prevJIInputEven = i1ForEvenPrev3
|
|
|
- jI *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * q1
|
|
|
- jQ = -jQEven[hilbertIdx]
|
|
|
- jQEven[hilbertIdx] = hilbertTempReal
|
|
|
- jQ += hilbertTempReal
|
|
|
- jQ -= prevJQEven
|
|
|
- prevJQEven = b * prevJQInputEven
|
|
|
- jQ += prevJQEven
|
|
|
- prevJQInputEven = q1
|
|
|
- jQ *= adjustedPrevPeriod
|
|
|
- hilbertIdx++
|
|
|
- if hilbertIdx == 3 {
|
|
|
- hilbertIdx = 0
|
|
|
- }
|
|
|
- q2 = (0.2 * (q1 + jI)) + (0.8 * prevq2)
|
|
|
- i2 = (0.2 * (i1ForEvenPrev3 - jQ)) + (0.8 * previ2)
|
|
|
- i1ForOddPrev3 = i1ForOddPrev2
|
|
|
- i1ForOddPrev2 = detrender
|
|
|
- } else {
|
|
|
- hilbertTempReal = a * smoothedValue
|
|
|
- detrender = -detrenderOdd[hilbertIdx]
|
|
|
- detrenderOdd[hilbertIdx] = hilbertTempReal
|
|
|
- detrender += hilbertTempReal
|
|
|
- detrender -= prevDetrenderOdd
|
|
|
- prevDetrenderOdd = b * prevDetrenderInputOdd
|
|
|
- detrender += prevDetrenderOdd
|
|
|
- prevDetrenderInputOdd = smoothedValue
|
|
|
- detrender *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * detrender
|
|
|
- q1 = -q1Odd[hilbertIdx]
|
|
|
- q1Odd[hilbertIdx] = hilbertTempReal
|
|
|
- q1 += hilbertTempReal
|
|
|
- q1 -= prevq1Odd
|
|
|
- prevq1Odd = b * prevq1InputOdd
|
|
|
- q1 += prevq1Odd
|
|
|
- prevq1InputOdd = detrender
|
|
|
- q1 *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * i1ForOddPrev3
|
|
|
- jI = -jIOdd[hilbertIdx]
|
|
|
- jIOdd[hilbertIdx] = hilbertTempReal
|
|
|
- jI += hilbertTempReal
|
|
|
- jI -= prevJIOdd
|
|
|
- prevJIOdd = b * prevJIInputOdd
|
|
|
- jI += prevJIOdd
|
|
|
- prevJIInputOdd = i1ForOddPrev3
|
|
|
- jI *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * q1
|
|
|
- jQ = -jQOdd[hilbertIdx]
|
|
|
- jQOdd[hilbertIdx] = hilbertTempReal
|
|
|
- jQ += hilbertTempReal
|
|
|
- jQ -= prevJQOdd
|
|
|
- prevJQOdd = b * prevJQInputOdd
|
|
|
- jQ += prevJQOdd
|
|
|
- prevJQInputOdd = q1
|
|
|
- jQ *= adjustedPrevPeriod
|
|
|
- q2 = (0.2 * (q1 + jI)) + (0.8 * prevq2)
|
|
|
- i2 = (0.2 * (i1ForOddPrev3 - jQ)) + (0.8 * previ2)
|
|
|
- i1ForEvenPrev3 = i1ForEvenPrev2
|
|
|
- i1ForEvenPrev2 = detrender
|
|
|
- }
|
|
|
- Re = (0.2 * ((i2 * previ2) + (q2 * prevq2))) + (0.8 * Re)
|
|
|
- Im = (0.2 * ((i2 * prevq2) - (q2 * previ2))) + (0.8 * Im)
|
|
|
- prevq2 = q2
|
|
|
- previ2 = i2
|
|
|
- tempReal = period
|
|
|
- if (Im != 0.0) && (Re != 0.0) {
|
|
|
- period = 360.0 / (math.Atan(Im/Re) * rad2Deg)
|
|
|
- }
|
|
|
- tempReal2 := 1.5 * tempReal
|
|
|
- if period > tempReal2 {
|
|
|
- period = tempReal2
|
|
|
- }
|
|
|
- tempReal2 = 0.67 * tempReal
|
|
|
- if period < tempReal2 {
|
|
|
- period = tempReal2
|
|
|
- }
|
|
|
- if period < 6 {
|
|
|
- period = 6
|
|
|
- } else if period > 50 {
|
|
|
- period = 50
|
|
|
- }
|
|
|
- period = (0.2 * period) + (0.8 * tempReal)
|
|
|
- smoothPeriod = (0.33 * period) + (0.67 * smoothPeriod)
|
|
|
- if today >= startIdx {
|
|
|
- outReal[outIdx] = smoothPeriod
|
|
|
- outIdx++
|
|
|
- }
|
|
|
- today++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// HtDcPhase - Hilbert Transform - Dominant Cycle Phase (lookback=63)
|
|
|
-func HtDcPhase(inReal []float64) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
- a := 0.0962
|
|
|
- b := 0.5769
|
|
|
- detrenderOdd := make([]float64, 3)
|
|
|
- detrenderEven := make([]float64, 3)
|
|
|
- q1Odd := make([]float64, 3)
|
|
|
- q1Even := make([]float64, 3)
|
|
|
- jIOdd := make([]float64, 3)
|
|
|
- jIEven := make([]float64, 3)
|
|
|
- jQOdd := make([]float64, 3)
|
|
|
- jQEven := make([]float64, 3)
|
|
|
- smoothPriceIdx := 0
|
|
|
- maxIdxSmoothPrice := (50 - 1)
|
|
|
- smoothPrice := make([]float64, maxIdxSmoothPrice+1)
|
|
|
- tempReal := math.Atan(1)
|
|
|
- rad2Deg := 45.0 / tempReal
|
|
|
- constDeg2RadBy360 := tempReal * 8.0
|
|
|
- lookbackTotal := 63
|
|
|
- startIdx := lookbackTotal
|
|
|
- trailingWMAIdx := startIdx - lookbackTotal
|
|
|
- today := trailingWMAIdx
|
|
|
- tempReal = inReal[today]
|
|
|
- today++
|
|
|
- periodWMASub := tempReal
|
|
|
- periodWMASum := tempReal
|
|
|
- tempReal = inReal[today]
|
|
|
- today++
|
|
|
- periodWMASub += tempReal
|
|
|
- periodWMASum += tempReal * 2.0
|
|
|
- tempReal = inReal[today]
|
|
|
- today++
|
|
|
- periodWMASub += tempReal
|
|
|
- periodWMASum += tempReal * 3.0
|
|
|
- trailingWMAValue := 0.0
|
|
|
- i := 34
|
|
|
- smoothedValue := 0.0
|
|
|
- for ok := true; ok; {
|
|
|
- tempReal = inReal[today]
|
|
|
- today++
|
|
|
- periodWMASub += tempReal
|
|
|
- periodWMASub -= trailingWMAValue
|
|
|
- periodWMASum += tempReal * 4.0
|
|
|
- trailingWMAValue = inReal[trailingWMAIdx]
|
|
|
- trailingWMAIdx++
|
|
|
- smoothedValue = periodWMASum * 0.1
|
|
|
- periodWMASum -= periodWMASub
|
|
|
- i--
|
|
|
- ok = i != 0
|
|
|
- }
|
|
|
-
|
|
|
- hilbertIdx := 0
|
|
|
- detrender := 0.0
|
|
|
- prevDetrenderOdd := 0.0
|
|
|
- prevDetrenderEven := 0.0
|
|
|
- prevDetrenderInputOdd := 0.0
|
|
|
- prevDetrenderInputEven := 0.0
|
|
|
- q1 := 0.0
|
|
|
- prevq1Odd := 0.0
|
|
|
- prevq1Even := 0.0
|
|
|
- prevq1InputOdd := 0.0
|
|
|
- prevq1InputEven := 0.0
|
|
|
- jI := 0.0
|
|
|
- prevJIOdd := 0.0
|
|
|
- prevJIEven := 0.0
|
|
|
- prevJIInputOdd := 0.0
|
|
|
- prevJIInputEven := 0.0
|
|
|
- jQ := 0.0
|
|
|
- prevJQOdd := 0.0
|
|
|
- prevJQEven := 0.0
|
|
|
- prevJQInputOdd := 0.0
|
|
|
- prevJQInputEven := 0.0
|
|
|
- period := 0.0
|
|
|
- outIdx := 0
|
|
|
- previ2 := 0.0
|
|
|
- prevq2 := 0.0
|
|
|
- Re := 0.0
|
|
|
- Im := 0.0
|
|
|
- i1ForOddPrev3 := 0.0
|
|
|
- i1ForEvenPrev3 := 0.0
|
|
|
- i1ForOddPrev2 := 0.0
|
|
|
- i1ForEvenPrev2 := 0.0
|
|
|
- smoothPeriod := 0.0
|
|
|
- dcPhase := 0.0
|
|
|
- q2 := 0.0
|
|
|
- i2 := 0.0
|
|
|
- for today < len(inReal) {
|
|
|
- adjustedPrevPeriod := (0.075 * period) + 0.54
|
|
|
- todayValue := inReal[today]
|
|
|
- periodWMASub += todayValue
|
|
|
- periodWMASub -= trailingWMAValue
|
|
|
- periodWMASum += todayValue * 4.0
|
|
|
- trailingWMAValue = inReal[trailingWMAIdx]
|
|
|
- trailingWMAIdx++
|
|
|
- smoothedValue = periodWMASum * 0.1
|
|
|
- periodWMASum -= periodWMASub
|
|
|
- hilbertTempReal := 0.0
|
|
|
- smoothPrice[smoothPriceIdx] = smoothedValue
|
|
|
- if (today % 2) == 0 {
|
|
|
- hilbertTempReal = a * smoothedValue
|
|
|
- detrender = -detrenderEven[hilbertIdx]
|
|
|
- detrenderEven[hilbertIdx] = hilbertTempReal
|
|
|
- detrender += hilbertTempReal
|
|
|
- detrender -= prevDetrenderEven
|
|
|
- prevDetrenderEven = b * prevDetrenderInputEven
|
|
|
- detrender += prevDetrenderEven
|
|
|
- prevDetrenderInputEven = smoothedValue
|
|
|
- detrender *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * detrender
|
|
|
- q1 = -q1Even[hilbertIdx]
|
|
|
- q1Even[hilbertIdx] = hilbertTempReal
|
|
|
- q1 += hilbertTempReal
|
|
|
- q1 -= prevq1Even
|
|
|
- prevq1Even = b * prevq1InputEven
|
|
|
- q1 += prevq1Even
|
|
|
- prevq1InputEven = detrender
|
|
|
- q1 *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * i1ForEvenPrev3
|
|
|
- jI = -jIEven[hilbertIdx]
|
|
|
- jIEven[hilbertIdx] = hilbertTempReal
|
|
|
- jI += hilbertTempReal
|
|
|
- jI -= prevJIEven
|
|
|
- prevJIEven = b * prevJIInputEven
|
|
|
- jI += prevJIEven
|
|
|
- prevJIInputEven = i1ForEvenPrev3
|
|
|
- jI *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * q1
|
|
|
- jQ = -jQEven[hilbertIdx]
|
|
|
- jQEven[hilbertIdx] = hilbertTempReal
|
|
|
- jQ += hilbertTempReal
|
|
|
- jQ -= prevJQEven
|
|
|
- prevJQEven = b * prevJQInputEven
|
|
|
- jQ += prevJQEven
|
|
|
- prevJQInputEven = q1
|
|
|
- jQ *= adjustedPrevPeriod
|
|
|
- hilbertIdx++
|
|
|
- if hilbertIdx == 3 {
|
|
|
- hilbertIdx = 0
|
|
|
- }
|
|
|
- q2 = (0.2 * (q1 + jI)) + (0.8 * prevq2)
|
|
|
- i2 = (0.2 * (i1ForEvenPrev3 - jQ)) + (0.8 * previ2)
|
|
|
- i1ForOddPrev3 = i1ForOddPrev2
|
|
|
- i1ForOddPrev2 = detrender
|
|
|
- } else {
|
|
|
-
|
|
|
- hilbertTempReal = a * smoothedValue
|
|
|
- detrender = -detrenderOdd[hilbertIdx]
|
|
|
- detrenderOdd[hilbertIdx] = hilbertTempReal
|
|
|
- detrender += hilbertTempReal
|
|
|
- detrender -= prevDetrenderOdd
|
|
|
- prevDetrenderOdd = b * prevDetrenderInputOdd
|
|
|
- detrender += prevDetrenderOdd
|
|
|
- prevDetrenderInputOdd = smoothedValue
|
|
|
- detrender *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * detrender
|
|
|
- q1 = -q1Odd[hilbertIdx]
|
|
|
- q1Odd[hilbertIdx] = hilbertTempReal
|
|
|
- q1 += hilbertTempReal
|
|
|
- q1 -= prevq1Odd
|
|
|
- prevq1Odd = b * prevq1InputOdd
|
|
|
- q1 += prevq1Odd
|
|
|
- prevq1InputOdd = detrender
|
|
|
- q1 *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * i1ForOddPrev3
|
|
|
- jI = -jIOdd[hilbertIdx]
|
|
|
- jIOdd[hilbertIdx] = hilbertTempReal
|
|
|
- jI += hilbertTempReal
|
|
|
- jI -= prevJIOdd
|
|
|
- prevJIOdd = b * prevJIInputOdd
|
|
|
- jI += prevJIOdd
|
|
|
- prevJIInputOdd = i1ForOddPrev3
|
|
|
- jI *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * q1
|
|
|
- jQ = -jQOdd[hilbertIdx]
|
|
|
- jQOdd[hilbertIdx] = hilbertTempReal
|
|
|
- jQ += hilbertTempReal
|
|
|
- jQ -= prevJQOdd
|
|
|
- prevJQOdd = b * prevJQInputOdd
|
|
|
- jQ += prevJQOdd
|
|
|
- prevJQInputOdd = q1
|
|
|
- jQ *= adjustedPrevPeriod
|
|
|
- q2 = (0.2 * (q1 + jI)) + (0.8 * prevq2)
|
|
|
- i2 = (0.2 * (i1ForOddPrev3 - jQ)) + (0.8 * previ2)
|
|
|
- i1ForEvenPrev3 = i1ForEvenPrev2
|
|
|
- i1ForEvenPrev2 = detrender
|
|
|
- }
|
|
|
- Re = (0.2 * ((i2 * previ2) + (q2 * prevq2))) + (0.8 * Re)
|
|
|
- Im = (0.2 * ((i2 * prevq2) - (q2 * previ2))) + (0.8 * Im)
|
|
|
- prevq2 = q2
|
|
|
- previ2 = i2
|
|
|
- tempReal = period
|
|
|
- if (Im != 0.0) && (Re != 0.0) {
|
|
|
- period = 360.0 / (math.Atan(Im/Re) * rad2Deg)
|
|
|
- }
|
|
|
- tempReal2 := 1.5 * tempReal
|
|
|
- if period > tempReal2 {
|
|
|
- period = tempReal2
|
|
|
- }
|
|
|
- tempReal2 = 0.67 * tempReal
|
|
|
- if period < tempReal2 {
|
|
|
- period = tempReal2
|
|
|
- }
|
|
|
- if period < 6 {
|
|
|
- period = 6
|
|
|
- } else if period > 50 {
|
|
|
- period = 50
|
|
|
- }
|
|
|
- period = (0.2 * period) + (0.8 * tempReal)
|
|
|
- smoothPeriod = (0.33 * period) + (0.67 * smoothPeriod)
|
|
|
- DCPeriod := smoothPeriod + 0.5
|
|
|
- DCPeriodInt := math.Floor(DCPeriod)
|
|
|
- realPart := 0.0
|
|
|
- imagPart := 0.0
|
|
|
- idx := smoothPriceIdx
|
|
|
- for i := 0; i < int(DCPeriodInt); i++ {
|
|
|
- tempReal = (float64(i) * constDeg2RadBy360) / (DCPeriodInt * 1.0)
|
|
|
- tempReal2 = smoothPrice[idx]
|
|
|
- realPart += math.Sin(tempReal) * tempReal2
|
|
|
- imagPart += math.Cos(tempReal) * tempReal2
|
|
|
- if idx == 0 {
|
|
|
- idx = 50 - 1
|
|
|
- } else {
|
|
|
- idx--
|
|
|
- }
|
|
|
- }
|
|
|
- tempReal = math.Abs(imagPart)
|
|
|
- if tempReal > 0.0 {
|
|
|
- dcPhase = math.Atan(realPart/imagPart) * rad2Deg
|
|
|
- } else if tempReal <= 0.01 {
|
|
|
- if realPart < 0.0 {
|
|
|
- dcPhase -= 90.0
|
|
|
- } else if realPart > 0.0 {
|
|
|
- dcPhase += 90.0
|
|
|
- }
|
|
|
- }
|
|
|
- dcPhase += 90.0
|
|
|
- dcPhase += 360.0 / smoothPeriod
|
|
|
- if imagPart < 0.0 {
|
|
|
- dcPhase += 180.0
|
|
|
- }
|
|
|
- if dcPhase > 315.0 {
|
|
|
- dcPhase -= 360.0
|
|
|
- }
|
|
|
- if today >= startIdx {
|
|
|
- outReal[outIdx] = dcPhase
|
|
|
- outIdx++
|
|
|
- }
|
|
|
- smoothPriceIdx++
|
|
|
- if smoothPriceIdx > maxIdxSmoothPrice {
|
|
|
- smoothPriceIdx = 0
|
|
|
- }
|
|
|
-
|
|
|
- today++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// HtPhasor - Hibert Transform - Phasor Components (lookback=32)
|
|
|
-func HtPhasor(inReal []float64) ([]float64, []float64) {
|
|
|
-
|
|
|
- outInPhase := make([]float64, len(inReal))
|
|
|
- outQuadrature := make([]float64, len(inReal))
|
|
|
-
|
|
|
- a := 0.0962
|
|
|
- b := 0.5769
|
|
|
- detrenderOdd := make([]float64, 3)
|
|
|
- detrenderEven := make([]float64, 3)
|
|
|
- q1Odd := make([]float64, 3)
|
|
|
- q1Even := make([]float64, 3)
|
|
|
- jIOdd := make([]float64, 3)
|
|
|
- jIEven := make([]float64, 3)
|
|
|
- jQOdd := make([]float64, 3)
|
|
|
- jQEven := make([]float64, 3)
|
|
|
- rad2Deg := 180.0 / (4.0 * math.Atan(1))
|
|
|
- lookbackTotal := 32
|
|
|
- startIdx := lookbackTotal
|
|
|
- trailingWMAIdx := startIdx - lookbackTotal
|
|
|
- today := trailingWMAIdx
|
|
|
- tempReal := inReal[today]
|
|
|
- today++
|
|
|
- periodWMASub := tempReal
|
|
|
- periodWMASum := tempReal
|
|
|
- tempReal = inReal[today]
|
|
|
- today++
|
|
|
- periodWMASub += tempReal
|
|
|
- periodWMASum += tempReal * 2.0
|
|
|
- tempReal = inReal[today]
|
|
|
- today++
|
|
|
- periodWMASub += tempReal
|
|
|
- periodWMASum += tempReal * 3.0
|
|
|
- trailingWMAValue := 0.0
|
|
|
- i := 9
|
|
|
- smoothedValue := 0.0
|
|
|
- for ok := true; ok; {
|
|
|
- tempReal = inReal[today]
|
|
|
- today++
|
|
|
- periodWMASub += tempReal
|
|
|
- periodWMASub -= trailingWMAValue
|
|
|
- periodWMASum += tempReal * 4.0
|
|
|
- trailingWMAValue = inReal[trailingWMAIdx]
|
|
|
- trailingWMAIdx++
|
|
|
- smoothedValue = periodWMASum * 0.1
|
|
|
- periodWMASum -= periodWMASub
|
|
|
- i--
|
|
|
- ok = i != 0
|
|
|
- }
|
|
|
- hilbertIdx := 0
|
|
|
- detrender := 0.0
|
|
|
- prevDetrenderOdd := 0.0
|
|
|
- prevDetrenderEven := 0.0
|
|
|
- prevDetrenderInputOdd := 0.0
|
|
|
- prevDetrenderInputEven := 0.0
|
|
|
- q1 := 0.0
|
|
|
- prevq1Odd := 0.0
|
|
|
- prevq1Even := 0.0
|
|
|
- prevq1InputOdd := 0.0
|
|
|
- prevq1InputEven := 0.0
|
|
|
- jI := 0.0
|
|
|
- prevJIOdd := 0.0
|
|
|
- prevJIEven := 0.0
|
|
|
- prevJIInputOdd := 0.0
|
|
|
- prevJIInputEven := 0.0
|
|
|
- jQ := 0.0
|
|
|
- prevJQOdd := 0.0
|
|
|
- prevJQEven := 0.0
|
|
|
- prevJQInputOdd := 0.0
|
|
|
- prevJQInputEven := 0.0
|
|
|
- period := 0.0
|
|
|
- outIdx := 32
|
|
|
- previ2 := 0.0
|
|
|
- prevq2 := 0.0
|
|
|
- Re := 0.0
|
|
|
- Im := 0.0
|
|
|
- i1ForOddPrev3 := 0.0
|
|
|
- i1ForEvenPrev3 := 0.0
|
|
|
- i1ForOddPrev2 := 0.0
|
|
|
- i1ForEvenPrev2 := 0.0
|
|
|
- i2 := 0.0
|
|
|
- q2 := 0.0
|
|
|
- for today < len(inReal) {
|
|
|
- adjustedPrevPeriod := (0.075 * period) + 0.54
|
|
|
- todayValue := inReal[today]
|
|
|
- periodWMASub += todayValue
|
|
|
- periodWMASub -= trailingWMAValue
|
|
|
- periodWMASum += todayValue * 4.0
|
|
|
- trailingWMAValue = inReal[trailingWMAIdx]
|
|
|
- trailingWMAIdx++
|
|
|
- smoothedValue = periodWMASum * 0.1
|
|
|
- periodWMASum -= periodWMASub
|
|
|
- hilbertTempReal := 0.0
|
|
|
- if (today % 2) == 0 {
|
|
|
- hilbertTempReal = a * smoothedValue
|
|
|
- detrender = -detrenderEven[hilbertIdx]
|
|
|
- detrenderEven[hilbertIdx] = hilbertTempReal
|
|
|
- detrender += hilbertTempReal
|
|
|
- detrender -= prevDetrenderEven
|
|
|
- prevDetrenderEven = b * prevDetrenderInputEven
|
|
|
- detrender += prevDetrenderEven
|
|
|
- prevDetrenderInputEven = smoothedValue
|
|
|
- detrender *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * detrender
|
|
|
- q1 = -q1Even[hilbertIdx]
|
|
|
- q1Even[hilbertIdx] = hilbertTempReal
|
|
|
- q1 += hilbertTempReal
|
|
|
- q1 -= prevq1Even
|
|
|
- prevq1Even = b * prevq1InputEven
|
|
|
- q1 += prevq1Even
|
|
|
- prevq1InputEven = detrender
|
|
|
- q1 *= adjustedPrevPeriod
|
|
|
-
|
|
|
- if today >= startIdx {
|
|
|
- outQuadrature[outIdx] = q1
|
|
|
- outInPhase[outIdx] = i1ForEvenPrev3
|
|
|
- outIdx++
|
|
|
- }
|
|
|
- hilbertTempReal = a * i1ForEvenPrev3
|
|
|
- jI = -jIEven[hilbertIdx]
|
|
|
- jIEven[hilbertIdx] = hilbertTempReal
|
|
|
- jI += hilbertTempReal
|
|
|
- jI -= prevJIEven
|
|
|
- prevJIEven = b * prevJIInputEven
|
|
|
- jI += prevJIEven
|
|
|
- prevJIInputEven = i1ForEvenPrev3
|
|
|
- jI *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * q1
|
|
|
- jQ = -jQEven[hilbertIdx]
|
|
|
- jQEven[hilbertIdx] = hilbertTempReal
|
|
|
- jQ += hilbertTempReal
|
|
|
- jQ -= prevJQEven
|
|
|
- prevJQEven = b * prevJQInputEven
|
|
|
- jQ += prevJQEven
|
|
|
- prevJQInputEven = q1
|
|
|
- jQ *= adjustedPrevPeriod
|
|
|
- hilbertIdx++
|
|
|
- if hilbertIdx == 3 {
|
|
|
- hilbertIdx = 0
|
|
|
- }
|
|
|
- q2 = (0.2 * (q1 + jI)) + (0.8 * prevq2)
|
|
|
- i2 = (0.2 * (i1ForEvenPrev3 - jQ)) + (0.8 * previ2)
|
|
|
- i1ForOddPrev3 = i1ForOddPrev2
|
|
|
- i1ForOddPrev2 = detrender
|
|
|
- } else {
|
|
|
-
|
|
|
- hilbertTempReal = a * smoothedValue
|
|
|
- detrender = -detrenderOdd[hilbertIdx]
|
|
|
- detrenderOdd[hilbertIdx] = hilbertTempReal
|
|
|
- detrender += hilbertTempReal
|
|
|
- detrender -= prevDetrenderOdd
|
|
|
- prevDetrenderOdd = b * prevDetrenderInputOdd
|
|
|
- detrender += prevDetrenderOdd
|
|
|
- prevDetrenderInputOdd = smoothedValue
|
|
|
- detrender *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * detrender
|
|
|
- q1 = -q1Odd[hilbertIdx]
|
|
|
- q1Odd[hilbertIdx] = hilbertTempReal
|
|
|
- q1 += hilbertTempReal
|
|
|
- q1 -= prevq1Odd
|
|
|
- prevq1Odd = b * prevq1InputOdd
|
|
|
- q1 += prevq1Odd
|
|
|
- prevq1InputOdd = detrender
|
|
|
- q1 *= adjustedPrevPeriod
|
|
|
- if today >= startIdx {
|
|
|
- outQuadrature[outIdx] = q1
|
|
|
- outInPhase[outIdx] = i1ForOddPrev3
|
|
|
- outIdx++
|
|
|
- }
|
|
|
- hilbertTempReal = a * i1ForOddPrev3
|
|
|
- jI = -jIOdd[hilbertIdx]
|
|
|
- jIOdd[hilbertIdx] = hilbertTempReal
|
|
|
- jI += hilbertTempReal
|
|
|
- jI -= prevJIOdd
|
|
|
- prevJIOdd = b * prevJIInputOdd
|
|
|
- jI += prevJIOdd
|
|
|
- prevJIInputOdd = i1ForOddPrev3
|
|
|
- jI *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * q1
|
|
|
- jQ = -jQOdd[hilbertIdx]
|
|
|
- jQOdd[hilbertIdx] = hilbertTempReal
|
|
|
- jQ += hilbertTempReal
|
|
|
- jQ -= prevJQOdd
|
|
|
- prevJQOdd = b * prevJQInputOdd
|
|
|
- jQ += prevJQOdd
|
|
|
- prevJQInputOdd = q1
|
|
|
- jQ *= adjustedPrevPeriod
|
|
|
- q2 = (0.2 * (q1 + jI)) + (0.8 * prevq2)
|
|
|
- i2 = (0.2 * (i1ForOddPrev3 - jQ)) + (0.8 * previ2)
|
|
|
- i1ForEvenPrev3 = i1ForEvenPrev2
|
|
|
- i1ForEvenPrev2 = detrender
|
|
|
- }
|
|
|
- Re = (0.2 * ((i2 * previ2) + (q2 * prevq2))) + (0.8 * Re)
|
|
|
- Im = (0.2 * ((i2 * prevq2) - (q2 * previ2))) + (0.8 * Im)
|
|
|
- prevq2 = q2
|
|
|
- previ2 = i2
|
|
|
- tempReal = period
|
|
|
- if (Im != 0.0) && (Re != 0.0) {
|
|
|
- period = 360.0 / (math.Atan(Im/Re) * rad2Deg)
|
|
|
- }
|
|
|
- tempReal2 := 1.5 * tempReal
|
|
|
- if period > tempReal2 {
|
|
|
- period = tempReal2
|
|
|
- }
|
|
|
- tempReal2 = 0.67 * tempReal
|
|
|
- if period < tempReal2 {
|
|
|
- period = tempReal2
|
|
|
- }
|
|
|
- if period < 6 {
|
|
|
- period = 6
|
|
|
- } else if period > 50 {
|
|
|
- period = 50
|
|
|
- }
|
|
|
- period = (0.2 * period) + (0.8 * tempReal)
|
|
|
- today++
|
|
|
- }
|
|
|
- return outInPhase, outQuadrature
|
|
|
-}
|
|
|
-
|
|
|
-// HtSine - Hilbert Transform - SineWave (lookback=63)
|
|
|
-func HtSine(inReal []float64) ([]float64, []float64) {
|
|
|
-
|
|
|
- outSine := make([]float64, len(inReal))
|
|
|
- outLeadSine := make([]float64, len(inReal))
|
|
|
-
|
|
|
- a := 0.0962
|
|
|
- b := 0.5769
|
|
|
- detrenderOdd := make([]float64, 3)
|
|
|
- detrenderEven := make([]float64, 3)
|
|
|
- q1Odd := make([]float64, 3)
|
|
|
- q1Even := make([]float64, 3)
|
|
|
- jIOdd := make([]float64, 3)
|
|
|
- jIEven := make([]float64, 3)
|
|
|
- jQOdd := make([]float64, 3)
|
|
|
- jQEven := make([]float64, 3)
|
|
|
- smoothPriceIdx := 0
|
|
|
- maxIdxSmoothPrice := (50 - 1)
|
|
|
- smoothPrice := make([]float64, maxIdxSmoothPrice+1)
|
|
|
- tempReal := math.Atan(1)
|
|
|
- rad2Deg := 45.0 / tempReal
|
|
|
- deg2Rad := 1.0 / rad2Deg
|
|
|
- constDeg2RadBy360 := tempReal * 8.0
|
|
|
- lookbackTotal := 63
|
|
|
- startIdx := lookbackTotal
|
|
|
- trailingWMAIdx := startIdx - lookbackTotal
|
|
|
- today := trailingWMAIdx
|
|
|
- tempReal = inReal[today]
|
|
|
- today++
|
|
|
- periodWMASub := tempReal
|
|
|
- periodWMASum := tempReal
|
|
|
- tempReal = inReal[today]
|
|
|
- today++
|
|
|
- periodWMASub += tempReal
|
|
|
- periodWMASum += tempReal * 2.0
|
|
|
- tempReal = inReal[today]
|
|
|
- today++
|
|
|
- periodWMASub += tempReal
|
|
|
- periodWMASum += tempReal * 3.0
|
|
|
- trailingWMAValue := 0.0
|
|
|
- i := 34
|
|
|
- smoothedValue := 0.0
|
|
|
- for ok := true; ok; {
|
|
|
- tempReal = inReal[today]
|
|
|
- today++
|
|
|
- periodWMASub += tempReal
|
|
|
- periodWMASub -= trailingWMAValue
|
|
|
- periodWMASum += tempReal * 4.0
|
|
|
- trailingWMAValue = inReal[trailingWMAIdx]
|
|
|
- trailingWMAIdx++
|
|
|
- smoothedValue = periodWMASum * 0.1
|
|
|
- periodWMASum -= periodWMASub
|
|
|
- i--
|
|
|
- ok = i != 0
|
|
|
- }
|
|
|
-
|
|
|
- hilbertIdx := 0
|
|
|
- detrender := 0.0
|
|
|
- prevDetrenderOdd := 0.0
|
|
|
- prevDetrenderEven := 0.0
|
|
|
- prevDetrenderInputOdd := 0.0
|
|
|
- prevDetrenderInputEven := 0.0
|
|
|
- q1 := 0.0
|
|
|
- prevq1Odd := 0.0
|
|
|
- prevq1Even := 0.0
|
|
|
- prevq1InputOdd := 0.0
|
|
|
- prevq1InputEven := 0.0
|
|
|
- jI := 0.0
|
|
|
- prevJIOdd := 0.0
|
|
|
- prevJIEven := 0.0
|
|
|
- prevJIInputOdd := 0.0
|
|
|
- prevJIInputEven := 0.0
|
|
|
- jQ := 0.0
|
|
|
- prevJQOdd := 0.0
|
|
|
- prevJQEven := 0.0
|
|
|
- prevJQInputOdd := 0.0
|
|
|
- prevJQInputEven := 0.0
|
|
|
- period := 0.0
|
|
|
- outIdx := 63
|
|
|
- previ2 := 0.0
|
|
|
- prevq2 := 0.0
|
|
|
- Re := 0.0
|
|
|
- Im := 0.0
|
|
|
- i1ForOddPrev3 := 0.0
|
|
|
- i1ForEvenPrev3 := 0.0
|
|
|
- i1ForOddPrev2 := 0.0
|
|
|
- i1ForEvenPrev2 := 0.0
|
|
|
- smoothPeriod := 0.0
|
|
|
- dcPhase := 0.0
|
|
|
- hilbertTempReal := 0.0
|
|
|
- q2 := 0.0
|
|
|
- i2 := 0.0
|
|
|
- for today < len(inReal) {
|
|
|
- adjustedPrevPeriod := (0.075 * period) + 0.54
|
|
|
- todayValue := inReal[today]
|
|
|
- periodWMASub += todayValue
|
|
|
- periodWMASub -= trailingWMAValue
|
|
|
- periodWMASum += todayValue * 4.0
|
|
|
- trailingWMAValue = inReal[trailingWMAIdx]
|
|
|
- trailingWMAIdx++
|
|
|
- smoothedValue = periodWMASum * 0.1
|
|
|
- periodWMASum -= periodWMASub
|
|
|
- smoothPrice[smoothPriceIdx] = smoothedValue
|
|
|
- if (today % 2) == 0 {
|
|
|
- hilbertTempReal = a * smoothedValue
|
|
|
- detrender = -detrenderEven[hilbertIdx]
|
|
|
- detrenderEven[hilbertIdx] = hilbertTempReal
|
|
|
- detrender += hilbertTempReal
|
|
|
- detrender -= prevDetrenderEven
|
|
|
- prevDetrenderEven = b * prevDetrenderInputEven
|
|
|
- detrender += prevDetrenderEven
|
|
|
- prevDetrenderInputEven = smoothedValue
|
|
|
- detrender *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * detrender
|
|
|
- q1 = -q1Even[hilbertIdx]
|
|
|
- q1Even[hilbertIdx] = hilbertTempReal
|
|
|
- q1 += hilbertTempReal
|
|
|
- q1 -= prevq1Even
|
|
|
- prevq1Even = b * prevq1InputEven
|
|
|
- q1 += prevq1Even
|
|
|
- prevq1InputEven = detrender
|
|
|
- q1 *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * i1ForEvenPrev3
|
|
|
- jI = -jIEven[hilbertIdx]
|
|
|
- jIEven[hilbertIdx] = hilbertTempReal
|
|
|
- jI += hilbertTempReal
|
|
|
- jI -= prevJIEven
|
|
|
- prevJIEven = b * prevJIInputEven
|
|
|
- jI += prevJIEven
|
|
|
- prevJIInputEven = i1ForEvenPrev3
|
|
|
- jI *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * q1
|
|
|
- jQ = -jQEven[hilbertIdx]
|
|
|
- jQEven[hilbertIdx] = hilbertTempReal
|
|
|
- jQ += hilbertTempReal
|
|
|
- jQ -= prevJQEven
|
|
|
- prevJQEven = b * prevJQInputEven
|
|
|
- jQ += prevJQEven
|
|
|
- prevJQInputEven = q1
|
|
|
- jQ *= adjustedPrevPeriod
|
|
|
- hilbertIdx++
|
|
|
- if hilbertIdx == 3 {
|
|
|
- hilbertIdx = 0
|
|
|
- }
|
|
|
- q2 = (0.2 * (q1 + jI)) + (0.8 * prevq2)
|
|
|
- i2 = (0.2 * (i1ForEvenPrev3 - jQ)) + (0.8 * previ2)
|
|
|
- i1ForOddPrev3 = i1ForOddPrev2
|
|
|
- i1ForOddPrev2 = detrender
|
|
|
- } else {
|
|
|
- hilbertTempReal = a * smoothedValue
|
|
|
- detrender = -detrenderOdd[hilbertIdx]
|
|
|
- detrenderOdd[hilbertIdx] = hilbertTempReal
|
|
|
- detrender += hilbertTempReal
|
|
|
- detrender -= prevDetrenderOdd
|
|
|
- prevDetrenderOdd = b * prevDetrenderInputOdd
|
|
|
- detrender += prevDetrenderOdd
|
|
|
- prevDetrenderInputOdd = smoothedValue
|
|
|
- detrender *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * detrender
|
|
|
- q1 = -q1Odd[hilbertIdx]
|
|
|
- q1Odd[hilbertIdx] = hilbertTempReal
|
|
|
- q1 += hilbertTempReal
|
|
|
- q1 -= prevq1Odd
|
|
|
- prevq1Odd = b * prevq1InputOdd
|
|
|
- q1 += prevq1Odd
|
|
|
- prevq1InputOdd = detrender
|
|
|
- q1 *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * i1ForOddPrev3
|
|
|
- jI = -jIOdd[hilbertIdx]
|
|
|
- jIOdd[hilbertIdx] = hilbertTempReal
|
|
|
- jI += hilbertTempReal
|
|
|
- jI -= prevJIOdd
|
|
|
- prevJIOdd = b * prevJIInputOdd
|
|
|
- jI += prevJIOdd
|
|
|
- prevJIInputOdd = i1ForOddPrev3
|
|
|
- jI *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * q1
|
|
|
- jQ = -jQOdd[hilbertIdx]
|
|
|
- jQOdd[hilbertIdx] = hilbertTempReal
|
|
|
- jQ += hilbertTempReal
|
|
|
- jQ -= prevJQOdd
|
|
|
- prevJQOdd = b * prevJQInputOdd
|
|
|
- jQ += prevJQOdd
|
|
|
- prevJQInputOdd = q1
|
|
|
- jQ *= adjustedPrevPeriod
|
|
|
- q2 = (0.2 * (q1 + jI)) + (0.8 * prevq2)
|
|
|
- i2 = (0.2 * (i1ForOddPrev3 - jQ)) + (0.8 * previ2)
|
|
|
- i1ForEvenPrev3 = i1ForEvenPrev2
|
|
|
- i1ForEvenPrev2 = detrender
|
|
|
- }
|
|
|
- Re = (0.2 * ((i2 * previ2) + (q2 * prevq2))) + (0.8 * Re)
|
|
|
- Im = (0.2 * ((i2 * prevq2) - (q2 * previ2))) + (0.8 * Im)
|
|
|
- prevq2 = q2
|
|
|
- previ2 = i2
|
|
|
- tempReal = period
|
|
|
- if (Im != 0.0) && (Re != 0.0) {
|
|
|
- period = 360.0 / (math.Atan(Im/Re) * rad2Deg)
|
|
|
- }
|
|
|
- tempReal2 := 1.5 * tempReal
|
|
|
- if period > tempReal2 {
|
|
|
- period = tempReal2
|
|
|
- }
|
|
|
- tempReal2 = 0.67 * tempReal
|
|
|
- if period < tempReal2 {
|
|
|
- period = tempReal2
|
|
|
- }
|
|
|
- if period < 6 {
|
|
|
- period = 6
|
|
|
- } else if period > 50 {
|
|
|
- period = 50
|
|
|
- }
|
|
|
- period = (0.2 * period) + (0.8 * tempReal)
|
|
|
- smoothPeriod = (0.33 * period) + (0.67 * smoothPeriod)
|
|
|
- DCPeriod := smoothPeriod + 0.5
|
|
|
- DCPeriodInt := math.Floor(DCPeriod)
|
|
|
- realPart := 0.0
|
|
|
- imagPart := 0.0
|
|
|
- idx := smoothPriceIdx
|
|
|
- for i := 0; i < int(DCPeriodInt); i++ {
|
|
|
- tempReal = (float64(i) * constDeg2RadBy360) / (DCPeriodInt * 1.0)
|
|
|
- tempReal2 = smoothPrice[idx]
|
|
|
- realPart += math.Sin(tempReal) * tempReal2
|
|
|
- imagPart += math.Cos(tempReal) * tempReal2
|
|
|
- if idx == 0 {
|
|
|
- idx = 50 - 1
|
|
|
- } else {
|
|
|
- idx--
|
|
|
- }
|
|
|
- }
|
|
|
- tempReal = math.Abs(imagPart)
|
|
|
- if tempReal > 0.0 {
|
|
|
- dcPhase = math.Atan(realPart/imagPart) * rad2Deg
|
|
|
- } else if tempReal <= 0.01 {
|
|
|
- if realPart < 0.0 {
|
|
|
- dcPhase -= 90.0
|
|
|
- } else if realPart > 0.0 {
|
|
|
- dcPhase += 90.0
|
|
|
- }
|
|
|
- }
|
|
|
- dcPhase += 90.0
|
|
|
- dcPhase += 360.0 / smoothPeriod
|
|
|
- if imagPart < 0.0 {
|
|
|
- dcPhase += 180.0
|
|
|
- }
|
|
|
- if dcPhase > 315.0 {
|
|
|
- dcPhase -= 360.0
|
|
|
- }
|
|
|
- if today >= startIdx {
|
|
|
- outSine[outIdx] = math.Sin(dcPhase * deg2Rad)
|
|
|
- outLeadSine[outIdx] = math.Sin((dcPhase + 45) * deg2Rad)
|
|
|
- outIdx++
|
|
|
- }
|
|
|
- smoothPriceIdx++
|
|
|
- if smoothPriceIdx > maxIdxSmoothPrice {
|
|
|
- smoothPriceIdx = 0
|
|
|
- }
|
|
|
-
|
|
|
- today++
|
|
|
- }
|
|
|
- return outSine, outLeadSine
|
|
|
-}
|
|
|
-
|
|
|
-// HtTrendMode - Hilbert Transform - Trend vs Cycle Mode (lookback=63)
|
|
|
-func HtTrendMode(inReal []float64) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
- a := 0.0962
|
|
|
- b := 0.5769
|
|
|
- detrenderOdd := make([]float64, 3)
|
|
|
- detrenderEven := make([]float64, 3)
|
|
|
- q1Odd := make([]float64, 3)
|
|
|
- q1Even := make([]float64, 3)
|
|
|
- jIOdd := make([]float64, 3)
|
|
|
- jIEven := make([]float64, 3)
|
|
|
- jQOdd := make([]float64, 3)
|
|
|
- jQEven := make([]float64, 3)
|
|
|
- smoothPriceIdx := 0
|
|
|
- maxIdxSmoothPrice := (50 - 1)
|
|
|
- smoothPrice := make([]float64, maxIdxSmoothPrice+1)
|
|
|
- iTrend1 := 0.0
|
|
|
- iTrend2 := 0.0
|
|
|
- iTrend3 := 0.0
|
|
|
- daysInTrend := 0
|
|
|
- prevdcPhase := 0.0
|
|
|
- dcPhase := 0.0
|
|
|
- prevSine := 0.0
|
|
|
- sine := 0.0
|
|
|
- prevLeadSine := 0.0
|
|
|
- leadSine := 0.0
|
|
|
- tempReal := math.Atan(1)
|
|
|
- rad2Deg := 45.0 / tempReal
|
|
|
- deg2Rad := 1.0 / rad2Deg
|
|
|
- constDeg2RadBy360 := tempReal * 8.0
|
|
|
- lookbackTotal := 63
|
|
|
- startIdx := lookbackTotal
|
|
|
- trailingWMAIdx := startIdx - lookbackTotal
|
|
|
- today := trailingWMAIdx
|
|
|
- tempReal = inReal[today]
|
|
|
- today++
|
|
|
- periodWMASub := tempReal
|
|
|
- periodWMASum := tempReal
|
|
|
- tempReal = inReal[today]
|
|
|
- today++
|
|
|
- periodWMASub += tempReal
|
|
|
- periodWMASum += tempReal * 2.0
|
|
|
- tempReal = inReal[today]
|
|
|
- today++
|
|
|
- periodWMASub += tempReal
|
|
|
- periodWMASum += tempReal * 3.0
|
|
|
- trailingWMAValue := 0.0
|
|
|
- i := 34
|
|
|
-
|
|
|
- for ok := true; ok; {
|
|
|
- tempReal = inReal[today]
|
|
|
- today++
|
|
|
- periodWMASub += tempReal
|
|
|
- periodWMASub -= trailingWMAValue
|
|
|
- periodWMASum += tempReal * 4.0
|
|
|
- trailingWMAValue = inReal[trailingWMAIdx]
|
|
|
- trailingWMAIdx++
|
|
|
- //smoothedValue := periodWMASum * 0.1
|
|
|
- periodWMASum -= periodWMASub
|
|
|
- i--
|
|
|
- ok = i != 0
|
|
|
- }
|
|
|
-
|
|
|
- hilbertIdx := 0
|
|
|
- detrender := 0.0
|
|
|
- prevDetrenderOdd := 0.0
|
|
|
- prevDetrenderEven := 0.0
|
|
|
- prevDetrenderInputOdd := 0.0
|
|
|
- prevDetrenderInputEven := 0.0
|
|
|
- q1 := 0.0
|
|
|
- prevq1Odd := 0.0
|
|
|
- prevq1Even := 0.0
|
|
|
- prevq1InputOdd := 0.0
|
|
|
- prevq1InputEven := 0.0
|
|
|
- jI := 0.0
|
|
|
- prevJIOdd := 0.0
|
|
|
- prevJIEven := 0.0
|
|
|
- prevJIInputOdd := 0.0
|
|
|
- prevJIInputEven := 0.0
|
|
|
- jQ := 0.0
|
|
|
- prevJQOdd := 0.0
|
|
|
- prevJQEven := 0.0
|
|
|
- prevJQInputOdd := 0.0
|
|
|
- prevJQInputEven := 0.0
|
|
|
- period := 0.0
|
|
|
- outIdx := 63
|
|
|
- previ2 := 0.0
|
|
|
- prevq2 := 0.0
|
|
|
- Re := 0.0
|
|
|
- Im := 0.0
|
|
|
- i1ForOddPrev3 := 0.0
|
|
|
- i1ForEvenPrev3 := 0.0
|
|
|
- i1ForOddPrev2 := 0.0
|
|
|
- i1ForEvenPrev2 := 0.0
|
|
|
- smoothPeriod := 0.0
|
|
|
- dcPhase = 0.0
|
|
|
- smoothedValue := 0.0
|
|
|
- hilbertTempReal := 0.0
|
|
|
- q2 := 0.0
|
|
|
- i2 := 0.0
|
|
|
- for today < len(inReal) {
|
|
|
- adjustedPrevPeriod := (0.075 * period) + 0.54
|
|
|
- todayValue := inReal[today]
|
|
|
- periodWMASub += todayValue
|
|
|
- periodWMASub -= trailingWMAValue
|
|
|
- periodWMASum += todayValue * 4.0
|
|
|
- trailingWMAValue = inReal[trailingWMAIdx]
|
|
|
- trailingWMAIdx++
|
|
|
- smoothedValue = periodWMASum * 0.1
|
|
|
- periodWMASum -= periodWMASub
|
|
|
-
|
|
|
- smoothPrice[smoothPriceIdx] = smoothedValue
|
|
|
- if (today % 2) == 0 {
|
|
|
- hilbertTempReal = a * smoothedValue
|
|
|
- detrender = -detrenderEven[hilbertIdx]
|
|
|
- detrenderEven[hilbertIdx] = hilbertTempReal
|
|
|
- detrender += hilbertTempReal
|
|
|
- detrender -= prevDetrenderEven
|
|
|
- prevDetrenderEven = b * prevDetrenderInputEven
|
|
|
- detrender += prevDetrenderEven
|
|
|
- prevDetrenderInputEven = smoothedValue
|
|
|
- detrender *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * detrender
|
|
|
- q1 = -q1Even[hilbertIdx]
|
|
|
- q1Even[hilbertIdx] = hilbertTempReal
|
|
|
- q1 += hilbertTempReal
|
|
|
- q1 -= prevq1Even
|
|
|
- prevq1Even = b * prevq1InputEven
|
|
|
- q1 += prevq1Even
|
|
|
- prevq1InputEven = detrender
|
|
|
- q1 *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * i1ForEvenPrev3
|
|
|
- jI = -jIEven[hilbertIdx]
|
|
|
- jIEven[hilbertIdx] = hilbertTempReal
|
|
|
- jI += hilbertTempReal
|
|
|
- jI -= prevJIEven
|
|
|
- prevJIEven = b * prevJIInputEven
|
|
|
- jI += prevJIEven
|
|
|
- prevJIInputEven = i1ForEvenPrev3
|
|
|
- jI *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * q1
|
|
|
- jQ = -jQEven[hilbertIdx]
|
|
|
- jQEven[hilbertIdx] = hilbertTempReal
|
|
|
- jQ += hilbertTempReal
|
|
|
- jQ -= prevJQEven
|
|
|
- prevJQEven = b * prevJQInputEven
|
|
|
- jQ += prevJQEven
|
|
|
- prevJQInputEven = q1
|
|
|
- jQ *= adjustedPrevPeriod
|
|
|
- hilbertIdx++
|
|
|
- if hilbertIdx == 3 {
|
|
|
- hilbertIdx = 0
|
|
|
- }
|
|
|
- q2 = (0.2 * (q1 + jI)) + (0.8 * prevq2)
|
|
|
- i2 = (0.2 * (i1ForEvenPrev3 - jQ)) + (0.8 * previ2)
|
|
|
- i1ForOddPrev3 = i1ForOddPrev2
|
|
|
- i1ForOddPrev2 = detrender
|
|
|
- } else {
|
|
|
- hilbertTempReal = a * smoothedValue
|
|
|
- detrender = -detrenderOdd[hilbertIdx]
|
|
|
- detrenderOdd[hilbertIdx] = hilbertTempReal
|
|
|
- detrender += hilbertTempReal
|
|
|
- detrender -= prevDetrenderOdd
|
|
|
- prevDetrenderOdd = b * prevDetrenderInputOdd
|
|
|
- detrender += prevDetrenderOdd
|
|
|
- prevDetrenderInputOdd = smoothedValue
|
|
|
- detrender *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * detrender
|
|
|
- q1 = -q1Odd[hilbertIdx]
|
|
|
- q1Odd[hilbertIdx] = hilbertTempReal
|
|
|
- q1 += hilbertTempReal
|
|
|
- q1 -= prevq1Odd
|
|
|
- prevq1Odd = b * prevq1InputOdd
|
|
|
- q1 += prevq1Odd
|
|
|
- prevq1InputOdd = detrender
|
|
|
- q1 *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * i1ForOddPrev3
|
|
|
- jI = -jIOdd[hilbertIdx]
|
|
|
- jIOdd[hilbertIdx] = hilbertTempReal
|
|
|
- jI += hilbertTempReal
|
|
|
- jI -= prevJIOdd
|
|
|
- prevJIOdd = b * prevJIInputOdd
|
|
|
- jI += prevJIOdd
|
|
|
- prevJIInputOdd = i1ForOddPrev3
|
|
|
- jI *= adjustedPrevPeriod
|
|
|
- hilbertTempReal = a * q1
|
|
|
- jQ = -jQOdd[hilbertIdx]
|
|
|
- jQOdd[hilbertIdx] = hilbertTempReal
|
|
|
- jQ += hilbertTempReal
|
|
|
- jQ -= prevJQOdd
|
|
|
- prevJQOdd = b * prevJQInputOdd
|
|
|
- jQ += prevJQOdd
|
|
|
- prevJQInputOdd = q1
|
|
|
- jQ *= adjustedPrevPeriod
|
|
|
- q2 = (0.2 * (q1 + jI)) + (0.8 * prevq2)
|
|
|
- i2 = (0.2 * (i1ForOddPrev3 - jQ)) + (0.8 * previ2)
|
|
|
- i1ForEvenPrev3 = i1ForEvenPrev2
|
|
|
- i1ForEvenPrev2 = detrender
|
|
|
- }
|
|
|
- Re = (0.2 * ((i2 * previ2) + (q2 * prevq2))) + (0.8 * Re)
|
|
|
- Im = (0.2 * ((i2 * prevq2) - (q2 * previ2))) + (0.8 * Im)
|
|
|
- prevq2 = q2
|
|
|
- previ2 = i2
|
|
|
- tempReal = period
|
|
|
- if (Im != 0.0) && (Re != 0.0) {
|
|
|
- period = 360.0 / (math.Atan(Im/Re) * rad2Deg)
|
|
|
- }
|
|
|
- tempReal2 := 1.5 * tempReal
|
|
|
- if period > tempReal2 {
|
|
|
- period = tempReal2
|
|
|
- }
|
|
|
- tempReal2 = 0.67 * tempReal
|
|
|
- if period < tempReal2 {
|
|
|
- period = tempReal2
|
|
|
- }
|
|
|
- if period < 6 {
|
|
|
- period = 6
|
|
|
- } else if period > 50 {
|
|
|
- period = 50
|
|
|
- }
|
|
|
- period = (0.2 * period) + (0.8 * tempReal)
|
|
|
- smoothPeriod = (0.33 * period) + (0.67 * smoothPeriod)
|
|
|
- prevdcPhase = dcPhase
|
|
|
- DCPeriod := smoothPeriod + 0.5
|
|
|
- DCPeriodInt := math.Floor(DCPeriod)
|
|
|
- realPart := 0.0
|
|
|
- imagPart := 0.0
|
|
|
- idx := smoothPriceIdx
|
|
|
- for i := 0; i < int(DCPeriodInt); i++ {
|
|
|
- tempReal = (float64(i) * constDeg2RadBy360) / (DCPeriodInt * 1.0)
|
|
|
- tempReal2 = smoothPrice[idx]
|
|
|
- realPart += math.Sin(tempReal) * tempReal2
|
|
|
- imagPart += math.Cos(tempReal) * tempReal2
|
|
|
- if idx == 0 {
|
|
|
- idx = 50 - 1
|
|
|
- } else {
|
|
|
- idx--
|
|
|
- }
|
|
|
- }
|
|
|
- tempReal = math.Abs(imagPart)
|
|
|
- if tempReal > 0.0 {
|
|
|
- dcPhase = math.Atan(realPart/imagPart) * rad2Deg
|
|
|
- } else if tempReal <= 0.01 {
|
|
|
- if realPart < 0.0 {
|
|
|
- dcPhase -= 90.0
|
|
|
- } else if realPart > 0.0 {
|
|
|
- dcPhase += 90.0
|
|
|
- }
|
|
|
- }
|
|
|
- dcPhase += 90.0
|
|
|
- dcPhase += 360.0 / smoothPeriod
|
|
|
- if imagPart < 0.0 {
|
|
|
- dcPhase += 180.0
|
|
|
- }
|
|
|
- if dcPhase > 315.0 {
|
|
|
- dcPhase -= 360.0
|
|
|
- }
|
|
|
- prevSine = sine
|
|
|
- prevLeadSine = leadSine
|
|
|
- sine = math.Sin(dcPhase * deg2Rad)
|
|
|
- leadSine = math.Sin((dcPhase + 45) * deg2Rad)
|
|
|
- DCPeriod = smoothPeriod + 0.5
|
|
|
- DCPeriodInt = math.Floor(DCPeriod)
|
|
|
- idx = today
|
|
|
- tempReal = 0.0
|
|
|
- for i := 0; i < int(DCPeriodInt); i++ {
|
|
|
- tempReal += inReal[idx]
|
|
|
- idx--
|
|
|
- }
|
|
|
- if DCPeriodInt > 0 {
|
|
|
- tempReal = tempReal / (DCPeriodInt * 1.0)
|
|
|
- }
|
|
|
- trendline := (4.0*tempReal + 3.0*iTrend1 + 2.0*iTrend2 + iTrend3) / 10.0
|
|
|
- iTrend3 = iTrend2
|
|
|
- iTrend2 = iTrend1
|
|
|
- iTrend1 = tempReal
|
|
|
- trend := 1
|
|
|
- if ((sine > leadSine) && (prevSine <= prevLeadSine)) || ((sine < leadSine) && (prevSine >= prevLeadSine)) {
|
|
|
- daysInTrend = 0
|
|
|
- trend = 0
|
|
|
- }
|
|
|
- daysInTrend++
|
|
|
- if float64(daysInTrend) < (0.5 * smoothPeriod) {
|
|
|
- trend = 0
|
|
|
- }
|
|
|
- tempReal = dcPhase - prevdcPhase
|
|
|
- if (smoothPeriod != 0.0) && ((tempReal > (0.67 * 360.0 / smoothPeriod)) && (tempReal < (1.5 * 360.0 / smoothPeriod))) {
|
|
|
- trend = 0
|
|
|
- }
|
|
|
- tempReal = smoothPrice[smoothPriceIdx]
|
|
|
- if (trendline != 0.0) && (math.Abs((tempReal-trendline)/trendline) >= 0.015) {
|
|
|
- trend = 1
|
|
|
- }
|
|
|
- if today >= startIdx {
|
|
|
- outReal[outIdx] = float64(trend)
|
|
|
- outIdx++
|
|
|
- }
|
|
|
- smoothPriceIdx++
|
|
|
- if smoothPriceIdx > maxIdxSmoothPrice {
|
|
|
- smoothPriceIdx = 0
|
|
|
- }
|
|
|
-
|
|
|
- today++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-/* Statistic Functions */
|
|
|
-
|
|
|
-// Beta - Beta
|
|
|
-func Beta(inReal0 []float64, inReal1 []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal0))
|
|
|
-
|
|
|
- x := 0.0
|
|
|
- y := 0.0
|
|
|
- sSS := 0.0
|
|
|
- sXY := 0.0
|
|
|
- sX := 0.0
|
|
|
- sY := 0.0
|
|
|
- tmpReal := 0.0
|
|
|
- n := 0.0
|
|
|
- nbInitialElementNeeded := inTimePeriod
|
|
|
- startIdx := nbInitialElementNeeded
|
|
|
- trailingIdx := startIdx - nbInitialElementNeeded
|
|
|
- trailingLastPriceX := inReal0[trailingIdx]
|
|
|
- lastPriceX := trailingLastPriceX
|
|
|
- trailingLastPriceY := inReal1[trailingIdx]
|
|
|
- lastPriceY := trailingLastPriceY
|
|
|
- trailingIdx++
|
|
|
- i := trailingIdx
|
|
|
- for i < startIdx {
|
|
|
- tmpReal := inReal0[i]
|
|
|
- x := 0.0
|
|
|
- if !((-0.00000000000001 < lastPriceX) && (lastPriceX < 0.00000000000001)) {
|
|
|
- x = (tmpReal - lastPriceX) / lastPriceX
|
|
|
- }
|
|
|
- lastPriceX = tmpReal
|
|
|
- tmpReal = inReal1[i]
|
|
|
- i++
|
|
|
- y := 0.0
|
|
|
- if !((-0.00000000000001 < lastPriceY) && (lastPriceY < 0.00000000000001)) {
|
|
|
- y = (tmpReal - lastPriceY) / lastPriceY
|
|
|
- }
|
|
|
- lastPriceY = tmpReal
|
|
|
- sSS += x * x
|
|
|
- sXY += x * y
|
|
|
- sX += x
|
|
|
- sY += y
|
|
|
- }
|
|
|
- outIdx := inTimePeriod
|
|
|
- n = float64(inTimePeriod)
|
|
|
- for ok := true; ok; {
|
|
|
- tmpReal = inReal0[i]
|
|
|
- if !((-0.00000000000001 < lastPriceX) && (lastPriceX < 0.00000000000001)) {
|
|
|
- x = (tmpReal - lastPriceX) / lastPriceX
|
|
|
- } else {
|
|
|
- x = 0.0
|
|
|
- }
|
|
|
- lastPriceX = tmpReal
|
|
|
- tmpReal = inReal1[i]
|
|
|
- i++
|
|
|
- if !((-0.00000000000001 < lastPriceY) && (lastPriceY < 0.00000000000001)) {
|
|
|
- y = (tmpReal - lastPriceY) / lastPriceY
|
|
|
- } else {
|
|
|
- y = 0.0
|
|
|
- }
|
|
|
- lastPriceY = tmpReal
|
|
|
- sSS += x * x
|
|
|
- sXY += x * y
|
|
|
- sX += x
|
|
|
- sY += y
|
|
|
- tmpReal = inReal0[trailingIdx]
|
|
|
- if !(((-(0.00000000000001)) < trailingLastPriceX) && (trailingLastPriceX < (0.00000000000001))) {
|
|
|
- x = (tmpReal - trailingLastPriceX) / trailingLastPriceX
|
|
|
- } else {
|
|
|
- x = 0.0
|
|
|
- }
|
|
|
- trailingLastPriceX = tmpReal
|
|
|
- tmpReal = inReal1[trailingIdx]
|
|
|
- trailingIdx++
|
|
|
- if !(((-(0.00000000000001)) < trailingLastPriceY) && (trailingLastPriceY < (0.00000000000001))) {
|
|
|
- y = (tmpReal - trailingLastPriceY) / trailingLastPriceY
|
|
|
- } else {
|
|
|
- y = 0.0
|
|
|
- }
|
|
|
- trailingLastPriceY = tmpReal
|
|
|
- tmpReal = (n * sSS) - (sX * sX)
|
|
|
- if !(((-(0.00000000000001)) < tmpReal) && (tmpReal < (0.00000000000001))) {
|
|
|
- outReal[outIdx] = ((n * sXY) - (sX * sY)) / tmpReal
|
|
|
- } else {
|
|
|
- outReal[outIdx] = 0.0
|
|
|
- }
|
|
|
- outIdx++
|
|
|
- sSS -= x * x
|
|
|
- sXY -= x * y
|
|
|
- sX -= x
|
|
|
- sY -= y
|
|
|
- ok = i < len(inReal0)
|
|
|
- }
|
|
|
-
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Correl - Pearson's Correlation Coefficient (r)
|
|
|
-func Correl(inReal0 []float64, inReal1 []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal0))
|
|
|
-
|
|
|
- inTimePeriodF := float64(inTimePeriod)
|
|
|
- lookbackTotal := inTimePeriod - 1
|
|
|
- startIdx := lookbackTotal
|
|
|
- trailingIdx := startIdx - lookbackTotal
|
|
|
- sumXY, sumX, sumY, sumX2, sumY2 := 0.0, 0.0, 0.0, 0.0, 0.0
|
|
|
- today := trailingIdx
|
|
|
- for today = trailingIdx; today <= startIdx; today++ {
|
|
|
- x := inReal0[today]
|
|
|
- sumX += x
|
|
|
- sumX2 += x * x
|
|
|
- y := inReal1[today]
|
|
|
- sumXY += x * y
|
|
|
- sumY += y
|
|
|
- sumY2 += y * y
|
|
|
- }
|
|
|
- trailingX := inReal0[trailingIdx]
|
|
|
- trailingY := inReal1[trailingIdx]
|
|
|
- trailingIdx++
|
|
|
- tempReal := (sumX2 - ((sumX * sumX) / inTimePeriodF)) * (sumY2 - ((sumY * sumY) / inTimePeriodF))
|
|
|
- if !(tempReal < 0.00000000000001) {
|
|
|
- outReal[inTimePeriod-1] = (sumXY - ((sumX * sumY) / inTimePeriodF)) / math.Sqrt(tempReal)
|
|
|
- } else {
|
|
|
- outReal[inTimePeriod-1] = 0.0
|
|
|
- }
|
|
|
- outIdx := inTimePeriod
|
|
|
- for today < len(inReal0) {
|
|
|
- sumX -= trailingX
|
|
|
- sumX2 -= trailingX * trailingX
|
|
|
- sumXY -= trailingX * trailingY
|
|
|
- sumY -= trailingY
|
|
|
- sumY2 -= trailingY * trailingY
|
|
|
- x := inReal0[today]
|
|
|
- sumX += x
|
|
|
- sumX2 += x * x
|
|
|
- y := inReal1[today]
|
|
|
- today++
|
|
|
- sumXY += x * y
|
|
|
- sumY += y
|
|
|
- sumY2 += y * y
|
|
|
- trailingX = inReal0[trailingIdx]
|
|
|
- trailingY = inReal1[trailingIdx]
|
|
|
- trailingIdx++
|
|
|
- tempReal = (sumX2 - ((sumX * sumX) / inTimePeriodF)) * (sumY2 - ((sumY * sumY) / inTimePeriodF))
|
|
|
- if !(tempReal < (0.00000000000001)) {
|
|
|
- outReal[outIdx] = (sumXY - ((sumX * sumY) / inTimePeriodF)) / math.Sqrt(tempReal)
|
|
|
- } else {
|
|
|
- outReal[outIdx] = 0.0
|
|
|
- }
|
|
|
- outIdx++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// LinearReg - Linear Regression
|
|
|
-func LinearReg(inReal []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
-
|
|
|
- inTimePeriodF := float64(inTimePeriod)
|
|
|
- lookbackTotal := inTimePeriod
|
|
|
- startIdx := lookbackTotal
|
|
|
- outIdx := startIdx - 1
|
|
|
- today := startIdx - 1
|
|
|
- sumX := inTimePeriodF * (inTimePeriodF - 1) * 0.5
|
|
|
- sumXSqr := inTimePeriodF * (inTimePeriodF - 1) * (2*inTimePeriodF - 1) / 6
|
|
|
- divisor := sumX*sumX - inTimePeriodF*sumXSqr
|
|
|
- //initialize values of sumY and sumXY over first (inTimePeriod) input values
|
|
|
- sumXY := 0.0
|
|
|
- sumY := 0.0
|
|
|
- i := inTimePeriod
|
|
|
- for i != 0 {
|
|
|
- i--
|
|
|
- tempValue1 := inReal[today-i]
|
|
|
- sumY += tempValue1
|
|
|
- sumXY += float64(i) * tempValue1
|
|
|
- }
|
|
|
- for today < len(inReal) {
|
|
|
- //sumX and sumXY are already available for first output value
|
|
|
- if today > startIdx-1 {
|
|
|
- tempValue2 := inReal[today-inTimePeriod]
|
|
|
- sumXY += sumY - inTimePeriodF*tempValue2
|
|
|
- sumY += inReal[today] - tempValue2
|
|
|
- }
|
|
|
- m := (inTimePeriodF*sumXY - sumX*sumY) / divisor
|
|
|
- b := (sumY - m*sumX) / inTimePeriodF
|
|
|
- outReal[outIdx] = b + m*(inTimePeriodF-1)
|
|
|
- outIdx++
|
|
|
- today++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// LinearRegAngle - Linear Regression Angle
|
|
|
-func LinearRegAngle(inReal []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
-
|
|
|
- inTimePeriodF := float64(inTimePeriod)
|
|
|
- lookbackTotal := inTimePeriod
|
|
|
- startIdx := lookbackTotal
|
|
|
- outIdx := startIdx - 1
|
|
|
- today := startIdx - 1
|
|
|
- sumX := inTimePeriodF * (inTimePeriodF - 1) * 0.5
|
|
|
- sumXSqr := inTimePeriodF * (inTimePeriodF - 1) * (2*inTimePeriodF - 1) / 6
|
|
|
- divisor := sumX*sumX - inTimePeriodF*sumXSqr
|
|
|
- //initialize values of sumY and sumXY over first (inTimePeriod) input values
|
|
|
- sumXY := 0.0
|
|
|
- sumY := 0.0
|
|
|
- i := inTimePeriod
|
|
|
- for i != 0 {
|
|
|
- i--
|
|
|
- tempValue1 := inReal[today-i]
|
|
|
- sumY += tempValue1
|
|
|
- sumXY += float64(i) * tempValue1
|
|
|
- }
|
|
|
- for today < len(inReal) {
|
|
|
- //sumX and sumXY are already available for first output value
|
|
|
- if today > startIdx-1 {
|
|
|
- tempValue2 := inReal[today-inTimePeriod]
|
|
|
- sumXY += sumY - inTimePeriodF*tempValue2
|
|
|
- sumY += inReal[today] - tempValue2
|
|
|
- }
|
|
|
- m := (inTimePeriodF*sumXY - sumX*sumY) / divisor
|
|
|
- outReal[outIdx] = math.Atan(m) * (180.0 / math.Pi)
|
|
|
- outIdx++
|
|
|
- today++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// LinearRegIntercept - Linear Regression Intercept
|
|
|
-func LinearRegIntercept(inReal []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
-
|
|
|
- inTimePeriodF := float64(inTimePeriod)
|
|
|
- lookbackTotal := inTimePeriod
|
|
|
- startIdx := lookbackTotal
|
|
|
- outIdx := startIdx - 1
|
|
|
- today := startIdx - 1
|
|
|
- sumX := inTimePeriodF * (inTimePeriodF - 1) * 0.5
|
|
|
- sumXSqr := inTimePeriodF * (inTimePeriodF - 1) * (2*inTimePeriodF - 1) / 6
|
|
|
- divisor := sumX*sumX - inTimePeriodF*sumXSqr
|
|
|
- //initialize values of sumY and sumXY over first (inTimePeriod) input values
|
|
|
- sumXY := 0.0
|
|
|
- sumY := 0.0
|
|
|
- i := inTimePeriod
|
|
|
- for i != 0 {
|
|
|
- i--
|
|
|
- tempValue1 := inReal[today-i]
|
|
|
- sumY += tempValue1
|
|
|
- sumXY += float64(i) * tempValue1
|
|
|
- }
|
|
|
- for today < len(inReal) {
|
|
|
- //sumX and sumXY are already available for first output value
|
|
|
- if today > startIdx-1 {
|
|
|
- tempValue2 := inReal[today-inTimePeriod]
|
|
|
- sumXY += sumY - inTimePeriodF*tempValue2
|
|
|
- sumY += inReal[today] - tempValue2
|
|
|
- }
|
|
|
- m := (inTimePeriodF*sumXY - sumX*sumY) / divisor
|
|
|
- outReal[outIdx] = (sumY - m*sumX) / inTimePeriodF
|
|
|
- outIdx++
|
|
|
- today++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// LinearRegSlope - Linear Regression Slope
|
|
|
-func LinearRegSlope(inReal []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
-
|
|
|
- inTimePeriodF := float64(inTimePeriod)
|
|
|
- lookbackTotal := inTimePeriod
|
|
|
- startIdx := lookbackTotal
|
|
|
- outIdx := startIdx - 1
|
|
|
- today := startIdx - 1
|
|
|
- sumX := inTimePeriodF * (inTimePeriodF - 1) * 0.5
|
|
|
- sumXSqr := inTimePeriodF * (inTimePeriodF - 1) * (2*inTimePeriodF - 1) / 6
|
|
|
- divisor := sumX*sumX - inTimePeriodF*sumXSqr
|
|
|
- //initialize values of sumY and sumXY over first (inTimePeriod) input values
|
|
|
- sumXY := 0.0
|
|
|
- sumY := 0.0
|
|
|
- i := inTimePeriod
|
|
|
- for i != 0 {
|
|
|
- i--
|
|
|
- tempValue1 := inReal[today-i]
|
|
|
- sumY += tempValue1
|
|
|
- sumXY += float64(i) * tempValue1
|
|
|
- }
|
|
|
- for today < len(inReal) {
|
|
|
- //sumX and sumXY are already available for first output value
|
|
|
- if today > startIdx-1 {
|
|
|
- tempValue2 := inReal[today-inTimePeriod]
|
|
|
- sumXY += sumY - inTimePeriodF*tempValue2
|
|
|
- sumY += inReal[today] - tempValue2
|
|
|
- }
|
|
|
- outReal[outIdx] = (inTimePeriodF*sumXY - sumX*sumY) / divisor
|
|
|
- outIdx++
|
|
|
- today++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// StdDev - Standard Deviation
|
|
|
-func StdDev(inReal []float64, inTimePeriod int, inNbDev float64) []float64 {
|
|
|
-
|
|
|
- outReal := Var(inReal, inTimePeriod)
|
|
|
-
|
|
|
- if inNbDev != 1.0 {
|
|
|
- for i := 0; i < len(inReal); i++ {
|
|
|
- tempReal := outReal[i]
|
|
|
- if !(tempReal < 0.00000000000001) {
|
|
|
- outReal[i] = math.Sqrt(tempReal) * inNbDev
|
|
|
- } else {
|
|
|
- outReal[i] = 0.0
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- for i := 0; i < len(inReal); i++ {
|
|
|
- tempReal := outReal[i]
|
|
|
- if !(tempReal < 0.00000000000001) {
|
|
|
- outReal[i] = math.Sqrt(tempReal)
|
|
|
- } else {
|
|
|
- outReal[i] = 0.0
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Tsf - Time Series Forecast
|
|
|
-func Tsf(inReal []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
-
|
|
|
- inTimePeriodF := float64(inTimePeriod)
|
|
|
- lookbackTotal := inTimePeriod
|
|
|
- startIdx := lookbackTotal
|
|
|
- outIdx := startIdx - 1
|
|
|
- today := startIdx - 1
|
|
|
- sumX := inTimePeriodF * (inTimePeriodF - 1.0) * 0.5
|
|
|
- sumXSqr := inTimePeriodF * (inTimePeriodF - 1) * (2*inTimePeriodF - 1) / 6
|
|
|
- divisor := sumX*sumX - inTimePeriodF*sumXSqr
|
|
|
- //initialize values of sumY and sumXY over first (inTimePeriod) input values
|
|
|
- sumXY := 0.0
|
|
|
- sumY := 0.0
|
|
|
- i := inTimePeriod
|
|
|
- for i != 0 {
|
|
|
- i--
|
|
|
- tempValue1 := inReal[today-i]
|
|
|
- sumY += tempValue1
|
|
|
- sumXY += float64(i) * tempValue1
|
|
|
- }
|
|
|
- for today < len(inReal) {
|
|
|
- //sumX and sumXY are already available for first output value
|
|
|
- if today > startIdx-1 {
|
|
|
- tempValue2 := inReal[today-inTimePeriod]
|
|
|
- sumXY += sumY - inTimePeriodF*tempValue2
|
|
|
- sumY += inReal[today] - tempValue2
|
|
|
- }
|
|
|
- m := (inTimePeriodF*sumXY - sumX*sumY) / divisor
|
|
|
- b := (sumY - m*sumX) / inTimePeriodF
|
|
|
- outReal[outIdx] = b + m*inTimePeriodF
|
|
|
- today++
|
|
|
- outIdx++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Var - Variance
|
|
|
-func Var(inReal []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
-
|
|
|
- nbInitialElementNeeded := inTimePeriod - 1
|
|
|
- startIdx := nbInitialElementNeeded
|
|
|
- periodTotal1 := 0.0
|
|
|
- periodTotal2 := 0.0
|
|
|
- trailingIdx := startIdx - nbInitialElementNeeded
|
|
|
- i := trailingIdx
|
|
|
- if inTimePeriod > 1 {
|
|
|
- for i < startIdx {
|
|
|
- tempReal := inReal[i]
|
|
|
- periodTotal1 += tempReal
|
|
|
- tempReal *= tempReal
|
|
|
- periodTotal2 += tempReal
|
|
|
- i++
|
|
|
- }
|
|
|
- }
|
|
|
- outIdx := startIdx
|
|
|
- for ok := true; ok; {
|
|
|
- tempReal := inReal[i]
|
|
|
- periodTotal1 += tempReal
|
|
|
- tempReal *= tempReal
|
|
|
- periodTotal2 += tempReal
|
|
|
- meanValue1 := periodTotal1 / float64(inTimePeriod)
|
|
|
- meanValue2 := periodTotal2 / float64(inTimePeriod)
|
|
|
- tempReal = inReal[trailingIdx]
|
|
|
- periodTotal1 -= tempReal
|
|
|
- tempReal *= tempReal
|
|
|
- periodTotal2 -= tempReal
|
|
|
- outReal[outIdx] = meanValue2 - meanValue1*meanValue1
|
|
|
- i++
|
|
|
- trailingIdx++
|
|
|
- outIdx++
|
|
|
- ok = i < len(inReal)
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-/* Math Transform Functions */
|
|
|
-
|
|
|
-// Acos - Vector Trigonometric ACOS
|
|
|
-func Acos(inReal []float64) []float64 {
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
- for i := 0; i < len(inReal); i++ {
|
|
|
- outReal[i] = math.Acos(inReal[i])
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Asin - Vector Trigonometric ASIN
|
|
|
-func Asin(inReal []float64) []float64 {
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
- for i := 0; i < len(inReal); i++ {
|
|
|
- outReal[i] = math.Asin(inReal[i])
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Atan - Vector Trigonometric ATAN
|
|
|
-func Atan(inReal []float64) []float64 {
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
- for i := 0; i < len(inReal); i++ {
|
|
|
- outReal[i] = math.Atan(inReal[i])
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Ceil - Vector CEIL
|
|
|
-func Ceil(inReal []float64) []float64 {
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
- for i := 0; i < len(inReal); i++ {
|
|
|
- outReal[i] = math.Ceil(inReal[i])
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Cos - Vector Trigonometric COS
|
|
|
-func Cos(inReal []float64) []float64 {
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
- for i := 0; i < len(inReal); i++ {
|
|
|
- outReal[i] = math.Cos(inReal[i])
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Cosh - Vector Trigonometric COSH
|
|
|
-func Cosh(inReal []float64) []float64 {
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
- for i := 0; i < len(inReal); i++ {
|
|
|
- outReal[i] = math.Cosh(inReal[i])
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Exp - Vector atrithmetic EXP
|
|
|
-func Exp(inReal []float64) []float64 {
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
- for i := 0; i < len(inReal); i++ {
|
|
|
- outReal[i] = math.Exp(inReal[i])
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Floor - Vector FLOOR
|
|
|
-func Floor(inReal []float64) []float64 {
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
- for i := 0; i < len(inReal); i++ {
|
|
|
- outReal[i] = math.Floor(inReal[i])
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Ln - Vector natural log LN
|
|
|
-func Ln(inReal []float64) []float64 {
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
- for i := 0; i < len(inReal); i++ {
|
|
|
- outReal[i] = math.Log(inReal[i])
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Log10 - Vector LOG10
|
|
|
-func Log10(inReal []float64) []float64 {
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
- for i := 0; i < len(inReal); i++ {
|
|
|
- outReal[i] = math.Log10(inReal[i])
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Sin - Vector Trigonometric SIN
|
|
|
-func Sin(inReal []float64) []float64 {
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
- for i := 0; i < len(inReal); i++ {
|
|
|
- outReal[i] = math.Sin(inReal[i])
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Sinh - Vector Trigonometric SINH
|
|
|
-func Sinh(inReal []float64) []float64 {
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
- for i := 0; i < len(inReal); i++ {
|
|
|
- outReal[i] = math.Sinh(inReal[i])
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Sqrt - Vector SQRT
|
|
|
-func Sqrt(inReal []float64) []float64 {
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
- for i := 0; i < len(inReal); i++ {
|
|
|
- outReal[i] = math.Sqrt(inReal[i])
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Tan - Vector Trigonometric TAN
|
|
|
-func Tan(inReal []float64) []float64 {
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
- for i := 0; i < len(inReal); i++ {
|
|
|
- outReal[i] = math.Tan(inReal[i])
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Tanh - Vector Trigonometric TANH
|
|
|
-func Tanh(inReal []float64) []float64 {
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
- for i := 0; i < len(inReal); i++ {
|
|
|
- outReal[i] = math.Tanh(inReal[i])
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-/* Math Operator Functions */
|
|
|
-
|
|
|
-// Add - Vector arithmetic addition
|
|
|
-func Add(inReal0 []float64, inReal1 []float64) []float64 {
|
|
|
- outReal := make([]float64, len(inReal0))
|
|
|
- for i := 0; i < len(inReal0); i++ {
|
|
|
- outReal[i] = inReal0[i] + inReal1[i]
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Div - Vector arithmetic division
|
|
|
-func Div(inReal0 []float64, inReal1 []float64) []float64 {
|
|
|
- outReal := make([]float64, len(inReal0))
|
|
|
- for i := 0; i < len(inReal0); i++ {
|
|
|
- outReal[i] = inReal0[i] / inReal1[i]
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Max - Highest value over a period
|
|
|
-func Max(inReal []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
-
|
|
|
- if inTimePeriod < 2 {
|
|
|
- return outReal
|
|
|
- }
|
|
|
-
|
|
|
- nbInitialElementNeeded := inTimePeriod - 1
|
|
|
- startIdx := nbInitialElementNeeded
|
|
|
- outIdx := startIdx
|
|
|
- today := startIdx
|
|
|
- trailingIdx := startIdx - nbInitialElementNeeded
|
|
|
- highestIdx := -1
|
|
|
- highest := 0.0
|
|
|
-
|
|
|
- for today < len(outReal) {
|
|
|
-
|
|
|
- tmp := inReal[today]
|
|
|
-
|
|
|
- if highestIdx < trailingIdx {
|
|
|
- highestIdx = trailingIdx
|
|
|
- highest = inReal[highestIdx]
|
|
|
- i := highestIdx + 1
|
|
|
- for i <= today {
|
|
|
- tmp = inReal[i]
|
|
|
- if tmp > highest {
|
|
|
- highestIdx = i
|
|
|
- highest = tmp
|
|
|
- }
|
|
|
- i++
|
|
|
- }
|
|
|
- } else if tmp >= highest {
|
|
|
- highestIdx = today
|
|
|
- highest = tmp
|
|
|
- }
|
|
|
- outReal[outIdx] = highest
|
|
|
- outIdx++
|
|
|
- trailingIdx++
|
|
|
- today++
|
|
|
- }
|
|
|
-
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// MaxIndex - Index of highest value over a specified period
|
|
|
-func MaxIndex(inReal []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
-
|
|
|
- if inTimePeriod < 2 {
|
|
|
- return outReal
|
|
|
- }
|
|
|
-
|
|
|
- nbInitialElementNeeded := inTimePeriod - 1
|
|
|
- startIdx := nbInitialElementNeeded
|
|
|
- outIdx := startIdx
|
|
|
- today := startIdx
|
|
|
- trailingIdx := startIdx - nbInitialElementNeeded
|
|
|
- highestIdx := -1
|
|
|
- highest := 0.0
|
|
|
- for today < len(inReal) {
|
|
|
- tmp := inReal[today]
|
|
|
- if highestIdx < trailingIdx {
|
|
|
- highestIdx = trailingIdx
|
|
|
- highest = inReal[highestIdx]
|
|
|
- i := highestIdx + 1
|
|
|
- for i <= today {
|
|
|
- tmp := inReal[i]
|
|
|
- if tmp > highest {
|
|
|
- highestIdx = i
|
|
|
- highest = tmp
|
|
|
- }
|
|
|
- i++
|
|
|
- }
|
|
|
- } else if tmp >= highest {
|
|
|
- highestIdx = today
|
|
|
- highest = tmp
|
|
|
- }
|
|
|
- outReal[outIdx] = float64(highestIdx)
|
|
|
- outIdx++
|
|
|
- trailingIdx++
|
|
|
- today++
|
|
|
- }
|
|
|
-
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Min - Lowest value over a period
|
|
|
-func Min(inReal []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
-
|
|
|
- if inTimePeriod < 2 {
|
|
|
- return outReal
|
|
|
- }
|
|
|
-
|
|
|
- nbInitialElementNeeded := inTimePeriod - 1
|
|
|
- startIdx := nbInitialElementNeeded
|
|
|
- outIdx := startIdx
|
|
|
- today := startIdx
|
|
|
- trailingIdx := startIdx - nbInitialElementNeeded
|
|
|
- lowestIdx := -1
|
|
|
- lowest := 0.0
|
|
|
- for today < len(outReal) {
|
|
|
-
|
|
|
- tmp := inReal[today]
|
|
|
-
|
|
|
- if lowestIdx < trailingIdx {
|
|
|
- lowestIdx = trailingIdx
|
|
|
- lowest = inReal[lowestIdx]
|
|
|
- i := lowestIdx + 1
|
|
|
- for i <= today {
|
|
|
- tmp = inReal[i]
|
|
|
- if tmp < lowest {
|
|
|
- lowestIdx = i
|
|
|
- lowest = tmp
|
|
|
- }
|
|
|
- i++
|
|
|
- }
|
|
|
- } else if tmp <= lowest {
|
|
|
- lowestIdx = today
|
|
|
- lowest = tmp
|
|
|
- }
|
|
|
- outReal[outIdx] = lowest
|
|
|
- outIdx++
|
|
|
- trailingIdx++
|
|
|
- today++
|
|
|
- }
|
|
|
-
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// MinIndex - Index of lowest value over a specified period
|
|
|
-func MinIndex(inReal []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
-
|
|
|
- if inTimePeriod < 2 {
|
|
|
- return outReal
|
|
|
- }
|
|
|
-
|
|
|
- nbInitialElementNeeded := inTimePeriod - 1
|
|
|
- startIdx := nbInitialElementNeeded
|
|
|
- outIdx := startIdx
|
|
|
- today := startIdx
|
|
|
- trailingIdx := startIdx - nbInitialElementNeeded
|
|
|
- lowestIdx := -1
|
|
|
- lowest := 0.0
|
|
|
- for today < len(inReal) {
|
|
|
- tmp := inReal[today]
|
|
|
- if lowestIdx < trailingIdx {
|
|
|
- lowestIdx = trailingIdx
|
|
|
- lowest = inReal[lowestIdx]
|
|
|
- i := lowestIdx + 1
|
|
|
- for i <= today {
|
|
|
- tmp = inReal[i]
|
|
|
- if tmp < lowest {
|
|
|
- lowestIdx = i
|
|
|
- lowest = tmp
|
|
|
- }
|
|
|
- i++
|
|
|
- }
|
|
|
- } else if tmp <= lowest {
|
|
|
- lowestIdx = today
|
|
|
- lowest = tmp
|
|
|
- }
|
|
|
- outReal[outIdx] = float64(lowestIdx)
|
|
|
- outIdx++
|
|
|
- trailingIdx++
|
|
|
- today++
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// MinMax - Lowest and highest values over a specified period
|
|
|
-func MinMax(inReal []float64, inTimePeriod int) ([]float64, []float64) {
|
|
|
-
|
|
|
- outMin := make([]float64, len(inReal))
|
|
|
- outMax := make([]float64, len(inReal))
|
|
|
-
|
|
|
- nbInitialElementNeeded := (inTimePeriod - 1)
|
|
|
- startIdx := nbInitialElementNeeded
|
|
|
- outIdx := startIdx
|
|
|
- today := startIdx
|
|
|
- trailingIdx := startIdx - nbInitialElementNeeded
|
|
|
- highestIdx := -1
|
|
|
- highest := 0.0
|
|
|
- lowestIdx := -1
|
|
|
- lowest := 0.0
|
|
|
- for today < len(inReal) {
|
|
|
- tmpLow, tmpHigh := inReal[today], inReal[today]
|
|
|
- if highestIdx < trailingIdx {
|
|
|
- highestIdx = trailingIdx
|
|
|
- highest = inReal[highestIdx]
|
|
|
- i := highestIdx
|
|
|
- i++
|
|
|
- for i <= today {
|
|
|
- tmpHigh = inReal[i]
|
|
|
- if tmpHigh > highest {
|
|
|
- highestIdx = i
|
|
|
- highest = tmpHigh
|
|
|
- }
|
|
|
- i++
|
|
|
- }
|
|
|
- } else if tmpHigh >= highest {
|
|
|
- highestIdx = today
|
|
|
- highest = tmpHigh
|
|
|
- }
|
|
|
- if lowestIdx < trailingIdx {
|
|
|
- lowestIdx = trailingIdx
|
|
|
- lowest = inReal[lowestIdx]
|
|
|
- i := lowestIdx
|
|
|
- i++
|
|
|
- for i <= today {
|
|
|
- tmpLow = inReal[i]
|
|
|
- if tmpLow < lowest {
|
|
|
- lowestIdx = i
|
|
|
- lowest = tmpLow
|
|
|
- }
|
|
|
- i++
|
|
|
- }
|
|
|
- } else if tmpLow <= lowest {
|
|
|
- lowestIdx = today
|
|
|
- lowest = tmpLow
|
|
|
- }
|
|
|
- outMax[outIdx] = highest
|
|
|
- outMin[outIdx] = lowest
|
|
|
- outIdx++
|
|
|
- trailingIdx++
|
|
|
- today++
|
|
|
- }
|
|
|
- return outMin, outMax
|
|
|
-}
|
|
|
-
|
|
|
-// MinMaxIndex - Indexes of lowest and highest values over a specified period
|
|
|
-func MinMaxIndex(inReal []float64, inTimePeriod int) ([]float64, []float64) {
|
|
|
-
|
|
|
- outMinIdx := make([]float64, len(inReal))
|
|
|
- outMaxIdx := make([]float64, len(inReal))
|
|
|
-
|
|
|
- nbInitialElementNeeded := (inTimePeriod - 1)
|
|
|
- startIdx := nbInitialElementNeeded
|
|
|
- outIdx := startIdx
|
|
|
- today := startIdx
|
|
|
- trailingIdx := startIdx - nbInitialElementNeeded
|
|
|
- highestIdx := -1
|
|
|
- highest := 0.0
|
|
|
- lowestIdx := -1
|
|
|
- lowest := 0.0
|
|
|
- for today < len(inReal) {
|
|
|
- tmpLow, tmpHigh := inReal[today], inReal[today]
|
|
|
- if highestIdx < trailingIdx {
|
|
|
- highestIdx = trailingIdx
|
|
|
- highest = inReal[highestIdx]
|
|
|
- i := highestIdx
|
|
|
- i++
|
|
|
- for i <= today {
|
|
|
- tmpHigh = inReal[i]
|
|
|
- if tmpHigh > highest {
|
|
|
- highestIdx = i
|
|
|
- highest = tmpHigh
|
|
|
- }
|
|
|
- i++
|
|
|
- }
|
|
|
- } else if tmpHigh >= highest {
|
|
|
- highestIdx = today
|
|
|
- highest = tmpHigh
|
|
|
- }
|
|
|
- if lowestIdx < trailingIdx {
|
|
|
- lowestIdx = trailingIdx
|
|
|
- lowest = inReal[lowestIdx]
|
|
|
- i := lowestIdx
|
|
|
- i++
|
|
|
- for i <= today {
|
|
|
- tmpLow = inReal[i]
|
|
|
- if tmpLow < lowest {
|
|
|
- lowestIdx = i
|
|
|
- lowest = tmpLow
|
|
|
- }
|
|
|
- i++
|
|
|
- }
|
|
|
- } else if tmpLow <= lowest {
|
|
|
- lowestIdx = today
|
|
|
- lowest = tmpLow
|
|
|
- }
|
|
|
- outMaxIdx[outIdx] = float64(highestIdx)
|
|
|
- outMinIdx[outIdx] = float64(lowestIdx)
|
|
|
- outIdx++
|
|
|
- trailingIdx++
|
|
|
- today++
|
|
|
- }
|
|
|
- return outMinIdx, outMaxIdx
|
|
|
-}
|
|
|
-
|
|
|
-// Mult - Vector arithmetic multiply
|
|
|
-func Mult(inReal0 []float64, inReal1 []float64) []float64 {
|
|
|
- outReal := make([]float64, len(inReal0))
|
|
|
- for i := 0; i < len(inReal0); i++ {
|
|
|
- outReal[i] = inReal0[i] * inReal1[i]
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Sub - Vector arithmetic subtraction
|
|
|
-func Sub(inReal0 []float64, inReal1 []float64) []float64 {
|
|
|
- outReal := make([]float64, len(inReal0))
|
|
|
- for i := 0; i < len(inReal0); i++ {
|
|
|
- outReal[i] = inReal0[i] - inReal1[i]
|
|
|
- }
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// Sum - Vector summation
|
|
|
-func Sum(inReal []float64, inTimePeriod int) []float64 {
|
|
|
-
|
|
|
- outReal := make([]float64, len(inReal))
|
|
|
-
|
|
|
- lookbackTotal := inTimePeriod - 1
|
|
|
- startIdx := lookbackTotal
|
|
|
- periodTotal := 0.0
|
|
|
- trailingIdx := startIdx - lookbackTotal
|
|
|
- i := trailingIdx
|
|
|
- if inTimePeriod > 1 {
|
|
|
- for i < startIdx {
|
|
|
- periodTotal += inReal[i]
|
|
|
- i++
|
|
|
- }
|
|
|
- }
|
|
|
- outIdx := startIdx
|
|
|
- for i < len(inReal) {
|
|
|
- periodTotal += inReal[i]
|
|
|
- tempReal := periodTotal
|
|
|
- periodTotal -= inReal[trailingIdx]
|
|
|
- outReal[outIdx] = tempReal
|
|
|
- i++
|
|
|
- trailingIdx++
|
|
|
- outIdx++
|
|
|
- }
|
|
|
-
|
|
|
- return outReal
|
|
|
-}
|
|
|
-
|
|
|
-// HeikinashiCandles - from candle values extracts heikinashi candle values.
|
|
|
-//
|
|
|
-// Returns highs, opens, closes and lows of the heikinashi candles (in this order).
|
|
|
-//
|
|
|
-// NOTE: The number of Heikin-Ashi candles will always be one less than the number of provided candles, due to the fact
|
|
|
-// that a previous candle is necessary to calculate the Heikin-Ashi candle, therefore the first provided candle is not considered
|
|
|
-// as "current candle" in the algorithm, but only as "previous candle".
|
|
|
-func HeikinashiCandles(highs []float64, opens []float64, closes []float64, lows []float64) ([]float64, []float64, []float64, []float64) {
|
|
|
- N := len(highs)
|
|
|
-
|
|
|
- heikinHighs := make([]float64, N)
|
|
|
- heikinOpens := make([]float64, N)
|
|
|
- heikinCloses := make([]float64, N)
|
|
|
- heikinLows := make([]float64, N)
|
|
|
-
|
|
|
- for currentCandle := 1; currentCandle < N; currentCandle++ {
|
|
|
- previousCandle := currentCandle - 1
|
|
|
-
|
|
|
- heikinHighs[currentCandle] = math.Max(highs[currentCandle], math.Max(opens[currentCandle], closes[currentCandle]))
|
|
|
- heikinOpens[currentCandle] = (opens[previousCandle] + closes[previousCandle]) / 2
|
|
|
- heikinCloses[currentCandle] = (highs[currentCandle] + opens[currentCandle] + closes[currentCandle] + lows[currentCandle]) / 4
|
|
|
- heikinLows[currentCandle] = math.Min(highs[currentCandle], math.Min(opens[currentCandle], closes[currentCandle]))
|
|
|
- }
|
|
|
-
|
|
|
- return heikinHighs, heikinOpens, heikinCloses, heikinLows
|
|
|
-}
|
|
|
-
|
|
|
-// Hlc3 returns the Hlc3 values
|
|
|
-//
|
|
|
-// NOTE: Every Hlc item is defined as follows : (high + low + close) / 3
|
|
|
-// It is used as AvgPrice candle.
|
|
|
-func Hlc3(highs []float64, lows []float64, closes []float64) []float64 {
|
|
|
- N := len(highs)
|
|
|
- result := make([]float64, N)
|
|
|
- for i := range highs {
|
|
|
- result[i] = (highs[i] + lows[i] + closes[i]) / 3
|
|
|
- }
|
|
|
-
|
|
|
- return result
|
|
|
-}
|
|
|
-
|
|
|
-// Crossover returns true if series1 is crossing over series2.
|
|
|
-//
|
|
|
-// NOTE: Usually this is used with Media Average Series to check if it crosses for buy signals.
|
|
|
-// It assumes first values are the most recent.
|
|
|
-// The crossover function does not use most recent value, since usually it's not a complete candle.
|
|
|
-// The second recent values and the previous are used, instead.
|
|
|
-func Crossover(series1 []float64, series2 []float64) bool {
|
|
|
- if len(series1) < 3 || len(series2) < 3 {
|
|
|
- return false
|
|
|
- }
|
|
|
-
|
|
|
- N := len(series1)
|
|
|
-
|
|
|
- return series1[N-2] <= series2[N-2] && series1[N-1] > series2[N-1]
|
|
|
-}
|
|
|
-
|
|
|
-// Crossunder returns true if series1 is crossing under series2.
|
|
|
-//
|
|
|
-// NOTE: Usually this is used with Media Average Series to check if it crosses for sell signals.
|
|
|
-func Crossunder(series1 []float64, series2 []float64) bool {
|
|
|
- if len(series1) < 3 || len(series2) < 3 {
|
|
|
- return false
|
|
|
- }
|
|
|
-
|
|
|
- N := len(series1)
|
|
|
-
|
|
|
- return series1[N-1] <= series2[N-1] && series1[N-2] > series2[N-2]
|
|
|
-}
|
|
|
-
|
|
|
-// GroupCandles groups a set of candles in another set of candles, basing on a grouping factor.
|
|
|
-//
|
|
|
-// This is pretty useful if you want to transform, for example, 15min candles into 1h candles using same data.
|
|
|
-//
|
|
|
-// This avoid calling multiple times the exchange for multiple contexts.
|
|
|
-//
|
|
|
-// Example:
|
|
|
-//
|
|
|
-// To transform 15 minute candles in 30 minutes candles you have a grouping factor = 2
|
|
|
-//
|
|
|
-// To transform 15 minute candles in 1 hour candles you have a grouping factor = 4
|
|
|
-//
|
|
|
-// To transform 30 minute candles in 1 hour candles you have a grouping factor = 2
|
|
|
-func GroupCandles(highs []float64, opens []float64, closes []float64, lows []float64, groupingFactor int) ([]float64, []float64, []float64, []float64, error) {
|
|
|
- N := len(highs)
|
|
|
- if groupingFactor == 0 {
|
|
|
- return nil, nil, nil, nil, errors.New("Grouping factor must be > 0")
|
|
|
- } else if groupingFactor == 1 {
|
|
|
- return highs, opens, closes, lows, nil // no need to group in this case, return the parameters.
|
|
|
- }
|
|
|
- if N%groupingFactor > 0 {
|
|
|
- return nil, nil, nil, nil, errors.New("Cannot group properly, need a groupingFactor which is a factor of the number of candles")
|
|
|
- }
|
|
|
-
|
|
|
- groupedN := N / groupingFactor
|
|
|
-
|
|
|
- groupedHighs := make([]float64, groupedN)
|
|
|
- groupedOpens := make([]float64, groupedN)
|
|
|
- groupedCloses := make([]float64, groupedN)
|
|
|
- groupedLows := make([]float64, groupedN)
|
|
|
-
|
|
|
- lastOfCurrentGroup := groupingFactor - 1
|
|
|
-
|
|
|
- k := 0
|
|
|
- for i := 0; i < N; i += groupingFactor { // scan all param candles
|
|
|
- groupedOpens[k] = opens[i]
|
|
|
- groupedCloses[k] = closes[i+lastOfCurrentGroup]
|
|
|
-
|
|
|
- groupedHighs[k] = highs[i]
|
|
|
- groupedLows[k] = lows[i]
|
|
|
-
|
|
|
- endOfCurrentGroup := i + lastOfCurrentGroup
|
|
|
- for j := i + 1; j <= endOfCurrentGroup; j++ { // group high lows candles here
|
|
|
- if lows[j] < groupedLows[k] {
|
|
|
- groupedLows[k] = lows[j]
|
|
|
- }
|
|
|
- if highs[j] > groupedHighs[k] {
|
|
|
- groupedHighs[k] = highs[j]
|
|
|
- }
|
|
|
- }
|
|
|
- k++
|
|
|
- }
|
|
|
- return groupedHighs, groupedOpens, groupedCloses, groupedLows, nil
|
|
|
-}
|