Bruce,
In this case he is trying to calculate shares based on
portfolio cash position. So, SetPositionSize using spsShares does not apply
since portfolio cash is not known except in the custom
backtester.
Mike
--- In amibroker@xxxxxxxxxps.com,
"bruce1r" <brucer@xxx>
wrote:
>
> Markus -
>
> Saw this post also in
skimming. Another easy one that can be summed up as check the help (ALWAYS).
In this case look for the function related to PositionSize. It is
SetPositionSize(). See how # of shares is encoded in the signal object
for the backtester. Then, you can read or write it before processing the
signal in the CBT.
>
> Just a suggestion since you indicated you
were new to this, but targeted search of the help file for additional related
info is something that you'll find yourself doing often.
>
> --
BruceR
>
>
> --- In amibroker@xxxxxxxxxps.com,
"Mike" <sfclimbers@> wrote:
> >
> >
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@> 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
> > > >
>
> > > >
> > >
>
>
>