Stock Paper Trader in C# and .NET

Believe it or not, the inspiration for this article came to me the other day while watching an infomercial late at night. The infomercial was selling a package to teach people how to trade stocks, claiming that you could learn to trade stocks without any money.This method is better known as paper trading, as the infomercial pointed out, allowing you to place imaginary trades on real data.  I thought this would be fairly easy to duplicate having already written a stock capturing program into Excel. Now you too can become a stock trader and not lose your shirt!

The .NET Paper Trader starts you off with the paltry sum of 1,000,000 dollars (after all, in the virtual world, anyone can be a millionaire).Using this money, you can begin to place trades and watch your money grow (or shrink as in figure 1). The program will allow you to place a trade on any of the listed stocks.It will also track your working capital, your cash, and subtract the broker commission from your profits.You cannot sell short, so this program kind of forces you into a state of optimism.

StockPaperTrader.jpg

Figure 1 - Stock Paper Trader in Action

Paper Trader UML Design

The Paper Trade program consists of 4 classes:  the main form, a trade dialog, a portfolio object, and a trade object.  Below is the complete UML design drawn in WithClass: .

StockPaperTradeUML.jpg

Figure 2 - UML Diagram Reverse Engineered from C# in WithClass

As you can see from figure 2, the portfolio consists of a collection of trades. The program maintains the all the information from the trade in the Trades collection of the Portfolio object. The Portfolio object is serializable, and it has two functions Read and Write that allow you to persist your trades in a file. The Read and Write functions are shown below in listing 1, and take advantage of the BinaryFormatter object to serialize and deserialize the data. Note that in these functions, we don't serialize the whole class, but instead, serialize the individual members. Apparently, when I tried to serialize the whole class, the ArrayList collection of Trades does not get serialized. However, when I serialize the ArrayList separately, the trades are written.

Listing 1 - Read and Write methods of the Portfolio class for persisting the trade information

public void Write()
{
// construct the binary formatter for writing out the class members
BinaryFormatter bf = new BinaryFormatter();
FileStream fs =
new FileStream(sStorage, FileMode.Create, FileAccess.Write);
// write out the collection of trades in the ArrayList
bf.Serialize(fs, Trades);
// write out the total cash
bf.Serialize(fs, TotalCash);
fs.Close();
}
public static void Read(Portfolio p)
{
// check to see if there is a file to read
if (File.Exists(sStorage))
{
// create a binary formatter to read the class members
BinaryFormatter bf = new BinaryFormatter();
FileStream fs =
new FileStream(sStorage, FileMode.Open, FileAccess.Read);
// read the trades into the ArrayList
p.Trades = (ArrayList)bf.Deserialize(fs);
// read the total cash
p.TotalCash = (float)bf.Deserialize(fs);
fs.Close();
}
}

GUI in the Form

The ListView  in the main form (Form1) is used to display all the user's stock data.  This data is updated by a .NET timer every 10 seconds.  The event handler of the timer calls the method FillListViewWithTrades in the form. This method goes through each trade in the portfolio and writes it to the ListView (see Listing 2 below):

Listing 2 - Filling the ListView with the trades in the Portfolio

private void FillListViewWithTrades()
{
// clear all the items in the grid
listView1.Items.Clear();
// go through each trade in the portfolio and add it to the view
foreach (Trade t in MyPortfolio.Trades)
{
AddATradeToView(t);
}
// also fill totals
// calculate total capital and profits
float totalCapital = ComputeTotalCapital();
float totalProfit = ComputeTotalProfit();
listView1.Items.Add("");
// add blank row
// display the totals
DisplayTotals(totalCapital, totalProfit);
float totalSpent = MyPortfolio.CalcTotalOriginalSpent();
// show the available cash for trading
ShowTotalCash(totalCapital, totalSpent);
}

The AddTradeToView method (called from FillListViewWithTrades in Listing 2 above) takes a buy trade and displays it as a row in the ListView.  The AddTradeToView method takes advantage of the ListViews ListViewItem and ListViewSubItem properties to display the row and column data.  The ListViewSubItem has properties which allows you to change the forecolor and background colors of the cell.  In the .NET Paper Trader, we display positive profits in green and negative profits in red.

Listing 3 - Adding a row of trade information to the list view

private void AddATradeToView(Trade t)
{
// get a quote from the trading website
float currentPrice = GetQuote(t.Symbol);
// add the trade as a row to the list view
ListViewItem lvi = listView1.Items.Add(t.Symbol);
// allow the subitems to take on their own properties
lvi.UseItemStyleForSubItems = false;
// Add each trade property and right justify the prices and share amounts
lvi.SubItems.Add(RightJustify(currentPrice.ToString("0.00"), 12));
lvi.SubItems.Add(RightJustify(t.NumberOfShares.ToString("0.00"), 12));
lvi.SubItems.Add( RightJustify(CalculateTotal(currentPrice, t).ToString("0.00"), 2));
// calculate profit from current price, number of shares, and original share price
float profit = CalculateProfit(currentPrice, t);
// if profit is greater than zero, display profit in green, otherwise display in red
if (profit >= 0)
{
ListViewItem.ListViewSubItem si = lvi.SubItems.Add(RightJustify(profit.ToString("0.00"), 12), Color.Green,Color.White, listView1.Font);
si.ForeColor = Color.Green;
}
else
{
ListViewItem.ListViewSubItem si = lvi.SubItems.Add(RightJustify(profit.ToString("0.00"), 12), Color.Red,Color.White, listView1.Font);
si.ForeColor = Color.Red;
}
}

The Buy/Sell Dialog

BuySellDlg.jpg

Figure 3 - Buy Sell Dialog

This dialog allows you to enter a buy or sell trade on a particular stock.  Pressing the Execute button will buy or sell a stock, depending upon which trade option is selected.The Execute Button event handler routine is shown below in listing 4.  This method simply forms a trade object with the entered information on the Buy/Sell form and allows the singleton portfolio object handle the actual computations on the trade.

Listing 4 - Execute Button Event Handler to create and handle a new trade

private void ExecuteButton_Click(object sender, System.EventArgs e)
{
if (SellRadio.Checked)
{
// if sell checked, create a sell trade and handle the sell calculation in the main form
Trade t = new Trade(TradeAction.Sell, txtSymbol.Text, Convert.ToInt32(txtShares.Text), Form1.GetQuote(txtSymbol.Text ), Convert.ToSingle(txtCommission.Text), 0);
Form1.MyPortfolio.HandleSell(t);
}
else
{
// if buy checked, create a sell trade and handle the sell calculation in the main form
Trade t = new Trade(TradeAction.Buy, txtSymbol.Text, Convert.ToInt32(txtShares.Text), Form1.GetQuote(txtSymbol.Text ), Convert.ToSingle(txtCommission.Text), 0);
Form1.MyPortfolio.HandleBuy(t);
}
}

Buying and Selling from the Portfolio

The Portfolio object is used to deal with the buy and sell organization of the trade.  The HandleBuy method adds a trade to the portfolio of existing trades and also deducts the cost of the trade from the cash.

Listing 5a - HandleBuy method of the Portfolio class public void HandleBuy(Trade t)

{
// add the trade to the portfolio
Trades.Add(t);
// Deduct the money spent from the total liquid cash
TotalCash -= (t.SharePrice * t.NumberOfShares - t.CommissionPrice);
}

The HandleSell method of the Portfolio object has a little more work.This method needs to find the stock being sold in the existing portfolio and deduct the number of shares from the total of existing shares of that stock. It must then deduct the commission and add the value of the stock transaction to the existing cash.

Listing 5b - HandleSell method of the Portfolio class public void HandleSell(Trade t)

{
// find the stock in the portfolio
foreach (Trade nextTrade in Trades)
{
if (nextTrade.Symbol == t.Symbol)
{
// make sure the trader is not selling more than he owns
if (t.NumberOfShares > nextTrade.NumberOfShares)
{
MessageBox.Show("You can't sell more shares than you own of " + t.Symbol);
return;
}
Trade theTrade = nextTrade;
// deduct the number of shares sold from the amount in the portfolio of the stock
theTrade.NumberOfShares = nextTrade.NumberOfShares - t.NumberOfShares;
// increase the cash by the value of the shares sold minus commission
TotalCash += t.NumberOfShares * t.SharePrice - t.CommissionPrice;
// remove the stock from the portfolio if the number of shares equals zero
if (theTrade.NumberOfShares == 0)
{
Trades.Remove(theTrade);
// take it out
}
return;
}
}
// couldn't find the trade, tell the user
MessageBox.Show("You don't own this stock. -->" + t.Symbol);
}

Conclusion

This program will test your trading skills and help you to determine if you are ready for the deep waters of the stock market.  Perhaps with some practice you will figure out ways to trade that will help you increase your current capital a percentage above the interest of what the banks are paying (next to nothing..).This program could probably be improved a bit by adding the capability of selling short.  This way the trader can take advantage of a down market.We'll work on getting it in the next version.  In the meantime, try to bear the current state of the program, and accumulate large .net profits on the virtual trading floor of .NET.


Similar Articles