Balancing PosSizer

Modified on 2015/04/22 07:55 by Eugene — Categorized as: PosSizers

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<string, double>[] 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 Tuple<string, double>[numEntries]; 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; symInfos[0] = new Tuple<string, double>(entry1symbol,entry1portion.Value/100.0); symInfos[1] = new Tuple<string, double>(entry2symbol,entry2portion.Value/100.0); symInfos[2] = new Tuple<string, double>(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(symInfos[0].Item1,true); BuyAtMarket(bar + 1, symInfos[0].Item1 + " buy"); if (debugOut) PrintDebug(symInfos[0].Item1 + " Bought on " + Bars.Date[bar + 1]); } if(entry2bars.FirstActualBar <= bar) { SetContext(symInfos[1].Item1,true); BuyAtMarket(bar + 1, symInfos[1].Item1 + " buy"); if (debugOut) PrintDebug(symInfos[1].Item1 + " Bought on " + Bars.Date[bar + 1]); } if(entry3bars.FirstActualBar <= bar) { SetContext(symInfos[2].Item1,true); BuyAtMarket(bar + 1, symInfos[2].Item1 + " buy"); if (debugOut) PrintDebug(symInfos[2].Item1 + " Bought on " + Bars.Date[bar + 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.Date[bar + 1] + ", profit = " + p.NetProfitAsOfBarPercent(bar + 1)); } } holding = 0; } else holding++; } } } }