# Moving Averages Supported by BanTA: A Complete Guide to 12 MA Types

> Explore 12 moving average types like SMA EMA HMA and KAMA supported by BanTA for Go and Python. Learn to implement them efficiently with slice functions and series methods.

- Repository: [banbox/banta](https://github.com/banbox/banta)
- Tags: tutorial
- Published: 2026-02-26

---

**BanTA supports 12 distinct moving average algorithms—including SMA, EMA, VWMA, WMA, HMA, KAMA, ALMA, and Wilder’s RMA—implemented as both slice-based functions and stateful Series methods for Go and Python.**

BanTA is the technical analysis engine inside the **banbox/banta** repository, designed for high-performance financial calculations. The library implements **moving averages supported by BanTA** through a dual API architecture: pure functions for batch processing in [`tav/indicators.go`](https://github.com/banbox/banta/blob/main/tav/indicators.go) and object-oriented methods for streaming data in [`sta_inds.go`](https://github.com/banbox/banta/blob/main/sta_inds.go). All implementations are NaN-tolerant, batch-optimized, and designed to handle real-world market data gaps.

## Overview of BanTA Moving Average Types

BanTA organizes its moving average implementations across two primary APIs to optimize for different computational contexts. The **slice-based functions** in [`tav/indicators.go`](https://github.com/banbox/banta/blob/main/tav/indicators.go) operate on `[]float64` slices and compute entire series in single passes. The **Series methods** in [`sta_inds.go`](https://github.com/banbox/banta/blob/main/sta_inds.go) provide stateful calculations on the `*Series` type, caching results and maintaining minimal auxiliary state for incremental updates.

### Core Design Principles

All **moving averages supported by BanTA** share three critical characteristics:

- **NaN-tolerant**: Any `math.NaN()` input produces NaN output at that index and resets internal state, handling market data gaps without manual preprocessing.
- **Batch-optimized**: Slice implementations compute entire arrays in single passes without per-point allocations.
- **Series-aware**: Stateful methods reuse cached results via `obj.To(...)` and maintain running calculations (cumulative sums, sliding windows, or exponential smoothing factors) for real-time data feeds.

## The 12 Moving Average Algorithms in BanTA

### Simple Moving Average (SMA)

The **SMA** calculates the arithmetic mean of the last *n* values. In [`tav/indicators.go`](https://github.com/banbox/banta/blob/main/tav/indicators.go), the slice implementation `func SMA(data []float64, period int) []float64` processes the entire array in a single pass. For streaming applications, [`sta_inds.go`](https://github.com/banbox/banta/blob/main/sta_inds.go) provides `func SMA(obj *Series, period int) *Series`, which maintains a sliding window sum to incrementally update averages without recalculating from scratch.

### Volume-Weighted Moving Average (VWMA)

The **VWMA** weights price by traded volume, giving high-volume bars greater influence. The slice function `func VWMA(price, volume []float64, period int) []float64` in [`tav/indicators.go`](https://github.com/banbox/banta/blob/main/tav/indicators.go) requires parallel price and volume slices. The Series method in [`sta_inds.go`](https://github.com/banbox/banta/blob/main/sta_inds.go) uses a `moreVWMA` struct to cache volume data and compute `func VWMA(obj *Series, volume *Series, period int) *Series`.

### Exponential Moving Average (EMA and EMABy)

The **EMA** applies exponential smoothing with factor α = 2/(n+1), weighting recent data more heavily. The basic implementation `func EMA(data []float64, period int) []float64` initializes using the SMA of the first period. For custom initialization, **EMABy** provides `func EMABy(data []float64, period int, initType int) []float64`, allowing the first value to be either the SMA or the first valid price. Both are available as Series methods `func EMA(obj *Series, period int) *Series` and `func EMABy(obj *Series, period int, initType int) *Series` in [`sta_inds.go`](https://github.com/banbox/banta/blob/main/sta_inds.go).

### Relative Moving Average (RMA and RMABy)

**RMA** implements Wilder’s smoothing with α = 1/n, commonly used in RSI calculations. The slice function `func RMA(data []float64, period int) []float64` and its variant **RMABy** `func RMABy(data []float64, period int, initType int, initVal float64) []float64` allow specifying an explicit initial value. The Series implementations `func RMA(obj *Series, period int) *Series` and `func RMABy(obj *Series, period int, initType int, initVal float64) *Series` maintain the running Wilder’s smoothing state for streaming data.

### Weighted Moving Average (WMA)

The **WMA** applies linear weights (1, 2, … , n) where the newest observation receives the highest weight. Implemented as `func WMA(data []float64, period int) []float64` for slices and `func WMA(obj *Series, period int) *Series` for Series objects.

### Hull Moving Average (HMA)

The **HMA** reduces lag by combining two WMAs and applying a final WMA to their difference, using period √n. The implementation `func HMA(data []float64, period int) []float64` handles the nested WMA calculations internally. The Series method `func HMA(obj *Series, period int) *Series` provides the same low-lag smoothing for streaming applications.

### Kaufman Adaptive Moving Average (KAMA)

**KAMA** adjusts smoothing based on the market “efficiency ratio,” becoming more responsive during strong trends and slower during noisy, sideways markets. The core logic resides in `func KAMABy(data []float64, period int, fast, slow float64) []float64`, with `func KAMA(data []float64, period int) []float64` serving as a convenience wrapper using default fast/slow parameters. The Series API exposes `func KAMA(obj *Series, period int) *Series`.

### Arnaud Legoux Moving Average (ALMA)

The **ALMA** uses Gaussian-shaped weights controlled by *σ* (smoothness) and *distOff* (offset), offering superior smoothness with minimal lag compared to standard moving averages. Implemented as `func ALMA(data []float64, period int, sigma, distOff float64) []float64` for slices and `func ALMA(obj *Series, period int, sigma, distOff float64) *Series` for Series objects.

## Implementation Architecture

BanTA organizes its moving average implementations across three key files to optimize for different use cases.

### Batch Processing with tav/indicators.go

The [`tav/indicators.go`](https://github.com/banbox/banta/blob/main/tav/indicators.go) file contains pure functions operating on `[]float64` slices. These implementations are **batch-optimized**, computing entire series in single passes without per-point allocations. All functions are **NaN-tolerant**: encountering `math.NaN()` resets internal state and propagates NaN to the output.

### Streaming Data with sta_inds.go

For real-time applications, [`sta_inds.go`](https://github.com/banbox/banta/blob/main/sta_inds.go) provides methods on the `*Series` type. These implementations cache results via `obj.To(...)` and maintain minimal auxiliary state—such as cumulative sums for SMA or exponential smoothing factors for EMA—to support incremental calculations in streaming scenarios.

### Python Bindings

The [`python/tav/index.go`](https://github.com/banbox/banta/blob/main/python/tav/index.go) file exposes the same moving average algorithms to Python via gopy, allowing data scientists to leverage BanTA's performance while working in Python ecosystems.

## Practical Code Examples

### Calculating SMA and EMA on Historical Data

```go
package main

import (
    "fmt"
    "github.com/banbox/banta/tav"
)

func main() {
    close := []float64{101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
                      111, 112, 113, 114, 115, 116, 117, 118, 119, 120}
    
    // Simple Moving Average
    sma20 := tav.SMA(close, 20)
    fmt.Printf("SMA(20): %v\n", sma20)
    
    // Exponential Moving Average
    ema20 := tav.EMA(close, 20)
    fmt.Printf("EMA(20): %v\n", ema20)
}

```

### Volume-Weighted Analysis with VWMA

```go
price := []float64{10, 10.2, 10.4, 10.1, 10.3, 10.5, 10.6, 10.7, 10.8, 11.0,
                   11.2, 11.1}
volume := []float64{1000, 1500, 1200, 1300, 1100, 1400, 1600, 1700, 1800, 1900,
                    2000, 2100}

vwma10 := tav.VWMA(price, volume, 10)

```

### Streaming Calculations with Series

```go
serie := tav.NewSeries(close)
smaSeries := tav.SMA(serie, 30)
latestSMA := smaSeries.Get(0)  // Retrieve most recent value

```

### Python Integration

```python
import tav

close = [101, 102, 103, 104, 105, 106, 107, 108, 109, 110]
sma = tav.SMA(close, 5)   # Returns [nan, nan, nan, nan, 103.0, 104.0, ...]

ema = tav.EMA(close, 5)

```

## Summary

- BanTA provides **12 distinct moving average algorithms** ranging from basic SMA to advanced adaptive methods like KAMA and ALMA.
- Each algorithm is available in two forms: slice-based functions in [`tav/indicators.go`](https://github.com/banbox/banta/blob/main/tav/indicators.go) for batch processing and stateful methods in [`sta_inds.go`](https://github.com/banbox/banta/blob/main/sta_inds.go) for streaming data.
- All implementations are **NaN-tolerant**, automatically handling gaps in market data without manual preprocessing.
- The library includes advanced low-lag options like **HMA**, **KAMA**, and **ALMA** for high-frequency trading applications.
- Python bindings in [`python/tav/index.go`](https://github.com/banbox/banta/blob/main/python/tav/index.go) expose the same functionality to data science workflows.

## Frequently Asked Questions

### What is the difference between EMA and RMA in BanTA?

**EMA** (Exponential Moving Average) uses a smoothing factor of α = 2/(n+1), making it highly responsive to recent price changes. **RMA** (Relative Moving Average) implements Wilder’s smoothing with α = 1/n, which reacts more slowly and is preferred for indicators like RSI. BanTA provides both `EMA()` and `RMA()` in [`tav/indicators.go`](https://github.com/banbox/banta/blob/main/tav/indicators.go), plus variant functions `EMABy()` and `RMABy()` that allow custom initialization types.

### How does BanTA handle missing data (NaN values) in moving average calculations?

All **moving averages supported by BanTA** are NaN-tolerant by design. When a `math.NaN()` value is encountered in the input slice, the output at that index becomes NaN, and the internal calculation state resets appropriately. This behavior is consistent across both the slice-based functions in [`tav/indicators.go`](https://github.com/banbox/banta/blob/main/tav/indicators.go) and the stateful Series methods in [`sta_inds.go`](https://github.com/banbox/banta/blob/main/sta_inds.go), ensuring robust handling of market data gaps without manual preprocessing.

### Can I use BanTA moving averages in Python, or is it Go-only?

BanTA provides Python bindings through the [`python/tav/index.go`](https://github.com/banbox/banta/blob/main/python/tav/index.go) file using gopy. You can import the `tav` module in Python and call the same moving average functions—such as `tav.SMA()`, `tav.EMA()`, and `tav.VWMA()`—with Python lists or arrays. The functions return Python lists of floats, maintaining the same NaN-handling semantics and calculation logic as the Go implementations.

### Which moving average should I use for reducing lag in fast-moving markets?

For **low-lag applications**, BanTA offers three specialized options. The **Hull Moving Average (HMA)** combines weighted moving averages with square-root period scaling to minimize delay. The **Kaufman Adaptive Moving Average (KAMA)** automatically adjusts smoothing based on market efficiency, becoming more responsive during strong trends. Finally, the **Arnaud Legoux Moving Average (ALMA)** uses Gaussian-shaped weights to achieve superior smoothness with minimal lag. All three are available in [`tav/indicators.go`](https://github.com/banbox/banta/blob/main/tav/indicators.go) as `HMA()`, `KAMA()`, and `ALMA()`.