sheet-historical-data-conve.../exchangeUtility/AggregateDailyToMonthly.go

123 lines
2.7 KiB
Go

package exchangeUtility
import (
"sort"
)
const (
Mean string = "Mean"
Median string = "Median"
Mode string = "Mode"
Min string = "Min"
Max string = "Max"
)
type AggregateDailyToMonthly struct {
AggregatedNumbers []float64
}
func (mm *AggregateDailyToMonthly) CalcValue(avgMethod string) float64 {
switch avgMethod {
case Mean:
return mm.CalcMean()
case Median:
return mm.CalcMedian()
case Mode:
return mm.CalcMode()
case Max:
return mm.GetMaxValue()
case Min:
return mm.GetMinValue()
}
return 0
}
// return the minimum value
func (mm *AggregateDailyToMonthly) GetMinValue() float64 {
sort.Float64s(mm.AggregatedNumbers) // sort the numbers
return mm.AggregatedNumbers[0]
}
// return the maximum value
func (mm *AggregateDailyToMonthly) GetMaxValue() float64 {
sort.Float64s(mm.AggregatedNumbers) // sort the numbers
return mm.AggregatedNumbers[len(mm.AggregatedNumbers)-1]
}
// calculate and return mode
func (mm *AggregateDailyToMonthly) CalcMode() float64 {
var modes []float64
frequencies := make(map[float64]int, len(mm.AggregatedNumbers))
highestFrequency := 0
for _, x := range mm.AggregatedNumbers {
frequencies[x]++
if frequencies[x] > highestFrequency {
highestFrequency = frequencies[x]
}
}
for x, frequency := range frequencies {
if frequency == highestFrequency {
modes = append(modes, x)
}
}
if highestFrequency == 1 || len(modes) == len(mm.AggregatedNumbers) {
modes = modes[:0] // Or: modes = []float64{}
}
sort.Float64s(modes)
mm.AggregatedNumbers = modes
return mm.CalcMean()
}
// calculate the range values
// last value - first value
func (mm *AggregateDailyToMonthly) CalcRangeValues() float64 {
sort.Float64s(mm.AggregatedNumbers) // sort the numbers
return mm.GetMaxValue() - mm.GetMinValue()
}
// calculate the "mean" value
// sum of all the values
// divided by its quantity
func (mm *AggregateDailyToMonthly) CalcMean() float64 {
total := 0.0
for _, v := range mm.AggregatedNumbers {
total += v
}
return total / float64(len(mm.AggregatedNumbers))
}
// calculate the "median" value
// if the total of numbers is odd
// takes the middle value
//
// if the total of numbers is even
// calculate the "mean" of the middle two values
func (mm *AggregateDailyToMonthly) CalcMedian() float64 {
sort.Float64s(mm.AggregatedNumbers) // sort the numbers
mNumber := len(mm.AggregatedNumbers) / 2
if mm.IsOdd() {
return mm.AggregatedNumbers[mNumber]
}
return (mm.AggregatedNumbers[mNumber-1] + mm.AggregatedNumbers[mNumber]) / 2
}
// check if the total of numbers is
// odd or even
func (mm *AggregateDailyToMonthly) IsOdd() bool {
if len(mm.AggregatedNumbers)%2 == 0 {
return false
}
return true
}