Saturday, 13 December 2008

Download share price history from Yahoo Finance

This problem took me a little while to figure out so I'm pretty happy that I've finally managed to get it working, and with a pretty simple solution. The crux of the problem was how to fetch from the internet a share price history for any given stock over a period of days, months or even years. As it turns out yahoo.finance offers a HTTP page which nicely returns this information for you. The format of the page address looks something like this:

http://ichart.yahoo.com/table.csv?s=MSFT&a=01&b=00&c=2007&d=31&e=11&f=2008&g=d&ignore=.csv

where:

s=the stock code and stock index if outside the US (i.e. MSFT or TEL.NZ)

a=the day of the month for the start date

b=the month of the year for the start date. Note that months seem to start from 0 so Jan is 0 and 11 is Dec

c=the year of the start date

d=the day of the end date

e=the month of the end date (also convert to go from 00 to 11)

f=the year of the end date

This web query can be used in a browser to return a list of share price data for the named stock from the start date to the end date. The list will show the opening value, closing value, and other data for each day in comma separated format. You simply need to parse this result set in a loop and use it as required.

In the sample code below I've made use of the NSURL and NSData objects to grab the data. Note, this code is reference only. It won't actually work, it's just to give you an idea of how this is done:


httpString = [NSString stringWithFormat:@"http://ichart.yahoo.com/table.csv?s=%@&a=%@&b=%@&c=%@&d=%@&e=%@&f=%@&g=d&ignore=.csv", stockCode, firstMonth, firstDay, firstYear, lastMonth, lastDay, lastYear];

NSURL *url = [NSURL URLWithString:httpString];

NSData *data = [NSData dataWithContentsOfURL:url];

NSString *s = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];

NSArray *lines = [s componentsSeparatedByString:@"\n"];

NSArray *line;

for(i=0;i<[lines count];i++) {

 sCurLine = [lines objectAtIndex:i];

 line = [sCurLine componentsSeparatedByString:@","];


 /* the download should always contain 7 fields, but yahoo might change this at any time */

 if([line count]==7) {

  thisDate = [NSCalendarDate dateWithString:[line objectAtIndex:0] calendarFormat:@"%Y-%m-%d"];

  thisPrice = [[line objectAtIndex:4] floatValue];


  /* thisDate and thisPrice should now contain the date and price for this entry in the download (most recent first) */

  }

}

Tuesday, 2 December 2008

swishLounge

Having left my contract at Telecom I've had a little extra time to work on moneyLounge and I'm pretty happy with the results, it's starting to look and feel like a real application. The attached screenshot shows a few new features. I've added a ticker in the bottom left of the screen. This fades in and out details for various accounts/investments or categories that the user might be interested in. For example it can show price changes in an investment, how your net worth has changed in the month or how an account balance changed. The background of the ticker was created using a Quartz Composer Gradient interpolation and the effect is to give a subtle change of light intensity, as if a light is passing over the ticker. Most of the recent changes however have been made to the background code, mainly design tidy ups. I still need to implement a drag-drop facility to enable the user to grab an account or investment and drop it into the ticker to update it. Rather then using a Application Controller to manage all on screen objects I've divided the work up into a bunch of controllers for the different types of data objects, all of which are inherited from a generic moneyLounge controller. Some of the early objects I created have also had their interface tidied up and making changes or adding enhancements has become much easier with the cleaned up design. I've also begun methodical debugging of the code and am uncovering bugs underneath every stone that is unturned. Fortunately there's been no show-stoppers yet but next time I do something like this there will be a detailed design written before I start any coding.
Features requiring implementation include:
1. Complete the ticker
2. Various Universal graphs like Net Worth, Passive Income, Investment Performance.
3. File Export to QIF.
4. OCX load
5. Import share price history from CSV
6. Reinvestment dividends
7. Loan accounts
8. Color associations with Accounts and Investments.
9. (other stuff I haven't thought of just yet)
10. A design with the nine points I've mentioned above fleshed out properly

Thursday, 9 October 2008

A week with WoW makes all the difference

moneyLounge is starting to take shape nicely now. I'm still working in a corporate contract during the day, so I'm only really getting the evenings to spend working on moneyLounge but without Warcraft to distract me I'm finally making some decent progress again. Check out the screen shot included with this blog. I've added a vertical gradient fill to the line graphs to give a nice textured look to them. A horizontal gradient has been added to the bar graphs to make them look like pillars poking out of the x-axis. The NSDrawer to the right hand side of the screen now adjusts it's height at the window resizes and also self computes its own internal height by inspecting the objects within it's own view. I've attached the code that does all this at the bottom of the entry. Oddly by programmatically setting the value of the leadingoffset using [NSDrawer setLeadingOffset:x] it seems to significantly slow the response time of a window resize. The effect only appears noticeable it certain quick mouse movements, so I haven't invested too much time in fixing this.
The treeview now contains income and expense categories. When you select a category it'll also display a graph for that category showing monthly spend/income for the category across all accounts. You can use this to visually compare power bills for example. I've also implemented currency rate maintenance (i.e. add or delete new currency rates), and changes to currencies automatically flow through to dependent accounts and investments.
The whole Cocoa concept of bindings still eludes me however. I simply have not been able to use them at all in this project, meaning that I've had to develop everything with pages of old style glue code to stick the user interface and data objects together. It's very frustrating, but for now I'm going to have to live with it. Most of the maintenance type UI is now done so I shouldn't need to do much more of this.

/* ***************************************************************/
/* objectFrameInDrawer. */
/* Finds the visible height and width of the furtherest objects */
/* in the drawer. Used to setup the size of the drawer when the */
/* content view gets changed */
/* ***************************************************************/
-(NSSize)objectFrameInDrawer
{
id view;
NSEnumerator *viewEnumerator;
float width = 0.0, height = 0.0;
NSSize returnSize;

viewEnumerator = [[[entryDrawer contentView] subviews] objectEnumerator];

while(view=[viewEnumerator nextObject]) {
if(([view frame].origin.y + [view frame].size.height)>height)
height = [view frame].origin.y + [view frame].size.height;
if(([view frame].origin.x + [view frame].size.width)>width)
width = [view frame].origin.x + [view frame].size.width;
}

returnSize.height = height;
returnSize.width = width;

return returnSize;
}

-(void)alignDrawer
{
float defaultMargin = 50.00;

[entryDrawer setLeadingOffset:([window frame].size.height - drawerBounds.height - [entryDrawer trailingOffset])- defaultMargin];
}

/* **********************************************************************************/
/* objectFrameInDrawer. */
/* Before the drawer is opened determine the size of the view inside of the drawer */
/* set the minimum size and the size of the content view to this determined size */
/* and align the drawer vertically along the window */
/* **********************************************************************************/

-(void)drawerWillOpen:(NSNotification *)notification
{
drawerBounds = [self objectFrameInDrawer];
[entryDrawer setContentSize:drawerBounds];
[entryDrawer setMinContentSize:drawerBounds];

[self alignDrawer];
}

-(void)windowDidResize:(NSNotification *)notification
{
[self alignDrawer];
}

Saturday, 19 April 2008

MoneyLounge has a Graph


For the last month or so progress has slowed somewhat but I have been able to implement a nicely encapsulated graphing module to MoneyLounge. Now when clicking on a account, investment or currency a graph will appear showing details for those transactions. The graph can be a line graph or bar chart depending on the context of what is being displayed. It's all working quite nicely at the moment. Ideally I'd like users to be able to select several accounts and see a combined graph for all those accounts and doing that shouldn't be at all hard. I'll also need to add some extra reports such as "Net Worth Over Time" and "Spending/Month" etc. 

Monday, 24 March 2008

It's starting to come together


My understanding of Cocoa is getting pretty good now and I'm churning correct code out at a pretty quick rate now. Long gone are the days where I needed to check manuals or download code samples to figure out how to do things. I've changed the main selection menu to a outline view, allow the user to see context dependent information for accounts, investments and currencies. Next to a account name is the $ balance of the account. Next to an investment is the current value of that investment and next to a currency is the exchange rate of that currency to the base currency. Stock and currency prices are automatically downloaded from the Internet in a separate execution thread when the application starts. The yahoo.finance download site seems a little tempermental at the moment, but at least it doesn't cause my application to hang. Also I've changed the popout drawer to also handle investment transactions, meaning the user can add buy, sell, dividends etc.
I'm trying to get foreign currency exchange rate calculations setup. I still need to properly implement two-way account transfers and tidy everything up. The litmus test will be if I can start using the application to record my own financial data.
Finally the user interface needs to be cleaned up and graphs implemented. A big decision is going to be whether to install and develop this in leopard. Leopard does have some nice features included in X-Code but it would be cool to keep this application compatible with 10.4 - Tiger.

Sunday, 2 March 2008

Category maintenance


The whole of the last week has been spent trying to get to grips with the NSOutlineView provided by Cocoa. This gives you a standard leveled and expandable list, as shown in the window to the right. I've finally managed to implement to maintain Categories and SubCategories. No drag and drop yet but the basic functionality to allow users to view, insert, delete is all there. Even better it directly links in with all the underlying class datastructures, meaning that if you change the name of a category, say from "Cars" to "Vehicles" it will update all transactions from immediately. Surprisingly getting this all working wasn't exactly a trivial exercise. The documentation provided by Apple was a little terse and I resorted to plagiarising the only useful example I could find on the web from Big Nerd Ranch.
On a side note one thing I've started noticing about Cocoa is that is operates a quite different development for coding object events then all other development environments I've encountered. Visual Basic, Powerbuilder etc all allow you to object on an object in the interface builder, a push button for example, and directly let you write your code directly as an object property, in the "click" event for example. This means that the code tends to get scattered around the various objects that make up the window. In cocoa you write all your GUI code in a specific class for the window or application. I like this, in that it keeps the code together and hence makes debugging much easier. However for a complex window or application controller, I'm starting to find that the actual objective-c file starts getting enormous in size. Delegate methods get shared objects so every delegate needs to test what object it is that is sending the message. My AppController.m file is already up to 1,000 lines (including comments), and I've hardly started (gulp).

Sunday, 24 February 2008

MoneyLounge gets a Drawer


To the right is the latest screen shot of MoneyLounge. Progress has been somewhat slow over the past 10 days but a few enhancements have been made. The most visual addition has been the implementation of a Drawer, to the right of the window. When you click on a transaction the drawer opens upon allowing you to edit the details of the transaction. For example you can change the Payee from "Woolworths" to "New World" or the amount. You can also add and remove accounts. Most importantly I've made some changes to the way that the data is stored. Since I'm new to Mac development I've been developing MoneyLounge with a very much iterative prototyping approach, and I have hit a few roadblocks that have meant that I've needed to alter the underlying classes and data structures. Hopefully now everything is in better shape and this should speed up future work. As always the biggest problem has been memory allocation and trying to debug segmentation faults and core dumps. I still haven't got my head around this aspect of Cocoa development yet and am debugging with a trial and error approach.

Wednesday, 13 February 2008

MoneyLounge, 9 days old


MoneyLounge is now in development. After several weeks swatting up on Objective-C and Cocoa development I've kicked the project off and have managed to put together a very simple interface with some limited functionality. So far I can import .QIF account files, load and save data and scroll through accounts, transactions and categories. Not too bad a start, given it's only been 9 days so far. I was a little worried about how I was going to store all the data, but Objective-C supports a quite robust class archiving and encoding protocol, that allows you to very easily store an object-graph directly to disk. This means that assuming you've followed the flavor of Object Oriented Design encouraged by Objective-C, i.e. wrapping all data in classes, then load and saving the data stored in those classes is quite trivial. My one big headache so far has been memory allocation. Objective-C doesn't do background garbage collection for you and it's system of object retention is a little confusing for someone like me. I've been developing in languages like PL/SQL, PeopleCode & Powerbuilder for a few years now and allocating memory and cleaning up objects is something you just don't have to worry about. I've also found Objective-C to be somewhat verbose. To append one string to another string and assign it to another string in most languages you'd use something like:
s1 = s2 + s3.

In Objective-C that becomes:
s1 = [[s2 stringByAppendingString:s3] mutableCopy];

Still, you get used to it. The screen-shot attached to the blog is NOT some sort of early, primitive GUI design for how the final application will look. It's simply a bunch of text views to allow me to check that data has been loaded correctly. If this thing ever gets finished it'll be fun to look back at how the application looked when it was nine days old.

Saturday, 12 January 2008

MoneyLounge

Tired of hanging on to that old PC just to run MS Money when you wish you could keep track of your finances on your Mac? This is the situation I’ve found myself in for the last 3 years since switching over to OS X and finding a serious scarcity of applications that could load all my old MS Money data and allow me to do all the same things that MS Money could. I know there’s Quicken, and Moneydance and a whole host of financial programs on the web that I could potentially use but aside from the various lackluster reviews I’ve read there’s also the issue that none seem to have anything close to the groovy Mac interface that we expect from programs running on OS X. Why can’t we use a Coverflow like interface to swipe between our bank and investment accounts. How about dragging a transaction from one account to another to setup a transfer or throwing $100 from your Visa Card to the petrol pump icon to record that money you spent at BP last week. Let’s face it, keeping track of your finances is a pretty boring chore for most of us and the spreadsheet style interfaces of most of the applications we have to choose from aren’t exactly making this task any more interesting.

The idea of building something like MS Money for a Mac as been floating around in my head for a few years now and I’ve decided to take 2008 off work to have a crack at actually doing it. I’ve got a whole bunch of obstacles that’s going to make this a tricky ask, the trickiest being that I haven’t coded in Objective-C or Cocoa before. Objective-C is a ominous looking language that has been chosen by Apple as their preferred development tool for building OS X applications. I’ll be working alone on this at the start and keeping myself motivated is going to be a challenge. When you’re working at home and it’s a nice sunny day outside it’s sometimes hard to stay focused on fixing that annoying bug or researching some obscure piece of Cocoa API. The actually code required to keep track of financial transactions, download stocks and so on is actually quite simple, it’s going to be the User Interface that will be the big ask. I’ll try and keep updates of my progress coming through on this blog, so stay tuned and I hope I can come up with something to impress.