Find this useful? Enter your email to receive occasional updates for securing PHP code.
Signing you up...
Thank you for signing up!
PHP Decode
<?php /** * This is a PHP port of the Trader extension for PHP, which is a port of the T..
Decoded Output download
<?php
/**
* This is a PHP port of the Trader extension for PHP, which is a port of the TA-LIB C code.
*
* This port is written in PHP and without any other requirements.
* The goal is that this library can be used by those whom cannot install the PHP Trader extension.
*
* Below is the copyright information for TA-LIB found in the source code.
*/
/* TA-LIB Copyright (c) 1999-2007, Mario Fortier
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* - Neither name of author nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace LupeCode\phpTraderNative\TALib\Core;
use LupeCode\phpTraderNative\TALib\Enum\MovingAverageType;
use LupeCode\phpTraderNative\TALib\Enum\ReturnCode;
use LupeCode\phpTraderNative\TALib\Enum\UnstablePeriodFunctionID;
class OverlapStudies extends Core
{
public static function accbands(
int $startIdx,
int $endIdx,
array $inHigh,
array $inLow,
array $inClose,
int $optInTimePeriod,
int &$outBegIdx,
int &$outNBElement,
array &$outRealUpperBand,
array &$outRealMiddleBand,
array &$outRealLowerBand
): int {
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
$lookbackTotal = Lookback::smaLookback($optInTimePeriod);
if ($startIdx < $lookbackTotal) {
$startIdx = $lookbackTotal;
}
if ($startIdx > $endIdx) {
$outBegIdx = 0;
$outNBElement = 0;
return ReturnCode::Success;
}
$outputSize = $endIdx - $startIdx + 1;
$bufferSize = $outputSize + $lookbackTotal;
$tempBuffer1 = static::double($bufferSize);
$tempBuffer2 = static::double($bufferSize);
for ($j = 0, $i = $startIdx - $lookbackTotal; $i <= $endIdx; $i++, $j++) {
$tempReal = $inHigh[$i] + $inLow[$i];
if ($tempReal !== 0.0) {
$tempReal = 4 * ($inHigh[$i] - $inLow[$i]) / $tempReal;
$tempBuffer1[$j] = $inHigh[$i] * (1 + $tempReal);
$tempBuffer2[$j] = $inLow[$i] * (1 - $tempReal);
} else {
$tempBuffer1[$j] = $inHigh[$i];
$tempBuffer2[$j] = $inLow[$i];
}
}
$outRealMiddleBand = static::double($outputSize);
$retCode = static::sma(
$startIdx,
$endIdx,
$inClose,
$optInTimePeriod,
$outBegIdx,
$outNBElement,
$outRealMiddleBand
);
if ($retCode !== ReturnCode::Success || $outNBElement !== $outputSize) {
return $retCode;
}
$outRealUpperBand = static::double($outputSize);
$retCode = static::sma(
0,
$bufferSize - 1,
$tempBuffer1,
$optInTimePeriod,
$outBegIdx,
$outNBElement,
$outRealUpperBand
);
if ($retCode !== ReturnCode::Success || $outNBElement !== $outputSize) {
return $retCode;
}
$outRealLowerBand = static::double($outputSize);
$retCode = static::sma(
0,
$bufferSize - 1,
$tempBuffer2,
$optInTimePeriod,
$outBegIdx,
$outNBElement,
$outRealLowerBand
);
if ($retCode !== ReturnCode::Success || $outNBElement !== $outputSize) {
return $retCode;
}
$outBegIdx = $startIdx;
$outNBElement = $outputSize;
return ReturnCode::Success;
}
public static function bbands(
int $startIdx,
int $endIdx,
array $inReal,
int $optInTimePeriod,
float $optInNbDevUp,
float $optInNbDevDn,
int $optInMAType,
int &$outBegIdx,
int &$outNBElement,
array &$outRealUpperBand,
array &$outRealMiddleBand,
array &$outRealLowerBand
): int {
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
if ($optInTimePeriod === PHP_INT_MIN) {
$optInTimePeriod = 5;
} elseif ($optInTimePeriod < 2 || $optInTimePeriod > 100000) {
return ReturnCode::BadParam;
}
if ($optInNbDevUp === -4e+37) {
$optInNbDevUp = 2.000000e+0;
} elseif ($optInNbDevUp < -3.000000e+37 || $optInNbDevUp > 3.000000e+37) {
return ReturnCode::BadParam;
}
if ($optInNbDevDn === -4e+37) {
$optInNbDevDn = 2.000000e+0;
} elseif ($optInNbDevDn < -3.000000e+37 || $optInNbDevDn > 3.000000e+37) {
return ReturnCode::BadParam;
}
if ($inReal === $outRealUpperBand) {
$tempBuffer1 = $outRealMiddleBand;
$tempBuffer2 = $outRealLowerBand;
} elseif ($inReal === $outRealLowerBand) {
$tempBuffer1 = $outRealMiddleBand;
$tempBuffer2 = $outRealUpperBand;
} elseif ($inReal === $outRealMiddleBand) {
$tempBuffer1 = $outRealLowerBand;
$tempBuffer2 = $outRealUpperBand;
} else {
$tempBuffer1 = $outRealMiddleBand;
$tempBuffer2 = $outRealUpperBand;
}
if ($tempBuffer1 === $inReal || $tempBuffer2 === $inReal) {
return ReturnCode::BadParam;
}
$ReturnCode = self::movingAverage($startIdx, $endIdx, $inReal, $optInTimePeriod, $optInMAType, $outBegIdx, $outNBElement, $tempBuffer1);
if ($ReturnCode !== ReturnCode::Success || $outNBElement === 0) {
$outNBElement = 0;
return $ReturnCode;
}
if ($optInMAType === MovingAverageType::SMA) {
static::TA_INT_stddev_using_precalc_ma($inReal, $tempBuffer1, $outBegIdx, $outNBElement, $optInTimePeriod, $tempBuffer2);
} else {
$ReturnCode = StatisticFunctions::stdDev($outBegIdx, $endIdx, $inReal, $optInTimePeriod, 1.0, $outBegIdx, $outNBElement, $tempBuffer2);
if ($ReturnCode !== ReturnCode::Success) {
$outNBElement = 0;
return $ReturnCode;
}
}
if ($tempBuffer1 !== $outRealMiddleBand) {
$outRealMiddleBand = \array_slice($tempBuffer1, 0, $outNBElement);
}
if ($optInNbDevUp === $optInNbDevDn) {
if ($optInNbDevUp === 1.0) {
for ($i = 0; $i < $outNBElement; $i++) {
$tempReal = $tempBuffer2[$i];
$tempReal2 = $outRealMiddleBand[$i];
$outRealUpperBand[$i] = $tempReal2 + $tempReal;
$outRealLowerBand[$i] = $tempReal2 - $tempReal;
}
} else {
for ($i = 0; $i < $outNBElement; $i++) {
$tempReal = $tempBuffer2[$i] * $optInNbDevUp;
$tempReal2 = $outRealMiddleBand[$i];
$outRealUpperBand[$i] = $tempReal2 + $tempReal;
$outRealLowerBand[$i] = $tempReal2 - $tempReal;
}
}
} elseif ($optInNbDevUp === 1.0) {
for ($i = 0; $i < $outNBElement; $i++) {
$tempReal = $tempBuffer2[$i];
$tempReal2 = $outRealMiddleBand[$i];
$outRealUpperBand[$i] = $tempReal2 + $tempReal;
$outRealLowerBand[$i] = $tempReal2 - $tempReal * $optInNbDevDn;
}
} elseif ($optInNbDevDn === 1.0) {
for ($i = 0; $i < $outNBElement; $i++) {
$tempReal = $tempBuffer2[$i];
$tempReal2 = $outRealMiddleBand[$i];
$outRealLowerBand[$i] = $tempReal2 - $tempReal;
$outRealUpperBand[$i] = $tempReal2 + $tempReal * $optInNbDevUp;
}
} else {
for ($i = 0; $i < $outNBElement; $i++) {
$tempReal = $tempBuffer2[$i];
$tempReal2 = $outRealMiddleBand[$i];
$outRealUpperBand[$i] = $tempReal2 + $tempReal * $optInNbDevUp;
$outRealLowerBand[$i] = $tempReal2 - $tempReal * $optInNbDevDn;
}
}
return ReturnCode::Success;
}
public static function dema(int $startIdx, int $endIdx, array $inReal, int $optInTimePeriod, int &$outBegIdx, int &$outNBElement, array &$outReal): int
{
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
$firstEMABegIdx = 0;
$firstEMANbElement = 0;
$secondEMABegIdx = 0;
$secondEMANbElement = 0;
if ($optInTimePeriod === PHP_INT_MIN) {
$optInTimePeriod = 30;
} elseif ($optInTimePeriod < 2 || $optInTimePeriod > 100000) {
return ReturnCode::BadParam;
}
$outNBElement = 0;
$outBegIdx = 0;
$lookbackEMA = Lookback::emaLookback($optInTimePeriod);
$lookbackTotal = $lookbackEMA * 2;
if ($startIdx < $lookbackTotal) {
$startIdx = (int)$lookbackTotal;
}
if ($startIdx > $endIdx) {
return ReturnCode::Success;
}
if ($inReal === $outReal) {
$firstEMA = $outReal;
} else {
$tempInt = $lookbackTotal + ($endIdx - $startIdx) + 1;
$firstEMA = static::double($tempInt);
}
$k = 2.0 / (double)($optInTimePeriod + 1);
$ReturnCode = static::TA_INT_EMA(
$startIdx - $lookbackEMA,
$endIdx,
$inReal,
$optInTimePeriod,
$k,
$firstEMABegIdx,
$firstEMANbElement,
$firstEMA
);
if ($ReturnCode !== ReturnCode::Success || $firstEMANbElement === 0) {
return $ReturnCode;
}
$secondEMA = static::double($firstEMANbElement);
$ReturnCode = static::TA_INT_EMA(
0,
$firstEMANbElement - 1,
$firstEMA,
$optInTimePeriod,
$k,
$secondEMABegIdx,
$secondEMANbElement,
$secondEMA
);
if ($ReturnCode !== ReturnCode::Success || $secondEMANbElement === 0) {
return $ReturnCode;
}
$firstEMAIdx = $secondEMABegIdx;
$outIdx = 0;
while ($outIdx < $secondEMANbElement) {
$outReal[$outIdx] = 2.0 * $firstEMA[$firstEMAIdx++] - $secondEMA[$outIdx];
$outIdx++;
}
$outBegIdx = $firstEMABegIdx + $secondEMABegIdx;
$outNBElement = $outIdx;
return ReturnCode::Success;
}
public static function ema(int $startIdx, int $endIdx, array $inReal, int $optInTimePeriod, int &$outBegIdx, int &$outNBElement, array &$outReal): int
{
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
if ($optInTimePeriod === PHP_INT_MIN) {
$optInTimePeriod = 30;
} elseif ($optInTimePeriod < 2 || $optInTimePeriod > 100000) {
return ReturnCode::BadParam;
}
return static::TA_INT_EMA(
$startIdx,
$endIdx,
$inReal,
$optInTimePeriod,
2.0 / (double)($optInTimePeriod + 1),
$outBegIdx,
$outNBElement,
$outReal
);
}
public static function htTrendline(int $startIdx, int $endIdx, array $inReal, int &$outBegIdx, int &$outNBElement, array &$outReal): int
{
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
$a = 0.0962;
$b = 0.5769;
$detrender_Odd = static::double(3);
$detrender_Even = static::double(3);
$Q1_Odd = static::double(3);
$Q1_Even = static::double(3);
$jI_Odd = static::double(3);
$jI_Even = static::double(3);
$jQ_Odd = static::double(3);
$jQ_Even = static::double(3);
$smoothPrice_Idx = 0;
$maxIdx_smoothPricePrice = 50 - 1;
{
$smoothPrice = static::double($maxIdx_smoothPricePrice + 1);
}
$iTrend1 = $iTrend2 = $iTrend3 = 0.0;
$tempReal = atan(1);
$rad2Deg = 45.0 / $tempReal;
$lookbackTotal = 63 + static::$unstablePeriod[UnstablePeriodFunctionID::HtTrendline];
if ($startIdx < $lookbackTotal) {
$startIdx = $lookbackTotal;
}
if ($startIdx > $endIdx) {
$outBegIdx = 0;
$outNBElement = 0;
return ReturnCode::Success;
}
$outBegIdx = $startIdx;
$trailingWMAIdx = $startIdx - $lookbackTotal;
$today = $trailingWMAIdx;
$tempReal = $inReal[$today++];
$periodWMASub = $tempReal;
$periodWMASum = $tempReal;
$tempReal = $inReal[$today++];
$periodWMASub += $tempReal;
$periodWMASum += $tempReal * 2.0;
$tempReal = $inReal[$today++];
$periodWMASub += $tempReal;
$periodWMASum += $tempReal * 3.0;
$trailingWMAValue = 0.0;
$i = 34;
do {
$tempReal = $inReal[$today++];
{
$periodWMASub += $tempReal;
$periodWMASub -= $trailingWMAValue;
$periodWMASum += $tempReal * 4.0;
$trailingWMAValue = $inReal[$trailingWMAIdx++];
$smoothedValue = $periodWMASum * 0.1;
$periodWMASum -= $periodWMASub;
}
} while (--$i !== 0);
$hilbertIdx = 0;
{
$detrender_Odd[0] = 0.0;
$detrender_Odd[1] = 0.0;
$detrender_Odd[2] = 0.0;
$detrender_Even[0] = 0.0;
$detrender_Even[1] = 0.0;
$detrender_Even[2] = 0.0;
$detrender = 0.0;
$prev_detrender_Odd = 0.0;
$prev_detrender_Even = 0.0;
$prev_detrender_input_Odd = 0.0;
$prev_detrender_input_Even = 0.0;
}
{
$Q1_Odd[0] = 0.0;
$Q1_Odd[1] = 0.0;
$Q1_Odd[2] = 0.0;
$Q1_Even[0] = 0.0;
$Q1_Even[1] = 0.0;
$Q1_Even[2] = 0.0;
$Q1 = 0.0;
$prev_Q1_Odd = 0.0;
$prev_Q1_Even = 0.0;
$prev_Q1_input_Odd = 0.0;
$prev_Q1_input_Even = 0.0;
}
{
$jI_Odd[0] = 0.0;
$jI_Odd[1] = 0.0;
$jI_Odd[2] = 0.0;
$jI_Even[0] = 0.0;
$jI_Even[1] = 0.0;
$jI_Even[2] = 0.0;
$jI = 0.0;
$prev_jI_Odd = 0.0;
$prev_jI_Even = 0.0;
$prev_jI_input_Odd = 0.0;
$prev_jI_input_Even = 0.0;
}
{
$jQ_Odd[0] = 0.0;
$jQ_Odd[1] = 0.0;
$jQ_Odd[2] = 0.0;
$jQ_Even[0] = 0.0;
$jQ_Even[1] = 0.0;
$jQ_Even[2] = 0.0;
$jQ = 0.0;
$prev_jQ_Odd = 0.0;
$prev_jQ_Even = 0.0;
$prev_jQ_input_Odd = 0.0;
$prev_jQ_input_Even = 0.0;
}
$period = 0.0;
$outIdx = 0;
$prevI2 = $prevQ2 = 0.0;
$Re = $Im = 0.0;
$I1ForOddPrev3 = $I1ForEvenPrev3 = 0.0;
$I1ForOddPrev2 = $I1ForEvenPrev2 = 0.0;
$smoothPeriod = 0.0;
for ($i = 0; $i < 50; $i++) {
$smoothPrice[$i] = 0.0;
}
while ($today <= $endIdx) {
$adjustedPrevPeriod = 0.075 * $period + 0.54;
$todayValue = $inReal[$today];
{
$periodWMASub += $todayValue;
$periodWMASub -= $trailingWMAValue;
$periodWMASum += $todayValue * 4.0;
$trailingWMAValue = $inReal[$trailingWMAIdx++];
$smoothedValue = $periodWMASum * 0.1;
$periodWMASum -= $periodWMASub;
}
$smoothPrice[$smoothPrice_Idx] = $smoothedValue;
if ($today % 2 === 0) {
{
$hilbertTempReal = $a * $smoothedValue;
$detrender = -$detrender_Even[$hilbertIdx];
$detrender_Even[$hilbertIdx] = $hilbertTempReal;
$detrender += $hilbertTempReal;
$detrender -= $prev_detrender_Even;
$prev_detrender_Even = $b * $prev_detrender_input_Even;
$detrender += $prev_detrender_Even;
$prev_detrender_input_Even = $smoothedValue;
$detrender *= $adjustedPrevPeriod;
}
{
$hilbertTempReal = $a * $detrender;
$Q1 = -$Q1_Even[$hilbertIdx];
$Q1_Even[$hilbertIdx] = $hilbertTempReal;
$Q1 += $hilbertTempReal;
$Q1 -= $prev_Q1_Even;
$prev_Q1_Even = $b * $prev_Q1_input_Even;
$Q1 += $prev_Q1_Even;
$prev_Q1_input_Even = $detrender;
$Q1 *= $adjustedPrevPeriod;
}
{
$hilbertTempReal = $a * $I1ForEvenPrev3;
$jI = -$jI_Even[$hilbertIdx];
$jI_Even[$hilbertIdx] = $hilbertTempReal;
$jI += $hilbertTempReal;
$jI -= $prev_jI_Even;
$prev_jI_Even = $b * $prev_jI_input_Even;
$jI += $prev_jI_Even;
$prev_jI_input_Even = $I1ForEvenPrev3;
$jI *= $adjustedPrevPeriod;
}
{
$hilbertTempReal = $a * $Q1;
$jQ = -$jQ_Even[$hilbertIdx];
$jQ_Even[$hilbertIdx] = $hilbertTempReal;
$jQ += $hilbertTempReal;
$jQ -= $prev_jQ_Even;
$prev_jQ_Even = $b * $prev_jQ_input_Even;
$jQ += $prev_jQ_Even;
$prev_jQ_input_Even = $Q1;
$jQ *= $adjustedPrevPeriod;
}
if (++$hilbertIdx === 3) {
$hilbertIdx = 0;
}
$Q2 = 0.2 * ($Q1 + $jI) + 0.8 * $prevQ2;
$I2 = 0.2 * ($I1ForEvenPrev3 - $jQ) + 0.8 * $prevI2;
$I1ForOddPrev3 = $I1ForOddPrev2;
$I1ForOddPrev2 = $detrender;
} else {
{
$hilbertTempReal = $a * $smoothedValue;
$detrender = -$detrender_Odd[$hilbertIdx];
$detrender_Odd[$hilbertIdx] = $hilbertTempReal;
$detrender += $hilbertTempReal;
$detrender -= $prev_detrender_Odd;
$prev_detrender_Odd = $b * $prev_detrender_input_Odd;
$detrender += $prev_detrender_Odd;
$prev_detrender_input_Odd = $smoothedValue;
$detrender *= $adjustedPrevPeriod;
}
{
$hilbertTempReal = $a * $detrender;
$Q1 = -$Q1_Odd[$hilbertIdx];
$Q1_Odd[$hilbertIdx] = $hilbertTempReal;
$Q1 += $hilbertTempReal;
$Q1 -= $prev_Q1_Odd;
$prev_Q1_Odd = $b * $prev_Q1_input_Odd;
$Q1 += $prev_Q1_Odd;
$prev_Q1_input_Odd = $detrender;
$Q1 *= $adjustedPrevPeriod;
}
{
$hilbertTempReal = $a * $I1ForOddPrev3;
$jI = -$jI_Odd[$hilbertIdx];
$jI_Odd[$hilbertIdx] = $hilbertTempReal;
$jI += $hilbertTempReal;
$jI -= $prev_jI_Odd;
$prev_jI_Odd = $b * $prev_jI_input_Odd;
$jI += $prev_jI_Odd;
$prev_jI_input_Odd = $I1ForOddPrev3;
$jI *= $adjustedPrevPeriod;
}
{
$hilbertTempReal = $a * $Q1;
$jQ = -$jQ_Odd[$hilbertIdx];
$jQ_Odd[$hilbertIdx] = $hilbertTempReal;
$jQ += $hilbertTempReal;
$jQ -= $prev_jQ_Odd;
$prev_jQ_Odd = $b * $prev_jQ_input_Odd;
$jQ += $prev_jQ_Odd;
$prev_jQ_input_Odd = $Q1;
$jQ *= $adjustedPrevPeriod;
}
$Q2 = 0.2 * ($Q1 + $jI) + 0.8 * $prevQ2;
$I2 = 0.2 * ($I1ForOddPrev3 - $jQ) + 0.8 * $prevI2;
$I1ForEvenPrev3 = $I1ForEvenPrev2;
$I1ForEvenPrev2 = $detrender;
}
$Re = 0.2 * ($I2 * $prevI2 + $Q2 * $prevQ2) + 0.8 * $Re;
$Im = 0.2 * ($I2 * $prevQ2 - $Q2 * $prevI2) + 0.8 * $Im;
$prevQ2 = $Q2;
$prevI2 = $I2;
$tempReal = $period;
if ($Im !== 0.0 && $Re !== 0.0) {
$period = 360.0 / (atan($Im / $Re) * $rad2Deg);
}
$tempReal2 = 1.5 * $tempReal;
if ($period > $tempReal2) {
$period = $tempReal2;
}
$tempReal2 = 0.67 * $tempReal;
if ($period < $tempReal2) {
$period = $tempReal2;
}
if ($period < 6) {
$period = 6;
} elseif ($period > 50) {
$period = 50;
}
$period = 0.2 * $period + 0.8 * $tempReal;
$smoothPeriod = 0.33 * $period + 0.67 * $smoothPeriod;
$DCPeriod = $smoothPeriod + 0.5;
$DCPeriodInt = (int)$DCPeriod;
$idxothPricePrice = $today;
$tempReal = 0.0;
for ($i = 0; $i < $DCPeriodInt; $i++) {
$tempReal += $inReal[$idxothPricePrice--];
}
if ($DCPeriodInt > 0) {
$tempReal = $tempReal / (double)$DCPeriodInt;
}
$tempReal2 = (4.0 * $tempReal + 3.0 * $iTrend1 + 2.0 * $iTrend2 + $iTrend3) / 10.0;
$iTrend3 = $iTrend2;
$iTrend2 = $iTrend1;
$iTrend1 = $tempReal;
if ($today >= $startIdx) {
$outReal[$outIdx++] = $tempReal2;
}
{
$smoothPrice_Idx++;
if ($smoothPrice_Idx > $maxIdx_smoothPricePrice) {
$smoothPrice_Idx = 0;
}
}
$today++;
}
$outNBElement = $outIdx;
return ReturnCode::Success;
}
public static function kama(int $startIdx, int $endIdx, array $inReal, int $optInTimePeriod, int &$outBegIdx, int &$outNBElement, array &$outReal): int
{
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
$constMax = 2.0 / (30.0 + 1.0);
$constDiff = 2.0 / (2.0 + 1.0) - $constMax;
if ($optInTimePeriod === PHP_INT_MIN) {
$optInTimePeriod = 30;
} elseif ($optInTimePeriod < 2 || $optInTimePeriod > 100000) {
return ReturnCode::BadParam;
}
$outBegIdx = 0;
$outNBElement = 0;
$lookbackTotal = $optInTimePeriod + static::$unstablePeriod[UnstablePeriodFunctionID::KAMA];
if ($startIdx < $lookbackTotal) {
$startIdx = $lookbackTotal;
}
if ($startIdx > $endIdx) {
$outBegIdx = 0;
$outNBElement = 0;
return ReturnCode::Success;
}
$sumROC1 = 0.0;
$today = $startIdx - $lookbackTotal;
$trailingIdx = $today;
$i = $optInTimePeriod;
while ($i-- > 0) {
$tempReal = $inReal[$today++];
$tempReal -= $inReal[$today];
$sumROC1 += abs($tempReal);
}
$prevKAMA = $inReal[$today - 1];
$tempReal = $inReal[$today];
$tempReal2 = $inReal[$trailingIdx++];
$periodROC = $tempReal - $tempReal2;
$trailingValue = $tempReal2;
if ($sumROC1 <= $periodROC || (-0.00000001 < $sumROC1 && $sumROC1 < 0.00000001)) {
$tempReal = 1.0;
} else {
$tempReal = abs($periodROC / $sumROC1);
}
$tempReal = $tempReal * $constDiff + $constMax;
$tempReal *= $tempReal;
$prevKAMA = ($inReal[$today++] - $prevKAMA) * $tempReal + $prevKAMA;
while ($today <= $startIdx) {
$tempReal = $inReal[$today];
$tempReal2 = $inReal[$trailingIdx++];
$periodROC = $tempReal - $tempReal2;
$sumROC1 -= abs($trailingValue - $tempReal2);
$sumROC1 += abs($tempReal - $inReal[$today - 1]);
$trailingValue = $tempReal2;
if ($sumROC1 <= $periodROC || (-0.00000001 < $sumROC1 && $sumROC1 < 0.00000001)) {
$tempReal = 1.0;
} else {
$tempReal = abs($periodROC / $sumROC1);
}
$tempReal = $tempReal * $constDiff + $constMax;
$tempReal *= $tempReal;
$prevKAMA = ($inReal[$today++] - $prevKAMA) * $tempReal + $prevKAMA;
}
$outReal[0] = $prevKAMA;
$outIdx = 1;
$outBegIdx = $today - 1;
while ($today <= $endIdx) {
$tempReal = $inReal[$today];
$tempReal2 = $inReal[$trailingIdx++];
$periodROC = $tempReal - $tempReal2;
$sumROC1 -= abs($trailingValue - $tempReal2);
$sumROC1 += abs($tempReal - $inReal[$today - 1]);
$trailingValue = $tempReal2;
if ($sumROC1 <= $periodROC || (-0.00000001 < $sumROC1 && $sumROC1 < 0.00000001)) {
$tempReal = 1.0;
} else {
$tempReal = abs($periodROC / $sumROC1);
}
$tempReal = $tempReal * $constDiff + $constMax;
$tempReal *= $tempReal;
$prevKAMA = ($inReal[$today++] - $prevKAMA) * $tempReal + $prevKAMA;
$outReal[$outIdx++] = $prevKAMA;
}
$outNBElement = $outIdx;
return ReturnCode::Success;
}
public static function movingAverage(int $startIdx, int $endIdx, array $inReal, int $optInTimePeriod, int $optInMAType, int &$outBegIdx, int &$outNBElement, array &$outReal): int
{
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
if ($optInTimePeriod === PHP_INT_MIN) {
$optInTimePeriod = 30;
} elseif ($optInTimePeriod < 1 || $optInTimePeriod > 100000) {
return ReturnCode::BadParam;
}
if ($optInTimePeriod === 1) {
$nbElement = $endIdx - $startIdx + 1;
$outNBElement = $nbElement;
for ($todayIdx = $startIdx, $outIdx = 0; $outIdx < $nbElement; $outIdx++, $todayIdx++) {
$outReal[$outIdx] = $inReal[$todayIdx];
}
$outBegIdx = $startIdx;
return ReturnCode::Success;
}
switch ($optInMAType) {
case MovingAverageType::SMA:
$ReturnCode = self::sma(
$startIdx,
$endIdx,
$inReal,
$optInTimePeriod,
$outBegIdx,
$outNBElement,
$outReal
);
break;
case MovingAverageType::EMA:
$ReturnCode = self::ema(
$startIdx,
$endIdx,
$inReal,
$optInTimePeriod,
$outBegIdx,
$outNBElement,
$outReal
);
break;
case MovingAverageType::WMA:
$ReturnCode = self::wma(
$startIdx,
$endIdx,
$inReal,
$optInTimePeriod,
$outBegIdx,
$outNBElement,
$outReal
);
break;
case MovingAverageType::DEMA:
$ReturnCode = self::dema(
$startIdx,
$endIdx,
$inReal,
$optInTimePeriod,
$outBegIdx,
$outNBElement,
$outReal
);
break;
case MovingAverageType::TEMA:
$ReturnCode = self::tema(
$startIdx,
$endIdx,
$inReal,
$optInTimePeriod,
$outBegIdx,
$outNBElement,
$outReal
);
break;
case MovingAverageType::TRIMA:
$ReturnCode = self::trima(
$startIdx,
$endIdx,
$inReal,
$optInTimePeriod,
$outBegIdx,
$outNBElement,
$outReal
);
break;
case MovingAverageType::KAMA:
$ReturnCode = self::kama(
$startIdx,
$endIdx,
$inReal,
$optInTimePeriod,
$outBegIdx,
$outNBElement,
$outReal
);
break;
case MovingAverageType::MAMA:
$dummyBuffer = static::double($endIdx - $startIdx + 1);
$ReturnCode = self::mama(
$startIdx,
$endIdx,
$inReal,
0.5,
0.05,
$outBegIdx,
$outNBElement,
$outReal,
$dummyBuffer
);
break;
case MovingAverageType::T3:
$ReturnCode = self::t3(
$startIdx,
$endIdx,
$inReal,
$optInTimePeriod,
0.7,
$outBegIdx,
$outNBElement,
$outReal
);
break;
default:
$ReturnCode = ReturnCode::BadParam;
break;
}
return $ReturnCode;
}
public static function mama(int $startIdx, int $endIdx, array $inReal, float $optInFastLimit, float $optInSlowLimit, int &$outBegIdx, int &$outNBElement, array &$outMAMA, array &$outFAMA): int
{
$a = 0.0962;
$b = 0.5769;
$detrender_Odd = static::double(3);
$detrender_Even = static::double(3);
$Q1_Odd = static::double(3);
$Q1_Even = static::double(3);
$jI_Odd = static::double(3);
$jI_Even = static::double(3);
$jQ_Odd = static::double(3);
$jQ_Even = static::double(3);
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
if ($optInFastLimit === -4e+37) {
$optInFastLimit = 5.000000e-1;
} elseif ($optInFastLimit < 1.000000e-2 || $optInFastLimit > 9.900000e-1) {
return ReturnCode::BadParam;
}
if ($optInSlowLimit === -4e+37) {
$optInSlowLimit = 5.000000e-2;
} elseif ($optInSlowLimit < 1.000000e-2 || $optInSlowLimit > 9.900000e-1) {
return ReturnCode::BadParam;
}
$rad2Deg = 180.0 / (4.0 * atan(1));
$lookbackTotal = 32 + static::$unstablePeriod[UnstablePeriodFunctionID::MAMA];
if ($startIdx < $lookbackTotal) {
$startIdx = $lookbackTotal;
}
if ($startIdx > $endIdx) {
$outBegIdx = 0;
$outNBElement = 0;
return ReturnCode::Success;
}
$outBegIdx = $startIdx;
$trailingWMAIdx = $startIdx - $lookbackTotal;
$today = $trailingWMAIdx;
$tempReal = $inReal[$today++];
$periodWMASub = $tempReal;
$periodWMASum = $tempReal;
$tempReal = $inReal[$today++];
$periodWMASub += $tempReal;
$periodWMASum += $tempReal * 2.0;
$tempReal = $inReal[$today++];
$periodWMASub += $tempReal;
$periodWMASum += $tempReal * 3.0;
$trailingWMAValue = 0.0;
$i = 9;
do {
$tempReal = $inReal[$today++];
{
$periodWMASub += $tempReal;
$periodWMASub -= $trailingWMAValue;
$periodWMASum += $tempReal * 4.0;
$trailingWMAValue = $inReal[$trailingWMAIdx++];
$smoothedValue = $periodWMASum * 0.1;
$periodWMASum -= $periodWMASub;
}
} while (--$i !== 0);
$hilbertIdx = 0;
{
$detrender_Odd[0] = 0.0;
$detrender_Odd[1] = 0.0;
$detrender_Odd[2] = 0.0;
$detrender_Even[0] = 0.0;
$detrender_Even[1] = 0.0;
$detrender_Even[2] = 0.0;
$detrender = 0.0;
$prev_detrender_Odd = 0.0;
$prev_detrender_Even = 0.0;
$prev_detrender_input_Odd = 0.0;
$prev_detrender_input_Even = 0.0;
}
{
$Q1_Odd[0] = 0.0;
$Q1_Odd[1] = 0.0;
$Q1_Odd[2] = 0.0;
$Q1_Even[0] = 0.0;
$Q1_Even[1] = 0.0;
$Q1_Even[2] = 0.0;
$Q1 = 0.0;
$prev_Q1_Odd = 0.0;
$prev_Q1_Even = 0.0;
$prev_Q1_input_Odd = 0.0;
$prev_Q1_input_Even = 0.0;
}
{
$jI_Odd[0] = 0.0;
$jI_Odd[1] = 0.0;
$jI_Odd[2] = 0.0;
$jI_Even[0] = 0.0;
$jI_Even[1] = 0.0;
$jI_Even[2] = 0.0;
$jI = 0.0;
$prev_jI_Odd = 0.0;
$prev_jI_Even = 0.0;
$prev_jI_input_Odd = 0.0;
$prev_jI_input_Even = 0.0;
}
{
$jQ_Odd[0] = 0.0;
$jQ_Odd[1] = 0.0;
$jQ_Odd[2] = 0.0;
$jQ_Even[0] = 0.0;
$jQ_Even[1] = 0.0;
$jQ_Even[2] = 0.0;
$jQ = 0.0;
$prev_jQ_Odd = 0.0;
$prev_jQ_Even = 0.0;
$prev_jQ_input_Odd = 0.0;
$prev_jQ_input_Even = 0.0;
}
$period = 0.0;
$outIdx = 0;
$prevI2 = $prevQ2 = 0.0;
$Re = $Im = 0.0;
$mama = $fama = 0.0;
$I1ForOddPrev3 = $I1ForEvenPrev3 = 0.0;
$I1ForOddPrev2 = $I1ForEvenPrev2 = 0.0;
$prevPhase = 0.0;
while ($today <= $endIdx) {
$adjustedPrevPeriod = 0.075 * $period + 0.54;
$todayValue = $inReal[$today];
{
$periodWMASub += $todayValue;
$periodWMASub -= $trailingWMAValue;
$periodWMASum += $todayValue * 4.0;
$trailingWMAValue = $inReal[$trailingWMAIdx++];
$smoothedValue = $periodWMASum * 0.1;
$periodWMASum -= $periodWMASub;
}
if ($today % 2 === 0) {
{
$hilbertTempReal = $a * $smoothedValue;
$detrender = -$detrender_Even[$hilbertIdx];
$detrender_Even[$hilbertIdx] = $hilbertTempReal;
$detrender += $hilbertTempReal;
$detrender -= $prev_detrender_Even;
$prev_detrender_Even = $b * $prev_detrender_input_Even;
$detrender += $prev_detrender_Even;
$prev_detrender_input_Even = $smoothedValue;
$detrender *= $adjustedPrevPeriod;
}
{
$hilbertTempReal = $a * $detrender;
$Q1 = -$Q1_Even[$hilbertIdx];
$Q1_Even[$hilbertIdx] = $hilbertTempReal;
$Q1 += $hilbertTempReal;
$Q1 -= $prev_Q1_Even;
$prev_Q1_Even = $b * $prev_Q1_input_Even;
$Q1 += $prev_Q1_Even;
$prev_Q1_input_Even = $detrender;
$Q1 *= $adjustedPrevPeriod;
}
{
$hilbertTempReal = $a * $I1ForEvenPrev3;
$jI = -$jI_Even[$hilbertIdx];
$jI_Even[$hilbertIdx] = $hilbertTempReal;
$jI += $hilbertTempReal;
$jI -= $prev_jI_Even;
$prev_jI_Even = $b * $prev_jI_input_Even;
$jI += $prev_jI_Even;
$prev_jI_input_Even = $I1ForEvenPrev3;
$jI *= $adjustedPrevPeriod;
}
{
$hilbertTempReal = $a * $Q1;
$jQ = -$jQ_Even[$hilbertIdx];
$jQ_Even[$hilbertIdx] = $hilbertTempReal;
$jQ += $hilbertTempReal;
$jQ -= $prev_jQ_Even;
$prev_jQ_Even = $b * $prev_jQ_input_Even;
$jQ += $prev_jQ_Even;
$prev_jQ_input_Even = $Q1;
$jQ *= $adjustedPrevPeriod;
}
if (++$hilbertIdx === 3) {
$hilbertIdx = 0;
}
$Q2 = 0.2 * ($Q1 + $jI) + 0.8 * $prevQ2;
$I2 = 0.2 * ($I1ForEvenPrev3 - $jQ) + 0.8 * $prevI2;
$I1ForOddPrev3 = $I1ForOddPrev2;
$I1ForOddPrev2 = $detrender;
if ($I1ForEvenPrev3 !== 0.0) {
$tempReal2 = atan($Q1 / $I1ForEvenPrev3) * $rad2Deg;
} else {
$tempReal2 = 0.0;
}
} else {
{
$hilbertTempReal = $a * $smoothedValue;
$detrender = -$detrender_Odd[$hilbertIdx];
$detrender_Odd[$hilbertIdx] = $hilbertTempReal;
$detrender += $hilbertTempReal;
$detrender -= $prev_detrender_Odd;
$prev_detrender_Odd = $b * $prev_detrender_input_Odd;
$detrender += $prev_detrender_Odd;
$prev_detrender_input_Odd = $smoothedValue;
$detrender *= $adjustedPrevPeriod;
}
{
$hilbertTempReal = $a * $detrender;
$Q1 = -$Q1_Odd[$hilbertIdx];
$Q1_Odd[$hilbertIdx] = $hilbertTempReal;
$Q1 += $hilbertTempReal;
$Q1 -= $prev_Q1_Odd;
$prev_Q1_Odd = $b * $prev_Q1_input_Odd;
$Q1 += $prev_Q1_Odd;
$prev_Q1_input_Odd = $detrender;
$Q1 *= $adjustedPrevPeriod;
}
{
$hilbertTempReal = $a * $I1ForOddPrev3;
$jI = -$jI_Odd[$hilbertIdx];
$jI_Odd[$hilbertIdx] = $hilbertTempReal;
$jI += $hilbertTempReal;
$jI -= $prev_jI_Odd;
$prev_jI_Odd = $b * $prev_jI_input_Odd;
$jI += $prev_jI_Odd;
$prev_jI_input_Odd = $I1ForOddPrev3;
$jI *= $adjustedPrevPeriod;
}
{
$hilbertTempReal = $a * $Q1;
$jQ = -$jQ_Odd[$hilbertIdx];
$jQ_Odd[$hilbertIdx] = $hilbertTempReal;
$jQ += $hilbertTempReal;
$jQ -= $prev_jQ_Odd;
$prev_jQ_Odd = $b * $prev_jQ_input_Odd;
$jQ += $prev_jQ_Odd;
$prev_jQ_input_Odd = $Q1;
$jQ *= $adjustedPrevPeriod;
}
$Q2 = 0.2 * ($Q1 + $jI) + 0.8 * $prevQ2;
$I2 = 0.2 * ($I1ForOddPrev3 - $jQ) + 0.8 * $prevI2;
$I1ForEvenPrev3 = $I1ForEvenPrev2;
$I1ForEvenPrev2 = $detrender;
if ($I1ForOddPrev3 !== 0.0) {
$tempReal2 = atan($Q1 / $I1ForOddPrev3) * $rad2Deg;
} else {
$tempReal2 = 0.0;
}
}
$tempReal = $prevPhase - $tempReal2;
$prevPhase = $tempReal2;
if ($tempReal < 1.0) {
$tempReal = 1.0;
}
if ($tempReal > 1.0) {
$tempReal = $optInFastLimit / $tempReal;
if ($tempReal < $optInSlowLimit) {
$tempReal = $optInSlowLimit;
}
} else {
$tempReal = $optInFastLimit;
}
$mama = $tempReal * $todayValue + (1 - $tempReal) * $mama;
$tempReal *= 0.5;
$fama = $tempReal * $mama + (1 - $tempReal) * $fama;
if ($today >= $startIdx) {
$outMAMA[$outIdx] = $mama;
$outFAMA[$outIdx++] = $fama;
}
$Re = 0.2 * ($I2 * $prevI2 + $Q2 * $prevQ2) + 0.8 * $Re;
$Im = 0.2 * ($I2 * $prevQ2 - $Q2 * $prevI2) + 0.8 * $Im;
$prevQ2 = $Q2;
$prevI2 = $I2;
$tempReal = $period;
if ($Im !== 0.0 && $Re !== 0.0) {
$period = 360.0 / (atan($Im / $Re) * $rad2Deg);
}
$tempReal2 = 1.5 * $tempReal;
if ($period > $tempReal2) {
$period = $tempReal2;
}
$tempReal2 = 0.67 * $tempReal;
if ($period < $tempReal2) {
$period = $tempReal2;
}
if ($period < 6) {
$period = 6;
} elseif ($period > 50) {
$period = 50;
}
$period = 0.2 * $period + 0.8 * $tempReal;
$today++;
}
$outNBElement = $outIdx;
return ReturnCode::Success;
}
public static function movingAverageVariablePeriod(
int $startIdx,
int $endIdx,
array $inReal,
array &$inPeriods,
int $optInMinPeriod,
int $optInMaxPeriod,
int $optInMAType,
int &$outBegIdx,
int &$outNBElement,
array &$outReal
): int {
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
$localBegIdx = 0;
$localNbElement = 0;
if ($optInMinPeriod === PHP_INT_MIN) {
$optInMinPeriod = 2;
} elseif ($optInMinPeriod < 2 || $optInMinPeriod > 100000) {
return ReturnCode::BadParam;
}
if ($optInMaxPeriod === PHP_INT_MIN) {
$optInMaxPeriod = 30;
} elseif ($optInMaxPeriod < 2 || $optInMaxPeriod > 100000) {
return ReturnCode::BadParam;
}
$lookbackTotal = Lookback::movingAverageLookback($optInMaxPeriod, $optInMAType);
if ($startIdx < $lookbackTotal) {
$startIdx = $lookbackTotal;
}
if ($startIdx > $endIdx) {
$outBegIdx = 0;
$outNBElement = 0;
return ReturnCode::Success;
}
if ($lookbackTotal > $startIdx) {
$tempInt = $lookbackTotal;
} else {
$tempInt = $startIdx;
}
if ($tempInt > $endIdx) {
$outBegIdx = 0;
$outNBElement = 0;
return ReturnCode::Success;
}
$outputSize = $endIdx - $tempInt + 1;
$localOutputArray = \array_pad([], $outputSize, 0.);
$localPeriodArray = \array_pad([], $outputSize, 0);
for ($i = 0; $i < $outputSize; $i++) {
$tempInt = (int)$inPeriods[$startIdx + $i];
if ($tempInt < $optInMinPeriod) {
$tempInt = $optInMinPeriod;
} elseif ($tempInt > $optInMaxPeriod) {
$tempInt = $optInMaxPeriod;
}
$localPeriodArray[$i] = $tempInt;
}
for ($i = 0; $i < $outputSize; $i++) {
$curPeriod = $localPeriodArray[$i];
if ($curPeriod !== 0) {
$ReturnCode = self::movingAverage(
$startIdx,
$endIdx,
$inReal,
$curPeriod,
$optInMAType,
$localBegIdx,
$localNbElement,
$localOutputArray
);
if ($ReturnCode !== ReturnCode::Success) {
$outBegIdx = 0;
$outNBElement = 0;
return $ReturnCode;
}
$outReal[$i] = $localOutputArray[$i];
for ($j = $i + 1; $j < $outputSize; $j++) {
if ($localPeriodArray[$j] === $curPeriod) {
$localPeriodArray[$j] = 0;
$outReal[$j] = $localOutputArray[$j];
}
}
}
}
$outBegIdx = $startIdx;
$outNBElement = $outputSize;
return ReturnCode::Success;
}
public static function midPoint(int $startIdx, int $endIdx, array $inReal, int $optInTimePeriod, int &$outBegIdx, int &$outNBElement, array &$outReal): int
{
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
if ($optInTimePeriod === PHP_INT_MIN) {
$optInTimePeriod = 14;
} elseif ($optInTimePeriod < 2 || $optInTimePeriod > 100000) {
return ReturnCode::BadParam;
}
$nbInitialElementNeeded = $optInTimePeriod - 1;
if ($startIdx < $nbInitialElementNeeded) {
$startIdx = $nbInitialElementNeeded;
}
if ($startIdx > $endIdx) {
$outBegIdx = 0;
$outNBElement = 0;
return ReturnCode::Success;
}
$outIdx = 0;
$today = $startIdx;
$trailingIdx = $startIdx - $nbInitialElementNeeded;
while ($today <= $endIdx) {
$lowest = $inReal[$trailingIdx++];
$highest = $lowest;
for ($i = $trailingIdx; $i <= $today; $i++) {
$tmp = $inReal[$i];
if ($tmp < $lowest) {
$lowest = $tmp;
} elseif ($tmp > $highest) {
$highest = $tmp;
}
}
$outReal[$outIdx++] = ($highest + $lowest) / 2.0;
$today++;
}
$outBegIdx = $startIdx;
$outNBElement = $outIdx;
return ReturnCode::Success;
}
public static function midPrice(int $startIdx, int $endIdx, array $inHigh, array $inLow, int $optInTimePeriod, int &$outBegIdx, int &$outNBElement, array &$outReal): int
{
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
if ($optInTimePeriod === PHP_INT_MIN) {
$optInTimePeriod = 14;
} elseif ($optInTimePeriod < 2 || $optInTimePeriod > 100000) {
return ReturnCode::BadParam;
}
$nbInitialElementNeeded = $optInTimePeriod - 1;
if ($startIdx < $nbInitialElementNeeded) {
$startIdx = $nbInitialElementNeeded;
}
if ($startIdx > $endIdx) {
$outBegIdx = 0;
$outNBElement = 0;
return ReturnCode::Success;
}
$outIdx = 0;
$today = $startIdx;
$trailingIdx = $startIdx - $nbInitialElementNeeded;
while ($today <= $endIdx) {
$lowest = $inLow[$trailingIdx];
$highest = $inHigh[$trailingIdx];
$trailingIdx++;
for ($i = $trailingIdx; $i <= $today; $i++) {
$tmp = $inLow[$i];
if ($tmp < $lowest) {
$lowest = $tmp;
}
$tmp = $inHigh[$i];
if ($tmp > $highest) {
$highest = $tmp;
}
}
$outReal[$outIdx++] = ($highest + $lowest) / 2.0;
$today++;
}
$outBegIdx = $startIdx;
$outNBElement = $outIdx;
return ReturnCode::Success;
}
public static function sar(int $startIdx, int $endIdx, array $inHigh, array $inLow, float $optInAcceleration, float $optInMaximum, int &$outBegIdx, int &$outNBElement, array &$outReal): int
{
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
$tempInt = 0;
$ep_temp = static::double(1);
if ($optInAcceleration === -4e+37) {
$optInAcceleration = 2.000000e-2;
} elseif ($optInAcceleration < 0.000000e+0 || $optInAcceleration > 3.000000e+37) {
return ReturnCode::BadParam;
}
if ($optInMaximum === -4e+37) {
$optInMaximum = 2.000000e-1;
} elseif ($optInMaximum < 0.000000e+0 || $optInMaximum > 3.000000e+37) {
return ReturnCode::BadParam;
}
if ($startIdx < 1) {
$startIdx = 1;
}
if ($startIdx > $endIdx) {
$outBegIdx = 0;
$outNBElement = 0;
return ReturnCode::Success;
}
$af = $optInAcceleration;
if ($af > $optInMaximum) {
$af = $optInAcceleration = $optInMaximum;
}
$ReturnCode = MomentumIndicators::minusDM(
$startIdx,
$startIdx,
$inHigh,
$inLow,
1,
$tempInt,
$tempInt,
$ep_temp
);
if ($ep_temp[0] > 0) {
$isLong = 0;
} else {
$isLong = 1;
}
if ($ReturnCode !== ReturnCode::Success) {
$outBegIdx = 0;
$outNBElement = 0;
return $ReturnCode;
}
$outBegIdx = $startIdx;
$outIdx = 0;
$todayIdx = $startIdx;
$newHigh = $inHigh[$todayIdx - 1];
$newLow = $inLow[$todayIdx - 1];
if ($isLong === 1) {
$ep = $inHigh[$todayIdx];
$sar = $newLow;
} else {
$ep = $inLow[$todayIdx];
$sar = $newHigh;
}
$newLow = $inLow[$todayIdx];
$newHigh = $inHigh[$todayIdx];
while ($todayIdx <= $endIdx) {
$prevLow = $newLow;
$prevHigh = $newHigh;
$newLow = $inLow[$todayIdx];
$newHigh = $inHigh[$todayIdx];
$todayIdx++;
if ($isLong === 1) {
if ($newLow <= $sar) {
$isLong = 0;
$sar = $ep;
if ($sar < $prevHigh) {
$sar = $prevHigh;
}
if ($sar < $newHigh) {
$sar = $newHigh;
}
$outReal[$outIdx++] = $sar;
$af = $optInAcceleration;
$ep = $newLow;
$sar = $sar + $af * ($ep - $sar);
if ($sar < $prevHigh) {
$sar = $prevHigh;
}
if ($sar < $newHigh) {
$sar = $newHigh;
}
} else {
$outReal[$outIdx++] = $sar;
if ($newHigh > $ep) {
$ep = $newHigh;
$af += $optInAcceleration;
if ($af > $optInMaximum) {
$af = $optInMaximum;
}
}
$sar = $sar + $af * ($ep - $sar);
if ($sar > $prevLow) {
$sar = $prevLow;
}
if ($sar > $newLow) {
$sar = $newLow;
}
}
} else {
if ($newHigh >= $sar) {
$isLong = 1;
$sar = $ep;
if ($sar > $prevLow) {
$sar = $prevLow;
}
if ($sar > $newLow) {
$sar = $newLow;
}
$outReal[$outIdx++] = $sar;
$af = $optInAcceleration;
$ep = $newHigh;
$sar = $sar + $af * ($ep - $sar);
if ($sar > $prevLow) {
$sar = $prevLow;
}
if ($sar > $newLow) {
$sar = $newLow;
}
} else {
$outReal[$outIdx++] = $sar;
if ($newLow < $ep) {
$ep = $newLow;
$af += $optInAcceleration;
if ($af > $optInMaximum) {
$af = $optInMaximum;
}
}
$sar = $sar + $af * ($ep - $sar);
if ($sar < $prevHigh) {
$sar = $prevHigh;
}
if ($sar < $newHigh) {
$sar = $newHigh;
}
}
}
}
$outNBElement = $outIdx;
return ReturnCode::Success;
}
public static function sarExt(
int $startIdx,
int $endIdx,
array $inHigh,
array $inLow,
float $optInStartValue,
float $optInOffsetOnReverse,
float $optInAccelerationInitLong,
float $optInAccelerationLong,
float $optInAccelerationMaxLong,
float $optInAccelerationInitShort,
float $optInAccelerationShort,
float $optInAccelerationMaxShort,
int &$outBegIdx,
int &$outNBElement,
array &$outReal
): int {
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
$tempInt = 0;
$ep_temp = static::double(1);
if ($optInStartValue < -4e+37) {
$optInStartValue = 0.000000e+0;
} elseif ($optInStartValue < -3.000000e+37 || $optInStartValue > 3.000000e+37) {
return ReturnCode::BadParam;
}
if ($optInOffsetOnReverse < -4e+37) {
$optInOffsetOnReverse = 0.000000e+0;
} elseif ($optInOffsetOnReverse < 0.000000e+0 || $optInOffsetOnReverse > 3.000000e+37) {
return ReturnCode::BadParam;
}
if ($optInAccelerationInitLong < -4e+37) {
$optInAccelerationInitLong = 2.000000e-2;
} elseif ($optInAccelerationInitLong < 0.000000e+0 || $optInAccelerationInitLong > 3.000000e+37) {
return ReturnCode::BadParam;
}
if ($optInAccelerationLong < -4e+37) {
$optInAccelerationLong = 2.000000e-2;
} elseif ($optInAccelerationLong < 0.000000e+0 || $optInAccelerationLong > 3.000000e+37) {
return ReturnCode::BadParam;
}
if ($optInAccelerationMaxLong < -4e+37) {
$optInAccelerationMaxLong = 2.000000e-1;
} elseif ($optInAccelerationMaxLong < 0.000000e+0 || $optInAccelerationMaxLong > 3.000000e+37) {
return ReturnCode::BadParam;
}
if ($optInAccelerationInitShort < -4e+37) {
$optInAccelerationInitShort = 2.000000e-2;
} elseif ($optInAccelerationInitShort < 0.000000e+0 || $optInAccelerationInitShort > 3.000000e+37) {
return ReturnCode::BadParam;
}
if ($optInAccelerationShort < -4e+37) {
$optInAccelerationShort = 2.000000e-2;
} elseif ($optInAccelerationShort < 0.000000e+0 || $optInAccelerationShort > 3.000000e+37) {
return ReturnCode::BadParam;
}
if ($optInAccelerationMaxShort < -4e+37) {
$optInAccelerationMaxShort = 2.000000e-1;
} elseif ($optInAccelerationMaxShort < 0.000000e+0 || $optInAccelerationMaxShort > 3.000000e+37) {
return ReturnCode::BadParam;
}
if ($startIdx < 1) {
$startIdx = 1;
}
if ($startIdx > $endIdx) {
$outBegIdx = 0;
$outNBElement = 0;
return ReturnCode::Success;
}
$afLong = $optInAccelerationInitLong;
$afShort = $optInAccelerationInitShort;
if ($afLong > $optInAccelerationMaxLong) {
$afLong = $optInAccelerationInitLong = $optInAccelerationMaxLong;
}
if ($optInAccelerationLong > $optInAccelerationMaxLong) {
$optInAccelerationLong = $optInAccelerationMaxLong;
}
if ($afShort > $optInAccelerationMaxShort) {
$afShort = $optInAccelerationInitShort = $optInAccelerationMaxShort;
}
if ($optInAccelerationShort > $optInAccelerationMaxShort) {
$optInAccelerationShort = $optInAccelerationMaxShort;
}
if ($optInStartValue === 0.0) {
$ReturnCode = MomentumIndicators::minusDM(
$startIdx,
$startIdx,
$inHigh,
$inLow,
1,
$tempInt,
$tempInt,
$ep_temp
);
if ($ep_temp[0] > 0) {
$isLong = 0;
} else {
$isLong = 1;
}
if ($ReturnCode !== ReturnCode::Success) {
$outBegIdx = 0;
$outNBElement = 0;
return $ReturnCode;
}
} elseif ($optInStartValue > 0) {
$isLong = 1;
} else {
$isLong = 0;
}
$outBegIdx = $startIdx;
$outIdx = 0;
$todayIdx = $startIdx;
$newHigh = $inHigh[$todayIdx - 1];
$newLow = $inLow[$todayIdx - 1];
if ($optInStartValue === 0.0) {
if ($isLong === 1) {
$ep = $inHigh[$todayIdx];
$sar = $newLow;
} else {
$ep = $inLow[$todayIdx];
$sar = $newHigh;
}
} elseif ($optInStartValue > 0) {
$ep = $inHigh[$todayIdx];
$sar = $optInStartValue;
} else {
$ep = $inLow[$todayIdx];
$sar = abs($optInStartValue);
}
$newLow = $inLow[$todayIdx];
$newHigh = $inHigh[$todayIdx];
while ($todayIdx <= $endIdx) {
$prevLow = $newLow;
$prevHigh = $newHigh;
$newLow = $inLow[$todayIdx];
$newHigh = $inHigh[$todayIdx];
$todayIdx++;
if ($isLong === 1) {
if ($newLow <= $sar) {
$isLong = 0;
$sar = $ep;
if ($sar < $prevHigh) {
$sar = $prevHigh;
}
if ($sar < $newHigh) {
$sar = $newHigh;
}
if ($optInOffsetOnReverse !== 0.0) {
$sar += $sar * $optInOffsetOnReverse;
}
$outReal[$outIdx++] = -$sar;
$afShort = $optInAccelerationInitShort;
$ep = $newLow;
$sar = $sar + $afShort * ($ep - $sar);
if ($sar < $prevHigh) {
$sar = $prevHigh;
}
if ($sar < $newHigh) {
$sar = $newHigh;
}
} else {
$outReal[$outIdx++] = $sar;
if ($newHigh > $ep) {
$ep = $newHigh;
$afLong += $optInAccelerationLong;
if ($afLong > $optInAccelerationMaxLong) {
$afLong = $optInAccelerationMaxLong;
}
}
$sar = $sar + $afLong * ($ep - $sar);
if ($sar > $prevLow) {
$sar = $prevLow;
}
if ($sar > $newLow) {
$sar = $newLow;
}
}
} elseif ($newHigh >= $sar) {
$isLong = 1;
$sar = $ep;
if ($sar > $prevLow) {
$sar = $prevLow;
}
if ($sar > $newLow) {
$sar = $newLow;
}
if ($optInOffsetOnReverse !== 0.0) {
$sar -= $sar * $optInOffsetOnReverse;
}
$outReal[$outIdx++] = $sar;
$afLong = $optInAccelerationInitLong;
$ep = $newHigh;
$sar = $sar + $afLong * ($ep - $sar);
if ($sar > $prevLow) {
$sar = $prevLow;
}
if ($sar > $newLow) {
$sar = $newLow;
}
} else {
$outReal[$outIdx++] = -$sar;
if ($newLow < $ep) {
$ep = $newLow;
$afShort += $optInAccelerationShort;
if ($afShort > $optInAccelerationMaxShort) {
$afShort = $optInAccelerationMaxShort;
}
}
$sar = $sar + $afShort * ($ep - $sar);
if ($sar < $prevHigh) {
$sar = $prevHigh;
}
if ($sar < $newHigh) {
$sar = $newHigh;
}
}
}
$outNBElement = $outIdx;
return ReturnCode::Success;
}
public static function sma(int $startIdx, int $endIdx, array $inReal, int $optInTimePeriod, int &$outBegIdx, int &$outNBElement, array &$outReal): int
{
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
if ($optInTimePeriod === PHP_INT_MIN) {
$optInTimePeriod = 30;
} elseif ($optInTimePeriod < 2 || $optInTimePeriod > 100000) {
return ReturnCode::BadParam;
}
return static::TA_INT_SMA(
$startIdx,
$endIdx,
$inReal,
$optInTimePeriod,
$outBegIdx,
$outNBElement,
$outReal
);
}
public static function t3(int $startIdx, int $endIdx, array $inReal, int $optInTimePeriod, float $optInVFactor, int &$outBegIdx, int &$outNBElement, array &$outReal): int
{
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
if ($optInTimePeriod === PHP_INT_MIN) {
$optInTimePeriod = 5;
} elseif ($optInTimePeriod < 2 || $optInTimePeriod > 100000) {
return ReturnCode::BadParam;
}
if ($optInVFactor === -4e+37) {
$optInVFactor = 7.000000e-1;
} elseif ($optInVFactor < 0.000000e+0 || $optInVFactor > 1.000000e+0) {
return ReturnCode::BadParam;
}
$lookbackTotal = 6 * ($optInTimePeriod - 1) + static::$unstablePeriod[UnstablePeriodFunctionID::T3];
if ($startIdx <= $lookbackTotal) {
$startIdx = (int)$lookbackTotal;
}
if ($startIdx > $endIdx) {
$outNBElement = 0;
$outBegIdx = 0;
return ReturnCode::Success;
}
$outBegIdx = $startIdx;
$today = $startIdx - $lookbackTotal;
$k = 2.0 / ($optInTimePeriod + 1.0);
$one_minus_k = 1.0 - $k;
$tempReal = $inReal[$today++];
for ($i = $optInTimePeriod - 1; $i > 0; $i--) {
$tempReal += $inReal[$today++];
}
$e1 = $tempReal / $optInTimePeriod;
$tempReal = $e1;
for ($i = $optInTimePeriod - 1; $i > 0; $i--) {
$e1 = $k * $inReal[$today++] + $one_minus_k * $e1;
$tempReal += $e1;
}
$e2 = $tempReal / $optInTimePeriod;
$tempReal = $e2;
for ($i = $optInTimePeriod - 1; $i > 0; $i--) {
$e1 = $k * $inReal[$today++] + $one_minus_k * $e1;
$e2 = $k * $e1 + $one_minus_k * $e2;
$tempReal += $e2;
}
$e3 = $tempReal / $optInTimePeriod;
$tempReal = $e3;
for ($i = $optInTimePeriod - 1; $i > 0; $i--) {
$e1 = $k * $inReal[$today++] + $one_minus_k * $e1;
$e2 = $k * $e1 + $one_minus_k * $e2;
$e3 = $k * $e2 + $one_minus_k * $e3;
$tempReal += $e3;
}
$e4 = $tempReal / $optInTimePeriod;
$tempReal = $e4;
for ($i = $optInTimePeriod - 1; $i > 0; $i--) {
$e1 = $k * $inReal[$today++] + $one_minus_k * $e1;
$e2 = $k * $e1 + $one_minus_k * $e2;
$e3 = $k * $e2 + $one_minus_k * $e3;
$e4 = $k * $e3 + $one_minus_k * $e4;
$tempReal += $e4;
}
$e5 = $tempReal / $optInTimePeriod;
$tempReal = $e5;
for ($i = $optInTimePeriod - 1; $i > 0; $i--) {
$e1 = $k * $inReal[$today++] + $one_minus_k * $e1;
$e2 = $k * $e1 + $one_minus_k * $e2;
$e3 = $k * $e2 + $one_minus_k * $e3;
$e4 = $k * $e3 + $one_minus_k * $e4;
$e5 = $k * $e4 + $one_minus_k * $e5;
$tempReal += $e5;
}
$e6 = $tempReal / $optInTimePeriod;
while ($today <= $startIdx) {
$e1 = $k * $inReal[$today++] + $one_minus_k * $e1;
$e2 = $k * $e1 + $one_minus_k * $e2;
$e3 = $k * $e2 + $one_minus_k * $e3;
$e4 = $k * $e3 + $one_minus_k * $e4;
$e5 = $k * $e4 + $one_minus_k * $e5;
$e6 = $k * $e5 + $one_minus_k * $e6;
}
$tempReal = $optInVFactor * $optInVFactor;
$c1 = -($tempReal * $optInVFactor);
$c2 = 3.0 * ($tempReal - $c1);
$c3 = -6.0 * $tempReal - 3.0 * ($optInVFactor - $c1);
$c4 = 1.0 + 3.0 * $optInVFactor - $c1 + 3.0 * $tempReal;
$outIdx = 0;
$outReal[$outIdx++] = $c1 * $e6 + $c2 * $e5 + $c3 * $e4 + $c4 * $e3;
while ($today <= $endIdx) {
$e1 = $k * $inReal[$today++] + $one_minus_k * $e1;
$e2 = $k * $e1 + $one_minus_k * $e2;
$e3 = $k * $e2 + $one_minus_k * $e3;
$e4 = $k * $e3 + $one_minus_k * $e4;
$e5 = $k * $e4 + $one_minus_k * $e5;
$e6 = $k * $e5 + $one_minus_k * $e6;
$outReal[$outIdx++] = $c1 * $e6 + $c2 * $e5 + $c3 * $e4 + $c4 * $e3;
}
$outNBElement = $outIdx;
return ReturnCode::Success;
}
public static function tema(int $startIdx, int $endIdx, array $inReal, int $optInTimePeriod, int &$outBegIdx, int &$outNBElement, array &$outReal): int
{
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
$firstEMABegIdx = 0;
$firstEMANbElement = 0;
$secondEMABegIdx = 0;
$secondEMANbElement = 0;
$thirdEMABegIdx = 0;
$thirdEMANbElement = 0;
if ($optInTimePeriod === PHP_INT_MIN) {
$optInTimePeriod = 30;
} elseif ($optInTimePeriod < 2 || $optInTimePeriod > 100000) {
return ReturnCode::BadParam;
}
$outNBElement = 0;
$outBegIdx = 0;
$lookbackEMA = Lookback::emaLookback($optInTimePeriod);
$lookbackTotal = $lookbackEMA * 3;
if ($startIdx < $lookbackTotal) {
$startIdx = (int)$lookbackTotal;
}
if ($startIdx > $endIdx) {
return ReturnCode::Success;
}
$tempInt = $lookbackTotal + ($endIdx - $startIdx) + 1;
$firstEMA = static::double($tempInt);
$k = 2.0 / (double)($optInTimePeriod + 1);
$ReturnCode = static::TA_INT_EMA(
$startIdx - $lookbackEMA * 2,
$endIdx,
$inReal,
$optInTimePeriod,
$k,
$firstEMABegIdx,
$firstEMANbElement,
$firstEMA
);
if ($ReturnCode !== ReturnCode::Success || $firstEMANbElement === 0) {
return $ReturnCode;
}
$secondEMA = static::double($firstEMANbElement);
$ReturnCode = static::TA_INT_EMA(
0,
$firstEMANbElement - 1,
$firstEMA,
$optInTimePeriod,
$k,
$secondEMABegIdx,
$secondEMANbElement,
$secondEMA
);
if ($ReturnCode !== ReturnCode::Success || $secondEMANbElement === 0) {
return $ReturnCode;
}
$ReturnCode = static::TA_INT_EMA(
0,
$secondEMANbElement - 1,
$secondEMA,
$optInTimePeriod,
$k,
$thirdEMABegIdx,
$thirdEMANbElement,
$outReal
);
if ($ReturnCode !== ReturnCode::Success || $thirdEMANbElement === 0) {
return $ReturnCode;
}
$firstEMAIdx = $thirdEMABegIdx + $secondEMABegIdx;
$secondEMAIdx = $thirdEMABegIdx;
$outBegIdx = $firstEMAIdx + $firstEMABegIdx;
$outIdx = 0;
while ($outIdx < $thirdEMANbElement) {
$outReal[$outIdx] += 3.0 * $firstEMA[$firstEMAIdx++] - 3.0 * $secondEMA[$secondEMAIdx++];
$outIdx++;
}
$outNBElement = $outIdx;
return ReturnCode::Success;
}
public static function trima(int $startIdx, int $endIdx, array $inReal, int $optInTimePeriod, int &$outBegIdx, int &$outNBElement, array &$outReal): int
{
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
if ($optInTimePeriod === PHP_INT_MIN) {
$optInTimePeriod = 30;
} elseif ($optInTimePeriod < 2 || $optInTimePeriod > 100000) {
return ReturnCode::BadParam;
}
$lookbackTotal = $optInTimePeriod - 1;
if ($startIdx < $lookbackTotal) {
$startIdx = $lookbackTotal;
}
if ($startIdx > $endIdx) {
$outBegIdx = 0;
$outNBElement = 0;
return ReturnCode::Success;
}
$outIdx = 0;
$i = $optInTimePeriod >> 1;
if ($optInTimePeriod % 2 === 1) {
$factor = ($i + 1) * ($i + 1);
$factor = 1.0 / $factor;
$trailingIdx = $startIdx - $lookbackTotal;
$middleIdx = $trailingIdx + $i;
$todayIdx = $middleIdx + $i;
$numerator = 0.0;
$numeratorSub = 0.0;
for ($i = $middleIdx; $i >= $trailingIdx; $i--) {
$tempReal = $inReal[$i];
$numeratorSub += $tempReal;
$numerator += $numeratorSub;
}
$numeratorAdd = 0.0;
$middleIdx++;
for ($i = $middleIdx; $i <= $todayIdx; $i++) {
$tempReal = $inReal[$i];
$numeratorAdd += $tempReal;
$numerator += $numeratorAdd;
}
$tempReal = $inReal[$trailingIdx++];
$outReal[$outIdx++] = $numerator * $factor;
$todayIdx++;
while ($todayIdx <= $endIdx) {
$numerator -= $numeratorSub;
$numeratorSub -= $tempReal;
$tempReal = $inReal[$middleIdx++];
$numeratorSub += $tempReal;
$numerator += $numeratorAdd;
$numeratorAdd -= $tempReal;
$tempReal = $inReal[$todayIdx++];
$numeratorAdd += $tempReal;
$numerator += $tempReal;
$tempReal = $inReal[$trailingIdx++];
$outReal[$outIdx++] = $numerator * $factor;
}
} else {
$factor = $i * ($i + 1);
$factor = 1.0 / $factor;
$trailingIdx = $startIdx - $lookbackTotal;
$middleIdx = $trailingIdx + $i - 1;
$todayIdx = $middleIdx + $i;
$numerator = 0.0;
$numeratorSub = 0.0;
for ($i = $middleIdx; $i >= $trailingIdx; $i--) {
$tempReal = $inReal[$i];
$numeratorSub += $tempReal;
$numerator += $numeratorSub;
}
$numeratorAdd = 0.0;
$middleIdx++;
for ($i = $middleIdx; $i <= $todayIdx; $i++) {
$tempReal = $inReal[$i];
$numeratorAdd += $tempReal;
$numerator += $numeratorAdd;
}
$tempReal = $inReal[$trailingIdx++];
$outReal[$outIdx++] = $numerator * $factor;
$todayIdx++;
while ($todayIdx <= $endIdx) {
$numerator -= $numeratorSub;
$numeratorSub -= $tempReal;
$tempReal = $inReal[$middleIdx++];
$numeratorSub += $tempReal;
$numeratorAdd -= $tempReal;
$numerator += $numeratorAdd;
$tempReal = $inReal[$todayIdx++];
$numeratorAdd += $tempReal;
$numerator += $tempReal;
$tempReal = $inReal[$trailingIdx++];
$outReal[$outIdx++] = $numerator * $factor;
}
}
$outNBElement = $outIdx;
$outBegIdx = $startIdx;
return ReturnCode::Success;
}
public static function wma(int $startIdx, int $endIdx, array $inReal, int $optInTimePeriod, int &$outBegIdx, int &$outNBElement, array &$outReal): int
{
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
if ($optInTimePeriod === PHP_INT_MIN) {
$optInTimePeriod = 30;
} elseif ($optInTimePeriod < 2 || $optInTimePeriod > 100000) {
return ReturnCode::BadParam;
}
$lookbackTotal = $optInTimePeriod - 1;
if ($startIdx < $lookbackTotal) {
$startIdx = $lookbackTotal;
}
if ($startIdx > $endIdx) {
$outBegIdx = 0;
$outNBElement = 0;
return ReturnCode::Success;
}
$divider = $optInTimePeriod * ($optInTimePeriod + 1) >> 1;
$outIdx = 0;
$trailingIdx = $startIdx - $lookbackTotal;
$periodSum = $periodSub = 0.0;
$inIdx = $trailingIdx;
$i = 1;
while ($inIdx < $startIdx) {
$tempReal = $inReal[$inIdx++];
$periodSub += $tempReal;
$periodSum += $tempReal * $i;
$i++;
}
$trailingValue = 0.0;
while ($inIdx <= $endIdx) {
$tempReal = $inReal[$inIdx++];
$periodSub += $tempReal;
$periodSub -= $trailingValue;
$periodSum += $tempReal * $optInTimePeriod;
$trailingValue = $inReal[$trailingIdx++];
$outReal[$outIdx++] = $periodSum / $divider;
$periodSum -= $periodSub;
}
$outNBElement = $outIdx;
$outBegIdx = $startIdx;
return ReturnCode::Success;
}
}
?>
Did this file decode correctly?
Original Code
<?php
/**
* This is a PHP port of the Trader extension for PHP, which is a port of the TA-LIB C code.
*
* This port is written in PHP and without any other requirements.
* The goal is that this library can be used by those whom cannot install the PHP Trader extension.
*
* Below is the copyright information for TA-LIB found in the source code.
*/
/* TA-LIB Copyright (c) 1999-2007, Mario Fortier
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* - Neither name of author nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace LupeCode\phpTraderNative\TALib\Core;
use LupeCode\phpTraderNative\TALib\Enum\MovingAverageType;
use LupeCode\phpTraderNative\TALib\Enum\ReturnCode;
use LupeCode\phpTraderNative\TALib\Enum\UnstablePeriodFunctionID;
class OverlapStudies extends Core
{
public static function accbands(
int $startIdx,
int $endIdx,
array $inHigh,
array $inLow,
array $inClose,
int $optInTimePeriod,
int &$outBegIdx,
int &$outNBElement,
array &$outRealUpperBand,
array &$outRealMiddleBand,
array &$outRealLowerBand
): int {
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
$lookbackTotal = Lookback::smaLookback($optInTimePeriod);
if ($startIdx < $lookbackTotal) {
$startIdx = $lookbackTotal;
}
if ($startIdx > $endIdx) {
$outBegIdx = 0;
$outNBElement = 0;
return ReturnCode::Success;
}
$outputSize = $endIdx - $startIdx + 1;
$bufferSize = $outputSize + $lookbackTotal;
$tempBuffer1 = static::double($bufferSize);
$tempBuffer2 = static::double($bufferSize);
for ($j = 0, $i = $startIdx - $lookbackTotal; $i <= $endIdx; $i++, $j++) {
$tempReal = $inHigh[$i] + $inLow[$i];
if ($tempReal !== 0.0) {
$tempReal = 4 * ($inHigh[$i] - $inLow[$i]) / $tempReal;
$tempBuffer1[$j] = $inHigh[$i] * (1 + $tempReal);
$tempBuffer2[$j] = $inLow[$i] * (1 - $tempReal);
} else {
$tempBuffer1[$j] = $inHigh[$i];
$tempBuffer2[$j] = $inLow[$i];
}
}
$outRealMiddleBand = static::double($outputSize);
$retCode = static::sma(
$startIdx,
$endIdx,
$inClose,
$optInTimePeriod,
$outBegIdx,
$outNBElement,
$outRealMiddleBand
);
if ($retCode !== ReturnCode::Success || $outNBElement !== $outputSize) {
return $retCode;
}
$outRealUpperBand = static::double($outputSize);
$retCode = static::sma(
0,
$bufferSize - 1,
$tempBuffer1,
$optInTimePeriod,
$outBegIdx,
$outNBElement,
$outRealUpperBand
);
if ($retCode !== ReturnCode::Success || $outNBElement !== $outputSize) {
return $retCode;
}
$outRealLowerBand = static::double($outputSize);
$retCode = static::sma(
0,
$bufferSize - 1,
$tempBuffer2,
$optInTimePeriod,
$outBegIdx,
$outNBElement,
$outRealLowerBand
);
if ($retCode !== ReturnCode::Success || $outNBElement !== $outputSize) {
return $retCode;
}
$outBegIdx = $startIdx;
$outNBElement = $outputSize;
return ReturnCode::Success;
}
public static function bbands(
int $startIdx,
int $endIdx,
array $inReal,
int $optInTimePeriod,
float $optInNbDevUp,
float $optInNbDevDn,
int $optInMAType,
int &$outBegIdx,
int &$outNBElement,
array &$outRealUpperBand,
array &$outRealMiddleBand,
array &$outRealLowerBand
): int {
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
if ($optInTimePeriod === PHP_INT_MIN) {
$optInTimePeriod = 5;
} elseif ($optInTimePeriod < 2 || $optInTimePeriod > 100000) {
return ReturnCode::BadParam;
}
if ($optInNbDevUp === -4e+37) {
$optInNbDevUp = 2.000000e+0;
} elseif ($optInNbDevUp < -3.000000e+37 || $optInNbDevUp > 3.000000e+37) {
return ReturnCode::BadParam;
}
if ($optInNbDevDn === -4e+37) {
$optInNbDevDn = 2.000000e+0;
} elseif ($optInNbDevDn < -3.000000e+37 || $optInNbDevDn > 3.000000e+37) {
return ReturnCode::BadParam;
}
if ($inReal === $outRealUpperBand) {
$tempBuffer1 = $outRealMiddleBand;
$tempBuffer2 = $outRealLowerBand;
} elseif ($inReal === $outRealLowerBand) {
$tempBuffer1 = $outRealMiddleBand;
$tempBuffer2 = $outRealUpperBand;
} elseif ($inReal === $outRealMiddleBand) {
$tempBuffer1 = $outRealLowerBand;
$tempBuffer2 = $outRealUpperBand;
} else {
$tempBuffer1 = $outRealMiddleBand;
$tempBuffer2 = $outRealUpperBand;
}
if ($tempBuffer1 === $inReal || $tempBuffer2 === $inReal) {
return ReturnCode::BadParam;
}
$ReturnCode = self::movingAverage($startIdx, $endIdx, $inReal, $optInTimePeriod, $optInMAType, $outBegIdx, $outNBElement, $tempBuffer1);
if ($ReturnCode !== ReturnCode::Success || $outNBElement === 0) {
$outNBElement = 0;
return $ReturnCode;
}
if ($optInMAType === MovingAverageType::SMA) {
static::TA_INT_stddev_using_precalc_ma($inReal, $tempBuffer1, $outBegIdx, $outNBElement, $optInTimePeriod, $tempBuffer2);
} else {
$ReturnCode = StatisticFunctions::stdDev($outBegIdx, $endIdx, $inReal, $optInTimePeriod, 1.0, $outBegIdx, $outNBElement, $tempBuffer2);
if ($ReturnCode !== ReturnCode::Success) {
$outNBElement = 0;
return $ReturnCode;
}
}
if ($tempBuffer1 !== $outRealMiddleBand) {
$outRealMiddleBand = \array_slice($tempBuffer1, 0, $outNBElement);
}
if ($optInNbDevUp === $optInNbDevDn) {
if ($optInNbDevUp === 1.0) {
for ($i = 0; $i < $outNBElement; $i++) {
$tempReal = $tempBuffer2[$i];
$tempReal2 = $outRealMiddleBand[$i];
$outRealUpperBand[$i] = $tempReal2 + $tempReal;
$outRealLowerBand[$i] = $tempReal2 - $tempReal;
}
} else {
for ($i = 0; $i < $outNBElement; $i++) {
$tempReal = $tempBuffer2[$i] * $optInNbDevUp;
$tempReal2 = $outRealMiddleBand[$i];
$outRealUpperBand[$i] = $tempReal2 + $tempReal;
$outRealLowerBand[$i] = $tempReal2 - $tempReal;
}
}
} elseif ($optInNbDevUp === 1.0) {
for ($i = 0; $i < $outNBElement; $i++) {
$tempReal = $tempBuffer2[$i];
$tempReal2 = $outRealMiddleBand[$i];
$outRealUpperBand[$i] = $tempReal2 + $tempReal;
$outRealLowerBand[$i] = $tempReal2 - $tempReal * $optInNbDevDn;
}
} elseif ($optInNbDevDn === 1.0) {
for ($i = 0; $i < $outNBElement; $i++) {
$tempReal = $tempBuffer2[$i];
$tempReal2 = $outRealMiddleBand[$i];
$outRealLowerBand[$i] = $tempReal2 - $tempReal;
$outRealUpperBand[$i] = $tempReal2 + $tempReal * $optInNbDevUp;
}
} else {
for ($i = 0; $i < $outNBElement; $i++) {
$tempReal = $tempBuffer2[$i];
$tempReal2 = $outRealMiddleBand[$i];
$outRealUpperBand[$i] = $tempReal2 + $tempReal * $optInNbDevUp;
$outRealLowerBand[$i] = $tempReal2 - $tempReal * $optInNbDevDn;
}
}
return ReturnCode::Success;
}
public static function dema(int $startIdx, int $endIdx, array $inReal, int $optInTimePeriod, int &$outBegIdx, int &$outNBElement, array &$outReal): int
{
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
$firstEMABegIdx = 0;
$firstEMANbElement = 0;
$secondEMABegIdx = 0;
$secondEMANbElement = 0;
if ($optInTimePeriod === PHP_INT_MIN) {
$optInTimePeriod = 30;
} elseif ($optInTimePeriod < 2 || $optInTimePeriod > 100000) {
return ReturnCode::BadParam;
}
$outNBElement = 0;
$outBegIdx = 0;
$lookbackEMA = Lookback::emaLookback($optInTimePeriod);
$lookbackTotal = $lookbackEMA * 2;
if ($startIdx < $lookbackTotal) {
$startIdx = (int)$lookbackTotal;
}
if ($startIdx > $endIdx) {
return ReturnCode::Success;
}
if ($inReal === $outReal) {
$firstEMA = $outReal;
} else {
$tempInt = $lookbackTotal + ($endIdx - $startIdx) + 1;
$firstEMA = static::double($tempInt);
}
$k = 2.0 / (double)($optInTimePeriod + 1);
$ReturnCode = static::TA_INT_EMA(
$startIdx - $lookbackEMA,
$endIdx,
$inReal,
$optInTimePeriod,
$k,
$firstEMABegIdx,
$firstEMANbElement,
$firstEMA
);
if ($ReturnCode !== ReturnCode::Success || $firstEMANbElement === 0) {
return $ReturnCode;
}
$secondEMA = static::double($firstEMANbElement);
$ReturnCode = static::TA_INT_EMA(
0,
$firstEMANbElement - 1,
$firstEMA,
$optInTimePeriod,
$k,
$secondEMABegIdx,
$secondEMANbElement,
$secondEMA
);
if ($ReturnCode !== ReturnCode::Success || $secondEMANbElement === 0) {
return $ReturnCode;
}
$firstEMAIdx = $secondEMABegIdx;
$outIdx = 0;
while ($outIdx < $secondEMANbElement) {
$outReal[$outIdx] = 2.0 * $firstEMA[$firstEMAIdx++] - $secondEMA[$outIdx];
$outIdx++;
}
$outBegIdx = $firstEMABegIdx + $secondEMABegIdx;
$outNBElement = $outIdx;
return ReturnCode::Success;
}
public static function ema(int $startIdx, int $endIdx, array $inReal, int $optInTimePeriod, int &$outBegIdx, int &$outNBElement, array &$outReal): int
{
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
if ($optInTimePeriod === PHP_INT_MIN) {
$optInTimePeriod = 30;
} elseif ($optInTimePeriod < 2 || $optInTimePeriod > 100000) {
return ReturnCode::BadParam;
}
return static::TA_INT_EMA(
$startIdx,
$endIdx,
$inReal,
$optInTimePeriod,
2.0 / (double)($optInTimePeriod + 1),
$outBegIdx,
$outNBElement,
$outReal
);
}
public static function htTrendline(int $startIdx, int $endIdx, array $inReal, int &$outBegIdx, int &$outNBElement, array &$outReal): int
{
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
$a = 0.0962;
$b = 0.5769;
$detrender_Odd = static::double(3);
$detrender_Even = static::double(3);
$Q1_Odd = static::double(3);
$Q1_Even = static::double(3);
$jI_Odd = static::double(3);
$jI_Even = static::double(3);
$jQ_Odd = static::double(3);
$jQ_Even = static::double(3);
$smoothPrice_Idx = 0;
$maxIdx_smoothPricePrice = 50 - 1;
{
$smoothPrice = static::double($maxIdx_smoothPricePrice + 1);
}
$iTrend1 = $iTrend2 = $iTrend3 = 0.0;
$tempReal = atan(1);
$rad2Deg = 45.0 / $tempReal;
$lookbackTotal = 63 + static::$unstablePeriod[UnstablePeriodFunctionID::HtTrendline];
if ($startIdx < $lookbackTotal) {
$startIdx = $lookbackTotal;
}
if ($startIdx > $endIdx) {
$outBegIdx = 0;
$outNBElement = 0;
return ReturnCode::Success;
}
$outBegIdx = $startIdx;
$trailingWMAIdx = $startIdx - $lookbackTotal;
$today = $trailingWMAIdx;
$tempReal = $inReal[$today++];
$periodWMASub = $tempReal;
$periodWMASum = $tempReal;
$tempReal = $inReal[$today++];
$periodWMASub += $tempReal;
$periodWMASum += $tempReal * 2.0;
$tempReal = $inReal[$today++];
$periodWMASub += $tempReal;
$periodWMASum += $tempReal * 3.0;
$trailingWMAValue = 0.0;
$i = 34;
do {
$tempReal = $inReal[$today++];
{
$periodWMASub += $tempReal;
$periodWMASub -= $trailingWMAValue;
$periodWMASum += $tempReal * 4.0;
$trailingWMAValue = $inReal[$trailingWMAIdx++];
$smoothedValue = $periodWMASum * 0.1;
$periodWMASum -= $periodWMASub;
}
} while (--$i !== 0);
$hilbertIdx = 0;
{
$detrender_Odd[0] = 0.0;
$detrender_Odd[1] = 0.0;
$detrender_Odd[2] = 0.0;
$detrender_Even[0] = 0.0;
$detrender_Even[1] = 0.0;
$detrender_Even[2] = 0.0;
$detrender = 0.0;
$prev_detrender_Odd = 0.0;
$prev_detrender_Even = 0.0;
$prev_detrender_input_Odd = 0.0;
$prev_detrender_input_Even = 0.0;
}
{
$Q1_Odd[0] = 0.0;
$Q1_Odd[1] = 0.0;
$Q1_Odd[2] = 0.0;
$Q1_Even[0] = 0.0;
$Q1_Even[1] = 0.0;
$Q1_Even[2] = 0.0;
$Q1 = 0.0;
$prev_Q1_Odd = 0.0;
$prev_Q1_Even = 0.0;
$prev_Q1_input_Odd = 0.0;
$prev_Q1_input_Even = 0.0;
}
{
$jI_Odd[0] = 0.0;
$jI_Odd[1] = 0.0;
$jI_Odd[2] = 0.0;
$jI_Even[0] = 0.0;
$jI_Even[1] = 0.0;
$jI_Even[2] = 0.0;
$jI = 0.0;
$prev_jI_Odd = 0.0;
$prev_jI_Even = 0.0;
$prev_jI_input_Odd = 0.0;
$prev_jI_input_Even = 0.0;
}
{
$jQ_Odd[0] = 0.0;
$jQ_Odd[1] = 0.0;
$jQ_Odd[2] = 0.0;
$jQ_Even[0] = 0.0;
$jQ_Even[1] = 0.0;
$jQ_Even[2] = 0.0;
$jQ = 0.0;
$prev_jQ_Odd = 0.0;
$prev_jQ_Even = 0.0;
$prev_jQ_input_Odd = 0.0;
$prev_jQ_input_Even = 0.0;
}
$period = 0.0;
$outIdx = 0;
$prevI2 = $prevQ2 = 0.0;
$Re = $Im = 0.0;
$I1ForOddPrev3 = $I1ForEvenPrev3 = 0.0;
$I1ForOddPrev2 = $I1ForEvenPrev2 = 0.0;
$smoothPeriod = 0.0;
for ($i = 0; $i < 50; $i++) {
$smoothPrice[$i] = 0.0;
}
while ($today <= $endIdx) {
$adjustedPrevPeriod = 0.075 * $period + 0.54;
$todayValue = $inReal[$today];
{
$periodWMASub += $todayValue;
$periodWMASub -= $trailingWMAValue;
$periodWMASum += $todayValue * 4.0;
$trailingWMAValue = $inReal[$trailingWMAIdx++];
$smoothedValue = $periodWMASum * 0.1;
$periodWMASum -= $periodWMASub;
}
$smoothPrice[$smoothPrice_Idx] = $smoothedValue;
if ($today % 2 === 0) {
{
$hilbertTempReal = $a * $smoothedValue;
$detrender = -$detrender_Even[$hilbertIdx];
$detrender_Even[$hilbertIdx] = $hilbertTempReal;
$detrender += $hilbertTempReal;
$detrender -= $prev_detrender_Even;
$prev_detrender_Even = $b * $prev_detrender_input_Even;
$detrender += $prev_detrender_Even;
$prev_detrender_input_Even = $smoothedValue;
$detrender *= $adjustedPrevPeriod;
}
{
$hilbertTempReal = $a * $detrender;
$Q1 = -$Q1_Even[$hilbertIdx];
$Q1_Even[$hilbertIdx] = $hilbertTempReal;
$Q1 += $hilbertTempReal;
$Q1 -= $prev_Q1_Even;
$prev_Q1_Even = $b * $prev_Q1_input_Even;
$Q1 += $prev_Q1_Even;
$prev_Q1_input_Even = $detrender;
$Q1 *= $adjustedPrevPeriod;
}
{
$hilbertTempReal = $a * $I1ForEvenPrev3;
$jI = -$jI_Even[$hilbertIdx];
$jI_Even[$hilbertIdx] = $hilbertTempReal;
$jI += $hilbertTempReal;
$jI -= $prev_jI_Even;
$prev_jI_Even = $b * $prev_jI_input_Even;
$jI += $prev_jI_Even;
$prev_jI_input_Even = $I1ForEvenPrev3;
$jI *= $adjustedPrevPeriod;
}
{
$hilbertTempReal = $a * $Q1;
$jQ = -$jQ_Even[$hilbertIdx];
$jQ_Even[$hilbertIdx] = $hilbertTempReal;
$jQ += $hilbertTempReal;
$jQ -= $prev_jQ_Even;
$prev_jQ_Even = $b * $prev_jQ_input_Even;
$jQ += $prev_jQ_Even;
$prev_jQ_input_Even = $Q1;
$jQ *= $adjustedPrevPeriod;
}
if (++$hilbertIdx === 3) {
$hilbertIdx = 0;
}
$Q2 = 0.2 * ($Q1 + $jI) + 0.8 * $prevQ2;
$I2 = 0.2 * ($I1ForEvenPrev3 - $jQ) + 0.8 * $prevI2;
$I1ForOddPrev3 = $I1ForOddPrev2;
$I1ForOddPrev2 = $detrender;
} else {
{
$hilbertTempReal = $a * $smoothedValue;
$detrender = -$detrender_Odd[$hilbertIdx];
$detrender_Odd[$hilbertIdx] = $hilbertTempReal;
$detrender += $hilbertTempReal;
$detrender -= $prev_detrender_Odd;
$prev_detrender_Odd = $b * $prev_detrender_input_Odd;
$detrender += $prev_detrender_Odd;
$prev_detrender_input_Odd = $smoothedValue;
$detrender *= $adjustedPrevPeriod;
}
{
$hilbertTempReal = $a * $detrender;
$Q1 = -$Q1_Odd[$hilbertIdx];
$Q1_Odd[$hilbertIdx] = $hilbertTempReal;
$Q1 += $hilbertTempReal;
$Q1 -= $prev_Q1_Odd;
$prev_Q1_Odd = $b * $prev_Q1_input_Odd;
$Q1 += $prev_Q1_Odd;
$prev_Q1_input_Odd = $detrender;
$Q1 *= $adjustedPrevPeriod;
}
{
$hilbertTempReal = $a * $I1ForOddPrev3;
$jI = -$jI_Odd[$hilbertIdx];
$jI_Odd[$hilbertIdx] = $hilbertTempReal;
$jI += $hilbertTempReal;
$jI -= $prev_jI_Odd;
$prev_jI_Odd = $b * $prev_jI_input_Odd;
$jI += $prev_jI_Odd;
$prev_jI_input_Odd = $I1ForOddPrev3;
$jI *= $adjustedPrevPeriod;
}
{
$hilbertTempReal = $a * $Q1;
$jQ = -$jQ_Odd[$hilbertIdx];
$jQ_Odd[$hilbertIdx] = $hilbertTempReal;
$jQ += $hilbertTempReal;
$jQ -= $prev_jQ_Odd;
$prev_jQ_Odd = $b * $prev_jQ_input_Odd;
$jQ += $prev_jQ_Odd;
$prev_jQ_input_Odd = $Q1;
$jQ *= $adjustedPrevPeriod;
}
$Q2 = 0.2 * ($Q1 + $jI) + 0.8 * $prevQ2;
$I2 = 0.2 * ($I1ForOddPrev3 - $jQ) + 0.8 * $prevI2;
$I1ForEvenPrev3 = $I1ForEvenPrev2;
$I1ForEvenPrev2 = $detrender;
}
$Re = 0.2 * ($I2 * $prevI2 + $Q2 * $prevQ2) + 0.8 * $Re;
$Im = 0.2 * ($I2 * $prevQ2 - $Q2 * $prevI2) + 0.8 * $Im;
$prevQ2 = $Q2;
$prevI2 = $I2;
$tempReal = $period;
if ($Im !== 0.0 && $Re !== 0.0) {
$period = 360.0 / (atan($Im / $Re) * $rad2Deg);
}
$tempReal2 = 1.5 * $tempReal;
if ($period > $tempReal2) {
$period = $tempReal2;
}
$tempReal2 = 0.67 * $tempReal;
if ($period < $tempReal2) {
$period = $tempReal2;
}
if ($period < 6) {
$period = 6;
} elseif ($period > 50) {
$period = 50;
}
$period = 0.2 * $period + 0.8 * $tempReal;
$smoothPeriod = 0.33 * $period + 0.67 * $smoothPeriod;
$DCPeriod = $smoothPeriod + 0.5;
$DCPeriodInt = (int)$DCPeriod;
$idxothPricePrice = $today;
$tempReal = 0.0;
for ($i = 0; $i < $DCPeriodInt; $i++) {
$tempReal += $inReal[$idxothPricePrice--];
}
if ($DCPeriodInt > 0) {
$tempReal = $tempReal / (double)$DCPeriodInt;
}
$tempReal2 = (4.0 * $tempReal + 3.0 * $iTrend1 + 2.0 * $iTrend2 + $iTrend3) / 10.0;
$iTrend3 = $iTrend2;
$iTrend2 = $iTrend1;
$iTrend1 = $tempReal;
if ($today >= $startIdx) {
$outReal[$outIdx++] = $tempReal2;
}
{
$smoothPrice_Idx++;
if ($smoothPrice_Idx > $maxIdx_smoothPricePrice) {
$smoothPrice_Idx = 0;
}
}
$today++;
}
$outNBElement = $outIdx;
return ReturnCode::Success;
}
public static function kama(int $startIdx, int $endIdx, array $inReal, int $optInTimePeriod, int &$outBegIdx, int &$outNBElement, array &$outReal): int
{
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
$constMax = 2.0 / (30.0 + 1.0);
$constDiff = 2.0 / (2.0 + 1.0) - $constMax;
if ($optInTimePeriod === PHP_INT_MIN) {
$optInTimePeriod = 30;
} elseif ($optInTimePeriod < 2 || $optInTimePeriod > 100000) {
return ReturnCode::BadParam;
}
$outBegIdx = 0;
$outNBElement = 0;
$lookbackTotal = $optInTimePeriod + static::$unstablePeriod[UnstablePeriodFunctionID::KAMA];
if ($startIdx < $lookbackTotal) {
$startIdx = $lookbackTotal;
}
if ($startIdx > $endIdx) {
$outBegIdx = 0;
$outNBElement = 0;
return ReturnCode::Success;
}
$sumROC1 = 0.0;
$today = $startIdx - $lookbackTotal;
$trailingIdx = $today;
$i = $optInTimePeriod;
while ($i-- > 0) {
$tempReal = $inReal[$today++];
$tempReal -= $inReal[$today];
$sumROC1 += abs($tempReal);
}
$prevKAMA = $inReal[$today - 1];
$tempReal = $inReal[$today];
$tempReal2 = $inReal[$trailingIdx++];
$periodROC = $tempReal - $tempReal2;
$trailingValue = $tempReal2;
if ($sumROC1 <= $periodROC || (-0.00000001 < $sumROC1 && $sumROC1 < 0.00000001)) {
$tempReal = 1.0;
} else {
$tempReal = abs($periodROC / $sumROC1);
}
$tempReal = $tempReal * $constDiff + $constMax;
$tempReal *= $tempReal;
$prevKAMA = ($inReal[$today++] - $prevKAMA) * $tempReal + $prevKAMA;
while ($today <= $startIdx) {
$tempReal = $inReal[$today];
$tempReal2 = $inReal[$trailingIdx++];
$periodROC = $tempReal - $tempReal2;
$sumROC1 -= abs($trailingValue - $tempReal2);
$sumROC1 += abs($tempReal - $inReal[$today - 1]);
$trailingValue = $tempReal2;
if ($sumROC1 <= $periodROC || (-0.00000001 < $sumROC1 && $sumROC1 < 0.00000001)) {
$tempReal = 1.0;
} else {
$tempReal = abs($periodROC / $sumROC1);
}
$tempReal = $tempReal * $constDiff + $constMax;
$tempReal *= $tempReal;
$prevKAMA = ($inReal[$today++] - $prevKAMA) * $tempReal + $prevKAMA;
}
$outReal[0] = $prevKAMA;
$outIdx = 1;
$outBegIdx = $today - 1;
while ($today <= $endIdx) {
$tempReal = $inReal[$today];
$tempReal2 = $inReal[$trailingIdx++];
$periodROC = $tempReal - $tempReal2;
$sumROC1 -= abs($trailingValue - $tempReal2);
$sumROC1 += abs($tempReal - $inReal[$today - 1]);
$trailingValue = $tempReal2;
if ($sumROC1 <= $periodROC || (-0.00000001 < $sumROC1 && $sumROC1 < 0.00000001)) {
$tempReal = 1.0;
} else {
$tempReal = abs($periodROC / $sumROC1);
}
$tempReal = $tempReal * $constDiff + $constMax;
$tempReal *= $tempReal;
$prevKAMA = ($inReal[$today++] - $prevKAMA) * $tempReal + $prevKAMA;
$outReal[$outIdx++] = $prevKAMA;
}
$outNBElement = $outIdx;
return ReturnCode::Success;
}
public static function movingAverage(int $startIdx, int $endIdx, array $inReal, int $optInTimePeriod, int $optInMAType, int &$outBegIdx, int &$outNBElement, array &$outReal): int
{
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
if ($optInTimePeriod === PHP_INT_MIN) {
$optInTimePeriod = 30;
} elseif ($optInTimePeriod < 1 || $optInTimePeriod > 100000) {
return ReturnCode::BadParam;
}
if ($optInTimePeriod === 1) {
$nbElement = $endIdx - $startIdx + 1;
$outNBElement = $nbElement;
for ($todayIdx = $startIdx, $outIdx = 0; $outIdx < $nbElement; $outIdx++, $todayIdx++) {
$outReal[$outIdx] = $inReal[$todayIdx];
}
$outBegIdx = $startIdx;
return ReturnCode::Success;
}
switch ($optInMAType) {
case MovingAverageType::SMA:
$ReturnCode = self::sma(
$startIdx,
$endIdx,
$inReal,
$optInTimePeriod,
$outBegIdx,
$outNBElement,
$outReal
);
break;
case MovingAverageType::EMA:
$ReturnCode = self::ema(
$startIdx,
$endIdx,
$inReal,
$optInTimePeriod,
$outBegIdx,
$outNBElement,
$outReal
);
break;
case MovingAverageType::WMA:
$ReturnCode = self::wma(
$startIdx,
$endIdx,
$inReal,
$optInTimePeriod,
$outBegIdx,
$outNBElement,
$outReal
);
break;
case MovingAverageType::DEMA:
$ReturnCode = self::dema(
$startIdx,
$endIdx,
$inReal,
$optInTimePeriod,
$outBegIdx,
$outNBElement,
$outReal
);
break;
case MovingAverageType::TEMA:
$ReturnCode = self::tema(
$startIdx,
$endIdx,
$inReal,
$optInTimePeriod,
$outBegIdx,
$outNBElement,
$outReal
);
break;
case MovingAverageType::TRIMA:
$ReturnCode = self::trima(
$startIdx,
$endIdx,
$inReal,
$optInTimePeriod,
$outBegIdx,
$outNBElement,
$outReal
);
break;
case MovingAverageType::KAMA:
$ReturnCode = self::kama(
$startIdx,
$endIdx,
$inReal,
$optInTimePeriod,
$outBegIdx,
$outNBElement,
$outReal
);
break;
case MovingAverageType::MAMA:
$dummyBuffer = static::double($endIdx - $startIdx + 1);
$ReturnCode = self::mama(
$startIdx,
$endIdx,
$inReal,
0.5,
0.05,
$outBegIdx,
$outNBElement,
$outReal,
$dummyBuffer
);
break;
case MovingAverageType::T3:
$ReturnCode = self::t3(
$startIdx,
$endIdx,
$inReal,
$optInTimePeriod,
0.7,
$outBegIdx,
$outNBElement,
$outReal
);
break;
default:
$ReturnCode = ReturnCode::BadParam;
break;
}
return $ReturnCode;
}
public static function mama(int $startIdx, int $endIdx, array $inReal, float $optInFastLimit, float $optInSlowLimit, int &$outBegIdx, int &$outNBElement, array &$outMAMA, array &$outFAMA): int
{
$a = 0.0962;
$b = 0.5769;
$detrender_Odd = static::double(3);
$detrender_Even = static::double(3);
$Q1_Odd = static::double(3);
$Q1_Even = static::double(3);
$jI_Odd = static::double(3);
$jI_Even = static::double(3);
$jQ_Odd = static::double(3);
$jQ_Even = static::double(3);
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
if ($optInFastLimit === -4e+37) {
$optInFastLimit = 5.000000e-1;
} elseif ($optInFastLimit < 1.000000e-2 || $optInFastLimit > 9.900000e-1) {
return ReturnCode::BadParam;
}
if ($optInSlowLimit === -4e+37) {
$optInSlowLimit = 5.000000e-2;
} elseif ($optInSlowLimit < 1.000000e-2 || $optInSlowLimit > 9.900000e-1) {
return ReturnCode::BadParam;
}
$rad2Deg = 180.0 / (4.0 * atan(1));
$lookbackTotal = 32 + static::$unstablePeriod[UnstablePeriodFunctionID::MAMA];
if ($startIdx < $lookbackTotal) {
$startIdx = $lookbackTotal;
}
if ($startIdx > $endIdx) {
$outBegIdx = 0;
$outNBElement = 0;
return ReturnCode::Success;
}
$outBegIdx = $startIdx;
$trailingWMAIdx = $startIdx - $lookbackTotal;
$today = $trailingWMAIdx;
$tempReal = $inReal[$today++];
$periodWMASub = $tempReal;
$periodWMASum = $tempReal;
$tempReal = $inReal[$today++];
$periodWMASub += $tempReal;
$periodWMASum += $tempReal * 2.0;
$tempReal = $inReal[$today++];
$periodWMASub += $tempReal;
$periodWMASum += $tempReal * 3.0;
$trailingWMAValue = 0.0;
$i = 9;
do {
$tempReal = $inReal[$today++];
{
$periodWMASub += $tempReal;
$periodWMASub -= $trailingWMAValue;
$periodWMASum += $tempReal * 4.0;
$trailingWMAValue = $inReal[$trailingWMAIdx++];
$smoothedValue = $periodWMASum * 0.1;
$periodWMASum -= $periodWMASub;
}
} while (--$i !== 0);
$hilbertIdx = 0;
{
$detrender_Odd[0] = 0.0;
$detrender_Odd[1] = 0.0;
$detrender_Odd[2] = 0.0;
$detrender_Even[0] = 0.0;
$detrender_Even[1] = 0.0;
$detrender_Even[2] = 0.0;
$detrender = 0.0;
$prev_detrender_Odd = 0.0;
$prev_detrender_Even = 0.0;
$prev_detrender_input_Odd = 0.0;
$prev_detrender_input_Even = 0.0;
}
{
$Q1_Odd[0] = 0.0;
$Q1_Odd[1] = 0.0;
$Q1_Odd[2] = 0.0;
$Q1_Even[0] = 0.0;
$Q1_Even[1] = 0.0;
$Q1_Even[2] = 0.0;
$Q1 = 0.0;
$prev_Q1_Odd = 0.0;
$prev_Q1_Even = 0.0;
$prev_Q1_input_Odd = 0.0;
$prev_Q1_input_Even = 0.0;
}
{
$jI_Odd[0] = 0.0;
$jI_Odd[1] = 0.0;
$jI_Odd[2] = 0.0;
$jI_Even[0] = 0.0;
$jI_Even[1] = 0.0;
$jI_Even[2] = 0.0;
$jI = 0.0;
$prev_jI_Odd = 0.0;
$prev_jI_Even = 0.0;
$prev_jI_input_Odd = 0.0;
$prev_jI_input_Even = 0.0;
}
{
$jQ_Odd[0] = 0.0;
$jQ_Odd[1] = 0.0;
$jQ_Odd[2] = 0.0;
$jQ_Even[0] = 0.0;
$jQ_Even[1] = 0.0;
$jQ_Even[2] = 0.0;
$jQ = 0.0;
$prev_jQ_Odd = 0.0;
$prev_jQ_Even = 0.0;
$prev_jQ_input_Odd = 0.0;
$prev_jQ_input_Even = 0.0;
}
$period = 0.0;
$outIdx = 0;
$prevI2 = $prevQ2 = 0.0;
$Re = $Im = 0.0;
$mama = $fama = 0.0;
$I1ForOddPrev3 = $I1ForEvenPrev3 = 0.0;
$I1ForOddPrev2 = $I1ForEvenPrev2 = 0.0;
$prevPhase = 0.0;
while ($today <= $endIdx) {
$adjustedPrevPeriod = 0.075 * $period + 0.54;
$todayValue = $inReal[$today];
{
$periodWMASub += $todayValue;
$periodWMASub -= $trailingWMAValue;
$periodWMASum += $todayValue * 4.0;
$trailingWMAValue = $inReal[$trailingWMAIdx++];
$smoothedValue = $periodWMASum * 0.1;
$periodWMASum -= $periodWMASub;
}
if ($today % 2 === 0) {
{
$hilbertTempReal = $a * $smoothedValue;
$detrender = -$detrender_Even[$hilbertIdx];
$detrender_Even[$hilbertIdx] = $hilbertTempReal;
$detrender += $hilbertTempReal;
$detrender -= $prev_detrender_Even;
$prev_detrender_Even = $b * $prev_detrender_input_Even;
$detrender += $prev_detrender_Even;
$prev_detrender_input_Even = $smoothedValue;
$detrender *= $adjustedPrevPeriod;
}
{
$hilbertTempReal = $a * $detrender;
$Q1 = -$Q1_Even[$hilbertIdx];
$Q1_Even[$hilbertIdx] = $hilbertTempReal;
$Q1 += $hilbertTempReal;
$Q1 -= $prev_Q1_Even;
$prev_Q1_Even = $b * $prev_Q1_input_Even;
$Q1 += $prev_Q1_Even;
$prev_Q1_input_Even = $detrender;
$Q1 *= $adjustedPrevPeriod;
}
{
$hilbertTempReal = $a * $I1ForEvenPrev3;
$jI = -$jI_Even[$hilbertIdx];
$jI_Even[$hilbertIdx] = $hilbertTempReal;
$jI += $hilbertTempReal;
$jI -= $prev_jI_Even;
$prev_jI_Even = $b * $prev_jI_input_Even;
$jI += $prev_jI_Even;
$prev_jI_input_Even = $I1ForEvenPrev3;
$jI *= $adjustedPrevPeriod;
}
{
$hilbertTempReal = $a * $Q1;
$jQ = -$jQ_Even[$hilbertIdx];
$jQ_Even[$hilbertIdx] = $hilbertTempReal;
$jQ += $hilbertTempReal;
$jQ -= $prev_jQ_Even;
$prev_jQ_Even = $b * $prev_jQ_input_Even;
$jQ += $prev_jQ_Even;
$prev_jQ_input_Even = $Q1;
$jQ *= $adjustedPrevPeriod;
}
if (++$hilbertIdx === 3) {
$hilbertIdx = 0;
}
$Q2 = 0.2 * ($Q1 + $jI) + 0.8 * $prevQ2;
$I2 = 0.2 * ($I1ForEvenPrev3 - $jQ) + 0.8 * $prevI2;
$I1ForOddPrev3 = $I1ForOddPrev2;
$I1ForOddPrev2 = $detrender;
if ($I1ForEvenPrev3 !== 0.0) {
$tempReal2 = atan($Q1 / $I1ForEvenPrev3) * $rad2Deg;
} else {
$tempReal2 = 0.0;
}
} else {
{
$hilbertTempReal = $a * $smoothedValue;
$detrender = -$detrender_Odd[$hilbertIdx];
$detrender_Odd[$hilbertIdx] = $hilbertTempReal;
$detrender += $hilbertTempReal;
$detrender -= $prev_detrender_Odd;
$prev_detrender_Odd = $b * $prev_detrender_input_Odd;
$detrender += $prev_detrender_Odd;
$prev_detrender_input_Odd = $smoothedValue;
$detrender *= $adjustedPrevPeriod;
}
{
$hilbertTempReal = $a * $detrender;
$Q1 = -$Q1_Odd[$hilbertIdx];
$Q1_Odd[$hilbertIdx] = $hilbertTempReal;
$Q1 += $hilbertTempReal;
$Q1 -= $prev_Q1_Odd;
$prev_Q1_Odd = $b * $prev_Q1_input_Odd;
$Q1 += $prev_Q1_Odd;
$prev_Q1_input_Odd = $detrender;
$Q1 *= $adjustedPrevPeriod;
}
{
$hilbertTempReal = $a * $I1ForOddPrev3;
$jI = -$jI_Odd[$hilbertIdx];
$jI_Odd[$hilbertIdx] = $hilbertTempReal;
$jI += $hilbertTempReal;
$jI -= $prev_jI_Odd;
$prev_jI_Odd = $b * $prev_jI_input_Odd;
$jI += $prev_jI_Odd;
$prev_jI_input_Odd = $I1ForOddPrev3;
$jI *= $adjustedPrevPeriod;
}
{
$hilbertTempReal = $a * $Q1;
$jQ = -$jQ_Odd[$hilbertIdx];
$jQ_Odd[$hilbertIdx] = $hilbertTempReal;
$jQ += $hilbertTempReal;
$jQ -= $prev_jQ_Odd;
$prev_jQ_Odd = $b * $prev_jQ_input_Odd;
$jQ += $prev_jQ_Odd;
$prev_jQ_input_Odd = $Q1;
$jQ *= $adjustedPrevPeriod;
}
$Q2 = 0.2 * ($Q1 + $jI) + 0.8 * $prevQ2;
$I2 = 0.2 * ($I1ForOddPrev3 - $jQ) + 0.8 * $prevI2;
$I1ForEvenPrev3 = $I1ForEvenPrev2;
$I1ForEvenPrev2 = $detrender;
if ($I1ForOddPrev3 !== 0.0) {
$tempReal2 = atan($Q1 / $I1ForOddPrev3) * $rad2Deg;
} else {
$tempReal2 = 0.0;
}
}
$tempReal = $prevPhase - $tempReal2;
$prevPhase = $tempReal2;
if ($tempReal < 1.0) {
$tempReal = 1.0;
}
if ($tempReal > 1.0) {
$tempReal = $optInFastLimit / $tempReal;
if ($tempReal < $optInSlowLimit) {
$tempReal = $optInSlowLimit;
}
} else {
$tempReal = $optInFastLimit;
}
$mama = $tempReal * $todayValue + (1 - $tempReal) * $mama;
$tempReal *= 0.5;
$fama = $tempReal * $mama + (1 - $tempReal) * $fama;
if ($today >= $startIdx) {
$outMAMA[$outIdx] = $mama;
$outFAMA[$outIdx++] = $fama;
}
$Re = 0.2 * ($I2 * $prevI2 + $Q2 * $prevQ2) + 0.8 * $Re;
$Im = 0.2 * ($I2 * $prevQ2 - $Q2 * $prevI2) + 0.8 * $Im;
$prevQ2 = $Q2;
$prevI2 = $I2;
$tempReal = $period;
if ($Im !== 0.0 && $Re !== 0.0) {
$period = 360.0 / (atan($Im / $Re) * $rad2Deg);
}
$tempReal2 = 1.5 * $tempReal;
if ($period > $tempReal2) {
$period = $tempReal2;
}
$tempReal2 = 0.67 * $tempReal;
if ($period < $tempReal2) {
$period = $tempReal2;
}
if ($period < 6) {
$period = 6;
} elseif ($period > 50) {
$period = 50;
}
$period = 0.2 * $period + 0.8 * $tempReal;
$today++;
}
$outNBElement = $outIdx;
return ReturnCode::Success;
}
public static function movingAverageVariablePeriod(
int $startIdx,
int $endIdx,
array $inReal,
array &$inPeriods,
int $optInMinPeriod,
int $optInMaxPeriod,
int $optInMAType,
int &$outBegIdx,
int &$outNBElement,
array &$outReal
): int {
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
$localBegIdx = 0;
$localNbElement = 0;
if ($optInMinPeriod === PHP_INT_MIN) {
$optInMinPeriod = 2;
} elseif ($optInMinPeriod < 2 || $optInMinPeriod > 100000) {
return ReturnCode::BadParam;
}
if ($optInMaxPeriod === PHP_INT_MIN) {
$optInMaxPeriod = 30;
} elseif ($optInMaxPeriod < 2 || $optInMaxPeriod > 100000) {
return ReturnCode::BadParam;
}
$lookbackTotal = Lookback::movingAverageLookback($optInMaxPeriod, $optInMAType);
if ($startIdx < $lookbackTotal) {
$startIdx = $lookbackTotal;
}
if ($startIdx > $endIdx) {
$outBegIdx = 0;
$outNBElement = 0;
return ReturnCode::Success;
}
if ($lookbackTotal > $startIdx) {
$tempInt = $lookbackTotal;
} else {
$tempInt = $startIdx;
}
if ($tempInt > $endIdx) {
$outBegIdx = 0;
$outNBElement = 0;
return ReturnCode::Success;
}
$outputSize = $endIdx - $tempInt + 1;
$localOutputArray = \array_pad([], $outputSize, 0.);
$localPeriodArray = \array_pad([], $outputSize, 0);
for ($i = 0; $i < $outputSize; $i++) {
$tempInt = (int)$inPeriods[$startIdx + $i];
if ($tempInt < $optInMinPeriod) {
$tempInt = $optInMinPeriod;
} elseif ($tempInt > $optInMaxPeriod) {
$tempInt = $optInMaxPeriod;
}
$localPeriodArray[$i] = $tempInt;
}
for ($i = 0; $i < $outputSize; $i++) {
$curPeriod = $localPeriodArray[$i];
if ($curPeriod !== 0) {
$ReturnCode = self::movingAverage(
$startIdx,
$endIdx,
$inReal,
$curPeriod,
$optInMAType,
$localBegIdx,
$localNbElement,
$localOutputArray
);
if ($ReturnCode !== ReturnCode::Success) {
$outBegIdx = 0;
$outNBElement = 0;
return $ReturnCode;
}
$outReal[$i] = $localOutputArray[$i];
for ($j = $i + 1; $j < $outputSize; $j++) {
if ($localPeriodArray[$j] === $curPeriod) {
$localPeriodArray[$j] = 0;
$outReal[$j] = $localOutputArray[$j];
}
}
}
}
$outBegIdx = $startIdx;
$outNBElement = $outputSize;
return ReturnCode::Success;
}
public static function midPoint(int $startIdx, int $endIdx, array $inReal, int $optInTimePeriod, int &$outBegIdx, int &$outNBElement, array &$outReal): int
{
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
if ($optInTimePeriod === PHP_INT_MIN) {
$optInTimePeriod = 14;
} elseif ($optInTimePeriod < 2 || $optInTimePeriod > 100000) {
return ReturnCode::BadParam;
}
$nbInitialElementNeeded = $optInTimePeriod - 1;
if ($startIdx < $nbInitialElementNeeded) {
$startIdx = $nbInitialElementNeeded;
}
if ($startIdx > $endIdx) {
$outBegIdx = 0;
$outNBElement = 0;
return ReturnCode::Success;
}
$outIdx = 0;
$today = $startIdx;
$trailingIdx = $startIdx - $nbInitialElementNeeded;
while ($today <= $endIdx) {
$lowest = $inReal[$trailingIdx++];
$highest = $lowest;
for ($i = $trailingIdx; $i <= $today; $i++) {
$tmp = $inReal[$i];
if ($tmp < $lowest) {
$lowest = $tmp;
} elseif ($tmp > $highest) {
$highest = $tmp;
}
}
$outReal[$outIdx++] = ($highest + $lowest) / 2.0;
$today++;
}
$outBegIdx = $startIdx;
$outNBElement = $outIdx;
return ReturnCode::Success;
}
public static function midPrice(int $startIdx, int $endIdx, array $inHigh, array $inLow, int $optInTimePeriod, int &$outBegIdx, int &$outNBElement, array &$outReal): int
{
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
if ($optInTimePeriod === PHP_INT_MIN) {
$optInTimePeriod = 14;
} elseif ($optInTimePeriod < 2 || $optInTimePeriod > 100000) {
return ReturnCode::BadParam;
}
$nbInitialElementNeeded = $optInTimePeriod - 1;
if ($startIdx < $nbInitialElementNeeded) {
$startIdx = $nbInitialElementNeeded;
}
if ($startIdx > $endIdx) {
$outBegIdx = 0;
$outNBElement = 0;
return ReturnCode::Success;
}
$outIdx = 0;
$today = $startIdx;
$trailingIdx = $startIdx - $nbInitialElementNeeded;
while ($today <= $endIdx) {
$lowest = $inLow[$trailingIdx];
$highest = $inHigh[$trailingIdx];
$trailingIdx++;
for ($i = $trailingIdx; $i <= $today; $i++) {
$tmp = $inLow[$i];
if ($tmp < $lowest) {
$lowest = $tmp;
}
$tmp = $inHigh[$i];
if ($tmp > $highest) {
$highest = $tmp;
}
}
$outReal[$outIdx++] = ($highest + $lowest) / 2.0;
$today++;
}
$outBegIdx = $startIdx;
$outNBElement = $outIdx;
return ReturnCode::Success;
}
public static function sar(int $startIdx, int $endIdx, array $inHigh, array $inLow, float $optInAcceleration, float $optInMaximum, int &$outBegIdx, int &$outNBElement, array &$outReal): int
{
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
$tempInt = 0;
$ep_temp = static::double(1);
if ($optInAcceleration === -4e+37) {
$optInAcceleration = 2.000000e-2;
} elseif ($optInAcceleration < 0.000000e+0 || $optInAcceleration > 3.000000e+37) {
return ReturnCode::BadParam;
}
if ($optInMaximum === -4e+37) {
$optInMaximum = 2.000000e-1;
} elseif ($optInMaximum < 0.000000e+0 || $optInMaximum > 3.000000e+37) {
return ReturnCode::BadParam;
}
if ($startIdx < 1) {
$startIdx = 1;
}
if ($startIdx > $endIdx) {
$outBegIdx = 0;
$outNBElement = 0;
return ReturnCode::Success;
}
$af = $optInAcceleration;
if ($af > $optInMaximum) {
$af = $optInAcceleration = $optInMaximum;
}
$ReturnCode = MomentumIndicators::minusDM(
$startIdx,
$startIdx,
$inHigh,
$inLow,
1,
$tempInt,
$tempInt,
$ep_temp
);
if ($ep_temp[0] > 0) {
$isLong = 0;
} else {
$isLong = 1;
}
if ($ReturnCode !== ReturnCode::Success) {
$outBegIdx = 0;
$outNBElement = 0;
return $ReturnCode;
}
$outBegIdx = $startIdx;
$outIdx = 0;
$todayIdx = $startIdx;
$newHigh = $inHigh[$todayIdx - 1];
$newLow = $inLow[$todayIdx - 1];
if ($isLong === 1) {
$ep = $inHigh[$todayIdx];
$sar = $newLow;
} else {
$ep = $inLow[$todayIdx];
$sar = $newHigh;
}
$newLow = $inLow[$todayIdx];
$newHigh = $inHigh[$todayIdx];
while ($todayIdx <= $endIdx) {
$prevLow = $newLow;
$prevHigh = $newHigh;
$newLow = $inLow[$todayIdx];
$newHigh = $inHigh[$todayIdx];
$todayIdx++;
if ($isLong === 1) {
if ($newLow <= $sar) {
$isLong = 0;
$sar = $ep;
if ($sar < $prevHigh) {
$sar = $prevHigh;
}
if ($sar < $newHigh) {
$sar = $newHigh;
}
$outReal[$outIdx++] = $sar;
$af = $optInAcceleration;
$ep = $newLow;
$sar = $sar + $af * ($ep - $sar);
if ($sar < $prevHigh) {
$sar = $prevHigh;
}
if ($sar < $newHigh) {
$sar = $newHigh;
}
} else {
$outReal[$outIdx++] = $sar;
if ($newHigh > $ep) {
$ep = $newHigh;
$af += $optInAcceleration;
if ($af > $optInMaximum) {
$af = $optInMaximum;
}
}
$sar = $sar + $af * ($ep - $sar);
if ($sar > $prevLow) {
$sar = $prevLow;
}
if ($sar > $newLow) {
$sar = $newLow;
}
}
} else {
if ($newHigh >= $sar) {
$isLong = 1;
$sar = $ep;
if ($sar > $prevLow) {
$sar = $prevLow;
}
if ($sar > $newLow) {
$sar = $newLow;
}
$outReal[$outIdx++] = $sar;
$af = $optInAcceleration;
$ep = $newHigh;
$sar = $sar + $af * ($ep - $sar);
if ($sar > $prevLow) {
$sar = $prevLow;
}
if ($sar > $newLow) {
$sar = $newLow;
}
} else {
$outReal[$outIdx++] = $sar;
if ($newLow < $ep) {
$ep = $newLow;
$af += $optInAcceleration;
if ($af > $optInMaximum) {
$af = $optInMaximum;
}
}
$sar = $sar + $af * ($ep - $sar);
if ($sar < $prevHigh) {
$sar = $prevHigh;
}
if ($sar < $newHigh) {
$sar = $newHigh;
}
}
}
}
$outNBElement = $outIdx;
return ReturnCode::Success;
}
public static function sarExt(
int $startIdx,
int $endIdx,
array $inHigh,
array $inLow,
float $optInStartValue,
float $optInOffsetOnReverse,
float $optInAccelerationInitLong,
float $optInAccelerationLong,
float $optInAccelerationMaxLong,
float $optInAccelerationInitShort,
float $optInAccelerationShort,
float $optInAccelerationMaxShort,
int &$outBegIdx,
int &$outNBElement,
array &$outReal
): int {
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
$tempInt = 0;
$ep_temp = static::double(1);
if ($optInStartValue < -4e+37) {
$optInStartValue = 0.000000e+0;
} elseif ($optInStartValue < -3.000000e+37 || $optInStartValue > 3.000000e+37) {
return ReturnCode::BadParam;
}
if ($optInOffsetOnReverse < -4e+37) {
$optInOffsetOnReverse = 0.000000e+0;
} elseif ($optInOffsetOnReverse < 0.000000e+0 || $optInOffsetOnReverse > 3.000000e+37) {
return ReturnCode::BadParam;
}
if ($optInAccelerationInitLong < -4e+37) {
$optInAccelerationInitLong = 2.000000e-2;
} elseif ($optInAccelerationInitLong < 0.000000e+0 || $optInAccelerationInitLong > 3.000000e+37) {
return ReturnCode::BadParam;
}
if ($optInAccelerationLong < -4e+37) {
$optInAccelerationLong = 2.000000e-2;
} elseif ($optInAccelerationLong < 0.000000e+0 || $optInAccelerationLong > 3.000000e+37) {
return ReturnCode::BadParam;
}
if ($optInAccelerationMaxLong < -4e+37) {
$optInAccelerationMaxLong = 2.000000e-1;
} elseif ($optInAccelerationMaxLong < 0.000000e+0 || $optInAccelerationMaxLong > 3.000000e+37) {
return ReturnCode::BadParam;
}
if ($optInAccelerationInitShort < -4e+37) {
$optInAccelerationInitShort = 2.000000e-2;
} elseif ($optInAccelerationInitShort < 0.000000e+0 || $optInAccelerationInitShort > 3.000000e+37) {
return ReturnCode::BadParam;
}
if ($optInAccelerationShort < -4e+37) {
$optInAccelerationShort = 2.000000e-2;
} elseif ($optInAccelerationShort < 0.000000e+0 || $optInAccelerationShort > 3.000000e+37) {
return ReturnCode::BadParam;
}
if ($optInAccelerationMaxShort < -4e+37) {
$optInAccelerationMaxShort = 2.000000e-1;
} elseif ($optInAccelerationMaxShort < 0.000000e+0 || $optInAccelerationMaxShort > 3.000000e+37) {
return ReturnCode::BadParam;
}
if ($startIdx < 1) {
$startIdx = 1;
}
if ($startIdx > $endIdx) {
$outBegIdx = 0;
$outNBElement = 0;
return ReturnCode::Success;
}
$afLong = $optInAccelerationInitLong;
$afShort = $optInAccelerationInitShort;
if ($afLong > $optInAccelerationMaxLong) {
$afLong = $optInAccelerationInitLong = $optInAccelerationMaxLong;
}
if ($optInAccelerationLong > $optInAccelerationMaxLong) {
$optInAccelerationLong = $optInAccelerationMaxLong;
}
if ($afShort > $optInAccelerationMaxShort) {
$afShort = $optInAccelerationInitShort = $optInAccelerationMaxShort;
}
if ($optInAccelerationShort > $optInAccelerationMaxShort) {
$optInAccelerationShort = $optInAccelerationMaxShort;
}
if ($optInStartValue === 0.0) {
$ReturnCode = MomentumIndicators::minusDM(
$startIdx,
$startIdx,
$inHigh,
$inLow,
1,
$tempInt,
$tempInt,
$ep_temp
);
if ($ep_temp[0] > 0) {
$isLong = 0;
} else {
$isLong = 1;
}
if ($ReturnCode !== ReturnCode::Success) {
$outBegIdx = 0;
$outNBElement = 0;
return $ReturnCode;
}
} elseif ($optInStartValue > 0) {
$isLong = 1;
} else {
$isLong = 0;
}
$outBegIdx = $startIdx;
$outIdx = 0;
$todayIdx = $startIdx;
$newHigh = $inHigh[$todayIdx - 1];
$newLow = $inLow[$todayIdx - 1];
if ($optInStartValue === 0.0) {
if ($isLong === 1) {
$ep = $inHigh[$todayIdx];
$sar = $newLow;
} else {
$ep = $inLow[$todayIdx];
$sar = $newHigh;
}
} elseif ($optInStartValue > 0) {
$ep = $inHigh[$todayIdx];
$sar = $optInStartValue;
} else {
$ep = $inLow[$todayIdx];
$sar = abs($optInStartValue);
}
$newLow = $inLow[$todayIdx];
$newHigh = $inHigh[$todayIdx];
while ($todayIdx <= $endIdx) {
$prevLow = $newLow;
$prevHigh = $newHigh;
$newLow = $inLow[$todayIdx];
$newHigh = $inHigh[$todayIdx];
$todayIdx++;
if ($isLong === 1) {
if ($newLow <= $sar) {
$isLong = 0;
$sar = $ep;
if ($sar < $prevHigh) {
$sar = $prevHigh;
}
if ($sar < $newHigh) {
$sar = $newHigh;
}
if ($optInOffsetOnReverse !== 0.0) {
$sar += $sar * $optInOffsetOnReverse;
}
$outReal[$outIdx++] = -$sar;
$afShort = $optInAccelerationInitShort;
$ep = $newLow;
$sar = $sar + $afShort * ($ep - $sar);
if ($sar < $prevHigh) {
$sar = $prevHigh;
}
if ($sar < $newHigh) {
$sar = $newHigh;
}
} else {
$outReal[$outIdx++] = $sar;
if ($newHigh > $ep) {
$ep = $newHigh;
$afLong += $optInAccelerationLong;
if ($afLong > $optInAccelerationMaxLong) {
$afLong = $optInAccelerationMaxLong;
}
}
$sar = $sar + $afLong * ($ep - $sar);
if ($sar > $prevLow) {
$sar = $prevLow;
}
if ($sar > $newLow) {
$sar = $newLow;
}
}
} elseif ($newHigh >= $sar) {
$isLong = 1;
$sar = $ep;
if ($sar > $prevLow) {
$sar = $prevLow;
}
if ($sar > $newLow) {
$sar = $newLow;
}
if ($optInOffsetOnReverse !== 0.0) {
$sar -= $sar * $optInOffsetOnReverse;
}
$outReal[$outIdx++] = $sar;
$afLong = $optInAccelerationInitLong;
$ep = $newHigh;
$sar = $sar + $afLong * ($ep - $sar);
if ($sar > $prevLow) {
$sar = $prevLow;
}
if ($sar > $newLow) {
$sar = $newLow;
}
} else {
$outReal[$outIdx++] = -$sar;
if ($newLow < $ep) {
$ep = $newLow;
$afShort += $optInAccelerationShort;
if ($afShort > $optInAccelerationMaxShort) {
$afShort = $optInAccelerationMaxShort;
}
}
$sar = $sar + $afShort * ($ep - $sar);
if ($sar < $prevHigh) {
$sar = $prevHigh;
}
if ($sar < $newHigh) {
$sar = $newHigh;
}
}
}
$outNBElement = $outIdx;
return ReturnCode::Success;
}
public static function sma(int $startIdx, int $endIdx, array $inReal, int $optInTimePeriod, int &$outBegIdx, int &$outNBElement, array &$outReal): int
{
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
if ($optInTimePeriod === PHP_INT_MIN) {
$optInTimePeriod = 30;
} elseif ($optInTimePeriod < 2 || $optInTimePeriod > 100000) {
return ReturnCode::BadParam;
}
return static::TA_INT_SMA(
$startIdx,
$endIdx,
$inReal,
$optInTimePeriod,
$outBegIdx,
$outNBElement,
$outReal
);
}
public static function t3(int $startIdx, int $endIdx, array $inReal, int $optInTimePeriod, float $optInVFactor, int &$outBegIdx, int &$outNBElement, array &$outReal): int
{
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
if ($optInTimePeriod === PHP_INT_MIN) {
$optInTimePeriod = 5;
} elseif ($optInTimePeriod < 2 || $optInTimePeriod > 100000) {
return ReturnCode::BadParam;
}
if ($optInVFactor === -4e+37) {
$optInVFactor = 7.000000e-1;
} elseif ($optInVFactor < 0.000000e+0 || $optInVFactor > 1.000000e+0) {
return ReturnCode::BadParam;
}
$lookbackTotal = 6 * ($optInTimePeriod - 1) + static::$unstablePeriod[UnstablePeriodFunctionID::T3];
if ($startIdx <= $lookbackTotal) {
$startIdx = (int)$lookbackTotal;
}
if ($startIdx > $endIdx) {
$outNBElement = 0;
$outBegIdx = 0;
return ReturnCode::Success;
}
$outBegIdx = $startIdx;
$today = $startIdx - $lookbackTotal;
$k = 2.0 / ($optInTimePeriod + 1.0);
$one_minus_k = 1.0 - $k;
$tempReal = $inReal[$today++];
for ($i = $optInTimePeriod - 1; $i > 0; $i--) {
$tempReal += $inReal[$today++];
}
$e1 = $tempReal / $optInTimePeriod;
$tempReal = $e1;
for ($i = $optInTimePeriod - 1; $i > 0; $i--) {
$e1 = $k * $inReal[$today++] + $one_minus_k * $e1;
$tempReal += $e1;
}
$e2 = $tempReal / $optInTimePeriod;
$tempReal = $e2;
for ($i = $optInTimePeriod - 1; $i > 0; $i--) {
$e1 = $k * $inReal[$today++] + $one_minus_k * $e1;
$e2 = $k * $e1 + $one_minus_k * $e2;
$tempReal += $e2;
}
$e3 = $tempReal / $optInTimePeriod;
$tempReal = $e3;
for ($i = $optInTimePeriod - 1; $i > 0; $i--) {
$e1 = $k * $inReal[$today++] + $one_minus_k * $e1;
$e2 = $k * $e1 + $one_minus_k * $e2;
$e3 = $k * $e2 + $one_minus_k * $e3;
$tempReal += $e3;
}
$e4 = $tempReal / $optInTimePeriod;
$tempReal = $e4;
for ($i = $optInTimePeriod - 1; $i > 0; $i--) {
$e1 = $k * $inReal[$today++] + $one_minus_k * $e1;
$e2 = $k * $e1 + $one_minus_k * $e2;
$e3 = $k * $e2 + $one_minus_k * $e3;
$e4 = $k * $e3 + $one_minus_k * $e4;
$tempReal += $e4;
}
$e5 = $tempReal / $optInTimePeriod;
$tempReal = $e5;
for ($i = $optInTimePeriod - 1; $i > 0; $i--) {
$e1 = $k * $inReal[$today++] + $one_minus_k * $e1;
$e2 = $k * $e1 + $one_minus_k * $e2;
$e3 = $k * $e2 + $one_minus_k * $e3;
$e4 = $k * $e3 + $one_minus_k * $e4;
$e5 = $k * $e4 + $one_minus_k * $e5;
$tempReal += $e5;
}
$e6 = $tempReal / $optInTimePeriod;
while ($today <= $startIdx) {
$e1 = $k * $inReal[$today++] + $one_minus_k * $e1;
$e2 = $k * $e1 + $one_minus_k * $e2;
$e3 = $k * $e2 + $one_minus_k * $e3;
$e4 = $k * $e3 + $one_minus_k * $e4;
$e5 = $k * $e4 + $one_minus_k * $e5;
$e6 = $k * $e5 + $one_minus_k * $e6;
}
$tempReal = $optInVFactor * $optInVFactor;
$c1 = -($tempReal * $optInVFactor);
$c2 = 3.0 * ($tempReal - $c1);
$c3 = -6.0 * $tempReal - 3.0 * ($optInVFactor - $c1);
$c4 = 1.0 + 3.0 * $optInVFactor - $c1 + 3.0 * $tempReal;
$outIdx = 0;
$outReal[$outIdx++] = $c1 * $e6 + $c2 * $e5 + $c3 * $e4 + $c4 * $e3;
while ($today <= $endIdx) {
$e1 = $k * $inReal[$today++] + $one_minus_k * $e1;
$e2 = $k * $e1 + $one_minus_k * $e2;
$e3 = $k * $e2 + $one_minus_k * $e3;
$e4 = $k * $e3 + $one_minus_k * $e4;
$e5 = $k * $e4 + $one_minus_k * $e5;
$e6 = $k * $e5 + $one_minus_k * $e6;
$outReal[$outIdx++] = $c1 * $e6 + $c2 * $e5 + $c3 * $e4 + $c4 * $e3;
}
$outNBElement = $outIdx;
return ReturnCode::Success;
}
public static function tema(int $startIdx, int $endIdx, array $inReal, int $optInTimePeriod, int &$outBegIdx, int &$outNBElement, array &$outReal): int
{
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
$firstEMABegIdx = 0;
$firstEMANbElement = 0;
$secondEMABegIdx = 0;
$secondEMANbElement = 0;
$thirdEMABegIdx = 0;
$thirdEMANbElement = 0;
if ($optInTimePeriod === PHP_INT_MIN) {
$optInTimePeriod = 30;
} elseif ($optInTimePeriod < 2 || $optInTimePeriod > 100000) {
return ReturnCode::BadParam;
}
$outNBElement = 0;
$outBegIdx = 0;
$lookbackEMA = Lookback::emaLookback($optInTimePeriod);
$lookbackTotal = $lookbackEMA * 3;
if ($startIdx < $lookbackTotal) {
$startIdx = (int)$lookbackTotal;
}
if ($startIdx > $endIdx) {
return ReturnCode::Success;
}
$tempInt = $lookbackTotal + ($endIdx - $startIdx) + 1;
$firstEMA = static::double($tempInt);
$k = 2.0 / (double)($optInTimePeriod + 1);
$ReturnCode = static::TA_INT_EMA(
$startIdx - $lookbackEMA * 2,
$endIdx,
$inReal,
$optInTimePeriod,
$k,
$firstEMABegIdx,
$firstEMANbElement,
$firstEMA
);
if ($ReturnCode !== ReturnCode::Success || $firstEMANbElement === 0) {
return $ReturnCode;
}
$secondEMA = static::double($firstEMANbElement);
$ReturnCode = static::TA_INT_EMA(
0,
$firstEMANbElement - 1,
$firstEMA,
$optInTimePeriod,
$k,
$secondEMABegIdx,
$secondEMANbElement,
$secondEMA
);
if ($ReturnCode !== ReturnCode::Success || $secondEMANbElement === 0) {
return $ReturnCode;
}
$ReturnCode = static::TA_INT_EMA(
0,
$secondEMANbElement - 1,
$secondEMA,
$optInTimePeriod,
$k,
$thirdEMABegIdx,
$thirdEMANbElement,
$outReal
);
if ($ReturnCode !== ReturnCode::Success || $thirdEMANbElement === 0) {
return $ReturnCode;
}
$firstEMAIdx = $thirdEMABegIdx + $secondEMABegIdx;
$secondEMAIdx = $thirdEMABegIdx;
$outBegIdx = $firstEMAIdx + $firstEMABegIdx;
$outIdx = 0;
while ($outIdx < $thirdEMANbElement) {
$outReal[$outIdx] += 3.0 * $firstEMA[$firstEMAIdx++] - 3.0 * $secondEMA[$secondEMAIdx++];
$outIdx++;
}
$outNBElement = $outIdx;
return ReturnCode::Success;
}
public static function trima(int $startIdx, int $endIdx, array $inReal, int $optInTimePeriod, int &$outBegIdx, int &$outNBElement, array &$outReal): int
{
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
if ($optInTimePeriod === PHP_INT_MIN) {
$optInTimePeriod = 30;
} elseif ($optInTimePeriod < 2 || $optInTimePeriod > 100000) {
return ReturnCode::BadParam;
}
$lookbackTotal = $optInTimePeriod - 1;
if ($startIdx < $lookbackTotal) {
$startIdx = $lookbackTotal;
}
if ($startIdx > $endIdx) {
$outBegIdx = 0;
$outNBElement = 0;
return ReturnCode::Success;
}
$outIdx = 0;
$i = $optInTimePeriod >> 1;
if ($optInTimePeriod % 2 === 1) {
$factor = ($i + 1) * ($i + 1);
$factor = 1.0 / $factor;
$trailingIdx = $startIdx - $lookbackTotal;
$middleIdx = $trailingIdx + $i;
$todayIdx = $middleIdx + $i;
$numerator = 0.0;
$numeratorSub = 0.0;
for ($i = $middleIdx; $i >= $trailingIdx; $i--) {
$tempReal = $inReal[$i];
$numeratorSub += $tempReal;
$numerator += $numeratorSub;
}
$numeratorAdd = 0.0;
$middleIdx++;
for ($i = $middleIdx; $i <= $todayIdx; $i++) {
$tempReal = $inReal[$i];
$numeratorAdd += $tempReal;
$numerator += $numeratorAdd;
}
$tempReal = $inReal[$trailingIdx++];
$outReal[$outIdx++] = $numerator * $factor;
$todayIdx++;
while ($todayIdx <= $endIdx) {
$numerator -= $numeratorSub;
$numeratorSub -= $tempReal;
$tempReal = $inReal[$middleIdx++];
$numeratorSub += $tempReal;
$numerator += $numeratorAdd;
$numeratorAdd -= $tempReal;
$tempReal = $inReal[$todayIdx++];
$numeratorAdd += $tempReal;
$numerator += $tempReal;
$tempReal = $inReal[$trailingIdx++];
$outReal[$outIdx++] = $numerator * $factor;
}
} else {
$factor = $i * ($i + 1);
$factor = 1.0 / $factor;
$trailingIdx = $startIdx - $lookbackTotal;
$middleIdx = $trailingIdx + $i - 1;
$todayIdx = $middleIdx + $i;
$numerator = 0.0;
$numeratorSub = 0.0;
for ($i = $middleIdx; $i >= $trailingIdx; $i--) {
$tempReal = $inReal[$i];
$numeratorSub += $tempReal;
$numerator += $numeratorSub;
}
$numeratorAdd = 0.0;
$middleIdx++;
for ($i = $middleIdx; $i <= $todayIdx; $i++) {
$tempReal = $inReal[$i];
$numeratorAdd += $tempReal;
$numerator += $numeratorAdd;
}
$tempReal = $inReal[$trailingIdx++];
$outReal[$outIdx++] = $numerator * $factor;
$todayIdx++;
while ($todayIdx <= $endIdx) {
$numerator -= $numeratorSub;
$numeratorSub -= $tempReal;
$tempReal = $inReal[$middleIdx++];
$numeratorSub += $tempReal;
$numeratorAdd -= $tempReal;
$numerator += $numeratorAdd;
$tempReal = $inReal[$todayIdx++];
$numeratorAdd += $tempReal;
$numerator += $tempReal;
$tempReal = $inReal[$trailingIdx++];
$outReal[$outIdx++] = $numerator * $factor;
}
}
$outNBElement = $outIdx;
$outBegIdx = $startIdx;
return ReturnCode::Success;
}
public static function wma(int $startIdx, int $endIdx, array $inReal, int $optInTimePeriod, int &$outBegIdx, int &$outNBElement, array &$outReal): int
{
if ($RetCode = static::validateStartEndIndexes($startIdx, $endIdx)) {
return $RetCode;
}
if ($optInTimePeriod === PHP_INT_MIN) {
$optInTimePeriod = 30;
} elseif ($optInTimePeriod < 2 || $optInTimePeriod > 100000) {
return ReturnCode::BadParam;
}
$lookbackTotal = $optInTimePeriod - 1;
if ($startIdx < $lookbackTotal) {
$startIdx = $lookbackTotal;
}
if ($startIdx > $endIdx) {
$outBegIdx = 0;
$outNBElement = 0;
return ReturnCode::Success;
}
$divider = $optInTimePeriod * ($optInTimePeriod + 1) >> 1;
$outIdx = 0;
$trailingIdx = $startIdx - $lookbackTotal;
$periodSum = $periodSub = 0.0;
$inIdx = $trailingIdx;
$i = 1;
while ($inIdx < $startIdx) {
$tempReal = $inReal[$inIdx++];
$periodSub += $tempReal;
$periodSum += $tempReal * $i;
$i++;
}
$trailingValue = 0.0;
while ($inIdx <= $endIdx) {
$tempReal = $inReal[$inIdx++];
$periodSub += $tempReal;
$periodSub -= $trailingValue;
$periodSum += $tempReal * $optInTimePeriod;
$trailingValue = $inReal[$trailingIdx++];
$outReal[$outIdx++] = $periodSum / $divider;
$periodSum -= $periodSub;
}
$outNBElement = $outIdx;
$outBegIdx = $startIdx;
return ReturnCode::Success;
}
}
Function Calls
None |
Stats
MD5 | 785166e535604e056f010251f5e2b2f9 |
Eval Count | 0 |
Decode Time | 117 ms |