- ago
I have two different TimeSeries, bars and pctRank, that come from different sources that need their DataTimes synchronized for a WriteToDebugLog statement in the Execute{} block. When they are correctly synchronized, the pctRanks of the second WriteToDebugLog statement should come out sorted. Right now they are scrambled. How do I fix this?


In the code below, only the WriteToDebugLog statements in the Execute block are relevant to the DateTimes sync problem. The rest of the code in only included for completeness. If you need my Local.Components.dll library to run this code, I can send it.
CODE:
using System; using System.Collections.Generic; using System.Drawing; using System.Text; using WealthLab.Core; using WealthLab.Backtest; using WealthLab.Indicators; using Superticker.Components; namespace WealthScript1 { public class SelSecTradeRank : UserStrategyBase {       public SelSecTradeRank()       {          AddParameter("Gain vs dip effect", ParameterTypes.Double, 1.00, 0.8, 1.8, 0.1)             .Hint="Influence of recent gain to merit ranking";          AddParameter("Dip recovery influence", ParameterTypes.Double, 0.90, 0.0, 0.9, 0.1)             .Hint="Recent dip recovery boost";          AddParameter("RegEMA affect", ParameterTypes.Double, 1, 0.0, 1.25, 0.25)             .Hint="EMA regularization";          SetChartDrawingOptions(WLUtil.HideVolume());       }       static List<BarHistory> topBuys = new List<BarHistory>();       static List<BarHistory> topHolds = new List<BarHistory>();       StringBuilder topBuysString = new StringBuilder(160);       public override void Initialize(BarHistory bars)       {          emaRegular = Parameters[2].AsDouble; //paramEmaRegular          meritScore = new TimeSeries(bars.DateTimes);          bars.Cache["MeritTS"] = meritScore; //Merit TimeSeries for sorting          decorrelated = RSDif.Decorrelate(bars);          bars.Cache["DecorrTS"] = decorrelated; //decorrelated TimeSeries          PlotTimeSeriesLine(decorrelated, bars.Symbol + " decorrelated", "decorrelated", Color.Green, 2, LineStyles.Solid);          SetPaneDrawingOptions("decorrelated", 150, -2);          RegEmaFit regEmaFit = new RegEmaFit(this as UserStrategyBase, decorrelated, "decorrelated", 0.4, emaRegular, decorrelated.Count, false);          PlotTimeSeriesLine(regEmaFit.YModelTS(), bars.Symbol + " regEMA", "decorrelated", Color.Red, 2, LineStyles.Dashed);          pctRank = bars.Close.PercentRank(220);          bars.Cache["PctRankTS"] = pctRank;          StartIndex = pctRank.FirstValidIndex;          PlotTimeSeriesLine(pctRank, bars.Symbol + " fractional rank", "percentRank", Color.YellowGreen, 2, LineStyles.Solid);          SetPaneDrawingOptions("percentRank", 60, 1);       }       //called once prior to the start of each bar; determine and sort by dipBuyMeritScore       public override void PreExecute(DateTime dt, List<BarHistory> participants)       {          double gainVsDip = Parameters[0].AsDouble; //paramGainVsDip          double rcntPerfBoost = Parameters[1].AsDouble; //paramRcntPerfBoost          double dipBuyMeritScore;          //for each fund in DataSet, calculate dipBuyMeritScore          foreach (BarHistory bars in participants)          {             decorrelated = (TimeSeries)bars.Cache["DecorrTS"];             int idx = GetCurrentIndex(bars); //rtn index of the BarHistory currently being processed             int lowestRecentBar = decorrelated.GetLowestBar(idx, 22); //lowest bar for past month             int gainBars = idx - lowestRecentBar; //#of bars to determine recent price gains (idx-1?)             pctRank = (TimeSeries)bars.Cache["PctRankTS"];             dipBuyMeritScore = 1 - pctRank[idx];             meritScore = (TimeSeries)bars.Cache["MeritTS"];             meritScore[idx] = dipBuyMeritScore;             bars.UserData = dipBuyMeritScore; //save merit score w/BarHistory instance          }          //sort highest meritScore values where participants[0]          participants.Sort((b,a) => a.UserDataAsDouble.CompareTo(b.UserDataAsDouble));          topBuys.Clear(); topHolds.Clear();          int nEndTop = Math.Min(3,participants.Count); //select top 3 funds          for (int n = 0; n < nEndTop; n++)          {             topBuys.Add(participants[n]);             topHolds.Add(participants[n]);             //WriteToDebugLog(string.Format("{0}=n {1:0.00}=meritScore",n,participants[n].UserDataAsDouble));          }          for (int n = nEndTop; n < Math.Min(11, participants.Count); n++) //hold top 20 funds          {             topHolds.Add(participants[n]);             //WriteToDebugLog(string.Format("{0}=n {1:0.00}=meritScore",n,participants[n].UserDataAsDouble));          }       }       public override void Execute(BarHistory bars, int idx)       {          //bool inBuyList = topBuys.Contains(bars);          if (HasOpenPosition(bars, PositionType.Long))          {             //sell logic, sell if stock is not in the topHolds list             if (!topHolds.Contains(bars))                PlaceTrade(bars, TransactionType.Sell, OrderType.Market);          }          else          {             //buy logic - buy if stock is in the topBuys list             if (topBuys.Contains(bars))             {                PlaceTrade(bars, TransactionType.Buy, OrderType.Market);                topBuysString.Clear();                foreach (BarHistory barsInTopList in topBuys)                {                   topBuysString.Append(barsInTopList.Symbol + " ");                }                DrawHeaderText("Buy " + bars.Symbol.Substring(1,3) + (idx+1).ToString(" @bar 000: ") + topBuysString.ToString(), Color.Green, 10, "decorrelated");                                topBuysString.Append("\n");                foreach (BarHistory barsInTopList in topHolds)                {                   pctRank = (TimeSeries)barsInTopList.Cache["PctRankTS"];                   WriteToDebugLog(bars.DateTimes[idx].ToShortDateString() + ", " + pctRank.DateTimes[idx].ToShortDateString());                   topBuysString.Append(string.Format("{0} {1:.00}, ",barsInTopList.Symbol.Substring(1,3),pctRank[idx]));                }                WriteToDebugLog("Buy " + bars.Symbol.Substring(1,3) + (idx+1).ToString(" @bar 000: ") + topBuysString.ToString());             }          }       }       public override void Cleanup(BarHistory bars)       {          meritScore = (TimeSeries)bars.Cache["MeritTS"];          PlotTimeSeries(meritScore, bars.Symbol + " merit scores", "meritScores", Color.DarkRed, PlotStyles.Dots);          SetPaneDrawingOptions("meritScores", 60, -1);       }       //shared strategy variables       double emaRegular;       TimeSeries meritScore,decorrelated,pctRank; } }
0
356
5 Replies

Reply

Bookmark

Sort
Cone8
 ( 24.57% )
- ago
#1
CODE:
         // IS:          pctRank = (TimeSeries)barsInTopList.Cache["PctRankTS"];                    // TRY THIS:          pctRank = TimeSeriesSynchronizer.Synchronize((TimeSeries)barsInTopList.Cache["PctRankTS"], bars.Close);
0
- ago
#2
That modification fixed the pctRank issue okay. Thanks a bunch! See fixed code below.

But the list of pctRank over the different funds (In the Execute WriteToDebugLog) remains scrambled when they should be sorted by design. See screenshot below. How can that be fixed?



Here's the new Execute code with the DateTime synchronization fix.
CODE:
      public override void Execute(BarHistory bars, int idx)       {          //bool inBuyList = topBuys.Contains(bars);          if (HasOpenPosition(bars, PositionType.Long))          {             //sell logic, sell if stock is not in the topHolds list             if (!topHolds.Contains(bars))                PlaceTrade(bars, TransactionType.Sell, OrderType.Market);          }          else          {             //buy logic - buy if stock is in the topBuys list             if (topBuys.Contains(bars))             {                PlaceTrade(bars, TransactionType.Buy, OrderType.Market);                topBuysString.Clear();                foreach (BarHistory barsInTopList in topBuys)                {                   topBuysString.Append(barsInTopList.Symbol + " ");                }                DrawHeaderText("Buy " + bars.Symbol.Substring(1,3) + (idx+1).ToString(" @bar 000: ") + topBuysString.ToString(), Color.Green, 10, "decorrelated");                                topBuysString.Append("\n");                foreach (BarHistory barsInTopList in topHolds)                {                   pctRank = TimeSeriesSynchronizer.Synchronize((TimeSeries)barsInTopList.Cache["PctRankTS"],bars);                   //pctRank = (TimeSeries)barsInTopList.Cache["PctRankTS"];                   WriteToDebugLog(bars.DateTimes[idx].ToShortDateString() + ", " + pctRank.DateTimes[idx].ToShortDateString());                   topBuysString.Append(string.Format("{0} {1:.00}, ",barsInTopList.Symbol.Substring(1,3),pctRank[idx]));                }                WriteToDebugLog("Buy " + bars.Symbol.Substring(1,3) + (idx+1).ToString(" @bar 000: ") + topBuysString.ToString());             }          }       }
Perhaps calling the Synchronizer within a ForEach loop isn't the best solution for efficiency if only one value is going to be used out of each pctRank TimeSeries. I appreciate that thought. But I'm just trying to get this to run for now. I'll go back and fix the efficiency issues later.
0
Glitch8
 ( 10.41% )
- ago
#3
I’m not at the computer at the moment, but a quick look at the circled numbers had me thinking that they appear sorted by numeric value to me. How did you want them to be sorted?
0
- ago
#4
QUOTE:
a quick look at the circled numbers had me thinking that they appear sorted by numeric value to me.
Interesting. You're right! I just paged through 20 of the funds in the DebugLog to verify that.

But they are sorted in inverted order from how they appear in the PreExecute sort.

UPDATE: I screwed up. The pctRank is flipped around from the meritScore (for buying the funds). That's why things look inverted. It's working as coded now. No problems I "think".
0
- ago
#5
I was able the rewrite the Execute block to replace "pctRank" with "meritScoreUnsync" and get rid of the Synchronize line for efficiency below. It is running "as designed". I only wish it made better money, but that's another problem.
CODE:
      public override void Execute(BarHistory bars, int idx)       {          if (HasOpenPosition(bars, PositionType.Long))          {             //sell logic, sell if stock is not in the topHolds list             if (!topHolds.Contains(bars))                PlaceTrade(bars, TransactionType.Sell, OrderType.Market);          }          else          {             //buy logic - buy if stock is in the topBuys list             if (topBuys.Contains(bars))             {                PlaceTrade(bars, TransactionType.Buy, OrderType.Market);                topBuysString.Clear();                foreach (BarHistory barsInTopList in topBuys)                {                   topBuysString.Append(barsInTopList.Symbol + " ");                }                DrawHeaderText("Buy " + bars.Symbol.Substring(1,3) + (idx+1).ToString(" @bar 000: ") + topBuysString.ToString(), Color.Green, 10, "decorrelated");                                topBuysString.Append("\n");                DateTime currentDate = bars.DateTimes[idx];                foreach (BarHistory barsInTopList in topHolds)                {                   //meritScore = TimeSeriesSynchronizer.Synchronize((TimeSeries)barsInTopList.Cache["MeritTS"],bars);                   TimeSeries meritScoreUnsync = (TimeSeries)barsInTopList.Cache["MeritTS"];                   //topBuysString.Append(string.Format("{0} {1:.00}, ",barsInTopList.Symbol.Substring(1,3),meritScore[idx]));                   topBuysString.Append(string.Format("{0} {1:.00}, ",barsInTopList.Symbol.Substring(1,3),meritScoreUnsync[meritScoreUnsync.IndexOf(currentDate)]));                }                WriteToDebugLog("Buy " + bars.Symbol.Substring(1,3) + (idx+1).ToString(" @bar 000: ") + topBuysString.ToString());             }          }       }

1

Reply

Bookmark

Sort