It's a very old format with a structure that is a total mess. I myself have spent a lot of time figuring how to properly read quotes in a jungle of different files and formats.
Here I present the actual C# code I use to interface with the database that I update every evening from my data vendor.
Information on the metastock data structure is scattered over the web. I've collected what seemed to work and implemented as a C# class. A special thank to Julian M Bucknall for providing the code to convert from MBF4 (Microsoft Binary Format single precision) to standard floating point IEEE number.
The library is organized as follows:
- the struct MetaStockRow stores one day of data
public struct MetaStockRow { public DateTime Day; public double Open; public double High; public double Low; public double Close; public double Volume; public double OpenInterest; }
- a set of MetaStockRow(s) forms a MetaStockTable, that is, the whole data for a stock symbol
- a set of MetaStockTable(s) forms a MetaStockCollection, which is useful when you have to work with more than one stock at a time. A special feature of MetaStockCollection is the capability to intersect dates, that is, making sure that the stocks you are working with have the same data points (days).
- MetaStockTables and MetaStockCollections are generated by the class MetaStockReader which is the main object that performs the low-level reading on the database files.
- Create a MetaStockReader object
- Use AddPath() to tell it where your metastock folders are located (usually there are more than one).
- Create a MetaStockCollection object
- Insert stocks in the collection with AddSymbol()
- Trim and synch dates in the collection with FilterPeriod() and IntersectDates()
- Get daily closes with GetCloseArray()
An example:
MetaStockReader MR = new MetaStockReader();
MR.AddPath(@"C:\MetaStock\NYSE");
MR.AddPath(@"C:\MetaStock\AMEX");
MetaStockCollection ML = new MetaStockCollection();
ML.AddSymbol("MSFT",MR);
ML.AddSymbol("BRK.A",MR);
ML = ML.FilterPeriod(DateTime.Parse("01/01/2000"),DateTime.Parse("31/12/2011"));
ML = ML.IntersectDates();
double[] s1 = ML[0].GetCloseArray();
double[] s2 = ML[1].GetCloseArray();
If you need to work with just one stock, you can avoid using MetaStockCollection and work directly with MetaStockTable objects and access to its MetaStockRow(s).
There is a little more in the code of what I've shown here, but if you have a look at the sources you can easily discover by yourself all the other features. I must warn you the code quality is rather poor, because I haven't spent much time in improving it. I stopped when it "worked" (shame on me!).
Download the C# source code here.