In this course, you will be working on a project called "Investment Portfolio", which will be built incrementally over the semester through three individual assignments. In addition to the implementation, you are also required to follow proper coding styles and establish good habits for testing and documentation.
An individual may have a portfolio that holds different kinds of investments and allows you to buy or sell investments, search for some investments, update prices, and compute the total gain of the portfolio. An investment is better modeled by an object so that you can distinguish different attributes and apply suitable methods for accessing and changing these attributes. For this project, we limit ourselves to two kinds of investments: Stock and MutualFund. Here are two examples illustrating the related attributes for Stock and MutualFund objects, respectively:
Attributes, Stock Example, MutualFund Example
symbol,TD, CIG677
name, Toronto Dominion Bank, CI Signature Select Canadian
quantity, 500, 450
price, 69.31, 26.95
bookValue, 25,009.99, 9,000.00
Each investment should have a symbol, a name, a quantity, a price, and a bookValue. For each stock, we need to pay commissons when buying or selling shares of the stock, which will affect the values for quantity and bookValue, and the calculation of the gain of the stock. We can assume that the commission fee is $9.99 each time we buy or sell certain shares of a stock. For example, if we initially buy 500 shares of TD stock at the price of $50.00 per share, the quantity will be 500, and the bookValue will be 500 x 50.00 + 9.99 = $25,009.99. Later on, if the price is changed to $69.31 per share, the gain will be (500 69.31 9.99) 25,009.99 = 34,645.01 25,009.99 = $9,635.02. Alternatively, if we sell 200 shares of this stock at $69.31 per share, the payment received will be 200 x 69.31 9.99 = $13,852.01, the quantity will be reduced to 300, and bookValue will be adjusted to 25,009.99 x 300/500 = $15,005.99.
For each mutual fund, we do not pay any fee if we buy certain units of the fund, but if we sell certain units of the fund, we need to pay a redemption fee of $45. For instance, if we initially buy 450 units of CIG677 at $20.00 per unit, the quantity will be 450 and the bookValue will be 450 x 20.00 = $9,000.00. Later on, if the price goes up to $26.95 per unit, the gain will be (450 x 26.95 45.00) 9,000.00 = 12,082.50 9,000.00 = $3,082.50. Similarly, if we sell 150 units of this fund at $26.95 per unit, the payment received will be 150 x 26.95 45.00 = $3,997.50, the quantity will be reduced to 300, and the bookValue will be changed to 9,000.00 x 300/450 = $6,000.00.
In a portfolio, one may own multiple stocks and/or mutual funds, and as a result, we need to use two ArrayLists to store them: one for all stocks and one for all mutual funds. One big advantage of using ArrayLists is that they are dynamic since their sizes can grow or shrink as needed when one buy or sell investments. Given a portfolio, we can perform different operations and for this project, we will implement five of them:
(1) buy: own a new investment or add more quantity to an existing investment.
(2) sell: reduce some quantity of an existing investment.
(3) update: refresh the prices of all existing investments.
(4) getGain: compute the total gain of the portfolio by accumulating the gains of all its investments.
(5) search: find all investments that match a search request and display the details of these investments. A search request may contain one or more of three fields: a symbol, a set of keywords that appear in the name of an investment, and a price range (with a pair of lower and upper values for the price). For example, a search request may just contain a symbol (e.g., TD) and in this case, only the investment with this symbol will be returned. If a search request contains the keywords Toronto Bank, then all investments whose names contain these keywords will be retured. If a search request contains more fields, e.g., TD as the symbol and 10.00-100.00 as the price range, then simply matching the symbol TD is not enough; the price of the investment should also fall within the given price range. There are several special cases for the price range. For example, 15.00 means exactly $15.00; 10.00- means $10.00 or higher; and -100.00 means $100.00 or lower. For any of these fields, if the input is empty, it will match any value in the corresponding attribute of an investment. At the extreme, if the user leaves all these fields empty for a search request, then all the investments will be matched and returned in the search result.
Assignment One will build a basic system for Investment Portfolio and the remaining two assignments will add some enhancements. More specifically, you are asked to implement the following tasks for this assignment:
(1) A command loop that accepts one of these commands: buy, sell, update, getGain, search, and quit. For the buy command, the user needs to enter the kind of investment (either stock or mutualfund), followed by all the required attributes for the investment. Note that bookValue is calculated based on quantity and price, and the current bookValue if one is adding additional quantity to an existing investment. For sell, the user needs to provide a symbol, an actual price, and a quantity value. Note that selling is only possible if the investment exists and the available quantity is greater or equal to the requested quantity, and if the remaining quantity is greater than 0, we will also adjust the bookValue; otherwise, we will delete the investment from the portfolio. For update, we simply go through all existing investments and ask the user to enter the new prices. For getGain, we will calculate the total gain for all the available investments based on their current prices. For search, the user needs to provide values for up to three fields: symbol, keywords for the name, and a price range. Note that the user can enter an empty string (i.e., no value) for any or all of these fields. The quit command simply exits the command loop and then terminates the program.
(2) As described earlier, you should use two ArrayLists to store the investments: one for stocks and the other for mutual funds. When adding an investment to the corresponding list, you need to check the list to see if an investment with the same symbol already exists. If so, just increase the quantity and adjust the bookValue of the available investment; otherwise, create a new investment with the given information. Since all investments should have unique symbols, we should also check the other list to make sure that no existing investments have the same symbol as what is given from the user.
(3) Based on the description so far, your implementation should include at least three classes: Stock, MutualFund, and Portfolio. Both Stock and MutualFund classes can have the same set of attributes, including symbol, name, quantity, price, and bookValue, but they may have different methods to compute the bookValue, payment received, and gain of an investment. The Portfolio class requires more work, such as maintaining two ArrayLists for stocks and mutualfunds, searching the lists sequentially for the matched investments, and displaying the result on the screen.
(4) For each search request, you typically need to scan through both lists for stocks and mutuals: for the price range, you need to make sure that it covers the price of each matched investment; and for the search keywords, you need to make sure that they all appear in the name attribute of an investment, although they can be in a different order. Note that when matching two keywords, they have to be equal at the word level but the cases can be ignored. For example, Bank and bank are a match, but Bank and Banking are not. Also, the keywords Toronto Bank is matched by the name Bank in Toronto, since the search keywords can be matched in any order as long as they are all matched within the name.
(5) For all the class definitions, you need to follow the conventions by making all the instance variables private and providing suitable accessor and mutator methods. Also, as much as possible, you should provide suitable constructors and any other commonly used methods for a class, including the equals and toString methods. Any methods that work on an individual stock or mutualfund should be defined in its corresponding class, but any methods that work on a list of investments should be defined in the Portfolio class.
(6) You should organize all of your classes in one package and use Javadoc to create a set of external documents.