This PosSizer was created by user 
Leszek Mazur. It facilitates backtesting of balancing a portfolio. It works in conjunction with specially prepared Strategy script and allows to optimize percentages of different symbols as well as the holding period. Below is the example Strategy code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using WealthLab;
using WealthLab.Indicators;
using WealthLab.PosSizers;
namespace WealthLab.Strategies
{
	public class RebalanceStrategy : WealthScript
	{
		/////////////////////////////////
		// config
		/////////////////////////////////
		bool debugOut = true;
		string entry1symbol = "Selected Symbol";
		string entry2symbol = "IEF";
		string entry3symbol = "GLD";
		int numEntries = 3;
		/////////////////////////////////
      
		StrategyParameter entry1portion;
		StrategyParameter entry2portion;
		StrategyParameter entry3portion;
		StrategyParameter holdingPeriod;
		Tuple[] symInfos;
		public RebalanceStrategy()
		{
			entry1portion = CreateParameter(entry1symbol + " portfolio percentage", 30, 0, 100, 5);
			entry2portion = CreateParameter(entry2symbol + " portfolio percentage", 30, 0, 100, 5);
			entry3portion = CreateParameter(entry3symbol + " portfolio percentage", 30, 0, 100, 5);
			holdingPeriod = CreateParameter("holding period", 60, 5, 200, 5);
         
			symInfos = new TuplenumEntries;
			MS123.PosSizers.BalancingPosSizer.SymInfos = symInfos;
		}
      
      
		private void OnLog(object sender, MS123.PosSizers.SizerMessageEventArgs args)
		{
			PrintDebug(args.Message);
		}
      
		protected override void Execute()
		{
			if (debugOut)
			{
				ClearDebug();
				MS123.PosSizers.BalancingPosSizer.ResetLog();
				MS123.PosSizers.BalancingPosSizer.LogMessage += OnLog;
			}
         
			// validation
			double total = 0;
			total += entry1portion.Value;
			total += entry2portion.Value;
			total += entry3portion.Value;
			if(total > 100)
			{
				if (debugOut)
					PrintDebug("Bailing out due to total percentage of holdings adding up to more than 100%, total=" + total);
				return;
			}
			entry1symbol = Bars.Symbol;
			Bars entry1bars = Bars;
			Bars entry2bars = GetExternalSymbol(entry2symbol, true);
			Bars entry3bars = GetExternalSymbol(entry3symbol, true);
			ChartPane pane0 = null;
			ChartPane pane1 = null;
         
			symInfos0 = new Tuple(entry1symbol,entry1portion.Value/100.0);
			symInfos1 = new Tuple(entry2symbol,entry2portion.Value/100.0);
			symInfos2 = new Tuple(entry3symbol,entry3portion.Value/100.0);
			pane0 = CreatePane(75, true, true);
			PlotSeries(pane0, entry2bars.Close, Color.BurlyWood, LineStyle.Solid, 2);
			pane1 = CreatePane(75, true, true);
			PlotSeries(pane1, entry3bars.Close, Color.BurlyWood, LineStyle.Solid, 2);
			int holding = 0;
			for (int bar = 0; bar < Bars.Count; bar++)
			{
				if(0 == holding)
				{
					if(entry1bars.FirstActualBar <= bar)
					{
						SetContext(symInfos0.Item1,true);
						BuyAtMarket(bar + 1, symInfos0.Item1 + " buy");
						if (debugOut)
							PrintDebug(symInfos0.Item1 + " Bought on " + Bars.Datebar + 1);
					}
					if(entry2bars.FirstActualBar <= bar)
					{
						SetContext(symInfos1.Item1,true);
						BuyAtMarket(bar + 1, symInfos1.Item1 + " buy");
						if (debugOut)
							PrintDebug(symInfos1.Item1 + " Bought on " + Bars.Datebar + 1);
					}
					if(entry3bars.FirstActualBar <= bar)
					{
						SetContext(symInfos2.Item1,true);
						BuyAtMarket(bar + 1, symInfos2.Item1 + " buy");
						if (debugOut)
							PrintDebug(symInfos2.Item1 + " Bought on " + Bars.Datebar + 1);
					}
					holding++;
				}
				else if(holding >= holdingPeriod.ValueInt)
				{
					foreach(Position p in Positions)
					{
						if(p.Active)
						{
							SellAtMarket(bar + 1, p, p.Symbol + " sell");
							if (debugOut)
								PrintDebug(p.Symbol + " Sold on " + Bars.Datebar + 1 + ", profit = " + p.NetProfitAsOfBarPercent(bar + 1));
						}
					}
					holding = 0;
				}
				else
					holding++;
			}
		}
	}
}