Markus,
To simplify your life, start first by not using any
commissions in your backtest (see Settings of Auto Analysis window). Then do
as you have outlined; set the position size to the Signal.Price multiplied by
the number of shares desired. You definitely do not want to work with either
trade list, that's too late - the trade has already taken place.
If you
have any rounding issues, post your formula here, or send it to support and
they can help clarify for you.
Mike
--- In amibroker@xxxxxxxxxps.com,
"Markus Witzler" <funnybiz@xx.> wrote:
>
> Hi
Mike,
>
> thanks loads for your thorough explanations!
>
> I´ll need to digest what you wrote but I´m still a little confused. I
had read the pdf you mentioned a couple of weeks ago but as it turns out
completely misunderstood!
>
> I don´t understand how I make sure
that exactly the number of shares is being bought that I want (whatever amount
of money that means)? If I specify sig.possize in signal loop (which implies a
given number shares?!), this could maybe (in some cases) result - due to
rounding issues- in a slightly differing number of shares, right (I don´t know
how AB rounds up or down)? Buying/selling the exact number of shares is
crucial for my purposes!
>
> So, where do I do that? The closed
trade list probably is not the right spot to determine # of shares since the
trades already have been closed. The open trade list probably not as well
since there the trades already have been initiated, right? And in signal list,
I can only specify the position size in terms of money rather than the number
of shares, even if I did it like this:
>
sharesize=round(((Heat*bo.cash)/(y*ATRmultiplier))/250)*250;
// i.e. # of shares/contracts
>
>
sig.possize=sharesize*sig.price; // i.e. position value in terms of
USD
>
> The other issue you mentioned (determening a trade´s bar
number) needs to wait until I have understood this issue - but it sounds
somehat complicated...
>
> Sorry for my ignorance!
>
> Markus
>
>
> ----- Original Message -----
> From: Mike
> To: amibroker@xxxxxxxxxps.com
> Sent: Wednesday, July 15, 2009 4:40 AM
> Subject: [amibroker]
Re: Using CBI the first time
>
>
>
>
>
> Markus,
>
> If you haven't already, it would be a good
idea to read "AmiBroker Custom Backtester Interface.pdf" found in the files
section of this group.
>
> The way your code is now, you are
trying to mix and match signals with trades, which is not permitted.
>
> A signal does not become a trade until *after* the signal has been
processed by the backtester. There are a number of portfoliio restrictions
that may prevent a signal from actually being accepted and made into a trade.
For example, you may not have sufficient funds, you may have exceeded the
number of allowable open positions, etc.
>
> You need to set the
position size on the Signal object. If the signal becomes a trade, that is
what will later dictate the Trade object's shares. Note that a Signal's
PosSize property can be expressed as a percetage of equity (negative) or as a
dollar amount (positive). Do the math and use a positive number to control the
number of shares (e.g. number of shares desired multiplied by share price,
remember to take into account commisions if you use them).
>
>
You will not have bar by bar access to the trade list as you do with signals.
Therefore, you must determine the bar index of the trade based on its entry
date then use Foreign to reference the bar by bar data using the bar index for
that date. An example of this approach can be seen in a similar post that I
made a short while ago:
>
> http://finance.groups.yahoo.com/group/amibroker/message/139969
>
> As for your custom trade metrics. I don't see a need for showing the
number of shares since this is already provided by AmiBroker in the backtest
report. Also, since Signal.PosSize ultimately ends up being the same as
Trade.Shares, this information is also already there. As for the cash position
prior to the trade, that would be available as the Low in ~~~Equity for the
bar prior to the bar of the trade as outlined in this message:
>
> http://finance.groups.yahoo.com/group/amibroker/message/139634
>
> Hope that helps.
>
> Mike
>
> --- In amibroker@xxxxxxxxxps.com,
"Markus Witzler" <funnybiz@> wrote:
> >
> > Hello
Mike,
> >
> > thanks from a newbie. I wasn´t aware of
that.
> >
> > I still have another problem:
> >
> > Since I use low-level code (to be able to employ proprietary
stops later on), I need to use the signal list to exit/enter trades.
>
>
> > Since I want to have a per-trade output of my metrics, I
need to use trade.addcustommetric rather than bo.addcustommetric.
>
>
> > But when I use trade.addcustommetric in a signal list,
I get an error (see code below).
> >
> > I understand the
problem but don´t find a way out.
> >
> > The same is true
for trader.shares (see code). I need it to calculate correct position value
which is then subtracted from actual cash position to get the new cash
position after a trade.
> >
> > Maybe, you can jump in once
again, if you don´t mind? This whole CBI thing is stilla little beyond me, to
be homest>G<.
> >
> > Thansk again
> >
> > Markus
> >
> >
SetCustomBacktestProc("");
> >
> > if
(Status("action") == actionPortfolio)
> >
> >
{
> >
> > bo = GetBacktesterObject(); // Get
backtester object
> >
> >
> >
> >
bo.PreProcess(); // Do pre-processing
> >
> >
>
> Initial_equity=bo.cash=1000000.00;
> >
> >
My_total_equity=0;
> >
> >
Value_open_positions=0;
> >
> > Heat=0.1;
> >
> > y=0;
> >
> > ATRmultiplier=5;
>
>
> > for (i = 0; i < BarCount; i++) // Loop through all
bars
> >
> >
> > {
> >
> > for
(sig = bo.GetFirstSignal(i); sig; sig = bo.GetNextSignal(i))
>
>
> > { // Loop through all signals at this bar
> >
> > // Long trades
> >
> > if (sig.IsEntry()
&& sig.IsLong()) // Process long entries
> >
>
>
> > {
> >
> > ATRexRounded =
Foreign("~ATRExpLagRounded_"+sig.Symbol, "V"); // Get symbol's
AtrExpLagRounded array, which is simply an exp. MA of the Average True range
of a given number of days. I used a proprietary code to set the first day´s
value as seed value rather than zero, as AB´s ATR() function apparrently does.
> >
> > ATRex = ATRexRounded[i]; // Reference a value
in the array
> >
> > if (i=0)
> >
> >
y=ATRexRounded[i];
> >
> > else
> >
>
>
> > if (i>0)
> >
> >
y=ATRexRounded[i-1];
> >
> >
> > }
>
>
> >
trade.shares=round(((Heat*bo.cash)/(y*ATRmultiplier))/250)*250;
// i.e. # of shares/contracts rounded to the nearest 250 lot and depending on
the actual cash position
> >
> >
sig.possize=pos_size_shares*sig.price; // i.e. position value,
expressed in USD
> >
> > bo.EnterTrade(i, sig.Symbol,
True, sig.Price, sig.PosSize);
> >
> >
trade.AddCustomMetric("initial equity", initial_equity); // to get
per-trade statistics!
> >
> >
trade.AddCustomMetric("Cash position", bo.cash);
> >
>
> trade.AddcustomMetric("Position size [shares]",
trade.shares);
> >
> >
trade.AddCustomMetric("Position Value", sig.possize);
> >
> > }
> >
> > else
> >
> > {
if (sig.IsExit() && sig.IsLong()) // Process long exits
(cover longs)
> >
> > bo.ExitTrade(i, sig.Symbol,
sig.Price);
> >
> > }
> >
> > // Short
side
> >
> > if (sig.IsEntry() &&
sig.IsLong()==False) // Process short entries
> >
> >
> > {
> >
> > ATRexRounded =
Foreign("~ATRExpLagRounded_"+sig.Symbol, "V"); // Get symbol's
AtrExpLagRounded array
> >
> > ATRex =
ATRexRounded[i]; // Reference a value in the array
> >
>
> if (i=0)
> >
> > {
> >
> >
y=ATRexRounded[i];
> >
> > }
> >
>
> else
> >
> > {
> >
> >
>
> y=ATRexRounded[i-1];
> >
> > }
> >
> >
trade.shares=round(((Heat*bo.cash)/(y*ATRmultiplier))/250)*250;
>
>
> >
sig.possize=pos_size_shares*sig.price;
> >
>
> bo.EnterTrade(i, sig.Symbol, False, sig.Price,
sig.PosSize);
> >
> > }
> >
> >
else
> >
> > {
> >
> > if
(sig.IsExit() && sig.IsLong()==False) // Process (cover)
short exits
> >
> >
> > bo.ExitTrade(i,
sig.Symbol, sig.Price);
> >
> > }
> >
>
> bo.HandleStops(i); // Process programmed stops or applystop at this
bar
> >
> > } // End of for loop over signals at this
bar
> >
> > for (trade = bo.GetFirstOpenPos(); trade;
trade = bo.GetNextOpenPos())
> >
> > { // Loop through
all open positions
> >
> >
> >
Value_open_positions=Value_open_positions+
trade.getprice(i,"C")*trade.shares;
> >
> >
trade.addCustomMetric("Value of open positions",
Value_open_positions);
> >
> >
My_total_equity=bo.cash+Value_open_positions;
> >
>
> trade.AddCustomMetric("My total equity",
My_total_equity);
> >
> > } // End of for loop over
trades at this bar
> >
> > bo.UpdateStats(i, 1); //
Update MAE/MFE stats for bar
> >
> > bo.UpdateStats(i,
2); // Update stats at bar's end
> >
> > } // End of for
loop over bars
> >
> > bo.PostProcess(); // Do
post-processing
> >
> > AddToComposite( My_total_equity,
"~~~My_total_equity", "X", atcFlagEnableInPortfolio |
atcFlagDefaults ); // to plot an indicator
> >
> >
AddToComposite( trade.shares,"~~~Position size [shares]", "X",
atcFlagEnableInPortfolio | atcFlagDefaults );
> >
> >
AddToComposite( sig.possize, "~~~Position Value", "X",
atcFlagEnableInPortfolio | atcFlagDefaults );
> >
> >
AddToComposite( bo.cash, "~~~Cash position", "X",
atcFlagEnableInPortfolio | atcFlagDefaults );
> >
> >
AddToComposite( Value_open_positions, "~~~Value of open positions", "X",
atcFlagEnableInPortfolio | atcFlagDefaults );
> >
> >
}
> >
> >
> >
> > ----- Original
Message -----
> > From: Mike
> > To: amibroker@xxxxxxxxxps.com
> > Sent: Tuesday, July 14, 2009 8:14 PM
> > Subject:
[amibroker] Re: Using CBI the first time
> >
> >
>
>
> >
> >
> > Hi,
> >
> >
I believe that your code says it all ;)
> >
> > > } //
End of for loop over trades at this bar
> > >
> > >
...
> > > trade.AddCustomMetric("My total equity",
My_total_equity);
> >
> > "trade" is null after the
loop.
> >
> > Mike
> >
> > --- In amibroker@xxxxxxxxxps.com,
"Markus Witzler" <funnybiz@> wrote:
> > >
> > >
Hello all,
> > >
> > > I intend to create a
proprietary formula for "My_total_equity" to able to modify it later on to
suit to my individual needs.
> > >
> > > Here, I_ use
"Value of cash position (bo.cash) + value (all open positions by their close)"
as a start.
> > >
> > > When I run backtest, I get
the following message:
> > >
> > > "Com Variable not
initialized or has invalid type" though I initialized
"Value_open_positions=0" and also "My_total_equity=0;"
>
> >
> > > The loop to determine the aggregate value of all
open positions goes like this:
> > >
> > > for (trade
= bo.GetFirstOpenPos(); trade; trade = bo.GetNextOpenPos())
>
> >
> > > { // Loop through all open positions
> >
>
> > >
> > >
Value_open_positions=Value_open_positions+
trade.getprice(i,"C")*trade.shares;
> > >
> >
> trade.addCustomMetric("Value of open positions",
Value_open_positions);
> > >
> > > } // End of
for loop over trades at this bar
> > >
> > >
>
> > My_total_equity=bo.cash+Value_open_positions;
> >
>
> > > trade.AddCustomMetric("My total equity",
My_total_equity);
> > >
> > > Where is the
mistake? If the whole code is required, please let me know.
> > >
> > > Thanks
> > >
> > > Markus
>
> >
> >
>