Search Framework:
TimeSeriesBase
Namespace: WealthLab.Core
Parent: DateSynchedList<double>
Descendants: BarHistory , TimeSeries

TimeSeriesBase is an abstract class that contains the plumbing for working with a time series keyed off a list of DateTimes. It exposes this list through the DateTimes property, which is a List<DateTime>. Two important concrete classes derive from TimeSeriesBase:

  • TimeSeries - which manages a series of double values
  • BarHistory - which represents historical open, high, low, close and volume data
Members
Cache
public ConcurrentDictionary<string, object> Cache

A generic cache Dictionary that can be used to store objects during a backtest run. Certain indicators such as ADX, ADXR, DIPlus and DIMinus use the Cache to store the collection of indicators that are all calculated together as a group.

Example Code
using WealthLab.Backtest;
using System;
using WealthLab.Core;
using WealthLab.Indicators;
using WealthLab.ChartWPF;
using System.Drawing;
using System.Collections.Generic;

namespace WealthLab
{
	public class MyStrategy : UserStrategyBase
	{
		//the list of symbols that we should buy each bar
		private static List<BarHistory> buys = new List<BarHistory>();

		//create the weight indicator and stash it into the BarHistory object for reference in PreExecute
		public override void Initialize(BarHistory bars)
		{
			rsi = new RSI(bars.Close, 14);
			//store the RSI indicator in the cache, so it can be accessed when PreExecute is called
			bars.Cache["RSI"] = rsi;
		}

		//this is called prior to the Execute loop, determine which symbols have the lowest RSI
		public override void PreExecute(DateTime dt, List<BarHistory> participants)
		{
			//store the symbols' RSI value in their BarHistory instances
			foreach (BarHistory bh in participants)
			{
				RSI rsi = (RSI)bh.Cache["RSI"];
				int idx = GetCurrentIndex(bh);  //this returns the index of the BarHistory for the bar currently being processed
				double rsiVal = rsi[idx];
				bh.UserData = rsiVal; //save the current RSI value along with the BarHistory instance
			}

			//sort the participants by RSI value (lowest to highest)
			participants.Sort((a, b) => a.UserDataAsDouble.CompareTo(b.UserDataAsDouble));

			//keep the top 3 symbols
			buys.Clear();
			for (int n = 0; n < 3; n++)
			{
				if (n >= participants.Count)
					break;
				buys.Add(participants[n]);
			}
		}

		//execute the strategy rules here, this is executed once for each bar in the backtest history
		public override void Execute(BarHistory bars, int idx)
		{
			bool inBuyList = buys.Contains(bars);
			if (!HasOpenPosition(bars, PositionType.Long))
			{
				//buy logic - buy if it's in the buys list
				if (inBuyList)
					PlaceTrade(bars, TransactionType.Buy, OrderType.Market);
			}
			else
			{
				//sell logic, sell if it's not in the buys list
				if (!inBuyList)
					PlaceTrade(bars, TransactionType.Sell, OrderType.Market);
			}
		}

		//declare private variables below
		private RSI rsi;
	}
}

Count
public int Count

Returns the number of items contained in the time series. The DateTimes property list contains this many DateTimes. For TimeSeries, the Values property contains this many values. And for BarHistory, the Open, High, Low, Close and Volume properties (all instances of the TimeSeries class) contain this many values.

Example Code
using WealthLab.Backtest;
using System;
using WealthLab.Core;
using WealthLab.Indicators;
using WealthLab.ChartWPF;
using System.Drawing;
using System.Collections.Generic;

namespace WealthLab
{
	public class MyStrategy : UserStrategyBase
	{
		//do some analysis of 10, 20, 50, 100 bars ago
		public override void Initialize(BarHistory bars)
		{
			SetTextDrawingOptions(WLColor.Beige, WLColor.Black, 1);
			ReportGainAfterNBars(bars, 10);
			ReportGainAfterNBars(bars, 20);
			ReportGainAfterNBars(bars, 50);
			ReportGainAfterNBars(bars, 100);
		}
		private void ReportGainAfterNBars(BarHistory bars, int numBars)
		{
			int idx = bars.Count - numBars;
			if (idx >= 0)
			{
				double gain = bars.Close[bars.Count - 1] - bars.Close[idx];
				gain = gain * 100.0 / bars.Close[idx];
				DrawBarAnnotation(numBars + " bar gain: " + gain.ToString("N2") + "%", idx, false, WLColor.Black, 7);
				DrawLine(idx, bars.Close[idx], bars.Count - 1, bars.Close[bars.Count - 1], WLColor.Gray, 2, LineStyle.Dotted);
			}
		}

		public override void Execute(BarHistory bars, int idx)
		{
		}
	}
}

DateTimes
public virtual List<DateTime> DateTimes

A list of DateTime objects that represents the date/time of each item in the time series. The derived classes maintain other lists that are synchronized with DateTimes. TimeSeries maintains a list of floating point double Values. BarHistory has TimeSeries properties for Open, High, Low, Close, and Volume. All of these other lists will have exactly the same number of elements as the DateTImes list, allowing you to use the same index to access their elements interchangably.

Example Code
using WealthLab.Backtest;
using System;
using WealthLab.Core;
using WealthLab.Indicators;
using WealthLab.ChartWPF;
using System.Drawing;
using System.Collections.Generic;

namespace WealthLab
{
    public class MyStrategy : UserStrategyBase
    {
        //annotate the 100 bar high and low
        public override void Initialize(BarHistory bars)
        {
			double lowVal = Double.MaxValue;
			double highVal = Double.MinValue;
			int lowIdx = -1;
			int highIdx = -1;
			for (int n = bars.Count - 1; n > bars.Count - 100; n--)
			{
				if (n >= 0)
				{
					if (bars.Low[n] < lowVal)
					{
						lowVal = bars.Low[n];
						lowIdx = n;
					}
					if (bars.High[n] > highVal)
					{
						highVal = bars.High[n];
						highIdx = n;
					}
				}
			}
			if (lowIdx >= 0)
			{
				string txt = "100 bar low occurred on " + bars.DateTimes[lowIdx].ToLongDateString();
				DrawBarAnnotation(txt, lowIdx, false, WLColor.Red, 8);
			}
			if (highIdx >= 0)
			{
				string txt = "100 bar high occurred on " + bars.DateTimes[highIdx].ToLongDateString();
				DrawBarAnnotation(txt, highIdx, true, WLColor.Green, 8);
			}
        }

        public override void Execute(BarHistory bars, int idx)
        {
        }
    }
}

EndDate
public DateTime EndDate

Returns the last DateTime in the DateTimes property list. If the list is empty, returns DateTime.MaxValue.

Example Code
using WealthLab.Backtest;
using System;
using WealthLab.Core;
using WealthLab.Indicators;
using WealthLab.ChartWPF;
using System.Drawing;
using System.Collections.Generic;

namespace WealthLab
{
    public class MyStrategy : UserStrategyBase
    {
        //create indicators and other objects here, this is executed prior to the main trading loop
        public override void Initialize(BarHistory bars)
        {
			SetTextDrawingOptions(WLColor.AliceBlue, WLColor.Black, 1);
			string s = "Chart end date is " + bars.EndDate.ToLongDateString();
			DrawHeaderText(s);   
        }
	    
        public override void Execute(BarHistory bars, int idx)
        {
        }
    }
}

IndexOf
public int IndexOf(DateTime dt, bool exactMatchOnly = false)

Returns the index into the DateTimes property list that contains the DateTime specified in the dt parameter. If exactMatchOnly is false, and an exact match does not exist, the method returns the index following the closest matching DateTime, unless the requested DateTime falls completely outside the range of the list, in which case it returns -1. If exactMatchOnly is true and no exact match exists, the method returns -1.

Example Code
using WealthLab.Backtest;
using System;
using WealthLab.Core;
using WealthLab.Indicators;
using WealthLab.ChartWPF;
using System.Drawing;
using System.Collections.Generic;

namespace WealthLab
{
    public class MyStrategy : UserStrategyBase
    {
        //whoever figures out the significance of this date will receive a one month free Premium membership credit
        public override void Initialize(BarHistory bars)
        {
			WLColor green = WLColor.FromArgb(128, 0, 255, 0);
	        if (bars.Count == 0)
				return;
			for (int yr = bars.StartDate.Year; yr <= bars.EndDate.Year; yr++)
			{
				DateTime dt = new DateTime(yr, 8, 25);
				int idx = bars.IndexOf(dt);
				if (idx >= 0)
					SetBackgroundColor(bars, idx, green);
			}
        }

        public override void Execute(BarHistory bars, int idx)
        {
        }
    }
}

IsUpToDate
public virtual bool IsUpToDate(DateTime endDate)

Returns whether the historical data appears up to date, as of the DateTime specified in the endDate parameter. The method accounts for weekends, market holidays, and market open and closing times, when called from a BarHistory object.

Example Code
using WealthLab.Backtest;
using System;
using WealthLab.Core;
using WealthLab.Indicators;
using WealthLab.ChartWPF;
using System.Drawing;
using System.Collections.Generic;

namespace WealthLab
{
    public class MyStrategy : UserStrategyBase
    {
        //report on whether data needs updating
        public override void Initialize(BarHistory bars)
        {
			string txt;
			WLColor c;
			if (bars.IsUpToDate(DateTime.Now))
			{
				txt = "Data appears to be up to date";
				c = WLColor.Green;
			}
			else
			{
				txt = "Data appears to need updating!";
				c = WLColor.Red;
			}
			DrawHeaderText(txt, c);
        }

        public override void Execute(BarHistory bars, int idx)
        {
        }
    }
}

StartDate
public DateTime StartDate

Returns the first DateTime in the DateTimes property list. If the list is empty, returns DateTime.MinValue.

Example Code
using WealthLab.Backtest;
using System;
using WealthLab.Core;
using WealthLab.Indicators;
using WealthLab.ChartWPF;
using System.Drawing;
using System.Collections.Generic;

namespace WealthLab
{
    public class MyStrategy : UserStrategyBase
    {
        //create indicators and other objects here, this is executed prior to the main trading loop
        public override void Initialize(BarHistory bars)
        {
			SetTextDrawingOptions(WLColor.AliceBlue, WLColor.Black, 1);
			string s = "Chart start date is " + bars.StartDate.ToLongDateString();
			DrawHeaderText(s);   
        }
	    
        public override void Execute(BarHistory bars, int idx)
        {
        }
    }
}

TimeSpan
public TimeSpan TimeSpan

Returns a TimeSpan that encompasses the range of the DateTimes in the DateTimes property list. If there are fewer than two DateTimes in the list, returns a zero TimeSpan.

Example Code
using WealthLab.Backtest;
using System;
using WealthLab.Core;
using WealthLab.Indicators;
using WealthLab.ChartWPF;
using System.Drawing;
using System.Collections.Generic;

namespace WealthLab
{
    public class MyStrategy : UserStrategyBase
    {
        //display total amount of time covered in chart
        public override void Initialize(BarHistory bars)
        {
			string txt = "Chart data comprised of " + bars.TimeSpan.TotalHours.ToString("N0") + " total hours";
			DrawHeaderText(txt);
        }

        public override void Execute(BarHistory bars, int idx)
        {
        }
    }
}

UserData
public object UserData

Allows you to store ad-hoc data in a property of a BarHistory or TimeSeries instance. You can store object instances, or primitive values like ints or doubles.


UserDataAsDouble
public double UserDataAsInt

Allows you to access a value you stored in a BarHistory or TimeSeries UserData property as a double.


UserDataAsInt
public int UserDataAsInt

Allows you to access a value you stored in a BarHistory or TimeSeries UserData property as an int.