Navigating through a series of both open and closed stock positions in an array or chain

I have a list of stock transactions that I need to process in order to determine the final position. The data is coming from a CSV file containing information on buys and sells. My goal is to loop through each transaction and calculate the remaining positions at the end.

At the end of the process, I want to generate an array with multiple objects, each describing a specific trade - for example: buying shares of Twitter (1 open trade), selling all purchased shares (closing the previous trade), making another purchase of Shop (1 open trade), selling a portion of those shares (updating the quantity of the previous trade and creating a new closed trade), then buying more shares and eventually selling all of them (creating a new open trade followed by closing all trades).

Here's an example from the CSV:

{
  Action: 'Buy',
  Symbol: 'SHOP',
  Quantity: '200',
  ...
},
{
  Action: 'Sell',
  Symbol: 'SHOP',
  Quantity: '200',
  ...
},
{
  Action: 'Buy',
  Symbol: 'SHOP',
  Quantity: '50',
  ...
},
{
  Action: 'Sell',
  Symbol: 'SHOP',
  Quantity: '25',
  ...
},
{
  Action: 'Sell',
  Symbol: 'SHOP',
  Quantity: '25',
  ...
},
{
  Action: 'Buy',
  Symbol: 'SHOP',
  Quantity: '1',
  ...
},

This data would be transformed into:

{
  stockTicker: 'SHOP',
  positionStatus: 'CLOSED',
  quantity: 200,
  ...
},
{
  stockTicker: 'SHOP',
  positionStatus: 'CLOSED',
  quantity: 25,
  ...
},
{
  stockTicker: 'SHOP',
  positionStatus: 'CLOSED',
  quantity: 25,
  ...
},
{
  stockTicker: 'SHOP',
  positionStatus: 'OPEN',
  quantity: 1,
  ...
}

The process seems simple if I use a recursive function. I can identify all open trades, match quantities to close trades, but then comes the challenge of handling partial quantity sales. How do I know when to stop iterating? At what point do I consider only open trades remaining as the correct result?

I'm facing uncertainty about knowing when to halt the iteration and search for matching positions.

Answer №1

Instead of using a recursive function, you can achieve the desired result by iterating through your trades array once to construct the positions object.

The trades.reduce(...) method processes the trades array and creates an object where keys represent unique symbols in trades, and values indicate the total quantity held.

The use of Object.entries and .map is optional and provides the convenience of converting the object into an array of objects.

const trades = [
{
  Action: 'Buy',
  Symbol: 'SHOP',
  Quantity: '200',
},
{
  Action: 'Sell',
  Symbol: 'SHOP',
  Quantity: '200',
},
{
  Action: 'Buy',
  Symbol: 'SHOP',
  Quantity: '50',
},
{
  Action: 'Sell',
  Symbol: 'SHOP',
  Quantity: '25',
},
{
  Action: 'Sell',
  Symbol: 'SHOP',
  Quantity: '25',
}
];

const positions = Object.entries(trades.reduce((acc, el) => {
  if (!acc[el.Symbol]) acc[el.Symbol] = 0;
  if (el.Action === "Sell") {
    acc[el.Symbol] -= Number(el.Quantity);
  } else {
    acc[el.Symbol] += Number(el.Quantity);
  }
  return acc;
}, {})).map(([Symbol, Quantity]) => ({Symbol, Quantity}));
console.log(positions);

Answer №2

In tackling this problem, I utilized two arrays: one for buy trades and another for sell trades. By iterating over both arrays, I closed positions that were complete and kept track of those with partial shares sold. Incorporating the Array.some() operator enabled me to streamline the code once the sell order was fully executed. It's worth noting that this solution is designed to handle multiple stock symbols.

Original Array:

investments = [{
  Action: 'Buy',
  Symbol: 'SHOP',
  Quantity: '200',
},{
  Action: 'Sell',
  Symbol: 'SHOP',
  Quantity: '200',
},{
  Action: 'Buy',
  Symbol: 'SHOP',
  Quantity: '50',
},{
  Action: 'Sell',
  Symbol: 'SHOP',
  Quantity: '25',
},{
  Action: 'Sell',
  Symbol: 'SHOP',
  Quantity: '25',
},{
  Action: 'Buy',
  Symbol: 'SHOP',
  Quantity: '1',
}];

Approach:

var buyTrades = investments
  .filter(trade => trade.Action === 'Buy')
  .map(trade => {
  return {
    stockSymbol: trade.Symbol,
    positionStatus: 'OPEN',
    quantity: trade.Quantity,
    remainingQuantity: Number(trade.Quantity)
  }
});

var sellTrades = investments
  .filter(trade => trade.Action === 'Sell')
  .map(trade => {
    return {
      stockSymbol: trade.Symbol,
      quantity: parseInt(trade.Quantity)
    }
});

sellTrades.forEach(sellTrade => {
  var currentSellQuantity = sellTrade.quantity;
  buyTrades.some(buyTrade => {
    if (buyTrade.positionStatus === 'OPEN' && currentSellQuantity !== 0) {
      if (parseInt(buyTrade.remainingQuantity) > currentSellQuantity) {
        buyTrade.remainingQuantity = buyTrade.remainingQuantity - currentSellQuantity;
        currentSellQuantity = 0;
      } else {
        buyTrade.positionStatus = 'CLOSED';
        currentSellQuantity = currentSellQuantity - buyTrade.remainingQuantity;
        delete buyTrade.remainingQuantity;
      }
    } 
    return currentSellQuantity === 0;
  });
});

console.log(buyTrades);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The Javascript code is malfunctioning

After delving into a more complex code structure for the first time, I find myself in a dilemma. My IDE claims it works fine, but jsfiddle disagrees by saying that only the two confirm functions - "confirmUserName();" and "confirmFullName();" are actually ...

What causes the absence of data in req.body after submitting a form in quiz.ejs?

app.js const express = require('express'); const mongoose = require('mongoose'); const path=require('path'); const app = express(); // Establish MongoDB connection async function initDatabase(){ await mongoose.connect(&ap ...

How can I implement Javascript for tracking webshop activity and affiliate links across multiple websites?

I operate a small front end for a webshop where I receive 5% of the sale amount for every customer who makes a purchase after being referred from my website. However, I am struggling to track these customers and need help in setting up a system to monitor ...

What is the most effective way to properly define class attributes?

Recently, I came across some code that I inherited and I'm currently working on getting it transpiled and up and running. So, as I was inspecting the components/TableAsset.tsx file, I stumbled upon these lines of code: import { Table } from "antd"; c ...

Populate the SPAN tag with the value selected from the dropdown

I'm fairly new to using jQuery and could use some guidance on a problem I'm facing. Within multiple LI items, each contains two SELECT elements. Upon clicking a button, I want to display two SPAN elements, each containing the value of one of the ...

Combine entities in Firebase when the names match

Currently, I am developing a simple shopping cart application. Whenever a user clicks on the Add To Cart button, I save the product in the database as an array item. If a user tries to add multiple items of the same product, I aim to group all products, ...

Error Encountered with Next.js 13.4.1 when using styled-components Button in React Server-Side Rendering

I am currently working on a React project using Next.js version 13.4.1 and styled-components. One problem I'm facing is with a custom Button component that I've created: import React from 'react'; import styled from 'styled-compone ...

"Unexpected compatibility issues arise when using TypeScript with React, causing errors in props functionality

Just the other day, my TypeScript+React project was running smoothly. But now, without making any changes to the configurations, everything seems to be broken. Even rolling back to previous versions using Git or reinstalling packages with NPM does not solv ...

Angular 6 tutorial: Creating a dynamic side navigation bar with swipe and drag functionality using Angular Material/Bootstrap

I am currently working on implementing a vertical swipeable/stretchable side nav-bar with angular-material in angular 6. However, I have encountered an issue with mouse interactions for stretching the nav-bar. Below is the code snippet: Here is the HTML c ...

Is it possible to establish multiple connections simultaneously using Stomp?

I have been utilizing the ng2-stomp-service in my Angular application. Is it advisable to set up multiple connections (not just multiple subscriptions)? In the past, I have always seen a single connection being established, with several subscriptions made ...

Locate the textbox that pertains to the element currently in focus

My HTML is structured as follows: <tr> <td colspan="2" class="borderBottomCell"> <div class="benefitInfo" style="WIDTH: 99%! important;"> <asp:DropDownList ...

Issues with invoking C# event through ajax communication

Whenever I click the Button, an Ajax method is called that triggers a webmethod on the server side. However, currently, the [WebMethod] is not being executed as expected. Below are the snippets of both the Ajax and server-side code: Ajax code $(document ...

Transforming a bitmap into a byte array, encoding it into a string, and then reversing the process

After experimenting with various methods from the java documentation and Stack Overflow, I managed to successfully convert a Bitmap into a byte[] and then back again. However, my current challenge is to now convert this byte[] into a String, then back int ...

Converting character array to a double after reading from a file

Currently, I'm in the process of reading a file that contains numbers separated by spaces. My goal is to store these numbers into an array of integers, but unfortunately, I seem to be doing something incorrectly because all I'm getting are zeros ...

Creating a fixed subarray in Java

Take a look at this code snippet: public class TestBench { private static final short matrix[][] = new short[][] {new short[] {}}; public static void main (String args[]) { matrix = new short[][] {new short[] {}}; // illegal matr ...

Is it possible to schedule a periodic GET request on the server-side without utilizing the client-side or frontend?

I am currently implementing a GET request to retrieve data from a third-party API. I want to regularly check for new data every 5-10 minutes on my backend. exports.get_alerts = async (req, res) => { const alertsUrl = `https://www.g2smart.com/g2smart/a ...

What could be the reason that the painting application is not functioning properly on mobile devices?

I am facing an issue with my painting app where it works perfectly on desktop browsers but fails to function on mobile devices. I tried adding event listeners for mobile events, which are understood by mobile devices, but unfortunately, that did not solve ...

How can I display the value entered in a text input field when using ajax upload?

Is there a way to display the value of an input type text when using ajax for file upload? I have successfully implemented code to upload files to a directory called attachments_files, but I am facing an issue. How can I retrieve and echo the value from i ...

What steps do I need to take in order to set up a private Git repository for my current project, specifically within a certain

Is there a way to set up a private Git Repository in Atom editor for a React Native project that I can share with just one other person, taking into account the project's specific local directory path? ...

Is there a discrepancy between the data posted using jQuery and the payload in Json?

Why is it that when I create a string in Jquery, the Chrome Javascript Debugger displays it like this: {"ClaimType":"Trade","ClaimedProductId":4,"ClaimingUserId":3,"Message":"","TradeOffers":"[{"OfferedProductId":"3","OfferedQuantity":"2"},{"OfferedProduc ...