|
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
|
|
|
* |
|
11
|
|
|
* Moving Average Crossover Divergence (MACD) indicator as a buy/sell signal. |
|
12
|
|
|
* When the MACD signal less than 0, the price is trending down and it's time to sell. |
|
13
|
|
|
* When the MACD signal greater than 0, the price is trending up it's time to buy. |
|
14
|
|
|
* |
|
15
|
|
|
* Used to catch trends early and can also help us spot trend reversals. |
|
16
|
|
|
* It consists of 2 moving averages (1 fast, 1 slow) and vertical lines called a histogram, |
|
17
|
|
|
* which measures the distance between the 2 moving averages. |
|
18
|
|
|
* Contrary to what many people think, the moving average lines are NOT moving averages of the price. |
|
19
|
|
|
* They are moving averages of other moving averages. |
|
20
|
|
|
* MACD’s downfall is its lag because it uses so many moving averages. |
|
21
|
|
|
* One way to use MACD is to wait for the fast line to “cross over” or “cross under” the slow line and |
|
22
|
|
|
* enter the trade accordingly because it signals a new trend. |
|
23
|
|
|
*/ |
|
24
|
|
|
class MovingAverageCrossoverDivergenceIndicator implements Indicator |
|
25
|
|
|
{ |
|
26
|
|
|
|
|
27
|
|
|
public function __invoke(Collection $ohlcv, int $period1 = 12, int $period2 = 26, int $period3 = 9): int |
|
28
|
|
|
{ |
|
29
|
|
|
|
|
30
|
|
|
/* |
|
31
|
|
|
* Create the MACD signal and pass in the three parameters: fast period, slow period, and the signal. |
|
32
|
|
|
* we will want to tweak these periods later for now these are fine. |
|
33
|
|
|
* data, fast period, slow period, signal period (2-100000) |
|
34
|
|
|
* array $real [, integer $fastPeriod [, integer $slowPeriod [, integer $signalPeriod ]]] |
|
35
|
|
|
*/ |
|
36
|
|
|
|
|
37
|
|
|
$macd = trader_macd( |
|
38
|
|
|
$ohlcv->get('close'), |
|
39
|
|
|
$period1, |
|
40
|
|
|
$period2, |
|
41
|
|
|
$period3 |
|
42
|
|
|
); |
|
43
|
|
|
|
|
44
|
|
|
if (false === $macd) { |
|
45
|
|
|
throw new NotEnoughDataPointsException('Not enough data points'); |
|
46
|
|
|
} |
|
47
|
|
|
|
|
48
|
|
|
|
|
49
|
|
|
$macd_raw = $macd[0]; |
|
50
|
|
|
$signal = $macd[1]; |
|
51
|
|
|
|
|
52
|
|
|
//If not enough Elements for the Function to complete |
|
53
|
|
|
if (!$macd || !$macd_raw) { |
|
54
|
|
|
throw new NotEnoughDataPointsException('Not enough data points'); |
|
55
|
|
|
} |
|
56
|
|
|
|
|
57
|
|
|
//$macd = $macd_raw[count($macd_raw)-1] - $signal[count($signal)-1]; |
|
|
|
|
|
|
58
|
|
|
$macd = (array_pop($macd_raw) - array_pop($signal)); |
|
59
|
|
|
|
|
60
|
|
|
// Close position for the pair when the MACD signal is negative |
|
61
|
|
|
|
|
62
|
|
|
if ($macd < 0) { |
|
63
|
|
|
return static::SELL; |
|
64
|
|
|
// Enter the position for the pair when the MACD signal is positive |
|
65
|
|
|
} elseif ($macd > 0) { |
|
66
|
|
|
return static::BUY; |
|
67
|
|
|
} else { |
|
68
|
|
|
return static::HOLD; |
|
69
|
|
|
} |
|
70
|
|
|
} |
|
71
|
|
|
} |
|
72
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.