They use a relative strength + volatility based rating. I am sorting by returns for two different periods (A, B) and volatility over period V.
I had the code working and for some reason it stopped. The BarsInProgress var stays at 0 even though BarsArray has 10 elements in it. I can't understand why. The only thing I did is redefined session templates under instrument manager and downloaded more data from kinetic.
I would appreciate if someone could look at this prelim code and see if I am doing something stupid that I have overlooked.
Since I was only playing around I coded it as an indicator where you would be able to selects ETFs defined by an ENUM that would then be added to the primary data series. One would then be able to select the dates and the calculations would be done. For now the dates are hard coded and the script looks for the bar# of the selected date and does the computation. Print() statements are used to debug the code ... I have included a screen shot from yesterday when it was working ,,, today it only runs BarsInProgress = 0 and does't even end up doing the computation as it is called only once BarsInProgress == BarsArray.Length - 1
Please any input would be appreciated!
protected override void Initialize() { // instantiate the etf collections etf = new List<EtfData>(); // make sure this charts series is added to the list if (!etf.Exists(delegate(EtfData item) { return item.Label == Instrument.FullName; })) etf.Add(new EtfData(Instrument.FullName)); // fill the collections with the selected ETFs if (etfsel != EtfType.ALL) { if (!etf.Exists(delegate(EtfData item) { return item.Label == etfsel.ToString(); })) etf.Add(new EtfData(etfsel.ToString())); } else {// add all the ETFs ... // ... by itterating over the values in the enum foreach (EtfType value in Enum.GetValues(typeof(EtfType))) { if (value == EtfType.ALL) continue; // with the exception of EtfType.ALL ... if (!etf.Exists(delegate(EtfData item) { return item.Label == value.ToString(); })) etf.Add(new EtfData(value.ToString())); } } // debug: added etfs Print("added etf(s) :"); foreach (EtfData item in etf) Print(item.Label); Print(""); ClearOutputWindow(); // go through the collection of ETFs and add them as dataseries to BarsArray // note: the indicator's chart series is already in BarsArray on index 0, // with each addition the corresponding value of BarsInProgress increases by 1 foreach (EtfData item in etf) { if (item.Label == Instrument.FullName) continue; // dont add it (already in by default) else Add(item.Label, PeriodType.Day, ndays); } // temp code ... endDate = new DateTime(2012, 11, 05); startDate = new DateTime(2012, 08, 05); // ............. // create the DateTimeSeries for getting the date of current bar date = new DateTimeSeries(this); Overlay = false; } /// <summary> /// Called on each bar update event (incoming tick) /// </summary> protected override void OnBarUpdate() { // make sure we have the right bars period type if (BarsPeriod.Id != PeriodType.Day && BarsPeriod.Value < 1) return; if (CurrentBar == 0) { Print(""); Print("all data series in BarsArray :"); for (int i = 0; i < BarsArray.Length; i++) Print(BarsArray[i].Instrument.FullName); Print(""); Print(""); Print("start date: " + startDate.ToString()); Print("end date: " + endDate.ToString()); Print(""); } // make sure there are enough bars if (CurrentBar <= GetMaxPeriod()) // in this case <= because [barsago+1] below return; /// Bars are already loaded and OnBarUpdate() will run only on a new bar ! /// need to use GetBar() to get data for bars with the correct dates int endbar = Bars.GetBar(endDate); int barsago = CurrentBar - endbar; int barsagoA = barsago + periodA; int barsagoB = barsago + periodB; if (CurrentBar == endbar) {// perform computation once CurrentBar # and endDate bar # match // debug: flow control Print("Processing ETF << " + etf[BarsInProgress].Label + " >>"); Print("BarsInProgress = " + BarsInProgress.ToString()); Print("Current bar is # " + CurrentBar.ToString()); Print("Current end bar is # " + CurrentBar.ToString()); Print("GetMaxPeriod() = " + GetMaxPeriod().ToString()); Print(""); // degug: start/end bar prices /* Print("start bar close : " + Close[barsagoA].ToString()); Print("end bar close : " + Close[barsagoB].ToString()); */ /// use BarsInProgress to make sure it is saved to the correct data series // get the 1st return double rA = (Close[barsago] - Close[barsagoA]) / Close[barsagoA]; // get the 2nd return double rB = (Close[barsago] - Close[barsagoB]) / Close[barsagoB]; // volatility calculation ... // a) get the individual returns for the defined period and // b) store them in the data set double[] vreturns = new double[periodV]; for (int i = barsago + (periodV-1); i >= 0; i--) // itterate down from 19 to 0 values ago from barsago (20 values) vreturns[barsago] = ((Close[barsago] - Close[barsago+1]) / Close[barsago+1]); // compute volatility // a) using standard deviation and // b) anualize it by multipling it by 252 // where 252 = trading days in a year double v = StandardDeviation(vreturns, periodV) * Math.Sqrt(252); // save results to etf data etf[BarsInProgress].ReturnA = rA; etf[BarsInProgress].ReturnB = rB; etf[BarsInProgress].Volatility = v; if (BarsInProgress == etf.Count-1) // with all series saved { // go ahead computing the rank by ... // make a copy of the original data List<List<EtfData>> data = new List<List<EtfData>>(); // add 3 copies of etf data (one for each sort) data.Add(etf); data.Add(etf); data.Add(etf); // sort the data by returns (A, B) and Volatility (V) // ... need to reverse order for sorting by returns because we need high to low (default sort is low to high) foreach(List<EtfData> container in data) { switch(data.IndexOf(container)) { case A: container.Sort( delegate (EtfData item1, EtfData item2) { return item1.ReturnA.CompareTo(item2.ReturnA); }); container.Reverse(); break; case B: container.Sort( delegate (EtfData item1, EtfData item2) { return item1.ReturnB.CompareTo(item2.ReturnB); }); container.Reverse(); break; case V: container.Sort( delegate (EtfData item1, EtfData item2) { return item1.Volatility.CompareTo(item2.Volatility); }); break; } } // compute rankby order of all data foreach(List<EtfData> container in data) { foreach (EtfData item in container) { switch(data.IndexOf(container)) { case A: item.RankByA = container.IndexOf(item); break; case B: item.RankByB = container.IndexOf(item); break; case V: item.RankByV = container.IndexOf(item); break; } } } // compute overall rank using weights & save the results foreach(EtfData item in etf) { item.RankByA = data[0].Find(delegate (EtfData d) { return d.Label == item.Label; }).RankByA; item.RankByB = data[0].Find(delegate (EtfData d) { return d.Label == item.Label; }).RankByB; item.RankByV = data[0].Find(delegate (EtfData d) { return d.Label == item.Label; }).RankByV; item.FinalRank = item.RankByA*weightA + item.RankByB*weightB + item.RankByV*weightV; } // sort the final etf results etf.Sort( delegate (EtfData item1, EtfData item2) { return item1.FinalRank.CompareTo(item2.FinalRank); } ); // etf should now contain the final result order ! // debug: contents of data Print(""); Print("*********************"); Print(" RESULTS "); Print("*********************"); foreach (EtfData item in etf) { Print("# " + (etf.IndexOf(item) + 1).ToString()+ " Etf << " + item.Label + " >>"); Print("RA = " + (item.ReturnA * 100).ToString("0.0")); Print("RB = " + (item.ReturnB * 100).ToString("0.0")); Print("V = " + (item.Volatility * 100).ToString("0.0")); Print(""); } Print(""); } } }
Comment