The set of trading indicators
$ go get github.com/evsamsonov/trading-indicators/indicator All indicators requires trading data in timeseries structure
dataset := []struct {
Time time.Time
High float64
Low float64
Open float64
Close float64
Volume int64
}{
{Time: time.Unix(1121979600, 0), High: 23, Low: 21.27, Open: 21.3125, Close: 22.1044, Volume: 4604900},
{Time: time.Unix(1122238800, 0), High: 23.31999, Low: 22.15, Open: 22.15, Close: 23.21608, Volume: 4132600},
}
series := timeseries.New()
for _, item := range dataset {
candle := timeseries.NewCandle(item.Time)
candle.Open = item.Open
candle.Close = item.Close
candle.High = item.High
candle.Low = item.Low
candle.Volume = item.Volume
err := series.AddCandle(candle)
if err != nil {
log.Printf("Failed to add candle: %v\n", err)
}
}Indicator calculates Average True Range (ATR)
period := 2
atrIndicator := indicator.NewAverageTrueRange(series, period)
fmt.Println(atrIndicator.Calculate(1)) // 1.4727950000000014Indicator calculates Average True Range using a simple moving average of the true range values.
period := 3
smaAtr := indicator.NewSmaAverageTrueRange(series, period)
fmt.Println(smaAtr.Calculate(3)) You can filter candles using WithSmaAverageTrueRangeFilter option. Filtered candles are skipped and the indicator looks back further to collect the required number of candles.
filter := func(i int, candle *timeseries.Candle) bool {
return candle.Volume > 0
}
period := 3
smaAtr := indicator.NewSmaAverageTrueRange(
series,
period,
indicator.WithSmaAverageTrueRangeFilter(filter),
)
fmt.Println(smaAtr.Calculate(3))Indicator calculates Average Volume
period := 2
atrIndicator := indicator.NewAverageVolume(series, period)
fmt.Println(atrIndicator.Calculate(1)) // 4368750You can filter candles using WithAverageVolumeFilter option. Filtered candles are skipped during calculation, and the indicator looks back further to collect the required number of candles.
// Skip candles with zero volume
filter := func(i int, candle *timeseries.Candle) bool {
return candle.Volume > 0
}
period := 2
avgVolume := indicator.NewAverageVolume(series, period, indicator.WithAverageVolumeFilter(filter))
fmt.Println(avgVolume.Calculate(1))Indicator calculates Exponential Moving Average
smoothInterval := 2
atrIndicator := indicator.NewExponentialMovingAverage(series, smoothInterval)
fmt.Println(atrIndicator.Calculate(1)) // 22.84552You can filter candles using WithExponentialMovingAverageFilter option. When a candle is filtered out, the indicator uses the previous EMA value instead of recalculating.
// Skip candles with low volume
filter := func(i int, candle *timeseries.Candle) bool {
return candle.Volume > 1000000
}
smoothInterval := 2
ema := indicator.NewExponentialMovingAverage(series, smoothInterval, indicator.WithExponentialMovingAverageFilter(filter))
fmt.Println(ema.Calculate(1))The indicator returns a trend direction. It bases on fast (with shorter period) and slow EMA. The third parameter (flatMaxDiff) of NewTrend allows setting max difference between fast and slow EMA when Calculate returns the flat. Option TrendWithFlatMaxDiffInPercent allows to pass flatMaxDiff in percent
fastEMAIndicator, err := indicator.NewExponentialMovingAverage(series, 14)
if err != nil {
log.Fatalln(err)
}
slowEMAIndicator, err := indicator.NewExponentialMovingAverage(series, 50)
if err != nil {
log.Fatalln(err)
}
trendIndicator := indicator.NewTrend(fastEMAIndicator, slowEMAIndicator, 0.6, TrendWithFlatMaxDiffInPercent(false))
trend := trendIndicator.Calculate(1)
switch trend {
case indicator.UpTrend:
fmt.Println("Up trend")
case indicator.DownTrend:
fmt.Println("Down trend")
case indicator.FlatTrend:
fmt.Println("Flat trend")
}