Anybody? . . . Thx,
PS --- In amibroker@yahoogroups.com, "vlanschot" <[EMAIL PROTECTED]> 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@yahoogroups.com, 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@yahoogroups.com, 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 > > > > > > > > > > > > > > >