diff --git a/ad.go b/ad.go index eaab1b4..af4af73 100644 --- a/ad.go +++ b/ad.go @@ -40,6 +40,10 @@ func (a *Ad) InitPeriod() int64 { return 0 } +func (a *Ad) Valid() bool { + return true +} + // Developed by Marc Chaikin, the Accumulation Distribution // Line is a volume-based indicator designed to measure the // cumulative flow of money into and out of a security. diff --git a/adosc.go b/adosc.go index 515cb78..0d1a19a 100644 --- a/adosc.go +++ b/adosc.go @@ -48,6 +48,7 @@ func NewAdOsc(fastN, slowN int64) *AdOsc { func (a *AdOsc) Update(h, l, c, v float64) float64 { a.sz++ + ad := a.ad.Update(h, l, c, v) if a.sz == 1 { a.fast = ad @@ -67,6 +68,10 @@ func (a *AdOsc) InitPeriod() int64 { return a.slowN - 1 } +func (a *AdOsc) Valid() bool { + return a.sz > a.InitPeriod() +} + // Developed by Marc Chaikin, the Chaikin Oscillator measures the // momentum of the Accumulation Distribution Line using the MACD // formula. (This makes it an indicator of an indicator.) The diff --git a/adx.go b/adx.go index f698afd..3339bcd 100644 --- a/adx.go +++ b/adx.go @@ -48,6 +48,7 @@ func NewAdx(n int64) *Adx { func (a *Adx) Update(h, l, c float64) float64 { a.sz++ + dx := a.dx.Update(h, l, c) if a.sz <= a.n { @@ -61,6 +62,10 @@ func (a *Adx) InitPeriod() int64 { return a.n } +func (a *Adx) Valid() bool { + return a.sz > a.InitPeriod() +} + // The Average Directional Index (ADX), Minus Directional // Indicator (-DI) and Plus Directional Indicator (+DI) // represent a group of directional movement indicators diff --git a/adxr.go b/adxr.go index ceb8c01..59190a0 100644 --- a/adxr.go +++ b/adxr.go @@ -32,6 +32,10 @@ func (a *AdxR) InitPeriod() int64 { return 3*a.n - 2 } +func (a *AdxR) Valid() bool { + return a.hist.size() > a.InitPeriod() +} + // Average Directional Movement Index Rating (ADXR) is a simple // average of today’s ADX value and the ADX from N periods ago. // https://www.fidelity.com/learning-center/trading-investing/technical-analysis/technical-indicator-guide/dmi diff --git a/apo.go b/apo.go index c229413..a8e0934 100644 --- a/apo.go +++ b/apo.go @@ -26,6 +26,7 @@ func NewApo(t MaType, fastN, slowN int64) *Apo { func (a *Apo) Update(v float64) float64 { a.sz++ + fast := a.fastMa.Update(v) slow := a.slowMa.Update(v) @@ -40,6 +41,10 @@ func (a *Apo) InitPeriod() int64 { return a.slowN - 1 } +func (a *Apo) Valid() bool { + return a.sz > a.InitPeriod() +} + // The Absolute Price Oscillator displays the difference // between two exponential moving averages of a security's // price and is expressed as an absolute value. diff --git a/aroon.go b/aroon.go index 842e2da..30d8ef2 100644 --- a/aroon.go +++ b/aroon.go @@ -40,9 +40,10 @@ func (a *Aroon) aroonValue(idx int64) float64 { } func (a *Aroon) Update(h, l float64) (float64, float64) { + a.sz++ + minIdx, _ := a.min.Update(l) maxIdx, _ := a.max.Update(h) - a.sz++ if a.sz <= a.n { return 0, 0 @@ -55,6 +56,10 @@ func (a *Aroon) InitPeriod() int64 { return a.n } +func (a *Aroon) Valid() bool { + return a.sz > a.InitPeriod() +} + // Developed by Tushar Chande in 1995, Aroon is an indicator // system that determines whether a stock is trending or not // and how strong the trend is. “Aroon” means “Dawn's Early Light” diff --git a/aroonosc.go b/aroonosc.go index 56c61d5..6ec3eba 100644 --- a/aroonosc.go +++ b/aroonosc.go @@ -34,6 +34,10 @@ func (a *AroonOsc) InitPeriod() int64 { return a.aroon.InitPeriod() } +func (a *AroonOsc) Valid() bool { + return a.aroon.Valid() +} + // The Aroon Oscillator is the difference between Aroon-Up // and Aroon-Down. These two indicators are usually plotted // together for easy comparison, but chartists can also view diff --git a/atr.go b/atr.go index b4ab751..3c4f57e 100644 --- a/atr.go +++ b/atr.go @@ -38,8 +38,10 @@ func NewAtr(n int64) *Atr { } func (a *Atr) Update(h, l, c float64) float64 { - tr := a.tr.Update(h, l, c) a.sz++ + + tr := a.tr.Update(h, l, c) + if a.sz == 1 { return 0 } @@ -51,6 +53,10 @@ func (a *Atr) InitPeriod() int64 { return 1 } +func (a *Atr) Valid() bool { + return a.sz > 1 +} + // Developed by J. Welles Wilder, the Average True Range (ATR) // is an indicator that measures volatility. As with most of // his indicators, Wilder designed ATR with commodities and diff --git a/bbands.go b/bbands.go index e9183bf..0161d0a 100644 --- a/bbands.go +++ b/bbands.go @@ -21,6 +21,7 @@ type BBands struct { stdDev *StdDev upNStdDev float64 dnNStdDev float64 + sz int64 } func NewBBands(t MaType, n int64, upNStdDev, dnNStdDev float64) *BBands { @@ -37,11 +38,14 @@ func NewBBands(t MaType, n int64, upNStdDev, dnNStdDev float64) *BBands { stdDev: stdDev, upNStdDev: upNStdDev, dnNStdDev: dnNStdDev, + sz: 0, } } // upper, middle, lower func (b *BBands) Update(v float64) (float64, float64, float64) { + b.sz++ + m := b.ma.Update(v) stddev := b.stdDev.Update(v) @@ -52,6 +56,10 @@ func (b *BBands) InitPeriod() int64 { return b.initPeriod } +func (b *BBands) Valid() bool { + return b.sz > b.initPeriod +} + // Developed by John Bollinger, Bollinger Bands are volatility // bands placed above and below a moving average. Volatility // is based on the standard deviation, which changes as volatility diff --git a/bop.go b/bop.go index ff33570..965ae63 100644 --- a/bop.go +++ b/bop.go @@ -31,6 +31,10 @@ func (b *Bop) InitPeriod() int64 { return 0 } +func (b *Bop) Valid() bool { + return true +} + // Balance of Power (BOP) is an oscillator that measures the // strength of buying and selling pressure. Introduced by Igor // Levshin in the August 2001 issue of Technical Analysis of diff --git a/cci.go b/cci.go index d51837a..7d3827b 100644 --- a/cci.go +++ b/cci.go @@ -20,6 +20,7 @@ type Cci struct { initPeriod int64 avg *Sma dev *Dev + sz int64 } func NewCci(n int64) *Cci { @@ -35,10 +36,13 @@ func NewCci(n int64) *Cci { initPeriod: a, avg: avg, dev: dev, + sz: 0, } } func (d *Cci) Update(h, l, c float64) float64 { + d.sz++ + m := (h + l + c) / 3.0 avg := d.avg.Update(m) dev := d.dev.Update(m) @@ -54,6 +58,10 @@ func (d *Cci) InitPeriod() int64 { return d.initPeriod } +func (d *Cci) Valid() bool { + return d.sz > d.initPeriod +} + // Developed by Donald Lambert and featured in Commodities // magazine in 1980, the Commodity Channel Index (CCI) is // a versatile indicator that can be used to identify a new diff --git a/cmo.go b/cmo.go index 49297e6..8e969ea 100644 --- a/cmo.go +++ b/cmo.go @@ -37,9 +37,10 @@ func NewCmo(n int64) *Cmo { } func (c *Cmo) Update(v float64) float64 { + c.sz++ + d := v - c.prevC c.prevC = v - c.sz++ if c.sz == 1 { return 0 @@ -66,6 +67,10 @@ func (c *Cmo) InitPeriod() int64 { return c.initPeriod } +func (c *Cmo) Valid() bool { + return c.sz > c.initPeriod +} + // The Chande momentum oscillator is a technical momentum // indicator introduced by Tushar Chande in his 1994 book // The New Technical Trader. The formula calculates the diff --git a/dema.go b/dema.go index 63d8793..30ecf2d 100644 --- a/dema.go +++ b/dema.go @@ -14,22 +14,23 @@ package tart // https://www.investopedia.com/terms/d/double-exponential-moving-average.asp type Dema struct { n int64 - sz int64 ema1 *Ema ema2 *Ema + sz int64 } func NewDema(n int64, k float64) *Dema { return &Dema{ n: n, - sz: 0, ema1: NewEma(n, k), ema2: NewEma(n, k), + sz: 0, } } func (d *Dema) Update(v float64) float64 { d.sz++ + e1 := d.ema1.Update(v) if d.sz > d.n-1 { @@ -46,6 +47,10 @@ func (d *Dema) InitPeriod() int64 { return d.n*2 - 2 } +func (d *Dema) Valid() bool { + return d.sz > d.InitPeriod() +} + // The Double Exponential Moving Average (DEMA) reduces the lag // of traditional EMAs, making it more responsive and better-suited // for short-term traders. DEMA was developed by Patrick Mulloy, diff --git a/diff.go b/diff.go index b48128d..07eec97 100644 --- a/diff.go +++ b/diff.go @@ -23,6 +23,7 @@ func NewDiff(n int64) *Diff { func (d *Diff) Update(v float64) float64 { d.sz++ + old := d.hist.append(v) if d.sz <= d.n { @@ -36,6 +37,10 @@ func (d *Diff) InitPeriod() int64 { return d.n } +func (d *Diff) Valid() bool { + return d.sz > d.InitPeriod() +} + // This is also known as Momentum (MOM). // The Momentum (MOM) indicator compares the current price with // the previous price from a selected number of periods ago. diff --git a/dx.go b/dx.go index 2524632..e196245 100644 --- a/dx.go +++ b/dx.go @@ -31,13 +31,14 @@ func NewDx(n int64) *Dx { } func (d *Dx) Update(h, l, c float64) float64 { + d.sz++ + tr := d.tr.Update(h, l, c) plusDm := h - d.prevH minusDm := d.prevL - l d.prevH = h d.prevL = l - d.sz++ if d.sz == 1 { return 0 } @@ -73,6 +74,10 @@ func (d *Dx) InitPeriod() int64 { return d.n } +func (d *Dx) Valid() bool { + return d.sz > d.InitPeriod() +} + // Refer to ADX. // https://school.stockcharts.com/doku.php?id=technical_indicators:average_directional_index_adx func DxArr(h, l, c []float64, n int64) []float64 { diff --git a/ema.go b/ema.go index cc2c901..f966e80 100644 --- a/ema.go +++ b/ema.go @@ -29,6 +29,7 @@ func NewEma(n int64, k float64) *Ema { func (e *Ema) Update(v float64) float64 { e.sz++ + if e.sz <= e.n { e.ma += v / float64(e.n) if e.sz < e.n { @@ -45,6 +46,10 @@ func (e *Ema) InitPeriod() int64 { return e.n - 1 } +func (e *Ema) Valid() bool { + return e.sz > e.InitPeriod() +} + // Exponential moving averages (EMAs) reduce the lag by // applying more weight to recent prices. The weighting // applied to the most recent price depends on the number diff --git a/exmaple/main.go b/exmaple/main.go index 1cbe99f..efb5aed 100644 --- a/exmaple/main.go +++ b/exmaple/main.go @@ -9,6 +9,11 @@ import ( func main() { sma := tart.NewSma(5) for i := 0; i < 20; i++ { - fmt.Printf("sma[%v] = %.4f\n", i, sma.Update(float64(i%7))) + val := sma.Update(float64(i % 7)) + if sma.Valid() { + fmt.Printf("sma[%v] = %.4f\n", i, val) + } else { + fmt.Printf("sma[%v] = unavail.\n", i) + } } } diff --git a/kama.go b/kama.go index 4fb3426..59e7d10 100644 --- a/kama.go +++ b/kama.go @@ -77,6 +77,10 @@ func (k *Kama) InitPeriod() int64 { return k.n } +func (k *Kama) Valid() bool { + return k.sz > k.InitPeriod() +} + // Developed by Perry Kaufman, Kaufman's Adaptive Moving // Average (KAMA) is a moving average designed to account // for market noise or volatility. KAMA will closely follow diff --git a/ma.go b/ma.go index 7fcc50a..773ba37 100644 --- a/ma.go +++ b/ma.go @@ -53,6 +53,10 @@ func (m *Ma) InitPeriod() int64 { return m.mu.InitPeriod() } +func (m *Ma) Valid() bool { + return m.mu.Valid() +} + // Convenient wrapper for different moving average types func MaArr(t MaType, in []float64, n int64) []float64 { out := make([]float64, len(in)) @@ -68,4 +72,5 @@ func MaArr(t MaType, in []float64, n int64) []float64 { type maUpdater interface { Update(v float64) float64 InitPeriod() int64 + Valid() bool } diff --git a/macdext.go b/macdext.go index fe316d1..9635f9c 100644 --- a/macdext.go +++ b/macdext.go @@ -32,6 +32,7 @@ func NewMacdExt(fastT MaType, fastN int64, slowT MaType, slowN int64, signalT Ma func (m *MacdExt) Update(v float64) (float64, float64, float64) { m.sz++ + slow := m.slow.Update(v) if m.sz <= m.slowN-m.fastN { @@ -60,6 +61,10 @@ func (m *MacdExt) InitPeriod() int64 { return m.n - 1 } +func (m *MacdExt) Valid() bool { + return m.sz > m.InitPeriod() +} + // Refer to MACD. // This is a general version of MACD with moving average types // for fast, slow, and signal lines as paremters. diff --git a/max.go b/max.go index 8620660..a14f80e 100644 --- a/max.go +++ b/max.go @@ -39,6 +39,10 @@ func (m *Max) InitPeriod() int64 { return m.n - 1 } +func (m *Max) Valid() bool { + return m.hist.size() > m.InitPeriod() +} + // Max value of the selected period. func MaxArr(in []float64, n int64) ([]int64, []float64) { outIdx := make([]int64, len(in)) diff --git a/mfi.go b/mfi.go index 1bb03ca..9be0bff 100644 --- a/mfi.go +++ b/mfi.go @@ -34,10 +34,11 @@ func NewMfi(n int64) *Mfi { } func (m *Mfi) Update(h, l, c, v float64) float64 { + m.sz++ + tp := (h + l + c) / 3.0 prevTp := m.prevTp m.prevTp = tp - m.sz++ if m.sz == 1 { return 0 @@ -64,6 +65,10 @@ func (m *Mfi) InitPeriod() int64 { return m.n } +func (m *Mfi) Valid() bool { + return m.sz > m.InitPeriod() +} + // The Money Flow Index (MFI) is an oscillator that uses // both price and volume to measure buying and selling // pressure. Created by Gene Quong and Avrum Soudack, diff --git a/min.go b/min.go index eeba9e5..ab327f5 100644 --- a/min.go +++ b/min.go @@ -39,6 +39,10 @@ func (m *Min) InitPeriod() int64 { return m.n - 1 } +func (m *Min) Valid() bool { + return m.hist.size() > m.InitPeriod() +} + // Min value of the selected period. func MinArr(in []float64, n int64) ([]int64, []float64) { outIdx := make([]int64, len(in)) diff --git a/natr.go b/natr.go index d74eedd..a4211f0 100644 --- a/natr.go +++ b/natr.go @@ -27,6 +27,10 @@ func (a *Natr) InitPeriod() int64 { return a.atr.InitPeriod() } +func (a *Natr) Valid() bool { + return a.atr.Valid() +} + // Normalized Average True Range (NATR) attempts to normalize // the average true range values across instruments by using // the closing price. diff --git a/obv.go b/obv.go index 9d2f98d..3ba977d 100644 --- a/obv.go +++ b/obv.go @@ -49,6 +49,10 @@ func (o *Obv) InitPeriod() int64 { return 0 } +func (o *Obv) Valid() bool { + return true +} + // On Balance Volume (OBV) measures buying and selling // pressure as a cumulative indicator, adding volume on // up days and subtracting it on down days. OBV was diff --git a/ppo.go b/ppo.go index e329549..51c4f7b 100644 --- a/ppo.go +++ b/ppo.go @@ -35,10 +35,11 @@ func NewPpo(t MaType, fastN, slowN int64) *Ppo { } func (p *Ppo) Update(v float64) float64 { + p.sz++ + fast := p.fast.Update(v) slow := p.slow.Update(v) - p.sz++ if p.sz < p.slowN { return 0 } @@ -53,6 +54,10 @@ func (p *Ppo) InitPeriod() int64 { return p.slowN - 1 } +func (p *Ppo) Valid() bool { + return p.sz > p.InitPeriod() +} + // The Percentage Price Oscillator (PPO) is a momentum oscillator // that measures the difference between two moving averages as a // percentage of the larger moving average. As with its cousin, diff --git a/roc.go b/roc.go index 4f5c27f..6ad7fe5 100644 --- a/roc.go +++ b/roc.go @@ -30,9 +30,10 @@ func NewRoc(n int64) *Roc { } func (r *Roc) Update(v float64) float64 { + r.sz++ + old := r.hist.append(v) - r.sz++ if r.sz <= r.n { return 0 } @@ -47,6 +48,10 @@ func (r *Roc) InitPeriod() int64 { return r.n } +func (r *Roc) Valid() bool { + return r.sz > r.InitPeriod() +} + // The Rate-of-Change (ROC) indicator, which is also referred to as simply // Momentum, is a pure momentum oscillator that measures the percent change // in price from one period to the next. The ROC calculation compares the diff --git a/rsi.go b/rsi.go index bdb2256..c495a99 100644 --- a/rsi.go +++ b/rsi.go @@ -39,9 +39,10 @@ func NewRsi(n int64) *Rsi { } func (r *Rsi) Update(v float64) float64 { + r.sz++ + chg := v - r.prevC r.prevC = v - r.sz++ if r.sz == 1 { return 0 @@ -72,6 +73,10 @@ func (r *Rsi) InitPeriod() int64 { return r.n } +func (r *Rsi) Valid() bool { + return r.sz > r.InitPeriod() +} + // Developed by J. Welles Wilder, the Relative Strength Index (RSI) is a momentum // oscillator that measures the speed and change of price movements. RSI oscillates // between zero and 100. According to Wilder, RSI is considered overbought when diff --git a/sma.go b/sma.go index 1368698..2f194d4 100644 --- a/sma.go +++ b/sma.go @@ -27,10 +27,11 @@ func NewSma(n int64) *Sma { } func (s *Sma) Update(v float64) float64 { + s.sz++ + old := s.hist.append(v) s.sum += v - old - s.sz++ if s.sz < s.n { return 0 } @@ -42,6 +43,10 @@ func (s *Sma) InitPeriod() int64 { return s.n - 1 } +func (s *Sma) Valid() bool { + return s.sz > s.InitPeriod() +} + // A simple moving average is formed by computing the average price of a security // over a specific number of periods. Most moving averages are based on closing // prices; for example, a 5-day simple moving average is the five-day sum of closing diff --git a/stddev.go b/stddev.go index 15e0bdf..f9208ac 100644 --- a/stddev.go +++ b/stddev.go @@ -34,6 +34,10 @@ func (s *StdDev) InitPeriod() int64 { return s.v.InitPeriod() } +func (s *StdDev) Valid() bool { + return s.v.Valid() +} + // Standard deviation is a statistical term that measures the amount of // variability or dispersion around an average. Standard deviation is also // a measure of volatility. Generally speaking, dispersion is the difference diff --git a/stochfast.go b/stochfast.go index 2dc13d6..df28905 100644 --- a/stochfast.go +++ b/stochfast.go @@ -33,9 +33,10 @@ func NewStochFast(kN int64, dt MaType, dN int64) *StochFast { } func (s *StochFast) Update(h, l, c float64) (float64, float64) { - k := s.stochK.Update(h, l, c) s.sz++ + k := s.stochK.Update(h, l, c) + if s.sz < s.kN { return 0, 0 } @@ -52,6 +53,10 @@ func (s *StochFast) InitPeriod() int64 { return s.kN + s.dN - 2 } +func (s *StochFast) Valid() bool { + return s.sz > s.InitPeriod() +} + // Developed by George C. Lane in the late 1950s, the Stochastic Oscillator is // a momentum indicator that shows the location of the close relative to the // high-low range over a set number of periods. According to an interview with diff --git a/stochrsi.go b/stochrsi.go index f741f47..b13de68 100644 --- a/stochrsi.go +++ b/stochrsi.go @@ -37,6 +37,7 @@ func NewStochRsi(n int64, kN int64, dt MaType, dN int64) *StochRsi { func (s *StochRsi) Update(v float64) (float64, float64) { s.sz++ + rsi := s.rsi.Update(v) if s.sz <= s.n { @@ -54,6 +55,10 @@ func (s *StochRsi) InitPeriod() int64 { return s.util - 1 } +func (s *StochRsi) Valid() bool { + return s.sz > s.InitPeriod() +} + // Developed by Tushar Chande and Stanley Kroll, StochRSI is an oscillator that // measures the level of RSI relative to its high-low range over a set time period. // StochRsi applies the Stochastics formula to RSI values, rather than price values, diff --git a/stochslow.go b/stochslow.go index d5c9d65..e8dcc96 100644 --- a/stochslow.go +++ b/stochslow.go @@ -33,6 +33,7 @@ func NewStochSlow(fastKN int64, kt MaType, slowKN int64, dt MaType, slowDN int64 func (s *StochSlow) Update(h, l, c float64) (float64, float64) { s.sz++ + fastK := s.stochK.Update(h, l, c) if s.sz < s.fastKN { @@ -52,6 +53,10 @@ func (s *StochSlow) InitPeriod() int64 { return s.util - 1 } +func (s *StochSlow) Valid() bool { + return s.sz > s.InitPeriod() +} + // The Slow Stochastic Oscillator is a momentum indicator that shows the location // of the close relative to the high-low range over a set number of periods. The // indicator can range from 0 to 100. The difference between the Slow and Fast diff --git a/sum.go b/sum.go index e88e764..31d7484 100644 --- a/sum.go +++ b/sum.go @@ -30,6 +30,10 @@ func (s *Sum) InitPeriod() int64 { return s.n - 1 } +func (s *Sum) Valid() bool { + return s.hist.size() > s.InitPeriod() +} + func SumArr(in []float64, n int64) []float64 { out := make([]float64, len(in)) diff --git a/tema.go b/tema.go index 2bafbc8..f7730bb 100644 --- a/tema.go +++ b/tema.go @@ -31,9 +31,10 @@ func NewTema(n int64, k float64) *Tema { } func (t *Tema) Update(v float64) float64 { - e1 := t.ema1.Update(v) t.sz++ + e1 := t.ema1.Update(v) + if t.sz > t.n-1 { e2 := t.ema2.Update(e1) @@ -53,6 +54,10 @@ func (t *Tema) InitPeriod() int64 { return t.n*3 - 3 } +func (t *Tema) Valid() bool { + return t.sz > t.InitPeriod() +} + // The Triple Exponential Moving Average (TEMA) reduces the lag of traditional // EMAs, making it more responsive and better-suited for short-term trading. // Shortly after developing the Double Exponential Moving Average (DEMA) in 1994, diff --git a/trange.go b/trange.go index 58a3161..0675151 100644 --- a/trange.go +++ b/trange.go @@ -23,10 +23,11 @@ func NewTRange() *TRange { } func (t *TRange) Update(h, l, c float64) float64 { + t.sz++ + d0 := math.Abs(h - t.prevC) d1 := math.Abs(l - t.prevC) t.prevC = c - t.sz++ if t.sz == 1 { return 0 @@ -42,6 +43,10 @@ func (t *TRange) InitPeriod() int64 { return 1 } +func (t *TRange) Valid() bool { + return t.sz > t.InitPeriod() +} + // Welles Wilder described these calculations to determine the trading range // for a stock or commodity. True Range is defined as the largest of the // following: (1) The distance from today's high to today's low. (2) The diff --git a/trima.go b/trima.go index 7a06463..5fb5cb7 100644 --- a/trima.go +++ b/trima.go @@ -69,6 +69,10 @@ func (t *Trima) InitPeriod() int64 { return t.n - 1 } +func (t *Trima) Valid() bool { + return t.hist.size() > t.InitPeriod() +} + // The triangular moving average (TMA) is a technical indicator that is similar // to other moving averages. The TMA shows the average (or mean) price of an // asset over a specified number of data points—usually a number of price bars. diff --git a/trix.go b/trix.go index e421845..a93334b 100644 --- a/trix.go +++ b/trix.go @@ -34,6 +34,7 @@ func NewTrix(n int64) *Trix { func (t *Trix) Update(v float64) float64 { t.sz++ + v = t.ema1.Update(v) if t.sz < t.n { return 0 @@ -61,6 +62,10 @@ func (t *Trix) InitPeriod() int64 { return 3*t.n - 3 } +func (t *Trix) Valid() bool { + return t.sz > t.InitPeriod() +} + // TRIX is a momentum oscillator that displays the percent rate of change of // a triple exponentially smoothed moving average. It was developed in the // early 1980's by Jack Hutson, an editor for Technical Analysis of Stocks diff --git a/ultosc.go b/ultosc.go index 2564ed1..516a507 100644 --- a/ultosc.go +++ b/ultosc.go @@ -86,6 +86,10 @@ func (u *UltOsc) InitPeriod() int64 { return u.n3 } +func (u *UltOsc) Valid() bool { + return u.sz > u.InitPeriod() +} + // Developed by Larry Williams in 1976 and featured in Stocks & Commodities // Magazine in 1985, the Ultimate Oscillator is a momentum oscillator designed // to capture momentum across three different timeframes. The multiple timeframe diff --git a/var.go b/var.go index 54dabaa..9dbaf98 100644 --- a/var.go +++ b/var.go @@ -44,6 +44,10 @@ func (r *Var) InitPeriod() int64 { return r.n - 1 } +func (r *Var) Valid() bool { + return r.hist.size() > r.InitPeriod() +} + // The term variance refers to a statistical measurement of the spread between // numbers in a data set. More specifically, variance measures how far each // number in the set is from the mean and thus from every other number in the diff --git a/willr.go b/willr.go index 7b67d3a..8ca293d 100644 --- a/willr.go +++ b/willr.go @@ -29,6 +29,7 @@ func NewWillR(n int64) *WillR { func (w *WillR) Update(h, l, c float64) float64 { w.sz++ + k := w.stoch.Update(h, l, c) if w.sz < w.n { @@ -41,6 +42,10 @@ func (w *WillR) InitPeriod() int64 { return w.n - 1 } +func (w *WillR) Valid() bool { + return w.sz > w.InitPeriod() +} + // Developed by Larry Williams, Williams %R is a momentum indicator that is // the inverse of the Fast Stochastic Oscillator. Also referred to as %R, // Williams %R reflects the level of the close relative to the highest high diff --git a/wma.go b/wma.go index 16ba4ba..712bc76 100644 --- a/wma.go +++ b/wma.go @@ -49,6 +49,10 @@ func (w *Wma) InitPeriod() int64 { return w.n - 1 } +func (w *Wma) Valid() bool { + return w.hist.size() > w.InitPeriod() +} + // A Weighted Moving Average puts more weight on recent data and less on past // data. This is done by multiplying each bar’s price by a weighting factor. // Because of its unique calculation, WMA will follow prices more closely