I am trying to use PHPs trader functions (available as a PECL extension) to calculate the moving average convergence/divergence (MACD) of various securities. However, the values returned do not seem to match my calculations.
Consider the following array of close prices for a stock:
$close = array (
0 => 459.99,
1 => 448.85,
2 => 446.06,
3 => 450.81,
4 => 442.8,
5 => 448.97,
6 => 444.57,
7 => 441.4,
8 => 430.47,
9 => 420.05,
10 => 431.14,
11 => 425.66,
12 => 430.58,
13 => 431.72,
14 => 437.87,
15 => 428.43,
16 => 428.35,
17 => 432.5,
18 => 443.66,
19 => 455.72,
20 => 454.49,
21 => 452.08,
22 => 452.73,
23 => 461.91,
24 => 463.58,
25 => 461.14,
26 => 452.08,
27 => 442.66,
28 => 428.91,
29 => 429.79,
30 => 431.99,
31 => 427.72,
32 => 423.2,
33 => 426.21,
34 => 426.98,
35 => 435.69,
36 => 434.33,
37 => 429.8,
38 => 419.85,
39 => 426.24,
40 => 402.8,
41 => 392.05,
42 => 390.53,
43 => 398.67,
44 => 406.13,
45 => 405.46,
46 => 408.38,
47 => 417.2,
48 => 430.12,
49 => 442.78,
50 => 439.29,
51 => 445.52,
52 => 449.98,
53 => 460.71,
54 => 458.66,
55 => 463.84,
56 => 456.77,
57 => 452.97,
58 => 454.74,
59 => 443.86,
60 => 428.85,
61 => 434.58,
62 => 433.26,
63 => 442.93,
64 => 439.66,
65 => 441.35,
);
Based on these numbers, the MACD, signal line, and MACD histogram should come out to:
// MACD
Array
(
[0] => 8.275269504
[1] => 7.703378381
[2] => 6.416074757
[3] => 4.237519783
[4] => 2.552583325
[5] => 1.37888572
[6] => 0.102981491
[7] => -1.258401953
[8] => -2.07055819
[9] => -2.621842328
[10] => -2.32906674
[11] => -2.181632115
[12] => -2.402626273
[13] => -3.342121681
[14] => -3.530363136
[15] => -5.507471249
[16] => -7.851274229
[17] => -9.719367455
[18] => -10.42286651
[19] => -10.26016216
[20] => -10.06920961
[21] => -9.571919612
[22] => -8.369633492
[23] => -6.301635724
[24] => -3.599681509
[25] => -1.720148361
[26] => 0.269003232
[27] => 2.180173247
[28] => 4.508637809
[29] => 6.118020154
[30] => 7.722430594
[31] => 8.327453809
[32] => 8.403441185
[33] => 8.508406323
[34] => 7.625761844
[35] => 5.649949083
[36] => 4.494654765
[37] => 3.432989362
[38] => 3.333473854
[39] => 2.956662856
[40] => 2.762561216
)
// Signal line
Array
(
[0] => 3.037525869
[1] => 1.905652229
[2] => 1.058708435
[3] => 0.410640325
[4] => -0.152012994
[5] => -0.790034732
[6] => -1.338100413
[7] => -2.17197458
[8] => -3.30783451
[9] => -4.590141099
[10] => -5.756686181
[11] => -6.657381376
[12] => -7.339747023
[13] => -7.786181541
[14] => -7.902871931
[15] => -7.58262469
[16] => -6.786036054
[17] => -5.772858515
[18] => -4.564486166
[19] => -3.215554283
[20] => -1.670715865
[21] => -0.112968661
[22] => 1.45411119
[23] => 2.828779714
[24] => 3.943712008
[25] => 4.856650871
[26] => 5.410473066
[27] => 5.458368269
[28] => 5.265625568
[29] => 4.899098327
[30] => 4.585973432
[31] => 4.260111317
[32] => 3.960601297
)
// MACD histogram
Array
(
[0] => -5.108084059
[1] => -4.527494558
[2] => -3.387775176
[3] => -2.59227244
[4] => -2.250613279
[5] => -2.55208695
[6] => -2.192262723
[7] => -3.335496669
[8] => -4.543439719
[9] => -5.129226357
[10] => -4.666180327
[11] => -3.602780783
[12] => -2.729462587
[13] => -1.785738071
[14] => -0.466761561
[15] => 1.280988966
[16] => 3.186354544
[17] => 4.052710154
[18] => 4.833489398
[19] => 5.39572753
[20] => 6.179353673
[21] => 6.230988815
[22] => 6.268319404
[23] => 5.498674095
[24] => 4.459729177
[25] => 3.651755452
[26] => 2.215288778
[27] => 0.191580814
[28] => -0.770970803
[29] => -1.466108965
[30] => -1.252499579
[31] => -1.303448461
[32] => -1.198040081
)
Note that the MACD requires the calculation of a 26 day moving average, so while there are 66 different data points for the close price, there are only 41 calculated MACD values. Additionally, the signal line (and therefore the MACD histogram which requires the signal line) requires a 9 day moving average of the MACD, so there are only 31 calculations for the signal line/MACD histogram.
The above data was calculated on excel and is the correct MACD. The short script I have to calculate the MACD in PHP is:
<?php
// The array $close is the same as it is in the above example, omitted here for brevity.
$macd = trader_macd($close, 12, 26);
var_dump($macd);
?>
However, var_dump($macd)
prints:
array(3) {
[0]=>
array(40) {
[24]=>
float(0)
[25]=>
float(4.415)
[26]=>
float(4.437)
[27]=>
float(3.652)
[28]=>
float(1.899)
[29]=>
float(0.574)
[30]=>
float(-0.295)
[31]=>
float(-1.314)
[32]=>
float(-2.457)
[33]=>
float(-3.085)
[34]=>
float(-3.48)
[35]=>
float(-3.055)
[36]=>
float(-2.796)
[37]=>
float(-2.923)
[38]=>
float(-3.782)
[39]=>
float(-3.903)
[40]=>
float(-5.822)
[41]=>
float(-8.118)
[42]=>
float(-9.945)
[43]=>
float(-10.614)
[44]=>
float(-10.422)
[45]=>
float(-10.206)
[46]=>
float(-9.688)
[47]=>
float(-8.467)
[48]=>
float(-6.384)
[49]=>
float(-3.67)
[50]=>
float(-1.779)
[51]=>
float(0.219)
[52]=>
float(2.138)
[53]=>
float(4.473)
[54]=>
float(6.088)
[55]=>
float(7.697)
[56]=>
float(8.306)
[57]=>
float(8.385)
[58]=>
float(8.493)
[59]=>
float(7.613)
[60]=>
float(5.639)
[61]=>
float(4.485)
[62]=>
float(3.425)
[63]=>
float(3.327)
}
[1]=>
array(40) {
[24]=>
float(4.437)
[25]=>
float(3.652)
[26]=>
float(1.899)
[27]=>
float(0.574)
[28]=>
float(-0.295)
[29]=>
float(-1.314)
[30]=>
float(-2.457)
[31]=>
float(-3.085)
[32]=>
float(-3.48)
[33]=>
float(-3.055)
[34]=>
float(-2.796)
[35]=>
float(-2.923)
[36]=>
float(-3.782)
[37]=>
float(-3.903)
[38]=>
float(-5.822)
[39]=>
float(-8.118)
[40]=>
float(-9.945)
[41]=>
float(-10.614)
[42]=>
float(-10.422)
[43]=>
float(-10.206)
[44]=>
float(-9.688)
[45]=>
float(-8.467)
[46]=>
float(-6.384)
[47]=>
float(-3.67)
[48]=>
float(-1.779)
[49]=>
float(0.219)
[50]=>
float(2.138)
[51]=>
float(4.473)
[52]=>
float(6.088)
[53]=>
float(7.697)
[54]=>
float(8.306)
[55]=>
float(8.385)
[56]=>
float(8.493)
[57]=>
float(7.613)
[58]=>
float(5.639)
[59]=>
float(4.485)
[60]=>
float(3.425)
[61]=>
float(3.327)
[62]=>
float(2.951)
[63]=>
float(2.758)
}
[2]=>
array(40) {
[24]=>
float(-4.437)
[25]=>
float(0.763)
[26]=>
float(2.538)
[27]=>
float(3.079)
[28]=>
float(2.194)
[29]=>
float(1.888)
[30]=>
float(2.162)
[31]=>
float(1.771)
[32]=>
float(1.023)
[33]=>
float(-0.03)
[34]=>
float(-0.684)
[35]=>
float(-0.133)
[36]=>
float(0.986)
[37]=>
float(0.98)
[38]=>
float(2.04)
[39]=>
float(4.215)
[40]=>
float(4.122)
[41]=>
float(2.496)
[42]=>
float(0.477)
[43]=>
float(-0.408)
[44]=>
float(-0.734)
[45]=>
float(-1.738)
[46]=>
float(-3.303)
[47]=>
float(-4.798)
[48]=>
float(-4.605)
[49]=>
float(-3.889)
[50]=>
float(-3.917)
[51]=>
float(-4.254)
[52]=>
float(-3.95)
[53]=>
float(-3.224)
[54]=>
float(-2.218)
[55]=>
float(-0.688)
[56]=>
float(-0.187)
[57]=>
float(0.772)
[58]=>
float(2.854)
[59]=>
float(3.127)
[60]=>
float(2.214)
[61]=>
float(1.159)
[62]=>
float(0.474)
[63]=>
float(0.569)
}
}
As is above, PHP returns an array containing 3 arrays. The documentation gives little hint as to what each array is, stating only that the MACD function
Returns an array with calculated data or false on failure.
A user contributed note (albeit one that has a score of -1) adds that the first array (index 0) is the MACD values, the second array (index 1) is the signal values, and the last array (index 2) is the divergence values.
Even if the users note is true, the returned arrays do not match my calculations (which I know to be correct). Why is trader_macd()
returning incorrect values/what am I doing wrong?
PHPs documentation of the trader functions contains little more than an argument list of each function. As a side note, is there anywhere I can get more detailed documentation for the trader extension? This is not the first time I have had trouble with a function in the extension.
I don't know PHP, but I can explain ta-lib behavior from C/C++ perspective. I've debugged its MACD with your dataset. If you call ta-lib's C function ta_macd()
for your data you'll get following.
macd signal hist
-3.08486 0.869685 -3.95455
-3.4801 -0.000272319 -3.47983
-3.05529 -0.611275 -2.44401
-2.79613 -1.04825 -1.74788
-2.92258 -1.42311 -1.49947
-3.78208 -1.89491 -1.88718
-3.90264 -2.29645 -1.60619
-5.82247 -3.00166 -2.82082
-8.11782 -4.02489 -4.09293
-9.9449 -5.20889 -4.73601
-10.6137 -6.28985 -4.32385
-10.4216 -7.11621 -3.30543
-10.2058 -7.73414 -2.47171
-9.68753 -8.12482 -1.56272
-8.46746 -8.19335 -0.274115
-6.38441 -7.83156 1.44715
-3.66972 -6.99919 3.32947
-1.77941 -5.95524 4.17582
0.218855 -4.72042 4.93927
2.13774 -3.34879 5.48653
4.47273 -1.78448 6.25722
6.08764 -0.210058 6.2977
7.69672 1.3713 6.32543
8.3057 2.75818 5.54752
8.38504 3.88355 4.50149
8.49283 4.80541 3.68743
7.61258 5.36684 2.24574
5.6388 5.42123 0.217565
4.48522 5.23403 -0.748811
3.42501 4.87223 -1.44722
3.32672 4.56312 -1.23641
2.95095 4.24069 -1.28974
2.75772 3.9441 -1.18637
It doesn't match your excel file bcs of following:
=AVERAGE(B19:B30)
in cell C30
and the excel results will match with C function results.E38-G70
.Well, that's how TA-Lib works as far as I can see. But if you compare my results with your PHP function results you'll find that they doesn't match too. But you can notice that my MACDs are equal to values in your 1st array starting from
[33]=>
float(-3.085)
And if you compare PHP results with Excel (updated) you'll find that first elements of 1st array are equal to E30-E37
. These are first 8 MACDs that TA-Libs omits as they don't have corresponding signal\hist values bcs signal is calculated with 9-days EMA. It also means following:
I would recommend looking inside PHP function source code. I couldn't find it. If you want to doublecheck vanilla C implementation of MACD in ta-lib, you shall refer to following pages: macd, ema.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With