Ed, Very creative! I will try integrating this into my own code and see if I can get it to behave as expected. My script allows for scale in, so I've still got a bit more work ahead of me.
For those reading along, Ed's original reply to a similar request, including a complete script showing the usage of the procedure below, can be found in message ID #113384. Thanks again, Mike --- In [email protected], "ed2000nl" <[EMAIL PROTECTED]> wrote: > > i'll try to reply directly from yahoo. My posts aren't coming through > anymore. Might be because of the ISP ... > > > so if I understand correctly the problem is not that the backtester > picks 20 stocks while there is only money for 10 but you have a problem > with the fact that if the 10 actual signals are not filled it will use > the lower ranking 10 signals and this is not what you want. You can > include this in the backtester. I explained the same thing some time > ago. For signals that you actually want to enter but in real life will > not be entered because the limit is not reached then you can tell the > backtester to enter at the open and exit at the open and do not allow > for a single bar trade (in the settings window). There might be > easier ways to do this (I mean using arrays only) but I have some > example code below. I did not check if the code is entirely correct but > I'll explain the idea: The Buy array is fed to the sellAtLimit procedure > and when it finds a buy it will check if the buy limit is reached for > that signal. If it is not reached (so if Low[ i ] >= buyLimit[ i ] ) > then you tell the backtester to enter and exit at the same price, same > bar. What happens is that the backtester reserves this money for this > trade and will not use it for another trade. The only thing that is not > realistic is that you will pay commission. But this will be a small > factor. rgds, Ed procedure > sellAtLimit_proc(Buy,BuyPrice,buyLimit,sellLimit) { > > global Sell; > global SellPrice; > global BuyAdjusted; > global BuyPriceAdjusted; > > > // initialise arrays > SellPrice = 0; > Sell = 0; > BuyAdjusted = 0; > BuyPriceAdjusted = 0; > > for (i = 1; i < BarCount; i++) { > > > // case where it is likely to enter a long position > if (Buy[ i ] == 1 AND Low[ i ] < buyLimit[ i ]) { > > > // buy at limit > BuyAdjusted[ i ] = 1; > > if (Open[ i ] < buyLimit[ i ]) { > > > BuyPriceAdjusted[ i ] = Open[ i ]; > > } else { > > BuyPriceAdjusted[ i ] = buyLimit[ i ]; > > } > > > // find a sell position + sellprice > for (j = i; j < BarCount; j++) { > > if (O[ j ] > sellLimit[ j ]) { > > Sell[ j ] = 1; > SellPrice[ j ] = O[ j ]; > i = j; > break; > > } else if (O[ j ] < sellLimit[ j ] AND H[ j ] > sellLimit [ j > ]) { > > Sell[ j ] = 1; > SellPrice[ j ] = sellLimit[ j ]; > i = j; > break; > > } else if (j == BarCount - 1) { > > i = BarCount; > > } > > > > > > } > > } else if (Buy[ i ] == 1 AND Low[ i ] >= buyLimit[ i ]) { > > // enter and exit at the same price and time ("VOID" trade) > BuyAdjusted[ i ] = 1; > BuyPriceAdjusted[ i ] = Open[ i ]; > > Sell[ i ] = 1; > SellPrice[ i ] = Open[ i ]; > > > } > > } > > > } // end procedure > > > --- In [email protected], "sfclimbers" <sfclimbers@> wrote: > > > > Thanks for your reply. I will look into your suggestion, but I don't > > think that that is the issue that I am up against. I have actual > > trade data from months of live trading. I am now trying to backtest > > the strategy used, and match the results to the actual data. > > > > My script, as written, is correctly entering and exiting with the > > correct number of shares and correct price points on all the correct > > days for all the trades that actually took place. > > > > The problem is that if I receive 20 "go long" signals on Monday > > night, but only have enough money to afford 8 more positions, then in > > real life I only place limit orders for the *top* 8 of the 20 > > candidates, not all 20. > > > > This means that in reality, if none of the top 8 dip to my limit > > order, then I will not get any fills on Tuesday, even though I still > > have not filled my slots, and even though some of the lesser > > candidates would have resulted in a fill had I place an order for > > them. > > > > However, the script is considering *all* 20 candidates, and fills up > > to 8 that dip enough to trigger a limit order. In other words, the > > script assumes that there are limit orders on all candidates instead > > of only the top 8. > > > > Using position score and position sizing is not enough, since these > > assume that the universe of candidates fitting the criteria is always > > available for prioritizing and filling available slots. But, in > > reality, only a subset are being bid on. > > > > As an example, if I'm currently holding: > > AAA, BBB > > > > And I then get signals for (in sorted order): > > CCC, DDD, EEE, FFF, GGG, HHH, III, JJJ, KKK, LLL, ... TTT > > > > I will only place limit orders for the top 8: > > CCC, DDD, EEE, FFF, GGG, HHH, III, JJJ > > > > If none of the top 8 above reach my limit, but say 8 lesser ones do > > (that I did not bid on), then in real life I will get no fills for > > the day. However, my script is saying that I picked up the 8 lesser > > fills since I had 8 slots open and these 8 met the limit price. > > > > How can I structure my code to recognize that 20 entry setups were > > found, but only 8 of them were acted upon, none of which actually > > worked out due to not meeting the limit price? > > > > I can't seem to use the custom backtester to sweep through the orders > > and null out the false buys that would not have taken place, since I > > don't have access to the scores of the candidates that didn't get > > filled. > > > > Yet, similarly, I can't seem to prevent triggering the buys in the > > first place, since I don't have access to the scores of the other > > candidates at that time either. > > > > When there are fewer signals than slots to fill, everything is > > great :) But this strategy often results in more signals than there > > is money to bid with :( > > > > Thanks. > > > > > > --- In [email protected], "Edward Pottasch" empottasch@ > > wrote: > > > > > > hi, > > > > > > the way you set it up it shoudl not be possible. However, what can > > happen is that the backtester finds exits for the next day and > > immediatelly fills them with new positions. So you need to make sure > > that you first exit your positions and tell the backtester to enter > > only on the next bar. This is usually the problem. There are several > > ways to achieve this. Maybe you will get a more satisfactory result > > when you set settradedelays(1,1,1,1). > > > > > > I use setttradedelays(0,0,0,0) but I make sure that the trade is > > entered 1 bar after the signal (same with the exits), > > > > > > Ed > > > > > > > > > > > > > > > ----- Original Message ----- > > > From: Michael White > > > To: [email protected] > > > Sent: Friday, August 24, 2007 11:37 AM > > > Subject: [amibroker] How do I backtest placing a restricted > > number of limit orders each night? > > > > > > > > > Can anyone help me model the following scenario? > > > > > > - Assume a portfolio is allowed to consist of some fixed number > > > of "slots" with equity equally divided among them (e.g. 10 slots > > at > > > 10% of equity). > > > - Check for setup criteria at close of each day. > > > - Place next day limit buy orders for as many unfilled slots as > > are > > > currently available (e.g. if already have 2 fills after day 1, > > then > > > there are only 10 - 2 = 8 slots remaining for day 2, etc.). > > > - Buy orders are prioritized by a calculated value. > > > > > > My problem is that if I receive a setup for more symbols than I > > have > > > available slots (e.g. receive 20 setups but only have 8 available > > > slots), my script will try to fill all 8 slots from the 20 > > > candidates, and the portfolio manager will correctly prevent me > > from > > > having more positions than allowed (e.g. no more than 10). > > > > > > However, in reality, I will only have placed as many limit orders > > as > > > I have available slots (e.g. 8 limit orders when 8 available > > slots, > > > not limit orders for all 20 candidates, since I only have funds > > to > > > cover placing 8 orders). > > > > > > What is happening is that my script is filling orders that I > > would > > > not have placed! I need a way to indicate that despite 20 setups, > > > only 8 limit orders were placed. > > > > > > Following is some script snippets. > > > > > > /* > > > * Assume an initial purse and brokerage fees ($0.01/share) > > > */ > > > SetOption("InitialEquity", 50000); > > > SetOption("CommissionMode", 3); > > > SetOption("CommissionAmount", 0.01); > > > > > > /* > > > * Carry fixed number of positions, dividing 100% of Equity between > > > * them (based on previous bar's closing). > > > */ > > > PositionSize = -100/10; // Each position is 10% of equity > > > > > > SetOption("MaxOpenPositions", 10); // No more than 10 positions > > > SetOption("UsePrevBarEquityForPosSizing", True); > > > > > > /* > > > * We recognize the sale signal at the close of a bar and execute > > the > > > * sale at the open of the next one, delay sale by 1 day. > > > */ > > > SetTradeDelays(0, 1, 0, 0); > > > > > > /* > > > * Trigger a Buy signal when previous bar meets the setup > > > * requirements AND this bar's Low has dropped to less than a fixed > > > * percentage below the previous bar's close. This emulates having > > > * placed a limit order the night before after having seen the > > signal > > > * on that day's close. > > > */ > > > setup = ... // Some position entry logic. > > > PositionScore = ... // Some prioritization logic. > > > > > > BuyPrice = Ref(Close, -1) * 0.95; > > > Buy = Ref(setup, -1) AND Low <= BuyPrice; // Problem here!!! > > > > > > Sell = ... // Some sell logic. > > > > > > As indicated in my earlier comments. The problem is that in > > reality I > > > will not actually have placed orders for all candidates, but > > rather > > > only for as many as there are available slots (e.g. 8). However, > > the > > > script will attempt to fill the available slots based on all > > > candidates (e.g. 20). > > > > > > How can I restrict the Buy assignment to only apply to the top X > > of Y > > > candidates based on priority (e.g. top 8 of 20 in example above). > > > > > > Thanks in advance. > > > > > >
