A high-performance Go library for calculating Exponential Weighted Moving Averages, designed to be easily integrated with Visual Basic .NET and C# applications.
- Overview
- Features
- Installation
- Building the Library
- Usage
- API Reference
- Mathematical Background
- Performance
- Examples
- Troubleshooting
- Contributing
- License
The EWMA (Exponential Weighted Moving Average) is a statistical method for smoothing time series data by giving exponentially decreasing weights to older observations. This library provides a fast, thread-safe implementation in Go that can be compiled as a shared library for use in .NET applications.
- High Performance: Written in Go for optimal speed
- Memory Efficient: Minimal memory footprint
- Cross-Platform: Supports Windows, Linux, and macOS
- Easy Integration: Simple C-style API for .NET interop
- State Persistence: JSON serialization/deserialization support
- Batch Processing: Efficient batch calculation support
- ✅ Thread-safe EWMA calculations
- ✅ Configurable alpha (smoothing factor) parameter
- ✅ Batch processing capabilities
- ✅ State serialization to JSON
- ✅ Multiple instance management
- ✅ Memory leak prevention
- ✅ Comprehensive error handling
- ✅ .NET wrapper classes (VB.NET and C#)
- ✅ Unit tests and benchmarks
- Go 1.21 or later
- CGO enabled
- GCC compiler (for building shared libraries)
- .NET Framework or .NET Core (for .NET examples)
Install MinGW-w64 for cross-compilation:
# Ubuntu/Debian
sudo apt-get install gcc-mingw-w64
# macOS with Homebrew
brew install mingw-w64# Clone the repository
git clone https://github.com/Fabricates/common4n.git
cd common4n
# Run tests
make test
# Build for all platforms
make all
# Build for specific platform
make build-windows # Creates libewma.dll
make build-linux # Creates libewma.so
make build-darwin # Creates libewma.dylib# For Windows DLL
CGO_ENABLED=1 GOOS=windows GOARCH=amd64 CC=x86_64-w64-mingw32-gcc go build -buildmode=c-shared -o libewma.dll ewma.go
# For Linux SO
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -buildmode=c-shared -o libewma.so ewma.go
# For macOS DYLIB
CGO_ENABLED=1 GOOS=darwin GOARCH=amd64 go build -buildmode=c-shared -o libewma.dylib ewma.gopackage main
import (
"fmt"
)
func main() {
// Create new EWMA with alpha = 0.3
ewma := NewEWMA(0.3)
// Process individual values
fmt.Println(ewma.Update(10.0)) // 10.0
fmt.Println(ewma.Update(20.0)) // 13.0
fmt.Println(ewma.Update(15.0)) // 13.6
// Batch processing
values := []float64{25.0, 30.0, 18.0}
results := ewma.CalculateBatch(values)
fmt.Println(results)
// State management
jsonState := ewma.ToJSON()
fmt.Println("State:", jsonState)
}Imports System
Module Program
Sub Main()
' Create EWMA wrapper
Using ewma As New EWMAWrapper(0.3)
' Update with individual values
Console.WriteLine(ewma.Update(10.0)) ' 10.0
Console.WriteLine(ewma.Update(20.0)) ' 13.0
Console.WriteLine(ewma.Update(15.0)) ' 13.6
' Batch processing
Dim values() As Double = {25.0, 30.0, 18.0}
Dim results() As Double = ewma.ProcessBatch(values)
For Each result In results
Console.WriteLine(result)
Next
' State management
Dim state As String = ewma.GetStateAsJSON()
Console.WriteLine("State: " & state)
End Using
End Sub
End Moduleusing System;
class Program
{
static void Main()
{
// Create EWMA wrapper
using (var ewma = new EWMAWrapper(0.3))
{
// Update with individual values
Console.WriteLine(ewma.Update(10.0)); // 10.0
Console.WriteLine(ewma.Update(20.0)); // 13.0
Console.WriteLine(ewma.Update(15.0)); // 13.6
// Batch processing
double[] values = {25.0, 30.0, 18.0};
double[] results = ewma.ProcessBatch(values);
foreach (var result in results)
{
Console.WriteLine(result);
}
// State management
string state = ewma.GetStateAsJSON();
Console.WriteLine($"State: {state}");
}
}
}Creates a new EWMA instance with the specified alpha parameter.
Parameters:
alpha: Smoothing factor (0 < alpha ≤ 1)
Returns: Pointer to EWMA instance
Updates the EWMA with a new observation.
Parameters:
value: New observation value
Returns: Updated EWMA value
Returns the current EWMA value.
Resets the EWMA to its initial state.
Updates the alpha parameter.
Parameters:
alpha: New smoothing factor
Returns: True if successful, false if invalid alpha
Calculates EWMA for a batch of values.
Parameters:
values: Slice of values to process
Returns: Slice of EWMA results
Serializes the EWMA state to JSON.
Deserializes EWMA state from JSON.
Creates a new EWMA instance and returns its ID.
Updates the specified EWMA instance with a new value.
Gets the current value of the specified EWMA instance.
Resets the specified EWMA instance.
Sets the alpha parameter for the specified instance.
Destroys the specified EWMA instance and frees memory.
Gets the state of the specified instance as JSON string.
Sets the state of the specified instance from JSON string.
Frees memory allocated for C strings.
Constructor that creates a new EWMA instance.
Updates the EWMA with a new value and returns the result.
Gets the current EWMA value.
Resets the EWMA to its initial state.
Sets a new alpha value.
Processes an array of values and returns the EWMA results.
Gets the current state as a JSON string.
Sets the state from a JSON string.
The Exponential Weighted Moving Average is calculated using the formula:
EWMA(t) = α × X(t) + (1 - α) × EWMA(t-1)
Where:
EWMA(t)is the EWMA value at time tX(t)is the observation at time tα(alpha) is the smoothing factor (0 < α ≤ 1)EWMA(t-1)is the previous EWMA value
The alpha parameter controls how much weight is given to recent observations:
- Higher α (closer to 1): More responsive to recent changes, less smoothing
- Lower α (closer to 0): More smoothing, less responsive to recent changes
Common alpha values:
0.1: Heavy smoothing, slow response0.3: Moderate smoothing, balanced response0.7: Light smoothing, fast response
Based on Go benchmarks (run make test to see current results):
BenchmarkEWMAUpdate-8 100000000 12.5 ns/op
BenchmarkEWMABatch-8 5000 325463 ns/op
- Single update: ~12.5 nanoseconds per operation
- Batch processing: ~325 microseconds for 1000 values
- Each EWMA instance uses approximately 32 bytes
- No memory allocations during updates
- Batch processing allocates memory for result slice only
See the examples/ directory for complete working examples:
EWMAWrapper.vb- VB.NET wrapper class for the EWMA libraryEWMAWrapper.cs- C# wrapper class for the EWMA library
EWMAExample.vb- Comprehensive VB.NET demonstrationEWMAExample.cs- Comprehensive C# demonstration
- Build the library for your platform
- Copy the appropriate shared library (
.dll,.so, or.dylib) to your project directory - Compile and run the example:
# For C# example
csc EWMAExample.cs
./EWMAExample.exe
# For VB.NET example
vbc EWMAExample.vb
./EWMAExample.exeSolution: Ensure the shared library is in the same directory as your executable or in the system PATH.
Solution: Verify that the DLL was built correctly and exports the required functions.
Solution: Always call Dispose() on the wrapper class or use using statements.
Solution: Ensure alpha is between 0 and 1 (exclusive of 0, inclusive of 1).
To enable debug output, set the environment variable:
export GODEBUG=cgocheck=1- Requires Visual C++ Redistributable
- Use
libewma.dll
- May require
sudo ldconfigafter installation - Use
libewma.so
- May need to bypass Gatekeeper:
xattr -d com.apple.quarantine libewma.dylib - Use
libewma.dylib
# Clone repository
git clone https://github.com/Fabricates/common4n.git
cd common4n
# Install dependencies
make deps
# Run tests
make test
# Format code
make fmt
# Lint code (requires golangci-lint)
make lint- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Run the test suite
- Submit a pull request
# Run unit tests
go test -v
# Run benchmarks
go test -bench=.
# Run with race detection
go test -race
# Test all platforms
make testThis project is licensed under the terms specified in the LICENSE file.
For questions, issues, or contributions:
- GitHub Issues: https://github.com/Fabricates/common4n/issues
- Documentation: This README and inline code comments
- Examples: See the
examples/directory
Note: This library is designed for production use but should be thoroughly tested in your specific environment before deployment.