Presentation is loading. Please wait.

Presentation is loading. Please wait.

STAT682 Final Project Group 2 Iliya Atanasov Matthew Ginley Aaron Mielke Lisa Stryjewski John Varghese.

Similar presentations


Presentation on theme: "STAT682 Final Project Group 2 Iliya Atanasov Matthew Ginley Aaron Mielke Lisa Stryjewski John Varghese."— Presentation transcript:

1 STAT682 Final Project Group 2 Iliya Atanasov Matthew Ginley Aaron Mielke Lisa Stryjewski John Varghese

2 The Basics Hold 50 stocks for 1 year Rebalance every year according to fundamentals

3 Reproducing O’Shaughnessy Assisted by ClariFI (backtesting software) Sales / Price Earnings Per Share / Price Book / Price Dividends Per Share / Price

4 Our Approach Created our own backtesting code Started with Sales / Price Exhaustive coverage of all Compustat Variables Reviewed high coverage and high correlation ratios Selected an additional ratio to complement Sales / Price

5 Using ClariFI

6 ClariFI

7

8 Results from ClariFI

9 Sales to Price

10

11

12

13 EPS to Price

14

15

16

17 Book to Price

18

19

20

21 Dividend Yield

22

23

24

25 Writing our Own Simulator C# Source Code

26 1. Variables var priceIndex = Enumerable.Range(0, headers.Length).First(i => headers[i] =="prcc_c"); var dividendIndex = Enumerable.Range(0, headers.Length).First(i => headers[i] =="dvpsx_c"); var yearIndex = Enumerable.Range(0, headers.Length).First(i => headers[i] == "fyear"); var sharesIndex = Enumerable.Range(0, headers.Length).First(i => headers[i] =="CSHO"); var epsIndex = Enumerable.Range(0, headers.Length).First(i => headers[i] == "EPSPX"); var idIndex = Enumerable.Range(0, headers.Length).First(i => headers[i] == "gvkey"); var ajexIndex = Enumerable.Range(0, headers.Length).First(i => headers[i] =="adjex_c");

27 2. Market Capitalization var marketCapMinimums = new int[Years]; yearToStocks = Enumerable.Range(0, Years).Select(i => new Dictionary ()).ToArray(); for (var i = 0; i < marketCapMinimums.Length; i++) { var year = i + MinYear; if (year < 1955) marketCapMinimums[i] = 27; else if (year < 1959) marketCapMinimums[i] = 27; else if (year < 1964) marketCapMinimums[i] = 28; else if (year < 1969) marketCapMinimums[i] = 31; else if (year < 1974) marketCapMinimums[i] = 34; else if (year < 1979) marketCapMinimums[i] = 44; else if (year < 1984) marketCapMinimums[i] = 64; else if (year < 1989) marketCapMinimums[i] = 97; else if (year < 1994) marketCapMinimums[i] = 117; else if (year < 1996) marketCapMinimums[i] = 150; else marketCapMinimums[i] = 185; }

28 3.A Reading Data while ((line = reader.ReadLine()) != null) { if (++count%10000 == 0) Console.WriteLine(count + ": " + (double) reader.BaseStream.Position/(double) reader.BaseStream.Length); var parts = line.Split(','); double price, shares, dividend, eps, ajex; int year; if (double.TryParse(parts[priceIndex], out price) == false || price == 0.0) continue; if (double.TryParse(parts[sharesIndex], out shares) == false) continue; if (double.TryParse(parts[epsIndex], out eps) == false) continue; if (int.TryParse(parts[yearIndex], out year) == false) continue; var marketCap = price*shares; yearToMarketCaps[year - MinYear].Add(marketCap); var marketCapMinimum = marketCapMinimums[year - MinYear]; if (marketCap < marketCapMinimum) continue;

29 3.B Reading Data double.TryParse(parts[ajexIndex], out ajex); double.TryParse(parts[dividendIndex], out dividend); var id = int.Parse(parts[idIndex]); if (ajex <= 0.0) ajex = 1.0; var values = Enumerable.Range(0, parts.Length).Select( i => { double value; if (double.TryParse(parts[i], out value) == false) value =double.NaN; return value; }).ToArray(); yearToStocks[year - MinYear].Add(id, new Stock(id, price, shares, dividend, ajex, values)); yearToMeanMarketCap = yearToMarketCaps.Select( marketCaps => marketCaps.Count == 0 ? 0.0 : marketCaps.Average() ).ToArray(); }

30 4. Calculating Returns public void CalculateReturns(Stock nextYears) { if (nextYears == null) return; Return = Ajex * (nextYears.Price + nextYears.Dividend) / Price / nextYears.Ajex - 1.0; }

31 5.A Ranking Stocks Func, List > rankStocks = getTestValue => { var rankAndStock = new List (count); for (var year = 0; year < Years - 1; year++) { var testSortedStockList = yearToStocks[year].Values.ToArray(); var returnSortedIndexes = Enumerable.Range(0, testSortedStockList.Length).ToArray(); Array.Sort(testSortedStockList, (x, y) => getTestValue(x).CompareTo(getTestValue(y))); Array.Sort(testSortedStockList.Select(s => s.Return.Value).ToArray(), returnSortedIndexes);

32 5.B Ranking Stocks var returnRanks = GenerateRanks(testSortedStockList.Length, i => testSortedStockList[returnSortedIndexes[i]], stock => stock.Return.Value); var testRanks = GenerateRanks(testSortedStockList.Length, i => testSortedStockList[i], getTestValue); for (var returnSortedIndex = 0; returnSortedIndex < returnSortedIndexes.Length; returnSortedIndex++) { var testSortedIndex = returnSortedIndexes[returnSortedIndex]; var stock = testSortedStockList[testSortedIndex]; if (double.IsNaN(getTestValue(stock))) continue; rankAndStock.Add(new RanksAndStock(testRanks[testSortedIndex], returnRanks[returnSortedIndex], stock)); } return rankAndStock; };

33 6. Pearson private static double CalculatePearson(IEnumerable ranksAndStocks) { var n = ranksAndStocks.Count(); var sumReturn = ranksAndStocks.Sum(ranksAndStock => ranksAndStock.ReturnRank); var sumReturnSquared = ranksAndStocks.Sum( ranksAndStock => ranksAndStock.ReturnRank*ranksAndStock.ReturnRank); var returnDifferences = ((n*sumReturnSquared) - (sumReturn*sumReturn)); var sumTest = ranksAndStocks.Sum(ranksAndStock => ranksAndStock.TestRank); var sumTestSquared = ranksAndStocks.Sum( ranksAndStock => ranksAndStock.TestRank*ranksAndStock.TestRank); var sumTestReturn = ranksAndStocks.Sum( ranksAndStock => ranksAndStock.TestRank*ranksAndStock.ReturnRank); var denom = Math.Sqrt(returnDifferences*((n*sumTestSquared) - (sumTest*sumTest))); var pearson = (n*sumTestReturn - (sumReturn*sumTest))/denom; return pearson; }

34 7. Single Values using (var writer = new StreamWriter("singles.csv")) { writer.WriteLine("column,r,%"); Parallel.For( 0, headers.Length, //new ParallelOptions{ MaxDegreeOfParallelism = 1}, header => { Func getTestValue = stock => stock.Values[header]; var rankAndStock = rankStocks(getTestValue); var pearson = CalculatePearson(rankAndStock); var temp = header + ":" + headers[header] + "," + pearson + "," + ((double) rankAndStock.Count/count); Console.WriteLine(temp); lock (writer) writer.WriteLine(temp); if (double.IsNaN(pearson) == false) lock (validColumns) validColumns.Add(header); }); }

35 8.A Ratios using (var writer = new StreamWriter("ratios.csv")) { writer.WriteLine("numerator,denominator,r,%"); Parallel.For( 0, validColumns.Count, //new ParallelOptions{ MaxDegreeOfParallelism = 1}, numeratorIndex => Parallel.For( 0, validColumns.Count, //new ParallelOptions{ MaxDegreeOfParallelism = 1}, denominatorIndex => { try { var numerator = validColumns[numeratorIndex]; var denominator = validColumns[denominatorIndex]; if (numerator == denominator) return;

36 8.B Ratios if (System.Threading.Interlocked.Increment(ref progress)%1000 == 0) Console.WriteLine("******* " + progress + "/" + total + "=" + ((double) progress/total) + " *******"); Func getTestValue = stock => stock.Values[numerator]/stock.Values[denominator]; var rankAndStock = rankStocks(getTestValue); var pearson = CalculatePearson(rankAndStock); var temp = numerator + ":" + headers[numerator] + "," + denominator + ":" + headers[denominator] + "," + pearson + "," + ((double) rankAndStock.Count/count); Console.WriteLine(temp); lock (writer) writer.WriteLine(temp); } catch (Exception e) { try { using (var errors = new StreamWriter("errors.txt", true)) errors.WriteLine(e.ToString()); } catch {} } })); }

37 9.A Multipliers using (var writer = new StreamWriter("multipliers.csv")) { writer.WriteLine("first,second,r,%"); Parallel.For( 0, validColumns.Count, //new ParallelOptions{ MaxDegreeOfParallelism = 1}, firstIndex => Parallel.For( 0, validColumns.Count, //new ParallelOptions{ MaxDegreeOfParallelism = 1}, secondIndex => { try { var first = validColumns[firstIndex]; var second = validColumns[secondIndex]; if (System.Threading.Interlocked.Increment(ref progress)%1000 == 0) Console.WriteLine("******* " + progress + "/" + total + "=” + ((double) progress/total) + " *******");

38 9.B Multipliers Func getTestValue = stock => stock.Values[first]*stock.Values[second]; var rankAndStock = rankStocks(getTestValue); var pearson = CalculatePearson(rankAndStock); var temp = first + ":" + headers[first] + "," + second + ":" + headers[second] + "," + pearson + "," + ((double) rankAndStock.Count/count); Console.WriteLine(temp); lock (writer) writer.WriteLine(temp); } catch (Exception e) { try { using (var errors = new StreamWriter("errors.txt", true)) errors.WriteLine(e.ToString()); } catch {} } ]})); }

39 10. Strategies var nameToTest = new Dictionary > { { "EPS_OVER_Price", stock => -stock.Values[258] / stock.Values[944]}, { "-EPS_OVER_Price", stock => stock.Values[258] / stock.Values[944]}, { "EBITDA_over_EV", stock => -stock.Values[250] / (stock.Values[944] * stock.Values[149] + stock.Values[194] + stock.Values[153] - stock.Values[109])}, { "Sales_OVER_Price", stock => -stock.Values[705] / stock.Values[944]}, { "Sales_OVER_Price_PLUS_IBCOM_OVER_NI", stock => -stock.Values[705] / stock.Values[944] + -stock.Values[352] / stock.Values[513]}, { "Dividends_OVER_Price", stock => -stock.Values[943] / stock.Values[944]}, { "IBCOM_OVER_NI", stock => -stock.Values[352] / stock.Values[513]} };

40 11.A Strategy Simulation for (var large = 0; large < 2; large++) { var strategies = nameToTest.ToArray(); for (var i = 0; i < nameToTest.Count; i++) { Func strategy; string name; if(i < nameToTest.Count) { strategy = strategies[i].Value; name = strategies[i].Key; } else { name = "Combo”; strategy = stock => { return strategies.Select(s => s.Value(stock)).Where(d => double.IsNaN(d) == false).Average(); }; }

41 11.B Strategy Simulation var largeName = large == 0 ? "_large" : string.Empty; using (var writer = new StreamWriter("returns_" + name + largeName + ".csv")) { writer.WriteLine("Year,Average Return"); Parallel.For( 1, Years - 1, new ParallelOptions {MaxDegreeOfParallelism = 1}, year => { var testSortedStockList = yearToStocks[year - 1].Values.ToArray(); if (large == 0) testSortedStockList = testSortedStockList.Where(s => s.Price * s.Shares >= yearToMeanMarketCap[year]).ToArray(); Array.Sort(testSortedStockList, (x, y) => strategy(x).CompareTo(strategy(y)));

42 11.C Strategy Simulation var returns = new List (); for (var index = 0; index < testSortedStockList.Length && returns.Count < 50; index++) { var lastYearsStock = testSortedStockList[index]; if (double.IsNaN(strategy(lastYearsStock))) continue; Stock thisYearsStock; if (yearToStocks[year].TryGetValue(lastYearsStock.ID, out thisYearsStock) == false) continue; returns.Add(thisYearsStock.Return.Value); } var line = (year + MinYear) + "," + (returns.Count() == 0 ? 0.0 : returns.Average()) + "," + string.Join(",", returns.Select(r => r.ToString())); Console.WriteLine(line); lock (writer) writer.WriteLine(line); }); }

43 12.A Unused CRSP Data using (var reader = new StreamReader(@"d:\data\stat\just price2.csv")) { string line; var priceHeaders = reader.ReadLine().Split(','); var idIndex = Enumerable.Range(0, priceHeaders.Length).First(i => priceHeaders[i] == "gvkey"); var dateIndex = Enumerable.Range(0, priceHeaders.Length).First(i => priceHeaders[i] == "datadate"); var priceIndex = Enumerable.Range(0, priceHeaders.Length).First(i => priceHeaders[i] == "PRCCM"); count = 0;

44 12.B Unused CRSP Data while ((line = reader.ReadLine()) != null) { if (++count%10000 == 0) Console.WriteLine(count + ": " + (double) reader.BaseStream.Position/(double) reader.BaseStream.Length); var parts = line.Split(','); double price; var date = DateTime.ParseExact(parts[dateIndex], "yyyyMMdd”, CultureInfo.InvariantCulture, DateTimeStyles.None); if (date.Month != 12) continue; var id = int.Parse(parts[idIndex]); if (double.TryParse(parts[priceIndex], out price) == false || price == 0.0) continue; yearToStockToPrice[date.Year - MinYear][id] = price; }

45 Our Results

46 Sales to Price (All Stocks)

47

48 Sales to Price (Large Stocks)

49

50 IBCOM to NI (All Stocks)

51

52 IBCOM to NI (Large Stocks)

53

54 S/P + IBCOM/NI (All Stocks)

55

56 S/P + IBCOM/NI (Large Stocks)

57


Download ppt "STAT682 Final Project Group 2 Iliya Atanasov Matthew Ginley Aaron Mielke Lisa Stryjewski John Varghese."

Similar presentations


Ads by Google