How to calculate MACD using PHP? - php

I get similar MACD and Signal values, using the following class in Binance:
I got this code from:
https://github.com/hurdad/doo-forex/blob/master/protected/class/Technical%20Indicators/MACD.php
How can I modify the class to arrive at the exact value?

You can use the php-trader lib, note that it works as CLI only.
But this is fairly simple math:
MACD = EMA26 - EMA12

/*
* Exponential moving average (EMA)
*
* The start of the EPA is seeded with the first data point.
* Then each day after that:
* EMAtoday = α⋅xtoday + (1-α)EMAyesterday
*
* where
* α: coefficient that represents the degree of weighting decrease, a constant smoothing factor between 0 and 1.
*
* #param array $numbers
* #param int $n Length of the EPA
* #return array of exponential moving averages
*/
function exponentialMovingAverage( $numbers, $n)
{
$m = count($numbers);
$α = 2 / ($n + 1);
$EMA = [];
// Start off by seeding with the first data point
$EMA[] = $numbers[0];
// Each day after: EMAtoday = α⋅xtoday + (1-α)EMAyesterday
for ($i = 1; $i < $m; $i++) {
$EMA[] = ($α * $numbers[$i]) + ((1 - $α) * $EMA[$i - 1]);
}
return $EMA;}

Related

Count by formula on php

I want to ask your help. I don't remember the Math, but I need to count by formula
I am going to make the loops like that.
$incomeDepositDay = $totalSum * $percent / ($typePerm *100);
for ($i = 1; $i <= $term; $i++) {
$incomeDepositTax = $percent/100 * $typePerm * ($totalSum * $i + ($incomeDepositDay * (1 - 13/100)));
}
But I see, that my code isn't correct. But I don't understand, where?
You don't need a loop, as the formula is a straightforward calculation.
You have a couple of errors in your sum. Try:
$incomeDepositDay = $totalSum * $percent / ($typePerm *100);
$incomeDepositTax = $percent/(100 * $typePerm) * ($totalSum * $i + ($i - 1) * $incomeDepositDay * (1 - 13/100));

Linear Regression without using R

I have a task which requires to generate the slope and interception of two sets of data by linear regression. According to the following link, it can be easily accomplished by R:
https://www.datacamp.com/community/tutorials/linear-regression-R
The codes are simply like
model <- lm(sales ~ youtube, data = marketing)
However, I will need to implement it in PHP. Is it possible ?
Normally you can do such operation easily in R.
But since you said you have to do it this time in PHP. You may use the following function:
<?php
function linear_regression($x, $y) {
// calculate number points
$n = count($x);
// ensure both arrays of points are the same size
if ($n != count($y)) {
trigger_error("linear_regression(): Number of elements in coordinate arrays do not match.", E_USER_ERROR);
}
// calculate sums
$x_sum = array_sum($x);
$y_sum = array_sum($y);
$xx_sum = 0;
$xy_sum = 0;
for($i = 0; $i < $n; $i++) {
$xy_sum+=($x[$i]*$y[$i]);
$xx_sum+=($x[$i]*$x[$i]);
}
// calculate slope
$m = (($n * $xy_sum) - ($x_sum * $y_sum)) / (($n * $xx_sum) - ($x_sum * $x_sum));
// calculate intercept
$b = ($y_sum - ($m * $x_sum)) / $n;
// return result
return array("m"=>$m, "b"=>$b);
}
?>
As an example, you may use the following codes to get the slope and intercept of the two sets of data:
$a=array();
$b=array();
array_push($a,$adata1);
array_push($a,$adata2);
array_push($a,$adata3);
array_push($a,$adata4);
array_push($b,$bdata1);
array_push($b,$bdata2);
array_push($b,$bdata3);
array_push($b,$bdata4);
$aa= linear_regression($a, $b);
$slope1= $aa["m"];
$intercept1= $aa["b"];

Calculating The Percentage Change Between Two Numbers

Looking for some clarification on below code for calculating the percentage change between two different number of which the original could be a greater or smaller number. So will this code work for showing either a increase + or a decrease - change? Thanks.
$original= 100;
$current = 95;
$percentChange = (1 - $original / $current ) * 100;
Find difference and then count percentage like this
<?php
$original= 100;
$current = 115;
$diff = $current - $original;
$more_less = $diff > 0 ? "More" : "Less";
$diff = abs($diff);
$percentChange = ($diff/$original)*100;
echo "$percentChange% $more_less agaist $original";
?>
Difference will be same for 110 and 90 against 100
Live demo : https://eval.in/872926
This function is more useful because it is protects from division by zero, the output is roundable, and it handles both positive (increase) and negative (decrease) return values.
if (! function_exists('pct_change')) {
/**
* Generate percentage change between two numbers.
*
* #param int|float $old
* #param int|float $new
* #param int $precision
* #return float
*/
function pct_change($old, $new, int $precision = 2): float
{
if ($old == 0) {
$old++;
$new++;
}
$change = (($new - $old) / $old) * 100;
return round($change, $precision);
}
}
Yes, it will work for showing either a increase + or a decrease - change.

Implementing Vincenty's Formula in PHP

I've been attempting to implement Vincenty's formulae with the following:
/* Implemented using Vincenty's formulae from http://en.wikipedia.org/wiki/Vincenty%27s_formulae,
* answers "Direct Problem".
* $latlng is a ('lat'=>x1, 'lng'=>y1) array
* $distance is in miles
* $angle is in degrees
*/
function addDistance($latlng, $distance, $bearing) {
//variables
$bearing = deg2rad($bearing);
$iterations = 20; //avoid too-early termination while avoiding the non-convergant case
//knowns
$f = EARTH_SPHEROID_FLATTENING; //1/298.257223563
$a = EARTH_RADIUS_EQUATOR_MILES; //3963.185 mi
$phi1 = deg2rad($latlng['lat']);
$l1 = deg2rad($latlng['lng']);
$b = (1 - $f) * $a;
//first block
$tanU1 = (1-$f)*tan($phi1);
$U1 = atan($tanU1);
$sigma1 = atan($tanU1 / cos($bearing));
$sinalpha = cos($U1)*sin($bearing);
$cos2alpha = (1 - $sinalpha) * (1 + $sinalpha);
$usquared = $cos2alpha * (($a*$a - $b*$b) / 2);
$A = 1 + ($usquared)/16384 * (4096+$usquared*(-768+$usquared*(320 - 175*$usquared)));
$B = ($usquared / 1024)*(256*$usquared*(-128 + $usquared * (74 - 47*$usquared)));
//the loop - determining our value
$sigma = $distance / ($b * $A);
for($i = 0; $i < $iterations; ++$i) {
$twosigmam = 2*$sigma1 + $sigma;
$delta_sigma = $B * sin($sigma) * (cos($twosigmam)+(1/4)*$B*(cos(-1 + 2*cos(cos($twosigmam))) - (1/6)*$B*cos($twosigmam)*(-3+4*sin(sin($sigma)))*(-3+4*cos(cos($twosigmam)))));
$sigma = $distance / ($b * $A) + $delta_sigma;
}
//second block
$phi2 = atan((sin($U1)*cos($sigma)+cos($U1)*sin($sigma)*cos($bearing)) / ((1-$f) * sqrt(sin($sinalpha) + pow(sin($U1)*sin($sigma) - cos($U1)*cos($sigma)*cos($bearing), 2))));
$lambda = atan((sin($sigma) * sin($bearing)) / (cos($U1)*cos($sigma) - sin($U1)*sin($sigma)*cos($bearing)));
$C = ($f / 16)* $cos2alpha * (4+$f*(4-3*$cos2alpha));
$L = $lambda - (1 - $C) * $f * $sinalpha * ($sigma + $C*sin($sigma)*(cos($twosigmam)+$C*cos($sigma)*(-1+2*cos(cos($twosigmam)))));
$alpha2 = atan($sinalpha / (-sin($U1)*sin($sigma) + cos($U1)*cos($sigma)*cos($bearing)));
//and return our results
return array('lat' => rad2deg($phi2), 'lng' => rad2deg($lambda));
}
var_dump(addDistance(array('lat' => 93.129, 'lng' => -43.221), 20, 135);
The issue is that the results are not reasonable - I'm getting variances of up to 20 latitude and longitude keeping the distance at 20. Is it not in units of elliptical distance on the sphere? Am I misunderstanding something, or is my implementation flawed?
There are a number of errors in transcription from the wikipedia page Direct Problem section:
Your u2 expression has 2 in the denominator where it should have b2;
Your A and B expressions are inconsistent about whether the initial fraction factor needs to be parenthesised to correctly express a / b * c as (a/b) * c - what happens without parentheses is a php syntax issue which I don't know the answer to, but you should favour clarity;
You should be iterating "until there is no significant change in sigma", which may or may not happen in your fixed number of iterations;
There are errors in your DELTA_sigma formula:
on the wikipedia page, the first term inside the square bracket [ is cos sigma (-1 etc, whereas you have cos (-1 etc, which is very different;
in the same formula and also later, note that cos2 x means (cos x)(cos x), not cos cos x!
Your phi_2 formula has a sin($sinalpha) where it should have a sin($sinalpha)*sin($sinalpha);
I think that's all.
Have you tried this:
https://github.com/treffynnon/Geographic-Calculations-in-PHP

Does PHP's range('A', 'Z') return a static array?

I was overlooking some code that I had written to generate an A-Z navigation on a product page, and the method in which it was done was a for loop; using ascii octals 65-91 and PHP's chr() function. I wondered if there was a simpler and/or more efficient way of doing this, and I discovered that PHP's range() function supports alphabetical ranges.
After I wrote my test code to compare the different methods, a few questions came to mind:
Does PHP store a static array of the alphabet?
How can I profile more deeply to look below the PHP layer to see
what's happening?
I have a cachegrind of the PHP script that can be attached if necessary, in addition to environment config. For those who might want to know the machine specs in which it was executed, here are some links:
root#workbox:~$ lshw
http://pastebin.com/cZZRjJcR
root#workbox:~$ sysinfo
http://pastebin.com/ihQkkPAJ
<?php
/*
* determine which method out of 3 for returning
* an array of uppercase alphabetic characters
* has the highest performance
*
* +++++++++++++++++++++++++++++++++++++++++++++
*
* 1) Array $alpha = for($x = 65; $x < 91; $x++) { $upperChr[] = chr($x); }
* 2) Array $alpha = range(chr(65), chr(90);
* 3) Array $alpha = range('A', 'Z');
*
* +++++++++++++++++++++++++++++++++++++++++++++
*
* test runs with iterations:
*
* 10,000:
* - 1) upperChrElapsed: 0.453785s
* - 2) upperRangeChrElapsed: 0.069262s
* - 3) upperRangeAZElapsed: 0.046110s
*
* 100,000:
* - 1) upperChrElapsed: 0.729015s
* - 2) upperRangeChrElapsed: 0.078652s
* - 3) upperRangeAZElapsed: 0.052071s
*
* 1,000,000:
* - 1) upperChrElapsed: 50.942950s
* - 2) upperRangeChrElapsed: 10.091785s
* - 3) upperRangeAZElapsed: 8.073058s
*/
ini_set('max_execution_time', 0);
ini_set('memory_limit', 0);
define('ITERATIONS', 1000000); // 1m loops x3
$upperChrStart = microtime(true);
for($i = 0; $i <= ITERATIONS; $i++) {
$upperChr = array();
for($x = 65; $x < 91; $x++) {
$upperChr[] = chr($x);
}
}
$upperChrElapsed = microtime(true) - $upperChrStart;
// +++++++++++++++++++++++++++++++++++++++++++++
$upperRangeChrStart = microtime(true);
for($i = 0; $i <= ITERATIONS; $i++) {
$upperRangeChr = range(chr(65), chr(90));
}
$upperRangeChrElapsed = microtime(true) - $upperRangeChrStart;
// +++++++++++++++++++++++++++++++++++++++++++++
$upperRangeAZStart = microtime(true);
for($i = 0; $i <= ITERATIONS; $i++) {
$upperRangeAZ = range('A', 'Z');
}
$upperRangeAZElapsed = microtime(true) - $upperRangeAZStart;
printf("upperChrElapsed: %f\n", $upperChrElapsed);
printf("upperRangeChrElapsed: %f\n", $upperRangeChrElapsed);
printf("upperRangeAZElapsed: %f\n", $upperRangeAZElapsed);
?>
Does PHP waste memory keeping an array of letters? I would doubt it. range() will work on a wide variety of values too.
If performance is an issue in such a case, you might want to declare the array outside of the loop so that it can be re-used. However, large gains rarely come from micro-optimizations. Using profiling on larger applications to get significant gains.
As for profiling at a lower level, you can simply use valgrind on PHP CLI. I've also seen it used on an apache process.
Related: How to profile my C++ application on linux

Categories