|
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
|
|
|
* Bollinger Band Indicator |
|
11
|
|
|
* |
|
12
|
|
|
* @https://www.investopedia.com/terms/b/bollingerbands.asp |
|
13
|
|
|
* |
|
14
|
|
|
* |
|
15
|
|
|
* This algorithm uses the talib Bollinger Bands function to determine entry entry |
|
16
|
|
|
* points for long and sell/short positions. |
|
17
|
|
|
* |
|
18
|
|
|
* When the price breaks out of the upper Bollinger band, a sell or short position |
|
19
|
|
|
* is opened. A long position is opened when the price dips below the lower band. |
|
20
|
|
|
* |
|
21
|
|
|
* |
|
22
|
|
|
* Used to measure the market’s volatility. |
|
23
|
|
|
* They act like mini support and resistance levels. |
|
24
|
|
|
* Bollinger Bounce |
|
25
|
|
|
* |
|
26
|
|
|
* A strategy that relies on the notion that price tends to always return to the middle of the Bollinger bands. |
|
27
|
|
|
* You buy when the price hits the lower Bollinger band. |
|
28
|
|
|
* You sell when the price hits the upper Bollinger band. |
|
29
|
|
|
* Best used in ranging markets. |
|
30
|
|
|
* Bollinger Squeeze |
|
31
|
|
|
* |
|
32
|
|
|
* A strategy that is used to catch breakouts early. |
|
33
|
|
|
* When the Bollinger bands “squeeze”, it means that the market is very quiet, and a breakout is eminent. |
|
34
|
|
|
* Once a breakout occurs, we enter a trade on whatever side the price makes its breakout. |
|
35
|
|
|
*/ |
|
36
|
|
|
class BollingerBandsIndicator implements Indicator |
|
37
|
|
|
{ |
|
38
|
|
|
|
|
39
|
|
|
public function __invoke(Collection $ohlcv, int $period = 10, int $devup = 2, int $devdn = 2): int |
|
40
|
|
|
{ |
|
41
|
|
|
|
|
42
|
|
|
$data2 = $ohlcv; |
|
43
|
|
|
|
|
44
|
|
|
// $prev_close = array_pop($data2['close']); #[count($data['close']) - 2]; // prior close |
|
|
|
|
|
|
45
|
|
|
$current = array_pop($data2->get('close')); #[count($data['close']) - 1]; // we assume this is current |
|
|
|
|
|
|
46
|
|
|
|
|
47
|
|
|
// array $real [, integer $timePeriod [, float $nbDevUp [, float $nbDevDn [, integer $mAType ]]]] |
|
|
|
|
|
|
48
|
|
|
$bbands = trader_bbands( |
|
49
|
|
|
$ohlcv->get('close'), |
|
50
|
|
|
$period, |
|
51
|
|
|
$devup, |
|
52
|
|
|
$devdn, |
|
53
|
|
|
0 |
|
54
|
|
|
); |
|
55
|
|
|
|
|
56
|
|
|
if (false === $bbands) { |
|
57
|
|
|
throw new NotEnoughDataPointsException('Not enough data points'); |
|
58
|
|
|
} |
|
59
|
|
|
|
|
60
|
|
|
$upper = $bbands[0]; |
|
61
|
|
|
|
|
62
|
|
|
// $middle = $bbands[1]; |
|
|
|
|
|
|
63
|
|
|
// we'll find a use for you, one day |
|
64
|
|
|
$lower = $bbands[2]; |
|
65
|
|
|
|
|
66
|
|
|
// If price is below the recent lower band |
|
67
|
|
|
if ($current <= array_pop($lower)) { |
|
68
|
|
|
return static::BUY; |
|
69
|
|
|
// If price is above the recent upper band |
|
70
|
|
|
} elseif ($current >= array_pop($upper)) { |
|
71
|
|
|
return static::SELL; |
|
72
|
|
|
} else { |
|
73
|
|
|
return static::HOLD; |
|
74
|
|
|
} |
|
75
|
|
|
} |
|
76
|
|
|
} |
|
77
|
|
|
|
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.