backend/fastify/buy-stock/server.js
2024-05-26 19:51:33 +02:00

141 lines
4.7 KiB
JavaScript

// Declare a route
function processHoldingsList(holdings) {
const stockGroups = {};
for (const stock of holdings) {
if (stock.symbol in stockGroups) {
stockGroups[stock.symbol].totalCost += stock.boughtPrice * stock.numberOfShares;
stockGroups[stock.symbol].totalShares += stock.numberOfShares;
} else {
stockGroups[stock.symbol] = {
totalCost: stock.boughtPrice * stock.numberOfShares,
totalShares: stock.numberOfShares,
name: stock.name,
assetType: stock.assetType,
currentPrice: stock.currentPrice,
dailyChange: stock.dailyChange,
sinceBoughtChange: stock.sinceBoughtChange,
};
}
// Update dailyChange automatically
stockGroups[stock.symbol].dailyChange = stock.dailyChange;
stockGroups[stock.symbol].sinceBoughtChange = stock.sinceBoughtChange;
stockGroups[stock.symbol].currentPrice = stock.currentPrice;
}
const updatedHoldings = [];
for (const symbol in stockGroups) {
const { totalCost, totalShares, name, assetType, currentPrice, dailyChange, sinceBoughtChange } = stockGroups[symbol];
const finalBoughtPrice = totalCost / totalShares;
const updatedStock = {
symbol,
name,
assetType,
boughtPrice: finalBoughtPrice,
currentPrice,
dailyChange,
sinceBoughtChange: Number(((currentPrice/finalBoughtPrice -1) * 100)?.toFixed(2)),
numberOfShares: totalShares,
};
updatedHoldings.push(updatedStock);
}
return updatedHoldings;
}
module.exports = function (fastify, opts, done) {
const pb = opts.pb;
fastify.post('/buy-stock', async (request, reply) => {
const holidays = ['2024-01-01', '2024-01-15','2024-02-19','2024-03-29','2024-05-27','2024-06-19','2024-07-04','2024-09-02','2024-11-28','2024-12-25'];
const currentDate = new Date().toISOString().split('T')[0];
// Get the current time in the ET time zone
const etTimeZone = 'America/New_York';
const currentTime = new Date().toLocaleString('en-US', { timeZone: etTimeZone });
// Determine if the NYSE is currently open or closed
const currentHour = new Date(currentTime).getHours();
const isWeekend = new Date(currentTime).getDay() === 6 || new Date(currentTime).getDay() === 0;
const isBeforeMarketOpen = currentHour < 9 || (currentHour === 9 && new Date(currentTime).getMinutes() < 30);
const isAfterMarketClose = currentHour >= 16;
const isStockMarketOpen = !(isWeekend || isBeforeMarketOpen || isAfterMarketClose || holidays?.includes(currentDate));
let output;
if (isStockMarketOpen === true) {
const data = request.body;
const currentDate = new Date();
const year = currentDate.getFullYear();
const month = String(currentDate.getMonth() + 1).padStart(2, '0'); // Month is zero-based
const day = '01';
const formattedDate = `${year}-${month}-${day}`; // Output: "yyyy-mm-01"
const userId = data?.userId;
let newHolding = {'symbol': data['symbol'],
'name': data['name'],
'assetType': data['assetType'],
'numberOfShares': data['numberOfShares'],
'boughtPrice': data['boughtPrice'],
'currentPrice': data['boughtPrice'],
'dailyChange': 0,
'sinceBoughtChange': 0 }
let currentPortfolio = await pb.collection("portfolios").getList(1, 500, {
filter: `user="${userId}" && created >="${formattedDate}" `,
});
currentPortfolio = currentPortfolio?.items[0];
let holdings = currentPortfolio?.holdings || [];
let tradingHistory = currentPortfolio?.tradingHistory || [];
let availableCash = currentPortfolio?.availableCash - data['estimatedTotal'];
holdings.push(newHolding)
const updatedHoldings = processHoldingsList(holdings)
tradingHistory.push({'symbol': data['symbol'],
'name': data['name'],
'assetType': data['assetType'],
'numberOfShares': data['numberOfShares'],
'price': Number(data['boughtPrice']),
'type': 'buy',
'date': new Date()});
try {
await pb.collection("portfolios").update(currentPortfolio?.id, {
"holdings": updatedHoldings,
"availableCash": availableCash,
"tradingHistory": tradingHistory,
})
output = 'success';
} catch (err) {
output = 'failure'
}
}
else {
output = 'marketClosed'
}
reply.send({ items: output })
})
done();
};