I can think on some dirty ways to calculate a moving average on Kotlin, but I'm not sure which one is the best. I know that kotlin has a lot of interesting features to work with collections and list. What do you think is the most efficient (or simplest) way to calculate a moving average?
How Do You Calculate a Simple Moving Average? To calculate a simple moving average, the number of prices within a time period is divided by the number of total periods.
A moving average is a technical indicator that investors and traders use to determine the trend direction of securities. It is calculated by adding up all the data points during a specific period and dividing the sum by the number of time periods.
A rolling average continuously updates the average of a data set to include all the data in the set until that point. For example, the rolling average of return quantities at March 2012 would be calculated by adding the return quantities in January, February, and March, and then dividing that sum by three.
Kotlin 1.2 will introduce a sliding window which you can combine with average
obviously.
val data = listOf(1,2,5,6,2,7,8,5,9)
// 3 "period" moving average
val movingAverage = data.windowed(3,1,List<Int>::average)
// OR
val movingAverage = data.windowed(3,1) { it.average() }
Until then you would have to introduce your own sliding sequence.
class SlidingSequence<out T>(val source: Iterable<T>,
val slideSize: Int,
val slideStep: Int) : Sequence<List<T>> {
override fun iterator(): Iterator<List<T>> = object : AbstractIterator<List<T>>() {
private val iterator = if (slideSize > 0) source.iterator() else emptyList<T>().iterator()
private var buffer = listOf<T>()
override fun computeNext() = when {
iterator.hasNext() -> {
buffer = buffer.drop(slideStep).let {
it + iterator.asSequence().take(slideSize - it.size)
}
setNext(buffer)
}
else -> done()
}
}
}
fun <T> Iterable<T>.windowed(size: Int,
step: Int = 1): Sequence<List<T>> {
return SlidingSequence(this, size, step)
}
// and then you can do
val data = listOf(1,2,5,6,2,7,8,5,9)
// 3 "period" moving average
val movingAverage = data.windowed(3).map(List<Int>::average)
PS. I haven't looked at the code of Kotlin 1.2 windowed
implementation, but since the function takes an immediate transform, I'm guessing the result is not lazy, where in the self implemented case above it's a lazy result, so you need to actually enumerate the sequence with something like .toList()
to get the actual values.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With