I am tracking my trading portfolio in two arrays of objects.
The sells and the buys for a specific trade currency as follows:
var sell {
sold_amount: sold,
bought_amount: bought,
price : price
}
var buy {
sold_amount: sold,
bought_amount: bought,
price : price
}
I am trying to the following:
Calculate my win-lose percentage in a LIFO manner. That means that I want to take the latest sell I made and start subtracting the price/amount from the latest buy and then move backwards.
If my sell was big enough, it would mean that I would need to look not only on the previous buy, but I would need to search an unknown number of previous buys until all my sell amount is exhausted so that I can calculate my win/lose.
My difficulty is that since sells and buys are done on different amount/prices, it is really difficult for me to calculate the result.
That means for example:
I bought 20 units of $javascript paying 32 units of $c++ ,
I bought 17 units of $javascript paying 29 units of $c++ ,
I sold 57 units of $c++ paying 31 units of $javascript,
I bought 22 units of $javascript paying 22 units of c++,
I sold 12 units of c++ paing 11 units of $javascript,
That means that at every sell I would need to look backwards and see the price I bought it recursively and calculate the win/lose according to the amount sold/bought.
I am not looking for a solution, just some guidelines or some advice.
You could take the transactions and maintain two indicators for total units and total price. The selling price does not matter for the calculation of the actually bought products.
Please have a look to FIFO and LIFO accounting.
To get an actual value with some sold items, the last buy is checked and if the last amount of units is smaller or equal to the sold units, the total values are updated, as well as the actual unit, until all units are taken from the latest buy.
If some buy has a rest of units, then this information is added to the items array.
As result, a dynamic array is maintained with the last purchases buys and sales.
------------------
t o t a l
action units price calc price units price comment
-------- -------- -------- -------- -------- -------- -------- -----------------
buy 20 32 20 * 32 640 20 640
buy 17 29 17 * 29 493 37 1133
sell 22 22 -17 * 29 -493 20 640 take last first
- 5 * 32 -160 15 480 take next to last
buy 31 57 31 * 57 1767 46 2247
sell 11 12 -11 * 57 -627 35 1620
------------------
var transactions = [
{ action: 'buy', product: 'foo', units: 20, price: 32 },
{ action: 'buy', product: 'foo', units: 17, price: 29 },
{ action: 'sell', product: 'foo', units: 22, price: 22 },
{ action: 'buy', product: 'foo', units: 31, price: 57 },
{ action: 'sell', product: 'foo', units: 11, price: 12 }
],
accounts = {};
transactions.forEach(({ action, product, units, price }) => {
var last;
accounts[product] = accounts[product] || { items: [], totalUnits: 0, totalPrice: 0 };
if (action === 'buy') {
accounts[product].totalUnits += units;
accounts[product].totalPrice += units * price;
accounts[product].items.push({ units, price });
} else {
while (units) {
last = accounts[product].items.pop();
if (last.units <= units) {
accounts[product].totalUnits -= last.units;
accounts[product].totalPrice -= last.units * last.price;
units -= last.units;
continue;
}
accounts[product].totalUnits -= units;
accounts[product].totalPrice -= units * last.price;
last.units -= units;
units = 0;
accounts[product].items.push(last);
}
}
console.log(accounts);
});
.as-console-wrapper { max-height: 100% !important; top: 0; }