Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
| Total | |
0.00% |
0 / 1 |
|
0.00% |
0 / 5 |
CRAP | |
97.24% |
1092 / 1123 |
| LupeCode\phpTraderNative\TALib\Core\CycleIndicators | |
0.00% |
0 / 1 |
|
0.00% |
0 / 5 |
118 | |
97.24% |
1092 / 1123 |
| htDcPeriod | |
0.00% |
0 / 1 |
15 | |
96.00% |
120 / 125 |
|||
| htDcPhase | |
0.00% |
0 / 1 |
25 | |
97.19% |
242 / 249 |
|||
| htPhasor | |
0.00% |
0 / 1 |
16 | |
97.63% |
206 / 211 |
|||
| htSine | |
0.00% |
0 / 1 |
25 | |
97.21% |
244 / 251 |
|||
| htTrendMode | |
0.00% |
0 / 1 |
37 | |
97.56% |
280 / 287 |
|||
| <?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\ReturnCode; | |
| use LupeCode\phpTraderNative\TALib\Enum\UnstablePeriodFunctionID; | |
| class CycleIndicators extends Core | |
| { | |
| /** | |
| * @param int $startIdx | |
| * @param int $endIdx | |
| * @param array $inReal | |
| * @param int $outBegIdx | |
| * @param int $outNBElement | |
| * @param array $outReal | |
| * | |
| * @return int | |
| */ | |
| public static function htDcPeriod(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 = $detrender_Even = $Q1_Odd = $Q1_Even = $jI_Odd = $jI_Even = $jQ_Odd = $jQ_Even = static::double(3); | |
| $rad2Deg = 180.0 / (4.0 * atan(1)); | |
| $lookbackTotal = 32 + (static::$unstablePeriod[UnstablePeriodFunctionID::HtDcPeriod]); | |
| 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 = $outIdx = 0; | |
| $detrender = $prev_detrender_Odd = $prev_detrender_Even = $prev_detrender_input_Odd = $prev_detrender_input_Even = 0.0; | |
| $Q1 = $prev_Q1_Odd = $prev_Q1_Even = $prev_Q1_input_Odd = $prev_Q1_input_Even = 0.0; | |
| $jI = $prev_jI_Odd = $prev_jI_Even = $prev_jI_input_Odd = $prev_jI_input_Even = 0.0; | |
| $jQ = $prev_jQ_Odd = $prev_jQ_Even = $prev_jQ_input_Odd = $prev_jQ_input_Even = 0.0; | |
| $period = $prevI2 = $prevQ2 = $Re = $Im = $I1ForOddPrev3 = $I1ForEvenPrev3 = $I1ForOddPrev2 = $I1ForEvenPrev2 = $smoothPeriod = 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] + $hilbertTempReal - $prev_detrender_Even + ($b * $prev_detrender_input_Even)) * $adjustedPrevPeriod; | |
| $detrender_Even[$hilbertIdx] = $hilbertTempReal; | |
| $prev_detrender_Even = $b * $prev_detrender_input_Even; | |
| $prev_detrender_input_Even = $smoothedValue; | |
| }; | |
| { | |
| $hilbertTempReal = $a * $detrender; | |
| $Q1 = (-$Q1_Even[$hilbertIdx] + $hilbertTempReal - $prev_Q1_Even + ($b * $prev_Q1_input_Even)) * $adjustedPrevPeriod; | |
| $Q1_Even[$hilbertIdx] = $hilbertTempReal; | |
| $prev_Q1_Even = $b * $prev_Q1_input_Even; | |
| $prev_Q1_input_Even = $detrender; | |
| }; | |
| { | |
| $hilbertTempReal = $a * $I1ForEvenPrev3; | |
| $jI = (-$jI_Even[$hilbertIdx] + $hilbertTempReal - $prev_jI_Even + ($b * $prev_jI_input_Even)) * $adjustedPrevPeriod; | |
| $jI_Even[$hilbertIdx] = $hilbertTempReal; | |
| $prev_jI_Even = $b * $prev_jI_input_Even; | |
| $prev_jI_input_Even = $I1ForEvenPrev3; | |
| }; | |
| { | |
| $hilbertTempReal = $a * $Q1; | |
| $jQ = (-$jQ_Even[$hilbertIdx] + $hilbertTempReal - $prev_jQ_Even + ($b * $prev_jQ_input_Even)) * $adjustedPrevPeriod; | |
| $jQ_Even[$hilbertIdx] = $hilbertTempReal; | |
| $prev_jQ_Even = $b * $prev_jQ_input_Even; | |
| $prev_jQ_input_Even = $Q1; | |
| }; | |
| 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] + $hilbertTempReal - $prev_detrender_Odd + ($b * $prev_detrender_input_Odd)) * $adjustedPrevPeriod; | |
| $detrender_Odd[$hilbertIdx] = $hilbertTempReal; | |
| $prev_detrender_Odd = $b * $prev_detrender_input_Odd; | |
| $prev_detrender_input_Odd = $smoothedValue; | |
| }; | |
| { | |
| $hilbertTempReal = $a * $detrender; | |
| $Q1 = (-$Q1_Odd[$hilbertIdx] + $hilbertTempReal - $prev_Q1_Odd + ($b * $prev_Q1_input_Odd)) * $adjustedPrevPeriod; | |
| $Q1_Odd[$hilbertIdx] = $hilbertTempReal; | |
| $prev_Q1_Odd = $b * $prev_Q1_input_Odd; | |
| $prev_Q1_input_Odd = $detrender; | |
| }; | |
| { | |
| $hilbertTempReal = $a * $I1ForOddPrev3; | |
| $jI = (-$jI_Odd[$hilbertIdx] + $hilbertTempReal - $prev_jI_Odd + ($b * $prev_jI_input_Odd)) * $adjustedPrevPeriod; | |
| $jI_Odd[$hilbertIdx] = $hilbertTempReal; | |
| $prev_jI_Odd = $b * $prev_jI_input_Odd; | |
| $prev_jI_input_Odd = $I1ForOddPrev3; | |
| }; | |
| { | |
| $hilbertTempReal = $a * $Q1; | |
| $jQ = (-$jQ_Odd[$hilbertIdx] + $hilbertTempReal - $prev_jQ_Odd + ($b * $prev_jQ_input_Odd)) * $adjustedPrevPeriod; | |
| $jQ_Odd[$hilbertIdx] = $hilbertTempReal; | |
| $prev_jQ_Odd = $b * $prev_jQ_input_Odd; | |
| $prev_jQ_input_Odd = $Q1; | |
| }; | |
| $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); | |
| if ($today >= $startIdx) { | |
| $outReal[$outIdx++] = $smoothPeriod; | |
| } | |
| $today++; | |
| } | |
| $outNBElement = $outIdx; | |
| return ReturnCode::Success; | |
| } | |
| /** | |
| * @param int $startIdx | |
| * @param int $endIdx | |
| * @param array $inReal | |
| * @param int $outBegIdx | |
| * @param int $outNBElement | |
| * @param array $outReal | |
| * | |
| * @return int | |
| */ | |
| public static function htDcPhase(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); | |
| }; | |
| $tempReal = atan(1); | |
| $rad2Deg = 45.0 / $tempReal; | |
| $constDeg2RadBy360 = $tempReal * 8.0; | |
| $lookbackTotal = 63 + (static::$unstablePeriod[UnstablePeriodFunctionID::HtDcPhase]); | |
| 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; | |
| } | |
| $DCPhase = 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; | |
| $realPart = 0.0; | |
| $imagPart = 0.0; | |
| $idxothPricePrice = $smoothPrice_Idx; | |
| for ($i = 0; $i < $DCPeriodInt; $i++) { | |
| $tempReal = ((double)$i * $constDeg2RadBy360) / (double)$DCPeriodInt; | |
| $tempReal2 = $smoothPrice[$idxothPricePrice]; | |
| $realPart += sin($tempReal) * $tempReal2; | |
| $imagPart += cos($tempReal) * $tempReal2; | |
| if ($idxothPricePrice == 0) { | |
| $idxothPricePrice = 50 - 1; | |
| } else { | |
| $idxothPricePrice--; | |
| } | |
| } | |
| $tempReal = abs($imagPart); | |
| if ($tempReal > 0.0) { | |
| $DCPhase = atan($realPart / $imagPart) * $rad2Deg; | |
| } elseif ($tempReal <= 0.01) { | |
| if ($realPart < 0.0) { | |
| $DCPhase -= 90.0; | |
| } elseif ($realPart > 0.0) { | |
| $DCPhase += 90.0; | |
| } | |
| } | |
| $DCPhase += 90.0; | |
| $DCPhase += 360.0 / $smoothPeriod; | |
| if ($imagPart < 0.0) { | |
| $DCPhase += 180.0; | |
| } | |
| if ($DCPhase > 315.0) { | |
| $DCPhase -= 360.0; | |
| } | |
| if ($today >= $startIdx) { | |
| $outReal[$outIdx++] = $DCPhase; | |
| } | |
| { | |
| $smoothPrice_Idx++; | |
| if ($smoothPrice_Idx > $maxIdx_smoothPricePrice) { | |
| $smoothPrice_Idx = 0; | |
| } | |
| }; | |
| $today++; | |
| } | |
| $outNBElement = $outIdx; | |
| return ReturnCode::Success; | |
| } | |
| /** | |
| * @param int $startIdx | |
| * @param int $endIdx | |
| * @param array $inReal | |
| * @param int $outBegIdx | |
| * @param int $outNBElement | |
| * @param array $outInPhase | |
| * @param array $outQuadrature | |
| * | |
| * @return int | |
| */ | |
| public static function htPhasor(int $startIdx, int $endIdx, array $inReal, int &$outBegIdx, int &$outNBElement, array &$outInPhase, array &$outQuadrature): 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); | |
| $rad2Deg = 180.0 / (4.0 * atan(1)); | |
| $lookbackTotal = 32 + (static::$unstablePeriod[UnstablePeriodFunctionID::HtPhasor]); | |
| 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; | |
| $I1ForOddPrev3 = $I1ForEvenPrev3 = 0.0; | |
| $I1ForOddPrev2 = $I1ForEvenPrev2 = 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; | |
| }; | |
| if ($today >= $startIdx) { | |
| $outQuadrature[$outIdx] = $Q1; | |
| $outInPhase[$outIdx++] = $I1ForEvenPrev3; | |
| } | |
| { | |
| $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; | |
| }; | |
| if ($today >= $startIdx) { | |
| $outQuadrature[$outIdx] = $Q1; | |
| $outInPhase[$outIdx++] = $I1ForOddPrev3; | |
| } | |
| { | |
| $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); | |
| $today++; | |
| } | |
| $outNBElement = $outIdx; | |
| return ReturnCode::Success; | |
| } | |
| /** | |
| * @param int $startIdx | |
| * @param int $endIdx | |
| * @param array $inReal | |
| * @param int $outBegIdx | |
| * @param int $outNBElement | |
| * @param array $outSine | |
| * @param array $outLeadSine | |
| * | |
| * @return int | |
| */ | |
| public static function htSine(int $startIdx, int $endIdx, array $inReal, int &$outBegIdx, int &$outNBElement, array &$outSine, array &$outLeadSine): 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); | |
| }; | |
| $tempReal = atan(1); | |
| $rad2Deg = 45.0 / $tempReal; | |
| $deg2Rad = 1.0 / $rad2Deg; | |
| $constDeg2RadBy360 = $tempReal * 8.0; | |
| $lookbackTotal = 63 + (static::$unstablePeriod[UnstablePeriodFunctionID::HtSine]); | |
| 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; | |
| } | |
| $DCPhase = 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; | |
| $realPart = 0.0; | |
| $imagPart = 0.0; | |
| $idxothPricePrice = $smoothPrice_Idx; | |
| for ($i = 0; $i < $DCPeriodInt; $i++) { | |
| $tempReal = ((double)$i * $constDeg2RadBy360) / (double)$DCPeriodInt; | |
| $tempReal2 = $smoothPrice[$idxothPricePrice]; | |
| $realPart += sin($tempReal) * $tempReal2; | |
| $imagPart += cos($tempReal) * $tempReal2; | |
| if ($idxothPricePrice == 0) { | |
| $idxothPricePrice = 50 - 1; | |
| } else { | |
| $idxothPricePrice--; | |
| } | |
| } | |
| $tempReal = abs($imagPart); | |
| if ($tempReal > 0.0) { | |
| $DCPhase = atan($realPart / $imagPart) * $rad2Deg; | |
| } elseif ($tempReal <= 0.01) { | |
| if ($realPart < 0.0) { | |
| $DCPhase -= 90.0; | |
| } elseif ($realPart > 0.0) { | |
| $DCPhase += 90.0; | |
| } | |
| } | |
| $DCPhase += 90.0; | |
| $DCPhase += 360.0 / $smoothPeriod; | |
| if ($imagPart < 0.0) { | |
| $DCPhase += 180.0; | |
| } | |
| if ($DCPhase > 315.0) { | |
| $DCPhase -= 360.0; | |
| } | |
| if ($today >= $startIdx) { | |
| $outSine[$outIdx] = sin($DCPhase * $deg2Rad); | |
| $outLeadSine[$outIdx++] = sin(($DCPhase + 45) * $deg2Rad); | |
| } | |
| { | |
| $smoothPrice_Idx++; | |
| if ($smoothPrice_Idx > $maxIdx_smoothPricePrice) { | |
| $smoothPrice_Idx = 0; | |
| } | |
| }; | |
| $today++; | |
| } | |
| $outNBElement = $outIdx; | |
| return ReturnCode::Success; | |
| } | |
| /** | |
| * @param int $startIdx | |
| * @param int $endIdx | |
| * @param array $inReal | |
| * @param int $outBegIdx | |
| * @param int $outNBElement | |
| * @param array $outInteger | |
| * | |
| * @return int | |
| */ | |
| public static function htTrendMode(int $startIdx, int $endIdx, array $inReal, int &$outBegIdx, int &$outNBElement, array &$outInteger): 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; | |
| $daysInTrend = 0; | |
| $prevDCPhase = $DCPhase = 0.0; | |
| $prevSine = $sine = 0.0; | |
| $prevLeadSine = $leadSine = 0.0; | |
| $tempReal = atan(1); | |
| $rad2Deg = 45.0 / $tempReal; | |
| $deg2Rad = 1.0 / $rad2Deg; | |
| $constDeg2RadBy360 = $tempReal * 8.0; | |
| $lookbackTotal = 63 + (static::$unstablePeriod[UnstablePeriodFunctionID::HtTrendMode]); | |
| 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; | |
| } | |
| $DCPhase = 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); | |
| $prevDCPhase = $DCPhase; | |
| $DCPeriod = $smoothPeriod + 0.5; | |
| $DCPeriodInt = (int)$DCPeriod; | |
| $realPart = 0.0; | |
| $imagPart = 0.0; | |
| $idxothPricePrice = $smoothPrice_Idx; | |
| for ($i = 0; $i < $DCPeriodInt; $i++) { | |
| $tempReal = ((double)$i * $constDeg2RadBy360) / (double)$DCPeriodInt; | |
| $tempReal2 = $smoothPrice[$idxothPricePrice]; | |
| $realPart += sin($tempReal) * $tempReal2; | |
| $imagPart += cos($tempReal) * $tempReal2; | |
| if ($idxothPricePrice == 0) { | |
| $idxothPricePrice = 50 - 1; | |
| } else { | |
| $idxothPricePrice--; | |
| } | |
| } | |
| $tempReal = abs($imagPart); | |
| if ($tempReal > 0.0) { | |
| $DCPhase = atan($realPart / $imagPart) * $rad2Deg; | |
| } elseif ($tempReal <= 0.01) { | |
| if ($realPart < 0.0) { | |
| $DCPhase -= 90.0; | |
| } elseif ($realPart > 0.0) { | |
| $DCPhase += 90.0; | |
| } | |
| } | |
| $DCPhase += 90.0; | |
| $DCPhase += 360.0 / $smoothPeriod; | |
| if ($imagPart < 0.0) { | |
| $DCPhase += 180.0; | |
| } | |
| if ($DCPhase > 315.0) { | |
| $DCPhase -= 360.0; | |
| } | |
| $prevSine = $sine; | |
| $prevLeadSine = $leadSine; | |
| $sine = sin($DCPhase * $deg2Rad); | |
| $leadSine = sin(($DCPhase + 45) * $deg2Rad); | |
| $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; | |
| } | |
| $trendline = (4.0 * $tempReal + 3.0 * $iTrend1 + 2.0 * $iTrend2 + $iTrend3) / 10.0; | |
| $iTrend3 = $iTrend2; | |
| $iTrend2 = $iTrend1; | |
| $iTrend1 = $tempReal; | |
| $trend = 1; | |
| if ((($sine > $leadSine) && ($prevSine <= $prevLeadSine)) || | |
| (($sine < $leadSine) && ($prevSine >= $prevLeadSine))) { | |
| $daysInTrend = 0; | |
| $trend = 0; | |
| } | |
| $daysInTrend++; | |
| if ($daysInTrend < (0.5 * $smoothPeriod)) { | |
| $trend = 0; | |
| } | |
| $tempReal = $DCPhase - $prevDCPhase; | |
| if (($smoothPeriod != 0.0) && | |
| (($tempReal > (0.67 * 360.0 / $smoothPeriod)) && ($tempReal < (1.5 * 360.0 / $smoothPeriod)))) { | |
| $trend = 0; | |
| } | |
| $tempReal = $smoothPrice[$smoothPrice_Idx]; | |
| if (($trendline != 0.0) && (abs(($tempReal - $trendline) / $trendline) >= 0.015)) { | |
| $trend = 1; | |
| } | |
| if ($today >= $startIdx) { | |
| $outInteger[$outIdx++] = $trend; | |
| } | |
| { | |
| $smoothPrice_Idx++; | |
| if ($smoothPrice_Idx > $maxIdx_smoothPricePrice) { | |
| $smoothPrice_Idx = 0; | |
| } | |
| }; | |
| $today++; | |
| } | |
| $outNBElement = $outIdx; | |
| return ReturnCode::Success; | |
| } | |
| } |