Becoming really rich with C#

-

Or maybe not, please do not hold me re­spon­si­ble if you lose money fol­low­ing this sys­tem. Having said that, it is my opin­ion that there are very few con­cepts that are im­por­tant in in­vest­ing. Three big ones are value, di­ver­si­fi­ca­tion and mo­men­tum. This post is about the lat­ter two and how to use C# to cre­ate a sim­ple trad­ing sys­tem that uses both.

Diversification is not put all your eggs in one bas­ket’ (contrary to put all of them in one bas­ket and watch that bas­ket’). I don’t be­lieve you can watch’ very much in fi­nan­cial mar­kets, so I tend to pre­fer di­ver­si­fi­ca­tion.

Momentum is a mys­te­ri­ous ten­dency of fi­nan­cial prices that have risen the most in the re­cent past, to con­tinue out­per­form­ing in the close fu­ture. In essence, buy­ing the top stocks/​sec­tors/​as­set classes tends to out­per­form buy­ing the bot­tom ones over hori­zons from three months to one year.

The idea then is to rank some as­sets (i.e. ETFs) by how fast they have risen in the past, go long the top ones and short the bot­tom ones. There are hun­dreds of vari­a­tions of this ba­sic strat­egy, we’ll add the rule that we won’t buy as­sets that are be­low their 200 days mov­ing av­er­age or sell short as­sets that are above it.

I’m writ­ing this code with VS 2010 Beta 2 (which has­n’t shipped yet). It should be triv­ial to mod­ify it to run on B1 (or maybe it does run on it al­ready). I at­tach the code and data files to this post.

struct Event {
    internal Event(DateTime date, double price) { Date = date; Price = price; }
    internal readonly DateTime Date;
    internal readonly double Price;
}

We’ll use this sim­ple struc­ture to load the clos­ing price for a par­tic­u­lar date. My use of in­ter­nal is kind of bizarre. Actually the whole code might look strange. It is an in­ter­est­ing (maybe un-el­e­gant) mix of ob­ject ori­en­ta­tion and func­tional pro­gram­ming.

class Summary {
    internal Summary(string ticker, string name, string assetClass,
                    string assetSubClass, double? weekly, double? fourWeeks,
                    double? threeMonths, double? sixMonths, double? oneYear,
                    double? stdDev, double price, double? mav200) {
        Ticker = ticker;
        Name = name;
        AssetClass = assetClass;
        AssetSubClass = assetSubClass;
        // Abracadabra ...
        LRS = (fourWeeks + threeMonths + sixMonths + oneYear) / 4;
        Weekly = weekly;
        FourWeeks = fourWeeks;
        ThreeMonths = threeMonths;
        SixMonths = sixMonths;
        OneYear = oneYear;
        StdDev = stdDev;
        Mav200 = mav200;
        Price = price;
    }
    internal readonly string Ticker;
    internal readonly string Name;
    internal readonly string AssetClass;
    internal readonly string AssetSubClass;
    internal readonly double? LRS;
    internal readonly double? Weekly;
    internal readonly double? FourWeeks;
    internal readonly double? ThreeMonths;
    internal readonly double? SixMonths;
    internal readonly double? OneYear;
    internal readonly double? StdDev;
    internal readonly double? Mav200;
    internal double Price;
    internal static void Banner() {
        Console.Write("{0,-6}", "Ticker");
        Console.Write("{0,-50}", "Name");
        Console.Write("{0,-12}", "Asset Class");
        //Console.Write("{0,-30}t", "Asset SubClass";
        Console.Write("{0,4}", "RS");
        Console.Write("{0,4}", "1Wk");
        Console.Write("{0,4}", "4Wk");
        Console.Write("{0,4}", "3Ms");
        Console.Write("{0,4}", "6Ms");
        Console.Write("{0,4}", "1Yr");
        Console.Write("{0,6}", "Vol");
        Console.WriteLine("{0,2}", "Mv");
        //Console.Write("{0,6}", "Pr");
        //Console.WriteLine("{0,6}", "M200");
    }
    internal void Print() {
        Console.Write("{0,-6}", Ticker);
        Console.Write("{0,-50}", new String(Name.Take(48).ToArray()));
        Console.Write("{0,-12}", new String(AssetClass.Take(10).ToArray()));
        //Console.Write("{0,-30}t", new String(AssetSubClass.Take(28).ToArray()));
        Console.Write("{0,4:N0}", LRS * 100);
        Console.Write("{0,4:N0}", Weekly * 100);
        Console.Write("{0,4:N0}", FourWeeks * 100);
        Console.Write("{0,4:N0}", ThreeMonths * 100);
        Console.Write("{0,4:N0}", SixMonths * 100);
        Console.Write("{0,4:N0}", OneYear * 100);
        Console.Write("{0,6:N0}", StdDev * 100);
        if (Price <= Mav200)
            Console.WriteLine("{0,2}", "X");
        else
            Console.WriteLine();
        //Console.Write("{0,6:N2}", Price);
        //Console.WriteLine("{0,6:N2}", Mav200);
    }
}

The class Summary above is how I want to pre­sent my re­sults. A few com­ments on the code. I use Nullable be­cause some of this val­ues can be null (i.e. not enough his­tory), but I still don’t want to worry about it. It ends up work­ing rather neatly.

I also print the re­sults out to Console, which is crazy. I re­ally should be us­ing WPF/Silverlight as the pre­sen­ta­tion layer. Also the {0,4:N0} no­ta­tion might be un­fa­mil­iar to some of you, but this is how mad Console guys like my­self avoid us­ing real UI frame­works. Sometimes we print things in color too.

The real meat is in the fol­low­ing line:

LRS = (fourWeeks + threeMonths + sixMonths + oneYear) / 4;

That is our high­way to rich­ness. It’s a very elab­o­rated quant for­mula, never be­fore shown, that cal­cu­late a mag­ick rel­a­tive strength (aka mo­men­tum) fac­tor as the av­er­age of the per­for­mance of four weeks, three months, six months and one year.

class TimeSeries {
    internal readonly string Ticker;
    readonly DateTime _start;
    readonly Dictionary<DateTime, double> _adjDictionary;
    readonly string _name;
    readonly string _assetClass;
    readonly string _assetSubClass;
    internal TimeSeries(string ticker, string name, string assetClass, string assetSubClass, 
IEnumerable<Event> events) { Ticker = ticker; _name = name; _assetClass = assetClass; _assetSubClass = assetSubClass; _start = events.Last().Date; _adjDictionary = events.ToDictionary(e => e.Date, e => e.Price); }

I then built my­self a lit­tle TimeSeries class that rep­re­sents a se­ries of (date, price). I choose a dic­tio­nary to store it be­cause of my as­sump­tion that I will be ac­cess­ing it by date a lot. In ret­ro­spect, I was kind of right and kind of wrong. It does­n’t re­ally mat­ter much.

bool GetPrice(DateTime when, out double price, out double shift) {
    // To nullify the effect of hours/min/sec/millisec being different from 0
    when = new DateTime(when.Year, when.Month, when.Day);
    var found = false;
    shift = 1;
    double aPrice = ;
    while (when >= _start && !found) {
        if (_adjDictionary.TryGetValue(when, out aPrice)) {
            found = true;
        }
        when = when.AddDays(-1);
        shift -= 1;
    }
    price = aPrice;
    return found;
}

A TimeSeries can give you back the price at a par­tic­u­lar date. This looks bizarre and com­plex, but there is a rea­son for it. I might ask for a date that does­n’t have a price as­so­ci­ated with it (i.e. hol­i­days, week-ends). In such cases I want to re­turn the pre­vi­ous price which could be N days in the past.

I also want to re­turn how many days in the past I had to go, so that other cal­cu­la­tions (i.e. Return) can mod­ify their end date by the same amount. Also I might not find such a price at all, in which case I don’t want to throw an ex­cep­tion, but in­stead no­tify the caller. In ret­ro­spect, I should have used dou­ble? to sig­nify price not found’.

double? GetReturn(DateTime start, DateTime end) {
    var startPrice = 0.0;
    var endPrice = 0.0;
    var shift = 0.0;
    var foundEnd = GetPrice(end, out endPrice, out shift);
    var foundStart = GetPrice(start.AddDays(shift), out startPrice, out shift);
    if (!foundStart || !foundEnd)
        return null;
    else
        return endPrice / startPrice - 1;
}

We can now go and cal­cu­late the re­turn be­tween two dates. Also the TimeSeries ob­ject needs to per­form a lit­tle more cal­cu­la­tions.

internal double? LastWeekReturn() {
        return GetReturn(DateTime.Now.AddDays(-7), DateTime.Now);
    }
    internal double? Last4WeeksReturn() {
        return GetReturn(DateTime.Now.AddDays(-28), DateTime.Now);
    }
    internal double? Last3MonthsReturn() {
        return GetReturn(DateTime.Now.AddMonths(-3), DateTime.Now);
    }
    internal double? Last6MonthsReturn() {
        return GetReturn(DateTime.Now.AddMonths(-6), DateTime.Now);
    }
    internal double? LastYearReturn() {
        return GetReturn(DateTime.Now.AddYears(-1), DateTime.Now);
    }
    internal double? StdDev() {
        var now = DateTime.Now;
        now = new DateTime(now.Year, now.Month, now.Day);
        var limit = now.AddYears(-3);
        var rets = new List<double>();
        while (now >= _start.AddDays(12) && now >= limit) {
            var ret = GetReturn(now.AddDays(-7), now);
            rets.Add(ret.Value);
            now = now.AddDays(-7);
        }
        var mean = rets.Average();
        var variance = rets.Select(r => Math.Pow(r - mean, 2)).Sum();
        var weeklyStdDev = Math.Sqrt(variance / rets.Count);
        return weeklyStdDev * Math.Sqrt(40);
    }
    internal double? MAV200() {
        return _adjDictionary
.ToList()
.OrderByDescending(k => k.Key)
.Take(200)
.Average(k => k.Value); } internal double TodayPrice() { var price = 0.0; var shift = 0.0; GetPrice(DateTime.Now, out price, out shift); return price; } internal Summary GetSummary() { return new Summary(Ticker, _name, _assetClass, _assetSubClass,
LastWeekReturn(), Last4WeeksReturn(), Last3MonthsReturn(),
Last6MonthsReturn(), LastYearReturn(), StdDev(), TodayPrice(),
MAV200()); } }

Nothing par­tic­u­larly in­ter­est­ing in this code. Just a bunch of cal­cu­la­tions. The MAV200 is the 200 days mov­ing av­er­age of clos­ing prices. It shows a more func­tional way of do­ing things. The StdDev func­tion is in­stead very im­per­a­tive.

We now can work on down­load­ing the prices. This is how you con­struct the right URL:

static string CreateUrl(string ticker, DateTime start, DateTime end) {
    return @"http://ichart.finance.yahoo.com/table.csv?s=" + ticker + "&a="
+ (start.Month - 1).ToString() + "&b=" + start.Day.ToString() + "&c="
+ start.Year.ToString() + "&d=" + (end.Month - 1).ToString() + "&e="
+ end.Day.ToString() + "&f=" + end.Year.ToString() + "&g=d&ignore=.csv"; }

 

And let’s set how many con­cur­rent con­nec­tions we are go­ing to use …

ServicePointManager.DefaultConnectionLimit = 10;

On my ma­chine, set­ting this num­ber too high causes er­rors to be re­turned. I’m not sure on which side of the con­nec­tion the prob­lem lies.

We can then load all the tick­ers we want to load from a file. One of the files has Leveraged ETFs, which I want to fil­ter out be­cause they tend to pop up al­ways at the top.

var tickers =
    //File.ReadAllLines("ETFs.csv")
    //File.ReadAllLines("ETFTest.csv")
    File.ReadAllLines("AssetClasses.csv")
    .Skip(1)
    .Select(l => l.Split(new[] { ',' }))
    .Where(v => v[2] != "Leveraged")
    .Select(values => Tuple.Create(values[], values[1], values[2], values[3]))
    .ToArray();
var len = tickers.Length;
var start = DateTime.Now.AddYears(-2);
var end = DateTime.Now;
var cevent = new CountdownEvent(len);
var summaries = new Summary[len];

And then load all of them, mak­ing sure to make an asyn­chro­nous call so not to keep the thread busy.

for(var i = 0; i < len; i++)  {
    var t = tickers[i];
    var url = CreateUrl(t.Item1, start, end);
    using (var webClient = new WebClient()) {
        webClient.DownloadStringCompleted +=
new DownloadStringCompletedEventHandler(downloadStringCompleted); webClient.DownloadStringAsync(new Uri(url), Tuple.Create(t, cevent, summaries, i)); } } cevent.Wait();

 

Notice the use of a Countdown event to wait for all the thread to com­plete be­fore print­ing out the re­sults. Also no­tice the new Tuple class used to pack­age things to send around.

We can then print out the top and bot­tom 15%:

var top15perc =
        summaries
        .Where(s => s.LRS.HasValue)
        .OrderByDescending(s => s.LRS)
        .Take((int)(len * 0.15));
var bottom15perc =
        summaries
        .Where(s => s.LRS.HasValue)
        .OrderBy(s => s.LRS)
        .Take((int)(len * 0.15));
Console.WriteLine();
Summary.Banner();
Console.WriteLine("TOP 15%");
foreach(var s in top15perc)
    s.Print();
Console.WriteLine();
Console.WriteLine("Bottom 15%");
foreach (var s in bottom15perc)
    s.Print();

 

Here is what we do when a re­quest comes back with data:

static void downloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) {
    var bigTuple =
(Tuple<Tuple<string, string, string, string>, CountdownEvent, Summary[], int>)
e.UserState; var tuple = bigTuple.Item1; var cevent = bigTuple.Item2; var summaries = bigTuple.Item3; var i = bigTuple.Item4; var ticker = tuple.Item1; var name = tuple.Item2; var asset = tuple.Item3; var subAsset = tuple.Item4; if (e.Error == null) { var adjustedPrices = e.Result .Split(new[] { 'n' }) .Skip(1) .Select(l => l.Split(new[] { ',' })) .Where(l => l.Length == 7) .Select(v => new Event(DateTime.Parse(v[]), Double.Parse(v[6]))); var timeSeries = new TimeSeries(ticker, name, asset, subAsset, adjustedPrices); summaries[i] = timeSeries.GetSummary(); cevent.Signal(); Console.Write("{0} ", ticker); } else { Console.WriteLine("[{0} ERROR] ", ticker); //Console.WriteLine(e.Error); summaries[i] = new Summary(ticker, name, "ERROR", "ERROR", , , , , , ,,); cevent.Signal(); } }

We first un­pack the Tuple we sent out orig­i­nally, we then ex­tract the Date and Price, cre­ate a Summary ob­ject and store it in the sum­maries ar­ray. It’s im­por­tant to re­mem­ber to Signal to the cevent in the er­ror case as well be­cause we want to print out the re­sults even if some down­load­ing failed.

And here is what you get for your ef­fort:

image

SystemCodeAndData.zip

Tags

13 Comments

Comments

Barry Kelly

2009-09-23T08:36:49Z

Indeed. This is called mo­men­tum in­vest­ing, and is prob­a­bly at least par­tially re­spon­si­ble for the bub­bles we’ve seen over the past few decades.
You can read more about it here - traders at Morgan Stanley de­scribed folks who used this ap­proach as fast money scum”:
http://​mar­ket­prog­nos­ti­ca­tor.blogspot.com/​2009/​07/​real-vam­pire-squid-on-face-of-hu­man­ity.html

I’m afraid there is plenty of re­search on this fac­tor (as there is on value). For a sum­mary of it read here: http://​www.cxoad­vi­sory.com/​blog/​in­ter­nal/​blog-mo­men­tum-in­vest­ing/​De­fault.asp

FYI
You can pull up a very sim­i­lar set of data points for every ETF in the U.S. Market on my web­site http://​ETFtable.com (also built in .NET)
You then sort by a num­ber of dif­fer­ent mea­sures of per­for­mance and trend, and also fil­ter the full list of ETFs to just a sub­set of ETFs that you track. Try it out and let me know what you think.

Lovely, I like the sim­plic­ity.
But I still like to be able to cus­tomize things even more. Then, con­sider my beau­ti­ful user in­ter­face :-)

take every­thing out and re­mem­ber this state­ment investment is not about tim­ing it is about time”

Or was it the other way around? :-) :-)

Liked the new C# tricks. Thanks for shar­ing!

Pretty nice, but I would have gone with a script­ing lan­guage for this job. I think the de­vel­op­ment speed would have been greater.

@ geo re: Pretty nice, but I would have gone with a script­ing lan­guage for this job. I think the de­vel­op­ment speed would have been greater.
Can some­one please ex­plain why a script­ing lan­guage would make de­vel­op­ment speed bet­ter, and any other ben­e­fits.  I’ve heard state­ments like this and am cu­ri­ous as to why you would choose it over some­thing like the au­thor used, es­pe­cially when he wrote it in a con­sole with­out much over­head.

Thanks for this great ex­am­ple on the power of C# .NET4. It has been a real eye opener for me. Amazing stuff!
It all makes sense ex­cept the Parallel For. I can see why it ends up work­ing, but it seems less than op­ti­mal and or need­lessly com­plex. Maybe I an miss­ing some­thing?
Parallel.For(0, len, i => {
   var t = tick­ers[i];
   var url = CreateUrl(t.Item1, start, end);
   using (var we­b­Client = new WebClient()) {
       webClient.DownloadStringCompleted +=
                         new DownloadStringCompletedEventHandler(downloadStringCompleted);
       webClient.DownloadStringAsync(new Uri(url), Tuple.Create(t, cevent, sum­maries, i));
   }
}
);
Observation 1: Surely by call­ing DownloadStringAsync you are han­dling the work of ac­tu­ally do­ing the http get to a thread in a thread pool. Doesn’t this make the Parallel For re­dun­dant? The only thing that it is po­ten­tially par­al­leliz­ing is the cre­ation of the URL string which is pretty mi­nor.
Observation 2: Surely you only need to cre­ate one WebClient ob­ject if you are go­ing to use DownloadStringAsync as it re­turns im­me­di­ately hand­ing off the job to a thread in thread pool.
Observation 3: With a sin­gle WebClient you would only need a sin­gle DownloadStringCompletedEventHandler. Not a big over­head but still.
Observation 4: The us­ing clause will call the dis­pose method on each WebClient. But pre­sum­ably this will block un­til we­b­Client.is­Busy() is false. So these (potential) threads cre­ated by the  Parallel For will cre­ate a url, hand off the work of ac­tu­ally get­ting the url to a thread pool (as a re­sult of call­ing DownloadStringAsync) and then block on the dis­pose method un­til the get method. Seems a bit of an overkill.
I have not ac­tu­ally run you code so I am not able to try my the­o­ries out! But surely this is all you need?
<pre>
we­b­Client.Down­load­String­Com­pleted +=
                         new DownloadStringCompletedEventHandler(downloadStringCompleted);
us­ing (var we­b­Client = new WebClient()) {
 for(i = 0; i < len, ++i) {
   var t = tick­ers[i];
   var url = CreateUrl(t.Item1, start, end);
   webClient.DownloadStringAsync(new Uri(url),
     Tuple.Create(t, cevent, sum­maries, i));
 }
}
</pre>
Apoligies if the code for­mat­ting is shot!
Anyway thanks for a su­perb blog and apolo­gies if I have mis­un­der­stood how WebClient.DownloadStringAsync works.

Hi Tim,
You are right. Parallel.For is un­nec­es­sary and I could have used just one WebClient.
Thanks for point­ing this out.

I should­n’t speak with­out try­ing out the code. Now I did and you are half right and half wrong. Parallel.For is some­how un­nec­es­sary as you are not do­ing much work in there, but mul­ti­ple WebClients are needed.
Something along the line of your code gives:
Unhandled Exception: System.NotSupportedException: WebClient does not sup­port con­cur­rent I/O op­er­a­tions.
  at System.Net.WebClient.ClearWebClientState()
  at System.Net.WebClient.DownloadStringAsync(Uri ad­dress, Object user­To­ken)
  at ETFAnalyzer.Program.Main(String[] args) in C:ProjectsETFAnalyzerETFAnalyzerProgram.cs:line 238
I will change the code to use a sim­ple for loop.

I found an ex­pli­ca­tion of why the Parallel For may be use­ful with WebClient.DownloadStringAsync here: http://​www.in­for­mit.com/​blogs/​blog.aspx?uk=Is-this-re­ally-asyn­chro­nous. Basically, DownloadStringAsync is not en­tirely asyn­chro­nous. It does the DNS lookup *on*the*calling*thread* first. The com­ment at the end of the ref­er­eced url, ex­plains why it might be still worth us­ing a new thread to call each DownloadStringAsync even though that would ap­pear to dou­ble the num­ber of threads re­quired. (There are sep­a­rate IO and pro­cess­ing threads ap­par­ently)