[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[amibroker] Re: CBT: Force full investment



PureBytes Links

Trading Reference Links

Anybody? . . . 

Thx,

PS

--- In amibroker@xxxxxxxxxxxxxxx, "vlanschot" <vlanschot@xxx> wrote:
>
> Yes, still struggling with this one, so I would appreciate any 
> guidance from the CBT-experts, like Graham, GP, and Ed (and TJ, of 
> course). I've included a stripped-down version of my CBT-code (see 
> below) which you may use to verify my strange observations. 
> 
> // CODE SECTION
> 
> // USE on WEEKLY DATA !!!
> 
> FullYr=52;
> AnnPer=52;
> QtrPer=13;
> MonthPer=4;
> WeekPer=1;
> DayPer=1/5;
> 
> ShortTrades = ParamToggle("Short Trades?","No|Yes",1);
> 
> MaxOpenPos = 50; // maximum total positions 
> //MaxShort = Param("ChoiceMaxShort",round((MaxOpenPos / 100) * 
> 50),0,MaxOpenPos);
> 
> SetOption("MaxOpenPositions",MaxOpenPos);
> 
> Startkapitaal = 1000000;
> 
> SetOption("InitialEquity", Startkapitaal);
> 
> if (ShortTrades==1)
> {
> 	MaxLong = round((MaxOpenPos / 100) * 50);
> 	MaxShort = round((MaxOpenPos / 100) * 50);
> 	TypePos = "_LS";
> 	LongPS = ShortPS = -100/(MaxLong+MaxShort); 
> }
> else if (ShortTrades==0)
> {
> 	MaxLong = MaxOpenPos;
> 	MaxShort = 0;
> 	TypePos = "_LO";
> 	LongPS = -100/(MaxLong+MaxShort);
> 	ShortPS = 0; 
> }
> 
> NaamBT = "~Trial_LS_";
> 
> BM = "MSWRLD$";
> 
> BMI=Foreign(BM,"C");
> 
> MA1 = Param("MA1",AnnPer,6*MonthPer,AnnPer,MonthPer);
> MA2 = Param("MA2",MonthPer,5*MonthPer,5*MonthPer,MonthPer);
> 
> Mom = ROC(C,MA1)-ROC(C,MA2);
> BMMom= ROC(BMI,MA1)-ROC(BMI,MA2);
> RelMom = Mom-BMMom;
> 
> Buy=RelMom>=0; Sell=RelMom<0;
> PositionScore=RelMom;
> 
> if (ShortTrades==1)
> {
> 	Short=Sell; Cover=Buy;
> }
> else Short=Cover=0;
> 
> PositionSize= IIf(Buy,LongPS,IIf(Short,ShortPS,0));
> 
> if (Interval()==inWeekly OR Interval() == inMonthly)
> BuyPrice=SellPrice=ShortPrice=CoverPrice=Open;
> else BuyPrice=SellPrice=ShortPrice=CoverPrice=Close;
> 
> TextOutput = ParamToggle("Raw Text Output?", "No|Yes");
> 
> UseCBT = ParamToggle("Use CBT?", "No|Yes",1);
> 
> FBT=LastValue(ValueWhen(Status("firstbarintest")==1,BarIndex()));
> LBT=LastValue(ValueWhen(Status("lastbarintest")==1,BarIndex()));
> 
> SetOption("UseCustomBacktestProc", UseCBT ); 
> 
> if( Status("action") == actionPortfolio )
> {
> 	bo = GetBacktesterObject();
> 	
> 	bo.PreProcess(); // Initialize backtester
> 	
> 	for(bar=0; bar<BarCount; bar++) 
> 	{	
> 		NrOpenPos = 0;
> 		NrOpenLongs = 0;
> 		NrOpenShorts = 0;		
> 		NrNewLongs = 0;
> 		NrNewShorts = 0;
> 		numExits = 0;
> 		
> 		bContinueLong = bContinueShort = True;
> 
> 		// First, list Exit Signals, and execute exit trades
> 		for ( sig=bo.GetFirstSignal(bar); sig; 
> sig=bo.GetNextSignal(bar) )
> 		{
> 			if (sig.IsExit() AND sig.Price != -1 ) 
> 			{
> 				// Exit Trade
> 				GoExit = bo.ExitTrade
> (bar,sig.symbol,sig.Price);
> 				
> 				if (GoExit==1) numExits = numExits + 
> 1;
> 			}
> 		}
> 		
> 		if (TextOutput==1)
> 		{bo.RawTextOutput("Nr Exits = " + numExits ); 
> bo.UpdateStats(bar,0);}
> 		
> 		//Second, establish remaining nr open positions
> 		for( pos = bo.GetFirstOpenPos(); pos; pos = 
> bo.GetNextOpenPos() ) 
>     {
>     	if (pos.IsLong) {LS =1; NrOpenLongs = NrOpenLongs+1;}
>     	else if (!pos.IsLong){ LS = -1; NrOpenShorts = NrOpenShorts + 
> 1;}
>     	// All pos are open, so pos.IsOpen not necessary
>         
>     	NrOpenPos = NrOpenPos + 1;
>     }
>     
>     if (TextOutput==1)
> 		{
> 			bo.RawTextOutput("Nr Open Longs = " + 
> NrOpenLongs);
> 			bo.RawTextOutput("Nr Open Shorts = " + 
> NrOpenShorts);
> 			bo.RawTextOutput("Nr Open Posits = " + 
> NrOpenPos);
> 		}
> 		
> 		if (NrOpenLongs>=MaxLong) bContinueLong = False;
> 		if (NrOpenShorts>=MaxShort) bContinueShort = False;
> 
> 		
> 		// update stats
> 		bo.UpdateStats(bar,0);
> 		
> 		Kas=bo.Cash; Eq = bo.Equity;
> 		
> 		if (bar>1) NewPosSize = Nz((Kas[bar]/numExits)/Eq[bar]
> *100, 100/MaxOpenPos);
> 		else NewPosSize = 100/MaxOpenPos ;
> 		
> 		LongPS = ShortPS = -NewPosSize;
> 		
> 		if (TextOutput==1) bo.RawTextOutput("New PosSize = " 
> + -NewPosSize );
> 		
> 		// Next, look for conditional Entry Signals
> 		for ( sig=bo.GetFirstSignal(bar); sig ; 
> sig=bo.GetNextSignal(bar)) 
> 		{
> 			if( sig.IsEntry() AND sig.Price != -1 AND 
> IsNull( bo.FindOpenPos( sig.Symbol ) ) ) 
> 			{
> 				// Enter Long
> 				if( sig.IsLong() AND NrNewLongs <= 
> (MaxLong-NrOpenLongs) AND bContinueLong)
> 				{
> 					GoLong = bo.EnterTrade(bar, 
> sig.symbol, True, sig.Price, LongPS );
> 					
> 					if( GoLong == 0 ) 
> bContinueLong = False;//If trade doesn't go through don't do 
anymore 
> trades
> 					else 
> 					NrNewLongs = NrNewLongs + 1;
> 					
> 				} 
> 				// Enter Short
> 				else if ( sig.IsLong()==0 AND 
> NrNewShorts <= (MaxShort - NrOpenShorts) AND bContinueShort)
> 				{
> 					GoShort = bo.EnterTrade(bar, 
> sig.symbol, False, sig.Price, ShortPS);
> 					
> 					if( GoShort == 0 ) 
> bContinueShort = False;//If trade doesn't go through don't do 
anymore 
> trades
> 					else NrNewShorts = 
> NrNewShorts + 1;
> 				}
> 			}
> 		}
> 		
> 		if (TextOutput==1)
> 		{
> 			bo.RawTextOutput("Nr NewLong = " + 
> NrNewLongs);
> 			bo.RawTextOutput("Nr NewShort = " + 
> NrNewShorts );
> 			bo.RawTextOutput("Cash End = " + Kas[bar] );
> 		}
> 		
> 		bo.ProcessTradeSignals( bar ); 		
> 	}
> 	
> 	bo.PostProcess(1);// Finalize backtester, but (1) means: do 
> NOT list trades
>    // i.e. use  AddCustomMetric (see below) to add custom metrics 
to 
> BT-report.
>    	
>   SumProfitPerRisk = 0; 
>   NumTrades = 0; 
>   
>   // ADDED LINE
>   dt = DateTime(); 
> 
>   AddToComposite( Foreign
("~~~EQUITY","C"), "~~"+NaamBT+TypePos, "C", 
> atcFlagDefaults | atcFlagEnableInPortfolio );
> 	AddToComposite( Foreign
> ("~~~EQUITY","L"), "~~"+NaamBT+TypePos, "L", atcFlagDefaults | 
> atcFlagEnableInPortfolio );
> 	
> 	CategoryAddSymbol("~~"+NaamBT+TypePos,	categoryGroup	,
> 	250	);
> 	
> 	Eq = Foreign("~~"+NaamBT+TypePos,"C");
> 	
> 	WBM = BMI = Foreign(BM, "C"); 
> 
>   BMR=ROC(WBM,1)/100;
> 	PFRet=ROC(Eq,1)/100;
> 
> 	ThisTestLB=LBT-FBT;
>   SystPerfFullP=(Eq[LBT]/StartKapitaal-1)*100;
>   
>   BMPerfFullP=(BMI[LBT]/BMI[FBT]-1)*100;
>   
>   SystRetsFullP=PFRet;
> 	
>   bo.AddCustomMetric("Other Stats (OTP = over test-period):","" );
> 	bo.AddCustomMetric("Relative Performance OTP (%)", 
> SystperfFullP-BMPerfFullP);
> 
>   bo.ListTrades(); 
> }
> 
> // END OF CODE
> 
> As you can see, the code:
> 
> 1) executes (and counts) all exits, in order to release as much 
cash 
> as possible;
> 2) determines the number of remaining long/short open positions;
> 3) switches the bContinueLong/-Short trigger to FALSE, as soon as 
the 
> open-long, respectively open-short positions are equal to the 
> respective prespecified maximum positions;
> 4) enters in the signal loop, executes long, respectively short 
> trades UNTIL (again) it hits the respective maximum positions. 
> 
> In short, I would like to hold an equal number (default: 25) of 
long 
> and short positions, and I had hoped that this code would achieve 
> this. However, if you run this, it shows, for example:
> 
> Nr Exits = 1
> Nr Open Longs = 23
> Nr Open Shorts = 26
> Nr Open Posits = 49
> 
> So, although the number of remaining open positions (49) correctly 
> reflects the required maximum open positions (50) minus any exits, 
it 
> also (and strangely) regularly shows that the number of open-longs 
or 
> open-shorts during the backtest exceed the maximum required 
> long/shorts. And this is not caused by a lack of long/short signals.
> 
> I don't understand this, although it could simply be a case 
of "code-
> blindness" with an easy solution. Again, any help much appreciated.
> 
> PS
> 
> 
> --- In amibroker@xxxxxxxxxxxxxxx, Graham <kavemanperth@> wrote:
> >
> > You need to actually check how many open positions you have after 
> the
> > exits and thus how many new trades you need to enter. You can do 
> this
> > with openpos loop
> > Then use bo.Cash to determine the position size for the new 
entries
> > 
> > -- 
> > Cheers
> > Graham Kav
> > AFL Writing Service
> > http://www.aflwriting.com
> > 
> > 
> > On 01/02/2008, vlanschot <vlanschot@> wrote:
> > > Thanks Graham,
> > >
> > > A follow-up question if I may.
> > >
> > > Indeed, in my CBT-loops, I first execute the exits, and keep 
> track of
> > > the number of exits. Based on this, and after bo.UpdateStats, 
I've
> > > added the following:
> > >
> > > (FYI: Cash = bo.Cash Eq = bo.Equity)
> > >
> > > if (bar>1) NewPosSize = Nz((Kas[bar]/numExits)/Eq[bar],
> > > MaxOpenPos/100);
> > > else NewPosSize = MaxOpenPos/100 ;
> > >
> > > LongPS = ShortPS = -NewPosSize*100;
> > >
> > > I then run through my entry signals.
> > >
> > > In other words, I assume the CBT re-calculates the cash amount 
> after
> > > exits, which I subsequently divide evenly over the potential new
> > > positions.
> > >
> > > However, for some reason I end up with less than 50 positions 
(my
> > > MaxOpenPos) at the end of the backtest. Whereas if I "delete" 
the
> > > above code, I do end up with 50 positions, but then with too 
much
> > > cash occassionally. Iow, the system generates enough valid 
> signals to
> > > fill any exits.
> > >
> > > Any clarification appreciated, although I realize I'm not 
giving 
> you
> > > much detail.
> > >
> > > PS
> > >
> > > --- In amibroker@xxxxxxxxxxxxxxx, Graham <kavemanperth@> wrote:
> > > >
> > > > In advanced backtest code you exit the trades, update the 
> values,
> > > then
> > > > enter signals with amended posSize
> > > >
> > > > --
> > > > Cheers
> > > > Graham Kav
> > > > AFL Writing Service
> > > > http://www.aflwriting.com
> > > >
> > > >
> > > > On 01/02/2008, vlanschot <vlanschot@> wrote:
> > > > > Perhaps somebody has a straightforward way to solve the
> > > following, or
> > > > > point out the error in my interpretation of AFL/CBT:
> > > > >
> > > > > My system keeps a constant number of 50 positions, based on 
a
> > > ranking
> > > > > (although I do not use rotational trading.) At the start the
> > > > > positions are equally weighted, i.e. PositionSize is 
defined 
> as
> > > 2%.
> > > > > As time moves on, some do very well, and reach, say, a 
weight 
> of
> > > 3%
> > > > > of equity. When the exit signal arrives, these positions are
> > > replaced
> > > > > by new ones, but now back to the 2% of equity as defined in
> > > > > PositionSize.
> > > > >
> > > > > The resulting problem is that at times I find I have too 
much 
> cash
> > > > > left. Now, I know that I can rebalance open positions (by 
> scaling
> > > > > in/out, for example via TJ's code
> > > > > http://www.amibroker.com/kb/2006/03/06/re-balancing-open-
> > > positions/).
> > > > > However, apart from the extra costs involved, I have found 
> that
> > > there
> > > > > is no way to determine/access the amount of cash BEFORE
> > > > > entering/rebalancing the new positions. In other words, 
> bo.Cash
> > > gives
> > > > > you the amount of cash "at the end of the bar". You can, of
> > > course,
> > > > > use the amount of cash of the previous bar, but you keep 
> lagging
> > > the
> > > > > actual trades.
> > > > >
> > > > > In short, I would like to force the backtester to always 
make 
> the
> > > > > system fully invested (except for round lots, etc.) It 
would 
> be
> > > > > great, for example, if there would be an option to 
> automatically
> > > > > assign the amount of cash which becomes available from the 
> first
> > > > > exited trade to the first new trade, etc. In my system this 
is
> > > very
> > > > > applicable, as I always have other trades to replace the 
> exited
> > > one.
> > > > >
> > > > > Any thoughts/suggestions welcome. If none, I'll forward 
this 
> to
> > > > > support.
> > > > >
> > > > > Thx.
> > > > >
> > > > > PS
> > > > >
> > > > >
> > > > >
> > > > > Please note that this group is for discussion between users 
> only.
> > > > >
> > > > > To get support from AmiBroker please send an e-mail 
directly 
> to
> > > > > SUPPORT {at} amibroker.com
> > > > >
> > > > > For NEW RELEASE ANNOUNCEMENTS and other news always check 
> DEVLOG:
> > > > > http://www.amibroker.com/devlog/
> > > > >
> > > > > For other support material please check also:
> > > > > http://www.amibroker.com/support.html
> > > > >
> > > > > Yahoo! Groups Links
> > > > >
> > > > >
> > > > >
> > > > >
> > > >
> > >
> > >
> > >
> > >
> > > Please note that this group is for discussion between users 
only.
> > >
> > > To get support from AmiBroker please send an e-mail directly to
> > > SUPPORT {at} amibroker.com
> > >
> > > For NEW RELEASE ANNOUNCEMENTS and other news always check 
DEVLOG:
> > > http://www.amibroker.com/devlog/
> > >
> > > For other support material please check also:
> > > http://www.amibroker.com/support.html
> > >
> > > Yahoo! Groups Links
> > >
> > >
> > >
> > >
> >
>




Please note that this group is for discussion between users only.

To get support from AmiBroker please send an e-mail directly to 
SUPPORT {at} amibroker.com

For NEW RELEASE ANNOUNCEMENTS and other news always check DEVLOG:
http://www.amibroker.com/devlog/

For other support material please check also:
http://www.amibroker.com/support.html
 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/amibroker/

<*> Your email settings:
    Individual Email | Traditional

<*> To change settings online go to:
    http://groups.yahoo.com/group/amibroker/join
    (Yahoo! ID required)

<*> To change settings via email:
    mailto:amibroker-digest@xxxxxxxxxxxxxxx 
    mailto:amibroker-fullfeatured@xxxxxxxxxxxxxxx

<*> To unsubscribe from this group, send an email to:
    amibroker-unsubscribe@xxxxxxxxxxxxxxx

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/