PureBytes Links
Trading Reference Links
|
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@xxx> 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@xxx> 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/
|