Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

CSC151 Stock Portfolio GUI Project Goal You are to write a GUI program that will

ID: 3123507 • Letter: C

Question

CSC151 Stock Portfolio GUI Project Goal You are to write a GUI program that will allow a user to buy, sell and view stocks in a stock portfolio. This document will describe the minimum expected functions for a grade of 90. Your mission is to “go and do better.” You’ll find a list of enhancement options at the end of this document. Objectives By the end of this project, the student will be able to • write a GUI program that maintains a cash balance, list of stock holdings, supports buying and selling of stocks and displays the current portfolio inventory • demonstrate the ability to assemble already-written classes into a larger, more complicated program • demonstrate the ability to segregate business logic from user interface code. Capabilities At a minimum, the program should • allow a user to buy a stock with a given number of shares and price per share. • display the current portfolio (stock ticker, number of shares, initial price). • update the portfolio display for purchases and sales. • allow the user to sell all the shares of a given stock. • give the user an initial cash balance, and update and display the balance according to the user's purchases and sales. • ignore any transaction that causes the cash position to go below $0. Sample Execution The initial frame has text fields for the stock ticker, number of shares, and price per share. It has a label for the current cash balance. It also has “buy” and “sell” buttons. Note, the focus of this project is functionality. WidgetView provides limited ability to “pretty up” the interface, so we’ll just live with that limitation. Figure 1 Initial Frame Let's buy Apple (ticker AAPL) shares. First, we enter the ticker, number of shares and price per share. Figure 2 Data for Apple Purchase Then we click “Buy.” Note our cash was reduced accordingly. Our portfolio inventory now displays since it's no longer empty. Figure 3 Click Buy to Purchase Apple Let's buy IBM. We enter the ticker, number of shares and price per share. Figure 4 Data to Purchase IBM We click “Buy.” Our cash is reduced appropriately, our portfolio is updated. WidgetView moves things around. We won't worry about that. We also won't worry about the not-quite-right truncation of the last penny of the cash balance. Figure 5 Click Buy to Purchase IBM Let's buy Microsoft (MSFT). We'll just skip to the completed transaction. Figure 6 Purchase of Microsoft We're losing faith in IBM's CEO; let's sell it. We need to tell our portfolio manager which stock we want to sell, and the selling price per share. Since we're selling all of our shares, we don't need to fill in that field. Figure 7 Data to Sell IBM We click “Sell,” and the portfolio listing and cash are updated. Figure 8 IBM is Sold Hints The StockHolding and PortfolioList classes from earlier Lessons should be directly usable in this project. The sample screens above were generated with a version of that code that had slightly different toString() methods, but that's not significant to the function of the program. Enhancements The following is a list of possible enhancements, along with their point value, from which you can choose. 1. track the profit or loss on the trades – 4 points 2. allow for sale of partial holding – 4 points 3. subsequent purchases to be added to an existing holding – 4 points 4. formatting of dollar values – 1 point 5. user entered numeric data error checking/reporting – 2 points 6. checking/reporting of data entry errors (e.g., can’t spend more than your balance on hand, can’t sell a stock you don’t own, can’t sell more shares than you own) – 3 points As you can see, it is possible to earn more than 100 points on this assignment. Submission of your project • Refer to Blackboard’s Announcement page for the due date • Utilize the same submission guidelines that have been used for labs • Screenshots should utilize the test data that appear in this document • In the screenshot Word document, identify/describe each enhancement that you made to the program. Identify each enhancement that you implement (use the enhancement number from above) and provide one or more screenshots which illustrate the enhancement. The actual number of points that you’ll earn will be based on the information that you supply and my subjective assessment of its “quality”. So, in a nutshell, impress me.

Explanation / Answer

SOURCE CODE:


package stock;

public class StockHolding {

private String ticker;
private int numShares;
private double initialSharePrice;
private double currentSharePrice;

public StockHolding(String ticker, int numberShares, double initialPrice) {
this.ticker = ticker;
numShares = numberShares;
initialSharePrice = initialPrice;
currentSharePrice = initialPrice;
}

public double getCurrentValue() {
return numShares * getCurrentSharePrice();
}

public double getInitialCost() {
return numShares * getInitialSharePrice();
}

public double getCurrentProfit() {
return getCurrentValue() - getInitialCost();
}
public double getCurrentSharePrice() {
return currentSharePrice;
}
public void setCurrentSharePrice(double currentSharePrice) {
this.currentSharePrice = currentSharePrice;
}
public String getTicker() {
return ticker;
}
public int getShares() {
return numShares;
}
public double getInitialSharePrice() {
return initialSharePrice;
}

public void setNumShares(int numShares) {
this.numShares = numShares;
}

@Override
public String toString() {
return "Stock " + ticker + ", " + numShares + ", shares bought at "
+ initialSharePrice + ", current price "
+ currentSharePrice;
}
}

-----------------------------------------------------------------------------------------------------------------------

package stock;

import java.util.ArrayList;

/**
*
* @author Gojkid
*/
public class PortfolioList {

private ArrayList<StockHolding> portfolio;

public PortfolioList() {
portfolio = new ArrayList<StockHolding>();
}

public void add(StockHolding stock) {
portfolio.add(stock);
}

public StockHolding find(String ticker) {
for (int i = 0; i < portfolio.size(); i++) {
StockHolding sh = portfolio.get(i);
if (sh.getTicker().equals(ticker)) {
return sh;
}
}
return null;
}
public int getPos(StockHolding sh)
{
return portfolio.indexOf(sh);
}
public int getSize()
{
return portfolio.size();
}
public StockHolding getElement(int i) {
return portfolio.get(i);
}
public void remove(String ticker) {
int pos = -1;
for (int i = 0; i < portfolio.size(); i++) {
StockHolding sh = portfolio.get(i);
if (sh.getTicker().equals(ticker)) {
pos = i;
}
}
if (pos != -1) {
portfolio.remove(pos);
}
}
}

-----------------------------------------------------------------------------------------------------------------------

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

/*
* StockTrading.java
*
* Created on Nov 29, 2016, 12:43:57 AM
*/
package stock;

import javax.swing.table.DefaultTableModel;

public class StockTrading extends javax.swing.JFrame {

/** Creates new form StockTrading */
public StockTrading() {
initComponents();
}

@SuppressWarnings("unchecked")
private void initComponents() {

ticker = new javax.swing.JComboBox();
jScrollPane1 = new javax.swing.JScrollPane();
portfolio = new javax.swing.JTable();
jLabel1 = new javax.swing.JLabel();
jLabel2 = new javax.swing.JLabel();
price = new javax.swing.JTextField();
number = new javax.swing.JSpinner();
buy = new javax.swing.JButton();
jLabel3 = new javax.swing.JLabel();
balance = new javax.swing.JTextField();
sell = new javax.swing.JButton();
jLabel4 = new javax.swing.JLabel();
message = new javax.swing.JLabel();

setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setTitle("Stock Trading Program");

ticker.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "A – Agilent Technologies", "AAPL – Apple Inc.", "BRK.A – Berkshire Hathaway", "C – Citigroup", "GOOG – Alphabet Inc.", "HOG – Harley-Davidson Inc.", "HPQ – Hewlett-Packard", "INTC – Intel", "KO – The Coca-Cola Company", "LUV - Southwest Airlines", "MMM – Minnesota Mining and Manufacturing", "MSFT – Microsoft", "T - AT&T", "TGT – Target Corporation", "TXN – Texas Instruments", "WMT – Walmart" }));

portfolio.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
{null, null, null, null},
{null, null, null, null},
{null, null, null, null},
{null, null, null, null}
},
new String [] {
"Ticker", "Number", "Current Price", "Intial Price"
}
) {
Class[] types = new Class [] {
java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class
};
boolean[] canEdit = new boolean [] {
false, false, false, false
};

public Class getColumnClass(int columnIndex) {
return types [columnIndex];
}

public boolean isCellEditable(int rowIndex, int columnIndex) {
return canEdit [columnIndex];
}
});
jScrollPane1.setViewportView(portfolio);

jLabel1.setText("Ticker :");

jLabel2.setText("Price:");

number.setModel(new javax.swing.SpinnerNumberModel(Integer.valueOf(1), Integer.valueOf(1), null, Integer.valueOf(1)));

buy.setText("Buy");
buy.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
buyActionPerformed(evt);
}
});

jLabel3.setText("Remaining Balance:");

balance.setText("$10000");

sell.setText("Sell");
sell.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
sellActionPerformed(evt);
}
});

jLabel4.setText("User's Portfolio");

message.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
message.setText(" ");

javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(30, 30, 30)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 723, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addGap(103, 103, 103)
.addComponent(jLabel3)
.addGap(29, 29, 29)
.addComponent(balance, javax.swing.GroupLayout.PREFERRED_SIZE, 67, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 34, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jLabel1)
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 291, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(buy)
.addGap(31, 31, 31)
.addComponent(sell))
.addGroup(layout.createSequentialGroup()
.addComponent(ticker, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(30, 30, 30)
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(price, javax.swing.GroupLayout.PREFERRED_SIZE, 57, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(33, 33, 33)
.addComponent(number, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))))
.addComponent(message, javax.swing.GroupLayout.PREFERRED_SIZE, 489, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(39, 39, 39))
.addGroup(layout.createSequentialGroup()
.addGap(365, 365, 365)
.addComponent(jLabel4)
.addContainerGap(878, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(33, 33, 33)
.addComponent(jLabel4)
.addGap(18, 18, 18)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 228, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(67, 67, 67)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel3)
.addComponent(balance, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGroup(layout.createSequentialGroup()
.addGap(102, 102, 102)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(ticker, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel2)
.addComponent(price, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(number, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel1))
.addGap(38, 38, 38)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(buy)
.addComponent(sell))
.addGap(64, 64, 64)
.addComponent(message)))
.addContainerGap(69, Short.MAX_VALUE))
);

pack();
}

private void buyActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
message.setText("");
price.setText(""+(int)(Math.random()*1000+Math.random()*100+Math.random()*10));
double p = Double.parseDouble(price.getText());
int n = ((Integer)number.getValue()).intValue();
StockHolding sh=new StockHolding((String)ticker.getSelectedItem(),n,p);
if(Double.parseDouble(balance.getText().substring(1))>=(p*n))
{
userPortfolio.add(sh);
bal=Double.parseDouble(balance.getText().substring(1))-(n*p);
balance.setText("$"+(int)bal);
}

else
message.setText("You don't have enough money to buy these shares");
updateTable();
  
}

private void sellActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
message.setText("");
if(userPortfolio.find((String)ticker.getSelectedItem())!=null)
{
if(userPortfolio.find((String)ticker.getSelectedItem()).getShares()>=((Integer)number.getValue()).intValue())
{
bal = Double.parseDouble(balance.getText().substring(1))+userPortfolio.find((String)ticker.getSelectedItem()).getCurrentSharePrice()*((Integer)number.getValue()).intValue();
userPortfolio.find((String)ticker.getSelectedItem()).setNumShares(userPortfolio.find((String)ticker.getSelectedItem()).getShares()-((Integer)number.getValue()).intValue());
balance.setText("$"+(int)bal);
}
else if(Double.parseDouble(balance.getText().substring(1))==(userPortfolio.find((String)ticker.getSelectedItem()).getCurrentSharePrice()*((Integer)number.getValue()).intValue()))
{
bal=Double.parseDouble(balance.getText().substring(1))-(((Integer)number.getValue()).intValue()*userPortfolio.find((String)ticker.getSelectedItem()).getCurrentSharePrice());
DefaultTableModel dtm = (DefaultTableModel) portfolio.getModel();
dtm.removeRow(userPortfolio.getPos(userPortfolio.find((String)ticker.getSelectedItem())));
userPortfolio.remove((String)ticker.getSelectedItem());
balance.setText("$"+(int)bal);
}
else
message.setText("You only have "+userPortfolio.find((String)ticker.getSelectedItem()).getShares()+" shares of"+ticker.getSelectedItem());
}
else
message.setText("You don't have any "+ticker.getSelectedItem()+" shares");
updateTable();
}

public void updateTable()
{
  
for (int i = 0; i < userPortfolio.getSize(); i++) {
StockHolding sh = userPortfolio.getElement(i);
if(i <= userPortfolio.getSize())
{
DefaultTableModel dtm = (DefaultTableModel) portfolio.getModel();
dtm.addRow(new Object[]{"", "", "",""});
  
}
sh.setCurrentSharePrice(sh.getInitialSharePrice()+Math.random()*10);
portfolio.setValueAt(sh.getTicker(), i, 0 );
portfolio.setValueAt(sh.getShares()+"", i, 1 );
portfolio.setValueAt("$"+(int)sh.getCurrentSharePrice(), i, 2 );
portfolio.setValueAt("$"+(int)sh.getInitialSharePrice(), i, 3 );
}
}
  
public static void main(String args[]) {

try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(StockTrading.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(StockTrading.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(StockTrading.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(StockTrading.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>

/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {

public void run() {
new StockTrading().setVisible(true);
}
});
}
private javax.swing.JTextField balance;
private javax.swing.JButton buy;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JLabel jLabel4;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JLabel message;
private javax.swing.JSpinner number;
private javax.swing.JTable portfolio;
private javax.swing.JTextField price;
private javax.swing.JButton sell;
private javax.swing.JComboBox ticker;

private PortfolioList userPortfolio = new PortfolioList();
private double bal;
}