Search Framework:
TimeSeriesCompressor
Namespace: WealthLab.Core
Parent:

TimeSeriesCompressor is a static utility class containing methods that let you compress a TimeSeries instance from one scale down to a more compressed scale. For example, you can call TimeSeriesCompressor.ToWeekly to compress a daily TimeSeries into a weekly one.

If you want to be able to plot a compressed TimeSeries onto the chart, you would need to first expand it back to the original scale. You can use the TimeSeriesSynchronizer utility class to accomplish this.

Static Methods
ToDaily
public static TimeSeries ToDaily(TimeSeries source)
public static TimeSeries ToDaily(TimeSeries source, MarketDetails market)

Compresses the source TimeSeries to a daily scale, returning a new TimeSeries instance. If compressing a Globex-type market that trades through midnight, pass the MarketDetails.

Remarks

  • Since the day's intraday closing price will not always match the daily settled close, indicators calculated from intraday-scaled data will not match their daily counterparts.
  • Pay attention to the filter Pre/Post Market Data Strategy Setting to get the desired result.
  • Use BarHistoryCompressor.ToDaily to access a daily low, high, or open series. TimeSeriesCompressor will return the low, high, or open of the last intraday bar.
Example Code
using WealthLab.Backtest;
using System;
using WealthLab.Core;
using WealthLab.Indicators;
using System.Drawing;
using System.Collections.Generic;

namespace WealthScript3
{
	public class IntradayToDailyScaleExample : UserStrategyBase
	{
		//create indicators and other objects here, this is executed prior to the main trading loop
		public override void Initialize(BarHistory bars)
		{
			if (!bars.IsIntraday)
			{
				throw new InvalidOperationException("Example is intended for an intraday BarHistory");
			}

			TimeSeries dayCloses = TimeSeriesCompressor.ToDaily(bars.Close);
			IndicatorBase daySma = SMA.Series(dayCloses, 10);
			_dailyAvgInBaseScale = TimeSeriesSynchronizer.Synchronize(daySma, bars.Close);
			PlotTimeSeries(_dailyAvgInBaseScale, "Daily SMA(10)", "Price", WLColor.Blue, PlotStyle.Dots);

		}

		public override void Execute(BarHistory bars, int idx)
		{
			if (!HasOpenPosition(bars, PositionType.Long))
			{
				//buy at market when the intraday price crosses over the daily moving average
				if (bars.Close.CrossesOver(_dailyAvgInBaseScale, idx))
					PlaceTrade(bars, TransactionType.Buy, OrderType.Market);
			}
			else
			{
				//sell using a stop at the daily moving average price
				PlaceTrade(bars, TransactionType.Sell, OrderType.Stop, _dailyAvgInBaseScale[idx]);
			}
		}

		TimeSeries _dailyAvgInBaseScale;
	}
}

ToMinute
public static TimeSeries ToMinute(TimeSeries source, int interval, MarketDetails market)

Compresses the source TimeSeries to an interval-minute scale, returning a new BarHistory instance. The source should be an intraday TimeSeries having a scale with a higher granularity than the requested interval. For example, it makes sense to compress a source of 1 minute data to a 5 minute interval, but not the other way around. The market parameter, if assigned, should be a MarketDetails instance that is used to determine the open time of the market, for purposes of synchronizing the intraday correctly to market open. If not supplied, the open time of the market will be determined from the source data itself.

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

namespace WealthScript123
{
    public class IntradayCompressionSample : UserStrategyBase
    {
        //create indicators and other objects here, this is executed prior to the main trading loop
        public override void Initialize(BarHistory bars)
        {
			if (!bars.IsIntraday || bars.Scale.Interval > 15)
			{
				throw new InvalidOperationException("Example is intended for an intraday BarHistory - 1, 2, 3, 5, 10, or 15 minute bars");
			}

			// RSI(10) in the base (chart) intraday scale			
			_rsi = RSI.Series(bars.Close, 10);
			PlotIndicatorLine(_rsi);
			
			// create an RSI(10) from 30 minute compressed bars
			TimeSeries compClose = TimeSeriesCompressor.ToMinute(bars.Close, 30, bars.Market);
			_rsi2 = RSI.Series(compClose, 10);

			// expand to the base scale and plot
			_rsi2 = TimeSeriesSynchronizer.Synchronize(_rsi2, bars); 	
			PlotTimeSeriesLine(_rsi2, _rsi2.Description, _rsi.PaneTag, WLColor.Fuchsia);

		}

        //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))
            {
                // buy when rsi crosses over 35, but only if the compressed rsi is below 40
	            if (_rsi2[idx] < 40)
					if (_rsi.CrossesOver(35, idx))
						PlaceTrade(bars, TransactionType.Buy, OrderType.Market);
            }
            else
            {
				//code your sell conditions here
				if (_rsi.CrossesOver(60, idx))
					PlaceTrade(bars, TransactionType.Sell, OrderType.Market);
            }
        }

		//declare private variables below
		RSI _rsi;
		TimeSeries _rsi2;

    }
}

ToMonthly
public static TimeSeries ToMonthly(TimeSeries source)

Compresses the source TimeSeries to a monthly scale, returning a new TimeSeries instance.

Remarks

  • The base scale synchronizes with the final bar of the month
  • For intraday source scales, pay attention to the filter Pre/Post Market Data Strategy Setting to get the desired result.
  • Use BarHistoryCompressor.ToMonthly to access a monthly low, high, or open series. TimeSeriesCompressor will return the low, high, or open of the last source bar for the month.
Example Code
using WealthLab.Backtest;
using System;
using WealthLab.Core;
using WealthLab.Indicators;
using System.Drawing;
using System.Collections.Generic;

namespace WealthScript4
{
	public class BaseToMonthlyScaleExample : UserStrategyBase
	{
		//create indicators and other objects here, this is executed prior to the main trading loop
		public override void Initialize(BarHistory bars)
		{

			TimeSeries monthCloses = TimeSeriesCompressor.ToMonthly(bars.Close);
			IndicatorBase monthSma = SMA.Series(monthCloses, 12);
			_monthSmaInBaseScale = TimeSeriesSynchronizer.Synchronize(monthSma, bars.Close);
			PlotTimeSeries(_monthSmaInBaseScale, "Monthly SMA(12)", "Price", WLColor.Blue, PlotStyle.Dots);
		}

		public override void Execute(BarHistory bars, int idx)
		{
			if (!HasOpenPosition(bars, PositionType.Long))
			{
				//buy at market when the base scale's price is above the monthly moving average
				if (bars.Close[idx] > _monthSmaInBaseScale[idx])
					PlaceTrade(bars, TransactionType.Buy, OrderType.Market);
			}
			else
			{
				//sell at market when price is below the monthly moving average
				if (bars.Close[idx] < _monthSmaInBaseScale[idx])
					PlaceTrade(bars, TransactionType.Sell, OrderType.Market);
			}
		}

		TimeSeries _monthSmaInBaseScale;
	}
}

ToQuarterly
public static TimeSeries ToQuarterly(TimeSeries source)

Compresses the source TimeSeries to a quarterly scale, returning a new TimeSeries instance.

Remarks

  • The base scale synchronizes with the final bar of the quarter (end of: March, June, September, and December)
  • For intraday source scales, pay attention to the filter Pre/Post Market Data Strategy Setting to get the desired result.
  • Use BarHistoryCompressor.ToQuarterly to access a quarterly low, high, or open series. TimeSeriesCompressor will return the low, high, or open of the last source bar for the quarter.
Example Code
using WealthLab.Backtest;
using System;
using WealthLab.Core;
using WealthLab.Indicators;
using System.Drawing;
using System.Collections.Generic;

namespace WealthScript5
{
	public class BaseToQtrlyScaleExample : UserStrategyBase
	{
		//create indicators and other objects here, this is executed prior to the main trading loop
		public override void Initialize(BarHistory bars)
		{			
			TimeSeries qtrCloses = TimeSeriesCompressor.ToQuarterly(bars.Close);
			IndicatorBase qtrSma = SMA.Series(qtrCloses, 4);
			_qtrSmaInBaseScale = TimeSeriesSynchronizer.Synchronize(qtrSma, bars.Close);
			PlotTimeSeries(_qtrSmaInBaseScale, "Quarterly SMA(4)", "Price", WLColor.Blue, PlotStyle.Dots);
		}

		public override void Execute(BarHistory bars, int idx)
		{
			if (!HasOpenPosition(bars, PositionType.Long))
			{
				//buy at market when the base scale's price is above the quarterly moving average
				if (bars.Close[idx] > _qtrSmaInBaseScale[idx])
					PlaceTrade(bars, TransactionType.Buy, OrderType.Market);
			}
			else
			{
				//sell at market when price is below the quarterly moving average
				if (bars.Close[idx] < _qtrSmaInBaseScale[idx])
					PlaceTrade(bars, TransactionType.Sell, OrderType.Market);
			}
		}

		TimeSeries _qtrSmaInBaseScale;
	}
}

ToWeekly
public static TimeSeries ToWeekly(TimeSeries source)

Compresses the source TimeSeries to a weekly scale, returning a new TimeSeries instance.

Remarks

  • The base scale synchronizes with the final bar of the week
  • For intraday source scales, pay attention to the filter Pre/Post Market Data Strategy Setting to get the desired result.
  • Use BarHistoryCompressor.ToWeekly to access a weekly low, high, or open series. TimeSeriesCompressor will return the low, high, or open of the last source bar for the week.
Example Code
using WealthLab.Backtest;
using WealthLab.Core;
using WealthLab.Indicators;
using System.Drawing;

namespace WealthLab
{
	public class MyStrategy1 : UserStrategyBase
	{
		//create indicators and other objects here, this is executed prior to the main trading loop
		public override void Initialize(BarHistory bars)
		{
			//get weekly closing price
			TimeSeries weeklyClose = TimeSeriesCompressor.ToWeekly(bars.Close);

			//calculate 4-week RSI
			RSI rsiWeekly = RSI.Series(weeklyClose, 4);

			//expand it back to daily scale
			TimeSeries expandedRSI = TimeSeriesSynchronizer.Synchronize(rsiWeekly, bars);

			//plot it
			PlotTimeSeries(expandedRSI, "RSI(4-week)", "RSI", 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)
		{
		}

		//declare private variables below

	}
}

ToYearly
public static TimeSeries ToYearly(TimeSeries source)

Compresses the source TimeSeries to a yearly scale, returning a new TimeSeries instance.