Here’s what I came up with for IDEA 2, above: “I’d like to run a backtest where all held securities are equally weighted. So after the 1st buy signal the security is weighted 100%. After the 2nd buy signal, each is weighted 50%, etc.”
I had to go with the low level backtester interface and do sells first to free up cash then {rescale open positions and do buys} weighted at -100/myNewPosCount.
Thanks to all for the helpful tips above and elsewhere in the forum.
//************************************************************************************************************************
// Options
//************************************************************************************************************************
Version( 6.20 );
SetOption("InitialEquity", 1000000 );
SetOption("MinShares", 0 );
SetOption("DisableRuinStop", True );
SetOption("FuturesMode", False );
SetOption("AllowPositionShrinking", True );
SetOption("AccountMargin", 100 ); // 100 = no margin
SetOption("CommissionMode", 1 ); // percent of trade
SetOption("CommissionAmount", 0.00 ); // no commissions
SetOption( "ExtraColumnsLocation", 1 );
SetTradeDelays( 0, 0, 0, 0 ); // no trade delays
//************************************************************************************************************************
// Model
//************************************************************************************************************************
FastMAbars = Optimize("Fast MA", 4, 2, 5, 1);
SlowMAbars = Optimize("Slow MA", 20, 6, 20, 1);
FastMA = MA( C, FastMAbars );
SlowMA = MA( C, SlowMAbars );
Buy = Cross( FastMA, SlowMA );
Sell = Cross( SlowMA, FastMA );
Buy = ExRem( Buy, Sell );
Sell = ExRem( Sell, Buy );
//************************************************************************************************************************
// Low-Level Backtester Interface
//************************************************************************************************************************
SetCustomBacktestProc( "" );
if( Status( "action" ) == actionPortfolio ) {
bo = GetBacktesterObject();
bo.PreProcess();
for( i = 0; i < BarCount; i++ ) {
// set N current positions, buy signals, sell signals, then calc myNewPosCount
myOldPosCount = 0; for( pos = bo.GetFirstOpenPos(); pos; pos = bo.GetNextOpenPos() ) { myOldPosCount++;}
myBuySigCount = 0;
mySellSigCount = 0;
for( sig = bo.GetFirstSignal( i ); sig; sig = bo.GetNextSignal( i ) ) {
if (sig.IsEntry() AND sig.IsLong()) {myBuySigCount++;}
if (sig.IsExit() AND sig.IsLong()) {mySellSigCount++;}
}
myNewPosCount = myOldPosCount + myBuySigCount - mySellSigCount;
// *** process exits first to create cash
for (sig = bo.GetFirstSignal(i); sig; sig = bo.GetNextSignal(i)) { if (sig.IsExit() AND sig.IsLong()) bo.ExitTrade(i, sig.Symbol, sig.Price); }
// *** rebalance current positions
for( pos = bo.GetFirstOpenPos(); pos; pos = bo.GetNextOpenPos() ) {
bo.ScaleTrade(i, pos.Symbol, (((0.9999*bo.Equity/myNewPosCount) - pos.GetPositionValue) > 0), pos.GetPrice(i,"C"), abs((bo.Equity/myNewPosCount) - pos.GetPositionValue));
}
// *** process entries
for (sig = bo.GetFirstSignal(i); sig; sig = bo.GetNextSignal(i)) {
if (sig.IsEntry() AND sig.IsLong()) {
sig.PosSize = -99.99/myNewPosCount;
bo.EnterTrade(i, sig.Symbol, True, sig.Price, sig.PosSize);
}
}
//bo.HandleStops(i); // system is stop-less
bo.UpdateStats(i,1);
bo.UpdateStats(i,2);
} //*** end i loop over bars ***
bo.PostProcess();
}