Skip to Main Content

Data Structures

Computer Science Department

Stock Market - 107 Course Points

Overview

A stock market is an economic network where consumers can buy and sell ownership shares (aka stocks) of companies. Companies sell stocks in order to raise money for growth, and investors buy stocks as a means of financial investment. Companies first offer their stocks via an Initial Public Offering, where investors may buy shares directly from the company. After that, stocks are traded among investors on a stock exchange. Trading between investors on stock exchanges is what most people are familiar with when they hear “Stock Market”.

The concept of stock markets has been around for hundreds of years, dating back to trading shares and debts in ancient civilizations. The first modern stock market was the Amsterdam Stock Exchange in 1602. The New York Stock Exchange (NYSE) is the market which currently has the highest market cap value ($31.7 trillion dollars), although there are many other similar and popular stock exchanges such as NASDAQ, Shanghai Stock Exchange, and Japan Exchange Group. 

This assignment will simulate a small stock exchange, where stocks are sold and bought between investors. Your job is to create and maintain an array of Stock data, then process and record BUY/SELL transactions. Once implemented, the included Driver will allow you to play this simulation by buying and selling stocks each day in order to maximize your profit.

Provided Classes

StockMarket.java is where you will code your simulation. There are three data structures you will implement: the stockData array, the portfolio list, and the transactions list.

The StockMarket class also holds the following instance variables:

     – private double balance;

     – private int currentDay;

     – private int transactionCount;

     – private int numHoldings;

You will code methods to readStockData(), buy/sell stocks, add transactions, and calculate statistics.

The following classes are provided to you, and comprise the OOP representation of the stock market:  

Driver.java  can be used to test your program, by interacting with the stock market simulation. Each method implements a crucial part of the Driver, although you can test many of them along the way as you work.

StdIn.java / StdOut.java are the IO libraries we use to read from input files.

Stock.java represents one company listed on the stock market, with the price history contained in it. It does not represent an investor’s share in the company.

Holding.java is the investors share in a company’s stock. It contains attributes for quantity, the holding ID, the cost of the holding, and purchase day. Note that one investor can hold multiple different holdings of the same company, at different prices/purchase times. 

Transaction.java stores information regarding a single buy or sell transaction the investor makes on the market. It stores info about the transaction type, date, stock, quantity, price, and total cost.

Note that: Transaction.java, Stock.java, and Holding.java all have the extends keyword in their class declarations.

  • Transaction extends Comparable112<Transaction>
  • Stock extends Comparable112<Stock>
  • Holding extends Comparable112<Holding

This simply means that each of these classes must implement the equals(), toString(), and compareTo() methods. These are provided for you, but may be useful.

Working with LLNode<> objects

For assignments/labs in CS112, we will use a cs112.jar file containing useful classes. This includes the LLNode<> class, which implements a singly linked list node.

  • The LLNode class takes in a generic type, which means it can store any type of data.
    • Making a node: LLNode<T> newNode = new LLNode<T>(data) (replace T with a type)
    • Note that the data must be passed in for the constructor, and the data of a node can not be changed later (aka it is immutable)
  • Methods:
    • getNext() – returns the next node in the linked list
    • getData() – returns the data stored in the current node
    • setNext(LLNode<T> nextNode) – sets the next node of the current node to nextNode

In this assignment, you will use LLNodes for the portfolio list of Holding objects and the transactions list of Transaction objects.

Input Files

Multiple csv input files are included; they store information regarding stocks and their prices across a select range of dates. You are welcome to create your own input files, as they will not be submitted to Autolab.

 stock_data.csv contains 5 years worth of NASDAQ data (July 9, 2020 – July 10, 2025)

  • Microsoft, Apple, Alphabet (Google), Meta, Amazon, Tesla, Coca-Cola, Netflix, Disney, Nike, Hershey, Hasbro, Capital One, Verizon, UPS, Best Buy, Nintendo, Spotify, Gamestop

Each input file is a CSV (Comma Separated Values) file,  where each line corresponds to one stock, and within each line the commas separate the different historical stock prices.

The first line of the input file contains an integer, corresponding to the number of unique stock symbols contained in the file.

Each following line then contains a Stock symbol, followed by its historical prices (double). The symbol, as well as each price, are separated by commas.

SONY,14.306,14.788,14.872,14.904, …

You will use this information to build the stockData array, which is the backbone of the simulation.

Directions

  • DO NOT add new import statements.
  • DO NOT add any new class attributes
  • DO NOT change any of the method’s signatures.
  • DO NOT modify the given constructor.

To complete this Lab, you will fill in StockMarket.java with methods to read, maintain, and analyze the Stock array as well as the Linked List transactions and holdings data structures.

To Run: run the following commands from the innermost StockMarket directory, containing the src and bin folders.

  • Compile:
    • javac -d bin -cp lib/cs112.jar src/market/*.java
    • (If you get a warning for unchecked operations then ignore it, dont use Xlint) 
  • Run:
    • Windows: java -cp “lib/cs112.jar;bin” market.Driver
    • Mac/Linux: java -cp bin:lib/cs112.jar market.Driver

readStockData(String inputFile)

This method initializes the stockData instance variable with the provided data from the input CSV file. Files in CSV format are plain text files that store data by delimiting data entries with commas.

Use the StdIn library to read from a file:

    • StdIn.setFile(inputFile) opens a file to be read. 
    • StdIn.readLine() reads the whole next line
    • StdIn.hasNextLine() returns true if there is another line in the file

To Complete This Method:

  1. Set StdIn to read from the given inputFile, and read the first line, and parse it using Integer.parseInt(). 
  2. Initialize the stockData array to a new Stock[], with the length you read in. Also create an int stockIndex var, and set it to 0.
  3. Loop through the lines of the input file. Split each using the .split(“,”) method, which returns a String[] array of the values for each line. Note that the numbers will be read as strings for now, you will parse them to doubles afterwards. 
    1. The first index will be the stock symbol.
    2. The rest of the indices, 1 to (length-1), will be the price values, from oldest to newest.
  4. For each line, create a double[] and loop over the prices, using Double.parseDouble() to populate the double array with the corresponding values. 
  5. Finally, create a Stock object with the symbol and prices, and insert it at the stockIndex in stockData. Increment your stockIndex var.

Submit StockMarket.java with this method completed under the Early Submission option in Autolab, to earn up to 5 extra credit points.

Testing this method:

  • To test this method, you can use the driver. This is what it looks like when you use stock_data.csv with ONLY readStockData() implemented.
    • At this point the other buttons may not do anything if pressed.

nextDay() 

The goal of this method is to allow the program to be able to advance to the next day.

  1. Increment the currentDay variable.
  2. Return true if the current day is strictly less than the price history array length for a stock in the stockData array, and false if not.
    1. Note: All stocks have the same length of their price arrays, so you can check any.

Note: The Driver dates SKIP weekend dates. Such as 7/11/20 and 7/12/20 not showing.

Testing this method:

  • When this method is implemented, the date in the Driver will show 7/10/2020 instead of 7/9/2020. Additionally, the Advance Day(s) button will become active, to move the simulation forward.
  • If the method is functioning properly, the simulation should end on 7/9/2025, and will show an end game screen.

updateBalance(int quantity, double pricePerShare, String type) 

The updateBalance method takes in three parameters:

  • int quantity – amount of stocks bought
  • double pricePerShare – cost of each stock
  • String type – will either be “BUY” or “SELL” depending on the trader’s action

The purpose of this method is to update the balance based on the trader’s action.

  1. If the type is “BUY”
    1. deduct the total value from the balance
  2. If the type is “SELL”
    1. add the total value to the balance

Note: totalValue = quantity * pricePerShare

Testing this method:

  • You MUST implement either buyStock() or sellStock() to test this method, as those methods will call this one.
  • Alternatively, you can use JUnit to test this method, since it does NOT rely on your data structures/buyStock()/sellStock() methods.

buyStock(String stockID, int qty)

The buyStock method takes in two parameters:

  • String stockID – the String representation of a stock based on the ticker symbol
  • int qty – amount of stocks bought

The purpose of this method is to simulate buying a stock and adding it to the portfolio

  1. If the quantity of stocks to buy is less than or equal to 0, return false.
  2. Traverse through stockData and retrieve the Stock object corresponding to the stockID parameter
    1. if the stockID is not found in stockData, return false 
  3. Retrieve the current stock price by accessing the Stock object’s priceHistory array at the currentDay index. Find the total price = qty * pricePerStock
  4. If the trader’s balance is less than the total price, return false.
  5. Create a new holding object, with holdingID, the stock, quantity, total cost, and current day.
    1. Use the getNextHoldingID() method to generate a holding ID.
  6. Add that holding to the front of the portfolio linked list, inside a LLNode
  7. Increment numHoldings, then call updateBalance() and addTransaction(). Finally, return true.

Testing this method:

  • To test this method, you can buy stocks from the stock market. 
  • The image below shows the portfolio after buying six holdings:
    • GME 1000 – Day 1 (7/10/20)
    • AAPL 2- Day 1 (7/10/20)
    • GME 500 – Day 2 (7/13/20)
    • META 5 – Day 2 (7/13/20)
    • GME 200 – Day 3 (7/14/20)
    • GME 300 – Day 4 (7/15/20
  • After viewing the holdings for each:
 

sellStock(String stockID, int qty)

The sellStock method takes in two parameters:

  • String stockID – the String representation of a stock based on the ticker symbol
  • int qty – amount of stocks bought

The purpose of this method is to simulate selling a quantity of stock owned from the portfolio

For this method, we want to sell the desired quantity of holdings for a certain stock. This includes if that quantity is made up of multiple different holdings of the same stock, we must sell them all to make up the amount

  • To do this, we want to prioritize the holdings with the highest value first.
  1. If the quantity of stocks to sell is less than or equal to 0, return false. 
  2. Loop over the portfolio to find the highest value holding for that stock. The value of a holding is its currentPrice * quantity.
    1. If no matching holding was found, return false
    2. Else If the max value holding’s quantity is greater than the desired sell quantity, then use setQuantity to subtract the sold quantity from the holding.
      1. Call updateBalance() and addTransaction() to record this.
    3. Else If the max value holding’s quantity is less than or equal to the desired sell quantity, then perform linked list removal on that Holding.
      1. Make sure to handle all cases of linked list (0, 1, or more items)
      2. Call updateBalance() and addTransaction() to record this.
      3. Then, ONLY IF the max value holding’s quantity was not enough to meet the desired sell quantity, recursively call sellStock(). Make sure to update the quantity to sell, to account for the stock you’ve just sold.
    4. Return true at the end, if we successful in selling ANY stock (even if we didn’t sell the entire desired quantity).

Testing this method:

  • To test this method, you can buy then sell stocks from the stock market.
    • Your buyStock() method must be fully tested before testing this. 
  • The image below shows the portfolio after buying four holdings:
    • GME 1000 – Day 1 (7/10/20)
    • AAPL 2- Day 1 (7/10/20)
    • GME 500 – Day 2 (7/13/20)
    • META 5 – Day 2 (7/13/20)
    • GME 200 – Day 3 (7/14/20)
    • GME 300 – Day 4 (7/15/20)
  • Then, after advancing to Day 155 and selling two holdings (click View Portfolio to see the sell button) — you can type 151 in the box next to Advance Day(s) then click the button to speed this up:
    • GME 1700 – Day 155 (1/27/21)
    • META 5 – Day 155 (1/27/21) 
 

addTransaction(Holding s, int quantity, int transactionDay, String type) 

The addTransaction method takes in three parameters:

  • Holding s – represents the holding of a stock that was purchased or sold
  • int quantity – the quantity of the stock which was bought/sold
  • int transactionDay – represents the day that the stock was purchased or sold as an integer
  • String type – will either be “BUY” or “SELL” depending on trader’s action

The purpose of this method is to create a Transaction object, add it to the front of the instance variable transactions linked list, and keep track of how many transactions there are.

  1. Create a Transaction object
    1. the transactionID is the transactionCount
    2. information about stockID and pricePerStock is from the Stock object
    3. Quantity is given via method parameters
    4. totalPrice = qty * pricePerStock
    5. the transactionDay and type are the parameters read in from the method
  2. Add the created Transaction object to the front of the transactionHistory linked list
    1. Hint: After creating a Transaction object, create a linked list node where transactionData represents a Transaction object:
      1. LLNode newHead = new LLNode<>(transactionData)
  3. Increment the transactionCount instance variable

Testing this method:

  • When this method is implemented your transactions should appear under the Analytics tab, when you press the View All Transactions button
  • After completing the 6 buy and 2 sell transactions shown for the sellStock() example above, your transactions list should look like this:

calculateROI(String stockID)

The calculateROI() method takes in one parameter:

  • String stockID – the stock to calculate ROI for

The goal of this method is to create a helper that shows you the return on the investments that lie within your portfolio!

  1. Iterate over all the holdings in your portfolio.
  2. For each which are for the matching stockID, sum their total costs and separately sum their total values (quantity * currentPrice).
  3. If the total value is zero, return zero.
  4. Else, return ((totalCurrValue – totalCost) / totalCost) * 100.0

Testing this method:

  • To test this method, you can build a portfolio, then view the ROI values under the Analytics tab in the Driver.
  • After completing the following transactions
    • BUY GME 1000 – Day 1 (7/10/20)
    • BUY AAPL 2- Day 1 (7/10/20)
    • BUY GME 500 – Day 2 (7/13/20)
    • BUY META 5 – Day 2 (7/13/20)
    • BUY GME 200 – Day 3 (7/14/20)
    • BUY GME 300 – Day 4 (7/15/20)
    • SELL GME 1700 – Day 155 (1/27/21)
    • SELL META 5 – Day 155 (1/27/21) 
    • BUY SONY 10 – Day 155 (1/27/21)
    • BUY NTDOY 100 – Day 155 (1/27/21)
    • BUY VZ 50 – Day 155 (1/27/21)
    • Advance to Day 300 (5/11/21) — 145 days later
  • You should have the following ROI values:
    • SONY = -0.98%
    • AAPL = 31.27%
    • NTDOY = -3.68%
    • VZ = 6.19%
    • GME = 3468.91%

findExtrema()

The goal of this method is to find the individual Holdings with the highest and lowest total values within your portfolio. For this method, we will treat holdings individually, rather than group them by stock.

  1. Make sure your portfolio is NOT empty.
  2. Traverse through your portfolio and find the holdings with the highest and lowest profit values.
    1. Profit is calculated as ((quantity * currentPrice) – cost)
  3. Return the highest and lowest stock symbols in a String array formatted as such: 
    1. [highest, lowest]

Note: If you return null in this method, the Driver will not work. If no extrema are found, return new String[]{“”,””};

Testing this method:

  • To test this method, you can build a portfolio, then view the ROI values under the Analytics tab in the Driver.
  • After completing the following transactions
    • BUY GME 1000 – Day 1 (7/10/20)
    • BUY AAPL 2- Day 1 (7/10/20)
    • BUY GME 500 – Day 2 (7/13/20)
    • BUY META 5 – Day 2 (7/13/20)
    • BUY GME 200 – Day 3 (7/14/20)
    • BUY GME 300 – Day 4 (7/15/20)
    • SELL GME 1700 – Day 155 (1/27/21)
    • SELL META 5 – Day 155 (1/27/21) 
    • BUY SONY 10 – Day 155 (1/27/21)
    • BUY NTDOY 100 – Day 155 (1/27/21)
    • BUY VZ 50 – Day 155 (1/27/21)
    • Advance to Day 300 (5/11/21) — 145 days later
  • You should have the following extrema:

How to open + run

First things first, make sure you have VS Code installed, a Java Development Kit (JDK) installed, and the Java Extension Pack enabled on VS Code. If you don’t, the FAQ tab of this site has download links.

Afterward, open the StockMarket folder in VS Code using File -> Open Folder. Open the StockMarket folder that directly contains the bin, src, and lib folders. If you have a StockMarket folder inside StockMarket, or you have CS112 Code -> StockMarket, you must open the innermost StockMarket folder. 

Next, when you’re ready to run your program, you can use either the terminal or the VS Code run option. 

If you use the terminal, run the following commands in order from the StockMarket directory that contains the bin, src and lib folders. If you’re having issues, please ensure that you’re in the right directory in VS Code and that you’ve typed the commands correctly and in order.

To Compile/Run: run the following commands from the innermost StockMarket directory, containing the src and bin folders.

  • Compile:
    • javac -d bin -cp lib/cs112.jar src/market/*.java
    • (If you get a warning for unchecked operations then ignore it, dont use Xlint) 
  • Run:
    • Windows: java -cp “lib/cs112.jar;bin” market.Driver
    • Mac/Linux: java -cp bin:lib/cs112.jar market.Driver

You can also use the “Run” option in VS Code to run your program by right-clicking Driver.java and selecting “Run Java”. 

JUnit Testing

The “test” folder in the project directory contains a StockMarketTest.java class which contains an empty JUnit test for each of the methods. You can fill out these tests to test some the correctness of your methods, by comparing your output to hardcoded reference output. 

Since most methods can be tested via the Driver, this is most useful to test updateBalance(), since you can call it without implementing buyStock() or sellStock().

Once you fill in a JUnit test, remove the fail() statement at the bottom of it. If you do not do this, the test will never pass.

Before submission

REMOVE all print statements you have written in StockMarket.java.

Collaboration policy. Read our collaboration policy on the course syllabus.

Submitting the assignment. Submit StockMarket.java separately via the web submission system called Autolab

Getting help

If anything is unclear, don’t hesitate to drop by office hours or post a question on Piazza.

  • Find instructors and Lead TAs office hours here
  • Find tutors office hours on Canvas -> Tutoring
  • In addition to office hours we have the Coding and Social Lounge (CSL), a community space staffed with lab assistants which are undergraduate students further along the CS major to answer questions.

By Vishal Saravanan, Sadhana Vasanthakumar, and George Janulis