The Formula call for variables. I've look all over and can't find what these variables are and what values they're supposed to represent.
RATE($nper, $pmt, $pv, $fv = 0.0, $type = 0, $guess = 0.1)
Is anyone familiar with this function? Do you know what values the variables are meant to represent?
From the Excel help file:
RATE(nper,pmt,pv,fv,type,guess)
For a complete description of the arguments nper, pmt, pv, fv, and
type, see PV.
Nper - is the total number of payment periods in an annuity.
Pmt - is the payment made each period and cannot change over the life of the annuity. Typically, pmt includes principal and interest
but no other fees or taxes. If pmt is omitted, you must include the fv
argument.
Pv - is the present value — the total amount that a series of future payments is worth now.
Fv - is the future value, or a cash balance you want to attain after the last payment is made. If fv is omitted, it is assumed to be 0 (the
future value of a loan, for example, is 0).
Type - is the number 0 or 1 and indicates when payments are due.
Set type equal to the following if payments are due:
0 or omitted - At the end of the period
1 - At the beginning of the period
Guess - is your guess for what the rate will be.
If you omit guess, it is assumed to be 10 percent.
If RATE does not converge, try different values for guess. RATE usually converges if guess is between 0 and 1.
Remark
Make sure that you are consistent about the units you use for
specifying guess and nper. If you make monthly payments on a four-year
loan at 12 percent annual interest, use 12%/12 for guess and 4*12 for
nper. If you make annual payments on the same loan, use 12% for guess
and 4 for nper
I dont know if you need to implement this function, but in any case, I looked at how this algorithm was built and even though I was not able to access the excel source code (or the google worksheet) I found that this is not a simple calculation. About this math, more can be read here:
https://brownmath.com/bsci/loan.htm#Eq8
The function, in PHP, may be something like this:
function rate($nprest, $vlrparc, $vp, $guess = 0.25) {
$maxit = 100;
$precision = 14;
$guess = round($guess,$precision);
for ($i=0 ; $i<$maxit ; $i++) {
$divdnd = $vlrparc - ( $vlrparc * (pow(1 + $guess , -$nprest)) ) - ($vp * $guess);
$divisor = $nprest * $vlrparc * pow(1 + $guess , (-$nprest - 1)) - $vp;
$newguess = $guess - ( $divdnd / $divisor );
$newguess = round($newguess, $precision);
if ($newguess == $guess) {
return $newguess;
} else {
$guess = $newguess;
}
}
return null;
}
Related
I am trying to figure out if there is a way to find the percentage between 2 numbers.
It's a progress / ranking system.
I want to find the percentage the $current_exp is between the $current_min and the $current_max values, is there a way to achieve this in PHP? So far I've got to this, but it doesn't work as you progress in ranks, it doesn't treat the $current_min as 0 so when you rank up, it says you are like 75% into your next rank progression when you're in fact 0. Does this make sense?
$currentProg = ($current_exp * 100) / $current_max;
Say the current minimum is 18750 and the current maximum is 25100, the current exp is 22000... What percentage from the min to the max is the current exp? This will change each rank as the $current_min and $current_max variables get set depending on the exp of the user.
The next rank is Current min is 25100 Current max is 34230
Currently, when you are at 26000 exp, the output is saying 75.956763073327% which is not correct, it should be like 1 or 2%?
Thanks in advance 🙏
Not a good mathematician, but it looks like it should be:
(Difference of rank - minimum) / (Difference of maximum - minimum) * 100
<?php
$x = 25100;
$z = 34230;
$y = 26000;
echo ($y - $x + 1) / ($z - $x + 1) * 100; // outputs 9.8674843938232 %
Online Demo
Note: + 1 is added to both numerator and denominator to avoid divide by zero errors.
First post, please be gentle.
I'm trying to create a simple market script where for example I have a number in my database ie 50.00 and I want to run a cron job php script to increase or decrease this randomly to a minimum of 10.00 and a maximum of 75.00.
I thought a random 0,1 follow by 2 if statements 1 rand(-0.01,0.05) if 2 rand(0.01,0.05) then $sql = "UPDATE price SET oil='RESULT'";
I've tried a few times at the above but I can't get it to run and the other crons in the file work.
<?php
//Get Oil Price from database
$oilchange = rand(1, 2);
if ($oilchange == '1') {
$oilnew = rand(0.01,0.05);
//Oil price from database times oil new.
} else {
$oilnew = rand(-0.01,-0.05);
//Oil price from database times oil new.
}
// Update Price
?>
Rand is for integers (whole numbers)
First up, your use of rand between two decimal values (called floats) won't work, as rand is for integers only. So, you'd first want to have a random function which does output floats, like this:
function randomFloat($min = 0, $max = 1) {
return $min + mt_rand() / mt_getrandmax() * ($max - $min);
}
Then we can safely use it between, say, 1% and 5%:
$percentSwing = randomFloat(0.01, 0.05);
Rand defaults to being 0 or 1. We can use that to randomly invert it, so we also cover -1% to -5%:
$percentSwing *= rand() ? 1 : -1;
The above could also be written like this:
if(rand() == 1){
// Do nothing:
$percentSwing *= 1;
}else{
// Invert it:
$percentSwing *= -1;
}
So, we now know how much we need to swing the number by. Let's say it was $oilPrice:
$oilPrice = 48;
We can just multiply the percent swing by that number to get the amount it's changing by, then add it back on:
$oilPrice += $percentSwing * $oilPrice;
So far so good! Now we need to make sure the price did not go out of our fixed range of 10 to 75. Assuming you want to 'clamp' the number - that means if it goes below 10, it's set at 10 and vice-versa, that's done like this:
if( $oilPrice < 10 ){
// It went below 10 - clamp it:
$oilPrice = 10;
}else if( $oilPrice > 75 ){
// It went above 75 - clamp it:
$oilPrice = 75;
}
The above can also be represented in one line, like this:
$oilPrice = max(10, min(75, $oilPrice));
So, that gives us the whole thing:
function randomFloat($min = 0, $max = 1) {
return $min + mt_rand() / mt_getrandmax() * ($max - $min);
}
// Define the oil price (e.g. pull from your database):
$oilPrice = 48;
// get a random 1% to 5% swing:
$percentSwing = randomFloat(0.01, 0.05);
// Invert it 50% of the time:
$percentSwing *= rand() ? 1 : -1;
// Swing the price now:
$oilPrice += $percentSwing * $oilPrice;
// Clamp it:
$oilPrice = max(10, min(75, $oilPrice));
// Output something!
echo $oilPrice;
As a side note here, money in real financial systems is never stored as a float, because rounding errors can cause major problems.
My question is how could I replace those if's with math formula?
if ($l <= 3500)
{
$min = 100;
}
elseif ($l <= 4000)
{
$min = 120;
}
elseif ($l <= 4500)
{
$min = 140;
}
elseif ($l <= 5000)
{
$min = 160;
}
As you see this is raising 20 for every 500 levels.
As you see this is raising 20 for every 500 levels.
Well, that's your formula right there.
$min = 100 + ceil(($l-3500)/500) * 20;
We start with 100, our base value and add that to the rest of the calculation.
$l starts with 3500 less.
We ceil() the result since we only want to jump when we pass the whole value.
We multiply that by 20.
If we want to address the case where $l is less than 3500 and set 100 as the minimum value, we also need to asset that $l-3500 is more than zero. We can do this as such:
$min = 100 + ceil(max(0,$l-3500)/500) * 20;
How did I get there?
What we're actually doing is plotting a line. Like you said yourself we go a constant amount for every constant amount. We have something called linear progression here.
Great, so we recognized the problem we're facing. We have an imaginary line to plot and we want integer values. What next? Well, let's see where the line starts?
In your case the answer is pretty straightforward.
if ($l <= 3500) {
$min = 100;
}
That's our starting point. So we know the point (3500,100) is on our line. This means the result starts at 100 and the origin starts at 3500.
We know that our formula is in the form of 100+<something>. What is that something?
Like you said, for every 500 levels you're raising 20. So we know we move 20/500 for every 1 level (because well, if we multiply that by 500 we get our original rule). We also know (from before) that we start from 3500.
Now, we might be tempted to use $min = 100 + ($l-3500) * (20/500); and that's almost right. The only problem here is that you only want integer values. This is why we ceil the value of level/500 to only get whole steps.
I tried to keep this with as little math terminology as possible, you can check the wikipedia page if you want things more formal. If you'd like any clarification - let me know
Here is my approach about this problem. It's not better than a single-line formula, but for sake of being modifiable, I generally decide this kind of solutions:
$min = 100;
for($i=3500; $i<=5000; $i+=500)
{
if($l <= $i) break;
$min += 20;
}
//Now $min has got desired value.
You can express the function as follows:
f(x) := a * x + b
The inclination of the line is calculated as:
a := 20 / 500
To find b you need to extrapolate a value that's on the line; in this case, that could be 3500 (x) and 120 (f(x)). That works out to be -40.
So the function has become:
f(x) := (20 / 500) * x - 40
There are two special cases:
Left of 3500 the value of f(x) must remain 100, even though f(x) is less.
The inclination is not continuous but discrete.
Both cases applied:
$min = max(100, ceil($l / 500) * 20 - 40)
I'm trying to create a dynamic point system based off of how much money is available in a bank account. For instance, if someone has 20 points and we have 100 dollars in the bank account, I want the formula to return something along the lines of $1.
I don't care too much about the ratio at this point - more about the formula to get there.
So far, I've come up with a handful of different formulas,
$val = (1 / $this->bank) * $amt; //goes the wrong way
$val = ($amt / $this->bank) * 5000; //isn't a good ratio
Assume val is the amount you can get with all the points, bank is how much is in the bank, and $amt is the amount of points the user has.
A gentle nudge in the right direction would be helpful!
Thanks!
$bank * ($points / 2000)
This satisfies your test case, giving 1 for $bank = 100 and $points = 20.
Saying $percentage is the percentage you want between your points and the bank account amount to have 1$ reward, you will have:
$percentage = 20;
$val = $amt * $this->bank / ($percentage * 100);
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.