|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace Laratrade\Indicators; |
|
4
|
|
|
|
|
5
|
|
|
use Illuminate\Support\Collection; |
|
6
|
|
|
use Laratrade\Indicators\Contracts\Indicator; |
|
7
|
|
|
use Laratrade\Indicators\Exceptions\NotEnoughDataPointsException; |
|
8
|
|
|
|
|
9
|
|
|
/** |
|
10
|
|
|
* Hilbert Transform - Instantaneous Trendline |
|
11
|
|
|
* |
|
12
|
|
|
* |
|
13
|
|
|
* @see http://www2.wealth-lab.com/WL5Wiki/HTTrendLine.ashx |
|
14
|
|
|
* |
|
15
|
|
|
* |
|
16
|
|
|
* The Hilbert Transform is a technique used to generate inphase and quadrature components of a de-trended real-valued |
|
17
|
|
|
* "analytic-like" signal (such as a Price Series) in order to analyze variations of the instantaneous phase and |
|
18
|
|
|
* amplitude. HTTrendline (or MESA Instantaneous Trendline) returns the Price Series value after the Dominant Cycle of |
|
19
|
|
|
* the analytic signal as generated by the Hilbert Transform has been removed. The Dominant Cycle can be thought of as |
|
20
|
|
|
* being the "most likely" period (in the range of 10 to 40) of a sine function of the Price Series. |
|
21
|
|
|
* |
|
22
|
|
|
* smoothed trendline, if the |
|
23
|
|
|
* price moves 1.5% away from the trendline we can declare a trend. |
|
24
|
|
|
* |
|
25
|
|
|
* |
|
26
|
|
|
* WMA(4) |
|
27
|
|
|
* trader_ht_trendline |
|
28
|
|
|
* |
|
29
|
|
|
* if WMA(4) < htl for five periods then in downtrend (sell in trend mode) |
|
30
|
|
|
* if WMA(4) > htl for five periods then in uptrend (buy in trend mode) |
|
31
|
|
|
* |
|
32
|
|
|
* // if price is 1.5% more than trendline, then declare a trend |
|
33
|
|
|
* (WMA(4)-trendline)/trendline >= 0.15 then trend = 1 |
|
34
|
|
|
*/ |
|
35
|
|
|
class HilbertTransformInstantaneousTrendlineIndicator implements Indicator |
|
36
|
|
|
{ |
|
37
|
|
|
|
|
38
|
|
|
public function __invoke(Collection $ohlcv, int $period = 14): int |
|
39
|
|
|
{ |
|
40
|
|
|
|
|
41
|
|
|
$declared = $uptrend = $downtrend = 0; |
|
42
|
|
|
$a_htl = $a_wma4 = []; |
|
43
|
|
|
$htl = trader_ht_trendline($ohlcv->get('close')); |
|
44
|
|
|
|
|
45
|
|
|
if (false === $htl) { |
|
46
|
|
|
throw new NotEnoughDataPointsException('Not enough data points'); |
|
47
|
|
|
} |
|
48
|
|
|
|
|
49
|
|
|
|
|
50
|
|
|
$wma4 = trader_wma($ohlcv->get('close'), 4); |
|
51
|
|
|
|
|
52
|
|
|
for ($a = 0; $a < 5; $a++) { |
|
53
|
|
|
$a_htl[$a] = array_pop($htl); |
|
54
|
|
|
$a_wma4[$a] = array_pop($wma4); |
|
55
|
|
|
$uptrend += ($a_wma4[$a] > $a_htl[$a] ? 1 : 0); |
|
56
|
|
|
$downtrend += ($a_wma4[$a] < $a_htl[$a] ? 1 : 0); |
|
57
|
|
|
|
|
58
|
|
|
$declared = (($a_wma4[$a] - $a_htl[$a]) / $a_htl[$a]); |
|
59
|
|
|
} |
|
60
|
|
|
|
|
61
|
|
|
|
|
62
|
|
|
if ($uptrend || $declared >= 0.15) { |
|
63
|
|
|
return static::BUY; |
|
64
|
|
|
} |
|
65
|
|
|
|
|
66
|
|
|
if ($downtrend || $declared <= 0.15) { |
|
67
|
|
|
return static::SELL; |
|
68
|
|
|
} |
|
69
|
|
|
|
|
70
|
|
|
return static::HOLD; |
|
71
|
|
|
} |
|
72
|
|
|
} |
|
73
|
|
|
|