calculating cumulative average growth rate in PHP - php

I am trying to compare the performance of 2 investments by calculating back the cumulative average growth rate.
I have found this formula which works perfectly in excel but I cannot get it to work in php...it simply returns '0' every time:
CAGR = (Xn/X0)^(1/t) - 1
where:
Xn = current market value of portfolio
X0 = initial portfolio's value
t = number of years
Any help is greatly appreciated. Thanks.

You can try Exponential expression function pow()
CAGR = pow(($Xn/$X0),(1/$t)) - 1

This should works:
$Xn = 123; // current market value of portfolio
$X0 = 50; // initial portfolio's value
$t = 5; // number of years
$CAGR = pow( ($Xn / $X0), (1 / $t) ) - 1 ;
print($CAGR);

Related

Trading view vs Binance DMI calculation?

I'm trying to calculate the directional movement indicator for 5m interval using the API of Binance. I'm using 288 values of "High", "Open" and "Close" and
I'm calculating the True range and then the Average True Range (ATR) with a simple moving average of a window with 14 values. I'm using the same Simple Moving average technique
for the calculation of the +DI, -DI and the ADX, but the values that I get don't match the ones that are shown in trading view for the DMI. I have also tried using an
exponential moving average the ATR, the +Di and the -DI, but I still don't get matching values. I have also noticed that the DMI of Binance and Trading view do not match.
Do you know which smoothing techinique is used by the DMI of trading view?
$url = 'https://api.binance.com/api/v3/klines?symbol=BNBBTC&interval=5m&limit=288';
$candles = file_get_contents($url);
$candles = json_decode($candles, true);
$arr_results = array();
$high = array();
$low = array();
$close_arr = array();
$average = array();
for($i= 0; $i < sizeof($candles); $i++){
array_push($high, $candles[$i][2]);
array_push($low, $candles[$i][3]);
array_push($close_arr, $candles[$i][4]);
$av = ($candles[$i][2] + $candles[$i][3]) /2;
array_push($average, $av);
}
$plus_di = array_pop(trader_plus_di($high, $low, $close_arr, 14));
$minus_di = array_pop(trader_minus_di($high, $low, $close_arr, 14));
$adx = array_pop(trader_adx ($high, $low, $close_arr, 14));
To calculate the ATR, you need to smooth the TR (True Range) according to the following method :
Take a smoothing period nbCandles (nbCandles=14 candles typically), then:
First ATR value: ATR(1) = Sum{TR(1 -> nbCandles)} (i.e you sum the nbCandles first values of the TR to get your first value of the ATR) - If nbCandles = 14 then your first ATR value will be the sum of the first 14 values of TR.
Then, for the following ATR values, you use the following formula:
ATR(i) = ATR(i-1) - ATR(i-1)/nbCandles + TR(i)
Here is an example (based on 30 1 minutes candles historical record and 14 as the smoothing factor (number of candles used for smoothing)) :
Binance BTCUSDT 1m

Calculate a given number to a percentage between two given numbers [duplicate]

This question already has answers here:
Negative & Positive Percentage Calculation
(6 answers)
Closed 1 year ago.
I'm trying to work out a percentage between two numbers by providing the number of which the percentage should be based (can't find this on Stack overflow - only percentage between two numbers).
Let me explain:
$start_number = 14700
$end_number = 14900
// This is the number to calculate a percentage for
// in this basic example this should come to 50%
$percentage_number = 14800
I know what I need to do but can't figure out how to write it:
Where $start_number is 0%
And $end_number is 100%
$percentage_number = X%
$difference = $end_number - $start_number; // 200
$difference_from_start = $end_number - $percentage_number; // 100
$percentage = $difference_from_start / $difference; // 0.5 (50%)
Is it what you want?
Well this is quite simple:
$start_number = 14700;
$end_number = 14900;
$percentage_number = 14800;
$result = (($end_number - $percentage_number) * 100) / ($end_number - $start_number);
echo $result;
OUTPUT:
50
I thik that the solution formula would be:
percentage = 100 * (percentage_number - start_number) / (end_number - start_number)
In that case $percentage_number should not be less than $start_number else the percentage will calculated in negative.
You can use the below formula:
( ($percentage_number - $start_number) / ($end_number - $start_number) ) * 100 ;
Hope it'ill help you.
Let's say you have two numbers, 40 and 30.
30/40*100 = 75.
So 30 is 75% of 40.
40/30*100 = 133.
So 40 is 133% of 30.
The percentage increase from 30 to 40 is:
(40-30)/30 * 100 = 33%
The percentage decrease from 40 to 30 is:
(40-30)/40 * 100 = 25%.
These calculations hold true whatever your two numbers.
In PHP
$oldFigure = 14;
$newFigure = 12.50;
$percentChange = (1 - $oldFigure / $newFigure) * 100;
echo $percentChange;
diff = $end_number - $start_number
(diff is now = 200)
mid = $end_number - (your number)
(mid is now = 100)
res = (mid / diff) * 100
(res is now = 50%)
If the scale begins at $start_number and ends at $end_number, its size is $end_number-$start_number. If $percentage_number is in the scale, it's $percentage_number-$start_number units from the start into the scale. Therefore, the relative ratio in the scale being:
($percentage_number-$start_number)/($end_number-$start_number)
Multiply by 100 and you'll get the percentage.

PHP Pow Function a reverse required

I have something with pow I need to return a whole inter for different results (reversed basically)
For Example (rounded to 4 decimals):
<?php
$var = 10 * pow(1.01,0); // = 10
$var = 10 * pow(1.01,1); // = 10.1
$var = 10 * pow(1.01,2); // = 10.201
$var = 10 * pow(1.01,3); // = 10.303
etc
How could I return the whole number for 10.1150 = 1 since it is above 10 * pow(1.01,1); and below 10 * pow(1.01,2);
The 1.01 can also be a number of variables, (percentage scaled point and figure charting), why I need the Whole number only of the percentage differences (1 box = 1 percentage change from the box above or below)
Thanks much all, I've battled with this issue in many different ways including x all price data points for 250 percentage changed into an array, that is fast, except to build the array becomes the slow issue. if else is the current solution but for 2500 price points on 250 charts = 2 seconds just to find a plot point, considering I'm doing 10's of millions of charts daily, 2 seconds = a lot of time accumulated.
Have you tried using log? It's the reverse of the pow function.
$orig = floor(log($var/10,1.01));

Round integer to nearest multiple of 5 in PHP

Searching for a function ro round numbers to the nearest multiple of 5
22 -> 20
23 -> 25
40 -> 40
46 -> 45
48 -> 50
and so on.
Tried this which always returns the higher value:
5 * ceil($n / 5);
Use round() instead of ceil().
5 * round($n / 5);
ceil() rounds a floating point number up to its next integer in sequence. round() will round to the nearest integer using standard rounding rules.
Back to maths, since round works with decimals, multiply by 5 and divide by 10 and then round, it. Multiply by 5 again to get what u want. (Other answer works as well, just a different way of looking at it)
function round_5($in)
{
return round(($in*2)/10)*5;
}
echo round_5(48);
See if this helps
Well, facing this issue while helping make an POS for a Canadian company, came up with this solution, hope it helps someone. (Canada removed the penny in 2012). Also includes for doing tax included pricing, just pass '1' as second argh.
//calculate price and tax
function calctax($amt,$tax_included = NULL){
$taxa = 'tax rate 1 here';
$taxb = 'tax rate 2 here';
$taxc = ($taxa + $taxb) + 1;
if(is_null($tax_included)){
$p = $amt;
}else{
$p = number_format(round($amt / $taxc,2),2);
}
$ta = round($p * $taxa,2);
$tb = round($p * $taxb,2);
$sp = number_format(round($p+($ta + $tb),2),2);
$tp = number_format(round(($sp*2)/10,2)*5,2);
$ret = array($ta,$tb,$tp);
return $ret;
}

Generate a fictitious stock option price variation

What I do
I am making graph of fictitious stock options.
The price is updated each second, with this function
function stockVariation($price,$max_up,$max_down)
{
// Price > 1
if($price > 1)
{
// Calculate
$ratio=(mt_rand(0,$max_up/2)-mt_rand(0,$max_down/2))/1000;
$price+=$ratio;
}
// Price <=1 (we don't want 0 or negative price...)
else
$price+=mt_rand(1,$max_up)/1000;
return round($price,3);
}
I use a max_up and max_down values (from 10 to 100) to make the price change progressively and simulate some volatility.
For example, with max_up : 40 and max_down : 45, the price will progressively go down.
My question
But the problem, is that prices generated are too much volatile, even if max_up = max_down.
The result is "non-natural". (for example +10 points in one day for a base price of 15,000).
Result of price evolution per hour in 24 hour
Perhaps making round($price,4) and divisions by 10 000 instead of 1 000, will be better ?
If anyone have an idea or an advice to generate "natural" prices evolution, thanks in advance.
There are 86400 seconds in a day, so you'll need to divide by a much larger number. And rather than adding and subtracting, you may want to multiply the current price by a factor that's slightly larger or smaller than 1. That would simulate a percentage increase or decrease, rather than an absolute gain or loss.
function stockVariation($price, $max_up, $max_down)
{
// Convert up/down to fractions of the current price.
// These will be very small positive numbers.
$random_up = mt_rand(0, $max_up) / $price;
$random_down = mt_rand(0, $max_down) / $price;
// Increase the price based on $max_up and decrease based on $max_down.
// This calculates the daily change that would result, which is slightly
// larger or smaller than 1.
$daily_change = (1 + $random_up) / (1 + $random_down);
// Since we're calling this function every second, we need to convert
// from change-per-day to change-per-second. This will make only a
// tiny change to $price.
$price = $price * $daily_change / 86400;
return round($price, 3);
}
Building upon the idea, you could use an actual volatility number. If you want e.g. a volatility of 35%/year, you can find the volatility per second. In pseudocode:
vol_yr = 0.35
vol_month = vol_yr * sqrt(1.0/12)
vol_second = vol_yr * sqrt(1.0/(252 * 86400)) # or 365 * 86400
Then, every second, you "flip a coin" and either multiply or divide current stock price by (1 + vol_second). This is the principle of how binomial trees are created to evaluate exotic stock options.

Categories