Monday 19 March 2012

MetaStock Conversion Utility

One invaluable tool for model development I haven't mentioned is Metastock. I have used this for many years to 'fine tune' the development of strategies and indicators. I tend to develop and test 'indicators' in Metastock and then convert this logic into C# code.

For the amateur trader, the biggest issue in using Metastock is how to convert data for it. I originally used end-of-day services such as those provided by Paritech, however, I found this somewhat restrictive as I wanted to control what data I converted e.g. FTSE100 or FTSE250 only. Unfortunately, Metastock does not appear keen to open up the workings of its data format and as such I have never found a pure open-source method of converting data for it. At the heart of my conversion code I use a dll called 'Metalib' (http://trading-tools.com)- my version of the dll is very old now (2007) but still does the job - it is proprietary so you will need to buy it.

Points to note in the ConverterEngine method are:
  •  The EPIC codes and Prices are pulled in from SQL using a Linq query.
  • All existing Metastock data files are deleted to start with.
  • There are two parts to the method: OpenSecurityBySymbol and AppendDataRec - the first creates the security file whilst the second adds subsequent price data to it.
  • The Sort method just sorts the files by name - the filenames are meaningless gibberish so the Sort method arranges them for when you open them in Metastock.
I use this conversion method with the version 11 of Metastock with no problems. It runs nightly after the price scrape has completed.

  
private readonly MLReader _metaReader;
private readonly MLWriter _metaWriter;
private readonly MLRegistration _mReg;
private MetastockDataContext _db;
private IQueryable _hemsList; 

public void ConverterEngine()  
     {  
       _db = new MetastockDataContext();  
       _db.Connection.ConnectionString = Database.ConnectionString;  
       _hemsList = from epic in _db.StatsLists  
             where epic.FTSE_Index.Replace("\"", "") == "FTSE100"  
             || epic.FTSE_Index.Replace("\"", "") == "FTSE250"  
             orderby epic.EPIC  
             select epic;  
       Console.WriteLine("[][][][][][][][]Doing METASTOCK conversion[][][][][][][][]");  
       _mReg.SetRegistrationInfo(PUT_YOUR_REG_HERE, KEY_HERE);  
       if (!Directory.Exists("C:/Metastock/Securities"))  
       {  
         Directory.CreateDirectory("C:/Metastock/Securities");  
       }  
       foreach (string sFile in Directory.GetFiles("C:/Metastock/Securities"))  
       {  
         File.Delete(sFile);  
       }  
       foreach (StatsList epicItem in _hemsList)  
       {  
         string epic = epicItem.EPIC.Replace("\"", "");  
         IQueryable<Price> prices = from p in _db.Prices  
                       where p.Epic == epic  
                       orderby p.Date ascending  
                       select p;  
         if (prices.Any())  
         {  
           Console.WriteLine("Processing " + epicItem.Share_Name.Replace("\"", ""));  
           foreach (Price price in prices)  
           {  
             DateTime priceDate = price.Date;  
             string yahooDate = priceDate.Year + priceDate.Month.ToString("00") +  
                       priceDate.Day.ToString("00");  
             _metaWriter.OpenDirectory("C:/Metastock/Securities");  
             if (_metaWriter.bSymbolExists[price.Epic])  
             {  
               _metaWriter.OpenSecurityBySymbol(price.Epic);  
               _metaWriter.AppendDataRec(Convert.ToInt32(yahooDate), 0,  
                            Convert.ToSingle(price.Open),  
                            Convert.ToSingle(price.High),  
                            Convert.ToSingle(price.Low),  
                            Convert.ToSingle(price.Close),  
                            Convert.ToSingle(price.Volume),  
                            0f);  
             }  
             else  
             {  
               _metaWriter.AppendSecurity(price.Epic, epicItem.Share_Name.Replace("\"", ""),  
                             PERIODICITY.Daily);  
               _metaWriter.AppendDataRec(Convert.ToInt32(yahooDate), 0,  
                            Convert.ToSingle(price.Open),  
                            Convert.ToSingle(price.High),  
                            Convert.ToSingle(price.Low),  
                            Convert.ToSingle(price.Close),  
                            Convert.ToSingle(price.Volume),  
                            0f);  
               _metaWriter.CloseSecurity();  
             }  
           }  
         }  
       }  
       _metaWriter.CloseDirectory();  
       Sort();  
     }  
     // Private Methods (1)   
     private void Sort()  
     {  
       _metaWriter.OpenDirectory(@"C:\MetaStock\Securities");  
       _metaWriter.Sort();  
       _metaWriter.CloseDirectory();  
     }  

No comments:

Post a Comment