Exactly, this is my problem.

Markus
  ----- Original Message ----- 
  From: Mike 
  To: [email protected] 
  Sent: Thursday, July 16, 2009 5:07 AM
  Subject: [amibroker] Re: Using CBI the first time


    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 [email protected], "bruce1r" <bru...@...> 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 [email protected], "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 [email protected], "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: [email protected] 
  > > > 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 [email protected], "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: [email protected] 
  > > > > 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 [email protected], "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
  > > > > >
  > > > >
  > > >
  > >
  >



  

Reply via email to