Code:
/*
avgx.cpp
A utility function for calculating flexible "averaging down" and "averaging up"
using an analytical method, ie. using a formula instead of a costly iterative method.
Written by: mutluit at tinystockexchange.com
2012-10-27-Sa
Platform: every modern C++ compiler should compile this. Tested with g++ on Debian GNU/Linux
Compile: g++ -o avgx.exe avgx.cpp
The math:
pps = (a*b + c*d) / (a+c) # a=qty1, b=price1, c=qty2, d=price2, pps=price per share
pl% = ((a+c)*d / (a*b + c*d) - 1.0) * 100 * (fShort ? -1.0 : 1.0)
--> (using solver at [url]www.quickmath.com[/url]):
#c = -(a*b*p - 100*a*d + 100*a*b) / (d*p)
c = -(a*b*p + (100*a*b - 100*a*d) * (fShort ? -1.0 : 1.0)) / (d*p)
d = -(a*b*p + 100*a*b * (fShort ? -1.0 : 1.0)) / (c*p - 100*a * (fShort ? -1.0 : 1.0))
Beware:
there is intentionally no plausibility of the user parameters built-in, ie. garbage in will give garbage out,
so test it throughly, if necessary add your own plausibility checks.
Examples:
./avgx.exe
gives
usage: avgx.exe curqty pricebought lastprice fShort wantPLpct
./avgx.exe 1000 100 90 0 -5
gives:
PLpct=-10.00 AddQty=1111.11 PLpctNew=-5.00 pps=94.7368
./avgx.exe 1000 100 110 1 -5
gives
PLpct=-10.00 AddQty=909.09 PLpctNew=-5.00 pps=104.7619
But the following parameter set will give, in the context of financial instruments, a nonsensical result,
although the method is correct, but the input is wrong:
./avgx.exe 1000 100 110 0 -5
gives
PLpct=10.00 AddQty=-2727.27 PLpctNew=-5.00 pps=115.7895
*/
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
int avgx(const double AdbQty0, const double AdbPrice0, const double AdbPrice, const bool AfShort, const double AdbWantPLpct)
{ // rc: 0=ok
const double& a = AdbQty0;
const double& b = AdbPrice0;
const double& d = AdbPrice;
const double& p = AdbWantPLpct;
double c = 0;
const double plpct1 = ((a+c)*d / (a*b + c*d) - 1.0) * 100 * (AfShort ? -1.0 : 1.0);
c = -(a*b*p + (100*a*b - 100*a*d) * (AfShort ? -1.0 : 1.0)) / (d*p);
const double plpct2 = ((a+c)*d / (a*b + c*d) - 1.0) * 100 * (AfShort ? -1.0 : 1.0);
const double pps = (a*b + c*d) / (a+c);
printf("PLpct=%.2lf AddQty=%.2lf PLpctNew=%.2lf pps=%.4lf\n", plpct1, c, plpct2, pps);
return 0;
}
int main(int argc, char* argv[])
{ // rc: 0=ok
if (argc < 6)
{
printf("usage: avgx.exe curqty pricebought lastprice fShort wantPLpct\n");
return 1;
}
int ixArg = 0;
const double AdbQty0 = atof(argv[++ixArg]);
const double AdbPrice0 = atof(argv[++ixArg]);
const double AdbPrice = atof(argv[++ixArg]);
const bool AfShort = !!atoi(argv[++ixArg]);
const double AdbWantPLpct = atof(argv[++ixArg]);
return avgx(AdbQty0, AdbPrice0, AdbPrice, AfShort, AdbWantPLpct);
}
