Search Framework:
BarHistory
Namespace: WealthLab.Core
Parent: TimeSeriesBase

The BarHistory class represents historical price and volume data for a market. When you work with code-based Strategies, you're passed an instance of a BarHistory object in the Initialize, Execute, and other methods. This instance contains the historical data your Strategy should backtest.

A "bar" of data contains an open price, a high, low and closing price. The BarHistory class exposes these through Open, High, Low, and Close properties, each of which is an instance of the TimeSeries class. Volume information is available via the Volume property, also a TimeSeries instance. Use the DateTimes property to access the list of DateTimes that these time series are keyed off of.

Alternate Price Components
AveragePriceHL
public TimeSeries AveragePriceHL

Calculates and returns the average price TimeSeries (high + low) / 2.

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

namespace WealthScript3
{
	public class MyStrategy : UserStrategyBase
	{
		//plot the average price, both versions
		public override void Initialize(BarHistory bars)
		{
			PlotTimeSeries(bars.AveragePriceHL, "Average Price", "Price", WLColor.Blue, PlotStyle.Line);
			PlotTimeSeries(bars.AveragePriceHLC, "Average Price w/Close", "Price", WLColor.Red, PlotStyle.Line);
		}

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

AveragePriceHLC
public TimeSeries AveragePriceHLC

Calculates and returns the average price TimeSeries (high + low + close) / 3.

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

namespace WealthScript3
{
	public class MyStrategy : UserStrategyBase
	{
		//plot the average price, both versions
		public override void Initialize(BarHistory bars)
		{
			PlotTimeSeries(bars.AveragePriceHL, "Average Price", "Price", WLColor.Blue, PlotStyle.Line);
			PlotTimeSeries(bars.AveragePriceHLC, "Average Price w/Close", "Price", WLColor.Red, PlotStyle.Line);
		}

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

AveragePriceHLCC
public TimeSeries AveragePriceHLCC

Calculates and returns the average price TimeSeries (high + low + close + close) / 4.

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

namespace WealthScript3
{
	public class MyStrategy : UserStrategyBase
	{
		//plot the average price, both versions
		public override void Initialize(BarHistory bars)
		{
			PlotTimeSeries(bars.AveragePriceOHLC, "Average Price OHLC", "Price", WLColor.Red, PlotStyle.Line);
			PlotTimeSeries(bars.AveragePriceHLCC, "Average Price w/ Double-weight Close", "Price", WLColor.Blue, PlotStyle.Line);
			PlotTimeSeries(bars.AveragePriceOC, "Average Price Open-Close", "Price", WLColor.Purple, PlotStyle.Line);
		}

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

AveragePriceOC
public TimeSeries AveragePriceOC

Calculates and returns the average price TimeSeries (open + close) / 2.

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

namespace WealthScript3
{
	public class MyStrategy : UserStrategyBase
	{
		//plot the average price, both versions
		public override void Initialize(BarHistory bars)
		{
			PlotTimeSeries(bars.AveragePriceOHLC, "Average Price OHLC", "Price", WLColor.Red, PlotStyle.Line);
			PlotTimeSeries(bars.AveragePriceHLCC, "Average Price w/ Double-weight Close", "Price", WLColor.Blue, PlotStyle.Line);
			PlotTimeSeries(bars.AveragePriceOC, "Average Price Open-Close", "Price", WLColor.Purple, PlotStyle.Line);
		}

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

AveragePriceOHLC
public TimeSeries AveragePriceOHLC

Calculates and returns the average price TimeSeries (open + high + low + close) / 4.

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

namespace WealthScript3
{
	public class MyStrategy : UserStrategyBase
	{
		//plot the average price, both versions
		public override void Initialize(BarHistory bars)
		{
			PlotTimeSeries(bars.AveragePriceOHLC, "Average Price OHLC", "Price", WLColor.Red, PlotStyle.Line);
			PlotTimeSeries(bars.AveragePriceHLCC, "Average Price w/ Double-weight Close", "Price", WLColor.Blue, PlotStyle.Line);
			PlotTimeSeries(bars.AveragePriceOC, "Average Price Open-Close", "Price", WLColor.Purple, PlotStyle.Line);
		}

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


Constructors
BarHistory
public BarHistory(string symbol, HistoryScale scale)
public BarHistory(string symbol, Frequency scale)
public BarHistory(BarHistory parent)

BarHistory has three constructors. The first assigns the Symbol and Scale based on the passed parameters. The second assigns the Symbol and creates a HistoryScale instance based on the passed Frequency enum value. The third takes a BarHistory as a parameter (parent), and assigns the various property values from that instance to the new BarHistory instance.



Event Data
EventDataPoints
public List<EventDataPoint> EventDataPoints

Returns a list of EventDataPoint instances that represents the event data that has been loaded along with the historical data.

Remarks

  • For intraday charts EventDataPoints will synchronize to the first bar of the Event Date.
Example Code
using WealthLab.Backtest;
using System;
using WealthLab.Core;
using WealthLab.Data;
using WealthLab.Indicators;
using WealthLab.ChartWPF;
using System.Drawing;
using System.Collections.Generic;

namespace WealthLab
{
    public class MyStrategy : UserStrategyBase
    {
        //report last event item
        public override void Initialize(BarHistory bars)
        {
	        if (bars.EventDataPoints.Count == 0)
				return;
			EventDataPoint fdp = bars.EventDataPoints[bars.EventDataPoints.Count - 1];
			DrawHeaderText($"Most recent event data occurred on {fdp.Date:yyyy-MM-dd}", WLColor.Red, 14);
			DrawHeaderText($"It was of type {fdp.Name} and value: {fdp.Value:N4}", WLColor.Red, 14);
        }

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

GetEventDataPoints
public List<EventDataPoint> GetEventDataPoints(string name)
public List<EventDataPoint> GetEventDataPoints(string name, int idx)

Returns a list of EventDataPoint instances for the event data specified in the name parameter. Specify the idx overload to return list of EventDataPoint only for events that occurred on the bar number idx.

Remarks

  • Event Providers can use the same name string. If there's a chance of duplication, put a checkmark next to the Event Provider desired and uncheck the rest. And/or you can test the EventDataPoint.ProviderName property to ensure you use the desired Provider.
Example Code
using WealthLab.Backtest;
using WealthLab.Core;
using WealthLab.Data;
using System.Drawing;

namespace WealthScript1
{
	public class MyStrategy2 : UserStrategyBase
	{
		//assumes an EventProvider with a "Dividend" item has been updated
		public override void Initialize(BarHistory bars)
		{
			if (bars.EventDataPoints.Count > 0)
			{
				foreach (EventDataPoint edp in bars.GetEventDataPoints("Dividend"))
				{
					WriteToDebugLog(edp.ProviderName + "\t" + edp.Name + "\t" + bars.IndexOf(edp.Date, false) + "\t" + edp.Value);
				}
			}
		}

		//execute the strategy rules here, this is executed once for each bar in the backtest history
		public override void Execute(BarHistory bars, int idx)
		{
		}
	}
}


Futures Mode
FuturesMode
public bool FuturesMode

Set by the backtester, returns true if Futures Mode was enabled for this backtest.


Margin
public double Margin

The amount of capital required to open a 1 share/contract position. In Futures Mode, the backtester uses Margin to determine the position's cost basis.


PointValue
public double PointValue

The point value for each 1 point move of the share/contract. In Futures Mode, the backtester multiplies a position's profit by PointValue.


TickSize
public double TickSize

The minimum resolution for a position's quantity. In Futures Mode, the backtester adjusts a position's quantity based on TickSize.



Members
Add
public int Add(DateTime dt, double o, double h, double l, double c, double v)

Allows you to add an datetime/open/high/low/close/volume group of values to this BarHistory. Normally you won't need to directly add values to a BarHistory. This method is most useful in the development of custom Historical Data Source extensions.


AddTradingDays
public DateTime AddTradingDays(int bar, int days)

Returns the date after adding the specified number of trading days to the DateTime of the specified bar.


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;
	}
}

Close
public TimeSeries Close

Returns a TimeSeries that represents the closing prices.

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 information about the most recent trading day
        public override void Initialize(BarHistory bars)
        {
			DrawHeaderText($"Closing price for the most recent trading day was: {bars.Close[bars.Count - 1]:C2}", WLColor.Red, 14);
        }

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

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)
        {
        }
    }
}

DisplayDecimals
public int DisplayDecimals

The number of decimals places to use when displaying price data.


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, WLColor.Red, 14);
        }
	    
        public override void Execute(BarHistory bars, int idx)
        {
        }
    }
}

ExtendedBars
public int ExtendedBars

You can assign a value to ExtendedBars to create projected space along the right edge of the chart. The chart is filled with a number of future date/time values equal to the value you assign to ExtendedBars. The projected OHLC/V are assigned Double.NaN.

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
	{
		//project 20 bar price trend 20 bars into the future
		public override void Initialize(BarHistory bars)
		{
			if (bars.Count < 20)
				return;
			int x1 = bars.Count - 20;
			double y1 = bars.Close[x1];
			int x2 = bars.Count - 1;
			double y2 = bars.Close[x2];
			DrawLine(x1, y1, x2, y2, WLColor.Teal, 2, LineStyle.Solid, "Price", false, true);
			bars.ExtendedBars = 20;
		}

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

GetNamedSeries
public TimeSeries GetNamedSeries(string name)

Returns the "Named TimeSeries" if it has been registered in the BarHistory object by specific data providers; otherwise, returns null.

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

namespace WealthScript6
{
	public class MyStrategy : UserStrategyBase
	{
		// Run this on a DataSet with defined Custom series

		// For example:
		//DATE;TIME;VOLUME;OPEN;CLOSE;MIN;MAX
		//06/08/2007;22:36:41;0;21.83;21.83;21.83;21.83
		//06/08/2007;22:36:51;0;21.83;21.83;21.83;21.83
		//06/08/2007;22:37:01;0;21.83;21.83;21.83;21.83
		// Will output the value of the 'Min' column

		public override void Initialize(BarHistory bars)
		{
			TimeSeries min = bars.GetNamedSeries("MIN");
		
			if (min?.Count > 0)
			{
				for(int i = 0; i < min.Count; i++)
					WriteToDebugLog(min[i]);
			}
		}

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

GetTimeAsInt
public int GetTimeAsInt(int bar)

Returns an integer value for the time of day. For example, returns 930 for 9:30 AM, but returns 2130 for 9:30 PM.

Remarks

  • See also GetTime() method inherited from TimeSeriesBase, which returns a TimeSpan type.
Example Code
using WealthLab.Backtest;
using System;
using WealthLab.Core;
using WealthLab.Indicators;
using System.Drawing;
using System.Collections.Generic;

namespace WealthScript1
{
	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)
		{
		}

		//execute the strategy rules here, this is executed once for each bar in the backtest history
		public override void Execute(BarHistory bars, int idx)
		{
			Position p = LastPosition;

			if (!HasOpenPosition(bars, PositionType.Long))
			{
				//one trade per day
				if (p == null || !p.IsOpen && p.EntryBar < (idx - bars.IntradayBarNumber(idx)))  // one trade per day
				{
					//buy on the first bar after 10:15AM
					if (bars.GetTimeAsInt(idx) >= 1015)
						PlaceTrade(bars, TransactionType.Buy, OrderType.Market);
				}

			}
			else
			{
				//sell on the first bar after 12:30PM
				if (bars.GetTimeAsInt(idx) >= 1230)
					ClosePosition(p, OrderType.Market);
			}
		}
	}
}

HasStreamingBar
public bool HasStreamingBar

Returns true if BarHistory has streaming bar. This property is not intended to be used in Strategy code, and will return inconsistent results. Rather, it is intended for use in Chart Style and other Extension development.


High
public TimeSeries High

Returns a TimeSeries that represents the high prices.

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 information about the most recent trading day
        public override void Initialize(BarHistory bars)
        {
			DrawHeaderText("High price for the most recent trading day was: $" + bars.High[bars.Count - 1].ToString("N2"));
        }

        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
    {
        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)
        {
        }
    }
}

IntradayBarNumber
public int IntradayBarNumber

Returns the intraday bar number of the day for intraday data. If the Bars object contains non-intraday data, IntradayBarNumber always returns -1. The first bar of a particular date returns 0, the next bar returns 1, and so on.

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

namespace WealthScript1
{
	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)
		{
			// Check for intraday data
			if (bars.Scale.IsIntraday)
			{
				// Color the middle of the trading day
				// First determine how many bars there are in one day
				int MaxBars = 0;
				double pct;

				for (int bar = bars.Count - 1; bar > -1; bar--)
					if (bars.IntradayBarNumber(bar) == 0)
					{
						MaxBars = bars.IntradayBarNumber(bar - 1);
						break;
					}
				if (MaxBars == 0)
					return;

				// Now color the bars 40 - 60% within the day's range            
				for (int bar = 0; bar < bars.Count; bar++)
				{
					pct = (double)bars.IntradayBarNumber(bar) / MaxBars;
					if ((pct >= 0.4) & (pct <= 0.6))
						SetBarColor(bars, bar, WLColor.Blue);

				}
			}
		}

		//execute the strategy rules here, this is executed once for each bar in the backtest history
		public override void Execute(BarHistory bars, int idx)
		{			
		}
	}
}

IsFirstBarOfDay
public bool IsFirstBarOfDay(int idx)

Returns true if the specified index is the first bar of data for the day. Useful for intraday Strategies.

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
	{
		//visually accent the first and last bars of the trading day
		public override void Execute(BarHistory bars, int idx)
		{
			if (bars.IsFirstBarOfDay(idx))
				SetBackgroundColor(bars, idx, WLColor.AliceBlue);
			if (bars.IsLastBarOfDay(idx))
				SetBackgroundColor(bars, idx, WLColor.Beige);
		}
	}
}

IsGap
public bool IsGap(int bar)

Returns true if the opening price has gapped up or down (see IsGapUp and IsGapDown) at given bar.

Example Code
using WealthLab.Backtest;
using WealthLab.Core;
using System.Drawing;

namespace WealthScript1
{
	public class MyStrategy : UserStrategyBase
	{
		public override void Initialize(BarHistory bars)
		{
		}

		public override void Execute(BarHistory bars, int idx)
		{
			if (bars.IsGap(idx))
				SetBackgroundColor(bars, idx, WLColor.FromArgb(30, WLColor.Silver));
		}
	}
}

IsGapDown
public bool IsGapDown(int bar)

Returns true if the opening price has gapped down at given bar. For this function, a gap is when the Open of bar is less than the previous bar's Low.

Example Code
using WealthLab.Backtest;
using WealthLab.Core;
using System.Drawing;

namespace WealthScript1
{
	public class MyStrategy : UserStrategyBase
	{
		public override void Initialize(BarHistory bars)
		{
		}

		public override void Execute(BarHistory bars, int idx)
		{
			if (bars.IsGapDown(idx))
				SetBackgroundColor(bars, idx, WLColor.FromArgb(30, WLColor.Red));
		}
	}
}

IsGapUp
public bool IsGapUp(int bar)

Returns true if the opening price has gapped up at given bar. For this function, a gap is when the Open of bar is greater than the previous bar's High.

Example Code
using WealthLab.Backtest;
using WealthLab.Core;
using System.Drawing;

namespace WealthScript1
{
	public class MyStrategy : UserStrategyBase
	{
		public override void Initialize(BarHistory bars)
		{
		}

		public override void Execute(BarHistory bars, int idx)
		{
			if (bars.IsGapUp(idx))
				SetBackgroundColor(bars, idx, WLColor.FromArgb(30, WLColor.Green));
		}
	}
}

IsLastBarOfDay
public bool IsLastBarOfDay(int idx)

Returns true if the specified index is the last bar of data for the regular trading session. Useful for intraday Strategies.

Remarks

  • Pass idx + 1 for minute-based strategies to determine if the next bar is the last bar of the session. You can use the result to place a trade at the start of the last bar of the day.
  • The method is designed to used with the Pre/Post Filter enabled.
  • Bars with timestamps after the session close time (post market) will also return true.
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
	{
		//visually accent the first and last bars of the trading day
		public override void Execute(BarHistory bars, int idx)
		{
			if (bars.IsFirstBarOfDay(idx))
				SetBackgroundColor(bars, idx, WLColor.AliceBlue);
			if (bars.IsLastBarOfDay(idx))
				SetBackgroundColor(bars, idx, WLColor.Beige);
		}
	}
}

IsLastTradingDayOfMonth
public bool IsLastTradingDayOfMonth(int bar)

Returns true if bar falls on the last trading day of a calendar month for the specifed BarHistory, otherwise false.

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

namespace WealthScript123
{
	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)
		{
		}

		//execute the strategy rules here, this is executed once for each bar in the backtest history
		public override void Execute(BarHistory bars, int idx)
		{
			//highlight the bar(s) on the last trading day of the month
			if (bars.IsLastTradingDayOfMonth(idx))
				SetBackgroundColorAllPanes(bars, idx, WLColor.FromArgb(40, WLColor.Blue));

		}
	}
}

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)
        {
        }
    }
}

Low
public TimeSeries Low

Returns a TimeSeries that represents the low prices.

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 information about the most recent trading day
        public override void Initialize(BarHistory bars)
        {
			DrawHeaderText("Low price for the most recent trading day was: $" + bars.Low[bars.Count - 1].ToString("N2"));
        }

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

Market
public MarketDetails Market

Returns an instance of the MarketDetails class that contains information about the market that the symbol belongs to. This instance is populated by the historical data provider that was used to obtain the data for the symbol.

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 information about the historical data
        public override void Initialize(BarHistory bars)
        {
			MarketDetails md = bars.Market;
			DrawHeaderText("Trades on the " + md.Name + " market, which operated in the " + md.BaseTimeZone + " zone");
        }

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

NamedSeries
public Dictionary<string, TimeSeries> NamedSeries

The NamedSeries property returns a list of all of the "Named TimeSeries" that have been registered in the BarHistory object. Named DataSeries can be registered with a BarHistory object by specific data providers. A common example of a possible Named TimeSeries is open interest for futures data. Another example are additional data fields that are imported in ASCII files.

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

namespace WealthScript6
{
	public class MyStrategy : UserStrategyBase
	{
		// Run this on a DataSet with defined Custom series

		// For example:
		//DATE;TIME;VOLUME;OPEN;CLOSE;MIN;MAX
		//06/08/2007;22:36:41;0;21.83;21.83;21.83;21.83
		//06/08/2007;22:36:51;0;21.83;21.83;21.83;21.83
		//06/08/2007;22:37:01;0;21.83;21.83;21.83;21.83
		// Will output 'Min' and 'Max'

		public override void Initialize(BarHistory bars)
		{
			if (bars.NamedSeries.Count > 0)
			{
				foreach (var ns in bars.NamedSeries)
					WriteToDebugLog(ns.Key);
			}
		}

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

NextOptionExpiryDate
public DateTime NextOptionExpiryDate(int bar)

Returns DateTime of the next closest monthly options expiration date as of the specified bar. Options expiration dates typically fall on the third Friday of every month.

Remarks

  • Returns the current date if it is an expiry date
  • If expiry Friday is a holiday, returns Thursday's date prior to the holday.
Example Code
using WealthLab.Backtest;
using System;
using WealthLab.Core;
using WealthLab.Indicators;
using System.Drawing;
using System.Collections.Generic;

namespace WealthScript123
{
	public class MyStrategy : UserStrategyBase
	{

		public override void Initialize(BarHistory bars)
		{
		}


		public override void Execute(BarHistory bars, int idx)
		{
			//make the background light	blue on	option expiry day
			if (bars.DateTimes[idx].IsOptionExpiry())
				SetBackgroundColor(bars, idx, WLColor.FromArgb(40, WLColor.Blue));

			if (!HasOpenPosition(bars, PositionType.Long))
			{
				//buy 4	trading	day	before the next	option expiry
				//using BarHistory method
				int daysToExpiry = bars.TradingDaysBetweenDates(bars.DateTimes[idx], bars.NextOptionExpiryDate(idx));

				//since	we buy on next bar,	test for 5 days
				if (daysToExpiry == 5)
					PlaceTrade(bars, TransactionType.Buy, OrderType.Market);
			}
			else
			{
				//get the expiry after the position	entry bar
				DateTime expiryAfterEntry = bars.NextOptionExpiryDate(LastPosition.EntryBar);

				//now get the following	expiry date using the DateTime extension method
				DateTime nextExpiry = expiryAfterEntry.AddDays(1).NextOptionExpiryDate(bars);

				int daysToExpiry = bars.TradingDaysBetweenDates(bars.DateTimes[idx], nextExpiry);

				//sell 11 trading days before the next expiry
				if (daysToExpiry == 12)
					PlaceTrade(bars, TransactionType.Sell, OrderType.Market);
			}
		}
	}
}

Open
public TimeSeries Open

Returns the TimeSeries that represents the open prices.

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 information about the most recent trading day
        public override void Initialize(BarHistory bars)
        {
			DrawHeaderText("Open price for the most recent trading day was: $" + bars.Open[bars.Count - 1].ToString("N2"));
        }

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

QuantityDecimals
public int QuantityDecimals

The number of decimal places to use when calculating the number of shares/contracts in a position.


ReadFromBinaryFile
public void ReadFromBinaryFile(string fileName, DateTime startDate, DateTime endDate, int maxBars)

Reads back a binary file in the Wealth-Lab 8 supported format (created programmatically or via WriteToBinaryFile). Specify the fileName, start and end dates to load the data, and maximum bars of data to load.

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

namespace WealthScript1
{
	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)
		{
			//download AAPL data
			string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
			BarHistory bh = GetHistoryUnsynched("AAPL", bars.Scale);
			//write it to a WL8 binary file on Desktop
			bh.WriteToBinaryFile(path);

			//create a blank BarHistory
			BarHistory fromFile = new BarHistory(bars);
			//read back the AAPL data from file
			fromFile.ReadFromBinaryFile(path, DateTime.MinValue, DateTime.MaxValue, 0);

			//plot it
			PlotBarHistory(fromFile, "AAPL");
		}

		//execute the strategy rules here, this is executed once for each bar in the backtest history
		public override void Execute(BarHistory bars, int idx)
		{
			if (!HasOpenPosition(bars, PositionType.Long))
			{
				//code your buy conditions here
			}
			else
			{
				//code your sell conditions here
			}
		}

		//declare private variables below

	}
}

RemoveAt
public void RemoveAt(int idx)

Removes the datetime/open/high/low/close/volume values from this BarHistory at the index specified in the idx parameter. You generally won't need to remove bars of data during normal Strategy development.


Scale
public HistoryScale Scale

The scale of the data being represented, as an instance of the HistoryScale class.

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 information about the historical data
        public override void Initialize(BarHistory bars)
        {
			DrawHeaderText("Symbol " + bars.Symbol + " has " + bars.Count + " bars of " + bars.Scale.Description + " data");
        }

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

SecurityName
public string SecurityName

The security name being represented, if available. For example, "Apple, Inc." for Apple corporation. Not all data sources provide a security name.

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 information about the historical data
		public override void Initialize(BarHistory bars)
		{
			string name = bars.SecurityName == "" ? bars.Symbol : bars.SecurityName;
			DrawHeaderText(name + " has " + bars.Count + " bars of data");
		}

		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)
        {
        }
    }
}

StreamingBar
public BarData StreamingBar

Returns an instance of BarData with its properties if the BarHistory object contains a streaming bar.


SubTradingDays
public DateTime SubTradingDays(int bar, int days)

Returns the date after subtracting the specified number of trading days to the DateTime of the specified bar.


Symbol
public string Symbol

The symbol being represented. For example, "MSFT" for Microsoft Corporation stock.

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 information about the historical data
        public override void Initialize(BarHistory bars)
        {
			DrawHeaderText("Symbol " + bars.Symbol + " has " + bars.Count + " bars of data");
        }

        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)
        {
        }
    }
}

TomorrowIsLastTradingDayOfWeek
public bool TomorrowIsLastTradingDayOfWeek(int bar)

Returns true if the next trading day is the last trading day of the week (Sunday through Saturday), otherwise false.

Tip!
Identify the current bar index as the last or first day of the week just by subtracting 1 or 2, respectively from the bar passed to the index. See example.

Remarks

  • Valid for Daily and Intraday frequencies.
  • Returns false for all other frequencies (Weekly, Monthly, etc.)
Example Code
using WealthLab.Backtest;
using System;
using WealthLab.Core;
using WealthLab.Indicators;
using System.Drawing;
using System.Collections.Generic;

namespace WealthScript9 
{
	public class MyStrategy : UserStrategyBase
	{
		public override void Initialize(BarHistory bars)
		{
			StartIndex = 2;
		}

		public override void Execute(BarHistory bars, int idx)
		{
			//use the function to identify the current bar as the first day of the week
			if (bars.TomorrowIsLastTradingDayOfWeek(idx - 2))
				DrawBarAnnotation(TextShape.DiamondHollow, idx, true, WLColor.NeonGreen, 14); 
			
			if (!HasOpenPosition(bars, PositionType.Long))
			{
				//buy at close on the last day of the week
				if (bars.TomorrowIsLastTradingDayOfWeek(idx))
					PlaceTrade(bars, TransactionType.Buy, OrderType.MarketClose);
			}
			else
			{
				//sell on the first day of the next week
				PlaceTrade(bars, TransactionType.Sell, OrderType.Market);
			}
		}
	}
}

TradingDaysBetweenDates
public int TradingDaysBetweenDates(DateTime dt1, DateTime dt2)

Returns the number of trading days between the specified dates. The value will be positive number if dt2 is later than dt1, and a negative number if dt2 is before dt1.

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

namespace WealthScript123
{
	public class MyStrategy : UserStrategyBase
	{

		public override void Initialize(BarHistory bars)
		{
		}


		public override void Execute(BarHistory bars, int idx)
		{
			//make the background light	blue on	option expiry day
			if (bars.DateTimes[idx].IsOptionExpiry())
				SetBackgroundColor(bars, idx, WLColor.FromArgb(40, WLColor.Blue));

			if (!HasOpenPosition(bars, PositionType.Long))
			{
				//buy 4	trading	day	before the next	option expiry
				//using BarHistory method
				int daysToExpiry = bars.TradingDaysBetweenDates(bars.DateTimes[idx], bars.NextOptionExpiryDate(idx));

				//since	we buy on next bar,	test for 5 days
				if (daysToExpiry == 5)
					PlaceTrade(bars, TransactionType.Buy, OrderType.Market);
			}
			else
			{
				//get the expiry after the position	entry bar
				DateTime expiryAfterEntry = bars.NextOptionExpiryDate(LastPosition.EntryBar);

				//now get the following	expiry date using the DateTime extension method
				DateTime nextExpiry = expiryAfterEntry.AddDays(1).NextOptionExpiryDate(bars);

				int daysToExpiry = bars.TradingDaysBetweenDates(bars.DateTimes[idx], nextExpiry);

				//sell 11 trading days before the next expiry
				if (daysToExpiry == 12)
					PlaceTrade(bars, TransactionType.Sell, OrderType.Market);
			}
		}
	}
}

TradingDaysRemaining
public int TradingDaysRemaining(int bar, Frequency interval)

Returns the number of trading days remaining in the specified Frequency interval enum, not including the trading day for the bar index. Valid Frequency enums for this function are Weekly, Monthly, Quarterly, Yearly.

For example, if Bars.DateTimes[bar].DayOfWeek is DayOfWeek.Friday, TradingDaysRemaining(bar, Frequency.Weekly) would return 0. Likewise if it's DayOfWeek.Tuesday, it would return 3, assuming no market holidays.

Example Code
using System;
using WealthLab.Core;
using WealthLab.Backtest;
using WealthLab.Indicators;
using Polly.Fallback;

namespace WealthScript123
{
    public class MyStrategy : UserStrategyBase
    {
		Parameter _period;
		SMA _ma;

        public override void Initialize(BarHistory bars)
        {
			_ma = SMA.Series(bars.Close, 20);
			PlotIndicator(_ma);
			StartIndex = 20;
        }

        public override void Execute(BarHistory bars, int idx)
        {
			int trdaysremain = bars.TradingDaysRemaining(idx, Frequency.Weekly);			
			DrawBarAnnotation(trdaysremain.ToString(), idx, true, WLColor.Red, 10);
			
            if (!HasOpenPosition(bars, PositionType.Long))
            {
				// don't open a trade on the last day of the week
				if (trdaysremain > 0 && bars.Close.CrossesOver(_ma, idx))		
				{
					Transaction t = PlaceTrade(bars, TransactionType.Buy, OrderType.Market); 					
				}
            }
            else
            {
				Position p = LastPosition;
				// exit at market on the morning of the last day of the week
				
				if (bars.IsLastBarOfDay(idx))				
					if (trdaysremain == 1)		// trigger signals the day *before*
						ClosePosition(p, OrderType.Market);
            }
        }
    }
}

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.


Volume
public TimeSeries Volume

Returns a TimeSeries that represents the volume data.

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 information about the most recent trading day
        public override void Initialize(BarHistory bars)
        {
			DrawHeaderText("Volume  for the most recent trading day was: " + bars.Volume[bars.Count - 1].ToString("N2"));
        }

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

WriteToBinaryFile
public void WriteToBinaryFile(string fileName)

Writes a BarHistory object to a binary file in the format supported by Wealth-Lab 8 on the disk at the specified location.

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

namespace WealthScript1
{
	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)
		{
			//download AAPL data
			string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
			BarHistory bh = GetHistoryUnsynched("AAPL", bars.Scale);
			//write it to a WL8 binary file on Desktop
			bh.WriteToBinaryFile(path);

			//create a blank BarHistory
			BarHistory fromFile = new BarHistory(bars);
			//read back the AAPL data from file
			fromFile.ReadFromBinaryFile(path, DateTime.MinValue, DateTime.MaxValue], 0);

			//plot it
			PlotBarHistory(fromFile, "AAPL");
		}

		//execute the strategy rules here, this is executed once for each bar in the backtest history
		public override void Execute(BarHistory bars, int idx)
		{
			if (!HasOpenPosition(bars, PositionType.Long))
			{
				//code your buy conditions here
			}
			else
			{
				//code your sell conditions here
			}
		}

		//declare private variables below

	}
}