Mike - Hard to follow these threads sometimes, but when Markus wrote -
"And in signal list, I can only specify the position size in terms of money rather than the number of shares ..." I thought that he didn't see how to encode number of shares directly in sig.PosSize in the Signal object in the CBT and have it used for the trade. So, I referred him to the help which details the encoding - that is, -2000 for number of shares. This can be calculated from cash and be set in the CBT signal list before making mid or low level calls to process signal trades. -- BruceR --- In [email protected], "Mike" <sfclimb...@...> wrote: > > 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" <brucer@> 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 > > > > > > > > > > > > > > > > > > > > >
