github.com/diadata-org/diadata@v1.4.593/internal/pkg/filtersBlockService/FilterEMA.go (about)

     1  package filters
     2  
     3  import (
     4  	"strconv"
     5  	"time"
     6  
     7  	"github.com/diadata-org/diadata/pkg/dia"
     8  	log "github.com/sirupsen/logrus"
     9  )
    10  
    11  // FilterEMA is the struct for a moving average filter implementing
    12  // the Filter interface.
    13  type FilterEMA struct {
    14  	asset           dia.Asset
    15  	exchange        string
    16  	currentTime     time.Time
    17  	previousPrices  []float64
    18  	previousVolumes []float64
    19  	lastTrade       *dia.FilterPoint
    20  	param           int
    21  	value           float64
    22  	modified        bool
    23  	filterName      string
    24  	multiplier      float64
    25  }
    26  
    27  // NewFilterEMA returns a moving average filter.
    28  func NewFilterEMA(asset dia.Asset, exchange string, currentTime time.Time, blockSize int) *FilterEMA {
    29  
    30  	s := &FilterEMA{
    31  		asset:           asset,
    32  		exchange:        exchange,
    33  		previousPrices:  []float64{},
    34  		previousVolumes: []float64{},
    35  		currentTime:     currentTime,
    36  		filterName:      "EMA" + strconv.Itoa(blockSize),
    37  		multiplier:      2 / (float64(blockSize) + 1),
    38  		param:           blockSize,
    39  	}
    40  	return s
    41  }
    42  
    43  func (s *FilterEMA) Compute(trade dia.FilterPoint) {
    44  	s.compute(trade)
    45  }
    46  
    47  func (s *FilterEMA) compute(trade dia.FilterPoint) {
    48  	s.modified = true
    49  	if s.lastTrade != nil {
    50  		if trade.Time.After(s.currentTime) {
    51  			log.Errorln("FilterMA: Ignoring Trade out of order ", s.currentTime, trade.Time)
    52  			return
    53  		}
    54  		s.fill(trade.Time, *s.lastTrade)
    55  	}
    56  	s.fill(trade.Time, trade)
    57  	log.Println("FilterEMA compute: filled order ", s.currentTime, trade)
    58  
    59  	s.lastTrade = &trade
    60  }
    61  
    62  func (e *FilterEMA) fill(t time.Time, trade dia.FilterPoint) {
    63  	log.Println("FilterEMA fill ", trade)
    64  	log.Println("FilterEMA time ", t)
    65  	log.Println("FilterEMA e.multiplier ", e.multiplier)
    66  	log.Println("FilterEMA e.value ", e.value)
    67  	e.currentTime = trade.Time
    68  	if e.value == 0 { // this is a proxy for "uninitialized"
    69  		e.value = trade.Value
    70  	} else {
    71  		e.value = (trade.Value * float64(e.multiplier)) + (e.value * (1 - float64(e.multiplier)))
    72  		log.Println("FilterEMA e.value and multiplier ", e.value, e.multiplier)
    73  
    74  	}
    75  	log.Println("FilterEMA e.value ", e.value)
    76  
    77  }
    78  
    79  func (s *FilterEMA) FinalCompute(t time.Time) float64 {
    80  	return s.finalCompute(t)
    81  }
    82  
    83  func (e *FilterEMA) finalCompute(t time.Time) float64 {
    84  	log.Infof("computed value %v at time %v ", e.value, t)
    85  	return e.value
    86  }
    87  
    88  func (e *FilterEMA) FilterPointForBlock() *dia.FilterPoint {
    89  	log.Println("FilterPointForBlock", e.value, e.currentTime, e.asset)
    90  
    91  	return &dia.FilterPoint{
    92  		Asset: e.asset,
    93  		Value: e.value,
    94  		Name:  "EMA" + strconv.Itoa(e.param),
    95  		Time:  e.currentTime,
    96  	}
    97  }