Кажется, есть ошибка в вычислении sma в коде ниже … может кто-то указать, где ..
/ **
* Простая скользящая средняя (СМА)
*
*
Скользящее среднее — это индикатор, который показывает среднее значение цены ценной бумаги за определенный период времени. При расчете скользящего среднего производится математический анализ среднего значения ценной бумаги за заранее определенный период времени. При изменении цены ценной бумаги ее средняя цена движется вверх или вниз.
*
*
Простое или арифметическое скользящее среднее рассчитывается путем сложения цены закрытия ценной бумаги за несколько периодов времени (например, 12 дней), а затем деления этой суммы на количество периодов времени. Результатом является средняя цена ценной бумаги за период времени. Простые скользящие средние дают равный вес каждой ежедневной цене.
*
*
Формула:
*
* — СУММА (закрытие n периодов) / n
* /
<?php
$data = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
class sma
{
/**
* @var double[]
*/
private $sma;
/**
* @param double[] $data
* @param int $range
* @return double[]
*/
function get( $data, $range )
{
$position = 0;
while ( empty( $data[ $position ] ) ) {
$position++;
}
$i = $position;
while ( true ) {
if ( empty( $data[ $i + $range - 1 ] ) ) {
break;
}
$temp_sum = 0;
for ( $j = $i; $j < $i + $range; $j++ ) {
$temp_sum += $data[ $j ];
}
$this->sma[ $i + $range - 1 ] = $temp_sum / $range;
$i++;
}
return $this->sma;
}
}
$mysma = new sma();
$mysma->get($data,5); $sma = $mysma->get();
echo mysma;
?>
Также вычисление sma в другом коде кажется более простым. Вот несколько примеров. Если кто-то сделал это в php аналогичным образом.
(defn moving-average
[coll n]
(cond
(< n 1) nil
(= n 1) coll
:else (let [sums (reductions + 0 coll)]
(map #(/ (- %1 %2) n) (drop n sums) sums))))
(time (doall (moving-average coll n)))
# "Elapsed time: 9.184 msecs"
Также это ..
double[] MovingAverage(int period, double[] source)
{
var ma = new double[source.Length];
double sum = 0;
for (int bar = 0; bar < period; bar++)
sum += source[bar];
ma[period - 1] = sum/period;
for (int bar = period; bar < source.Length; bar++)
ma[bar] = ma[bar - 1] + source[bar]/period
- source[bar - period]/period;
return ma;
}
Вот перевод, основанный на последнем фрагменте кода в вашем вопросе:
function get(array $data, $range)
{
$sum = array_sum(array_slice($data, 0, $range));
$result = array($range - 1 => $sum / $range);
for ($i = $range, $n = count($data); $i != $n; ++$i) {
$result[$i] = $result[$i - 1] + ($data[$i] - $data[$i - $range]) / $range;
}
return $result;
}
Других решений пока нет …