PureBytes Links
Trading Reference Links
|
Mike
My experience is similar to yours. I deal with Fidelity and their
system does not let you place limit orders more than your "buying
power".
--- In amibroker@xxxxxxxxxxxxxxx, "Mike" <sfclimbers@xxx> wrote:
>
> Tomasz,
>
> Thank you for your continued replies.
>
> I am trading in a REAL account in REAL life with 50% margin. Some
> nights I get few signals, other nights I get many. I trade over
7000
> symbols accross NYSE, NASDAQ, and AMEX. I have had as many as 60
> signals in one night. Even using all available margin, there are
> sometimes not enough funds to cover the orders.
>
> Saying that your strategies do not encounter the problem does not
> imply that the problem does not exist.
>
> I gave a simplistic one order example just to illustrate the point.
> Now that you understand the scenario, expand the example to a 10
> position account using any amount of margin and you hit the exact
> same issue as soon as you have more signals than available funds.
>
> Even using the simplistic one position example, I believe that the
> backtester would still THINK that there were enough funds available
> to fill the BB signal since it IGNORES funds allocated to the AA
> order that did not result in a signal. So, I think that your
comment
> does not apply here and BB would in fact get filled.
>
> The underlying problem is that AmiBroker does not appear to have a
> way to model the fact that the broker will commit funds to orders
> *placed*, even if those orders do not get *filled*. If I am not
> mistaken, AmiBroker only considers funds commited to a *filled*
order
> (i.e. a signal).
>
> There are at least 3 other forum members that have written about
this
> issue, so the scenario is real.
>
> Based on my experiments so far, my code will correctly model the
> scenario described. I was hoping for either A) a better solution,
or
> B) validation that the code works for others.
>
> Thanks,
>
> Mike
>
> --- In amibroker@xxxxxxxxxxxxxxx, "Tomasz Janeczko" <groups@>
> wrote:
> >
> > I disagree completely.
> > I am trading on REAL margin account in REAL life. With 50% margin
> account
> > I am always able to place limit orders for all signals I am
getting.
> >
> > As to "cleaner" solution to theoretical example that you have
> provided:
> > it is as easy as setting "MaxOpenPositions" to ONE.
> >
> > You would end up with no position open on Tuesday night (your
> desired behaviour) because backtester
> > STOPS opening positions if "top" signal can not enter due to lack
> of funds.
> >
> > Best regards,
> > Tomasz Janeczko
> > amibroker.com
> > ----- Original Message -----
> > From: "Mike" <sfclimbers@>
> > To: <amibroker@xxxxxxxxxxxxxxx>
> > Sent: Tuesday, September 04, 2007 9:11 PM
> > Subject: [amibroker] Re: How do I backtest placing a restricted
> number of limit orders each night?
> >
> >
> > > Tomasz,
> > >
> > > 1. Margin does not solve the problem, it just delays it. As
soon
> as
> > > you get one too many setups you hit the same problem again.
Also,
> for
> > > aggressive strategies using full margin, margin will already
have
> > > been accounted for when placing the first 10 orders of my
example.
> > >
> > > 2. When using a cash account you are not "DONE". Your code will
> > > accept the top ten *SIGNALS*. The problem is that the trader
can
> not
> > > afford to place all the *ORDERS*. Your system will accept
signals
> for
> > > orders that were *NEVER PLACED*.
> > >
> > > To make this as simple as possible:
> > >
> > > Monday day:
> > > - Have $5,000 available cash
> > > - Receive entry setup for AA, BB, CC
> > > - PositionScore for AA > BB > CC
> > >
> > > Monday night:
> > > - Place Tuesday limit order for $5,000 AA (since highest score)
> > > - Have $0 available cash (broker immediately *reserved* $5,000
> for AA)
> > > - Can *not* afford to place limit order for BB, CC
> > >
> > > Tuesday day:
> > > - Limit order for AA *not* met
> > > - Limit for BB *would* have been met, but order was *not* placed
> > > - Limit for CC *would* have been met, but order was *not* placed
> > >
> > > Tuesday night (YOUR CODE):
> > > - Holding $5,000 of BB <--- Wrong!
> > > - $0 available cash <--- Wrong!
> > >
> > > Tuesday night (REAL LIFE):
> > > - No holdings <--- Correct
> > > - $5,000 available cash <--- Correct
> > >
> > > In your code, I would be filled for $5,000 of BB which *I never
> > > placed an order for*. Your code correctly determined that there
> was
> > > only room to buy 1 position (e.g. did not also buy CC), but it
> used
> > > funds that were *not available*. All funds were already used up
> by
> > > the limit order placed for AA, so the signal for BB was
> impossible.
> > >
> > > In my code, the signals for BB and CC would be cancelled since
> their
> > > PositionScores are *less* than the top PositionScore (AA) and I
> only
> > > had room to place 1 order, regardless of the fact that AA was
> never
> > > filled. The system now correctly shows that there was no
*valid*
> > > signal for BB and CC.
> > >
> > > If you have a cleaner way to model this behavior, I would very
> much
> > > like to use it.
> > >
> > > Thanks,
> > >
> > > Mike
> > >
> > > --- In amibroker@xxxxxxxxxxxxxxx, "Tomasz Janeczko" <groups@>
> > > wrote:
> > >>
> > >> Hello,
> > >>
> > >> In addition to the fact that if you are using MARGIN account
> this
> > > is not a problem to place
> > >> 15 orders because they will all be within your buying power
> > > (including margin),
> > >> there is one more thing:
> > >> if you are using cash account that does not allow buying power
>
> > > cash
> > >> the problem you are describing is non-existing. Just define
> > >> SetOption("MaxOpenPositions", 10 )
> > >> and you are DONE. The code will accept only TEN TOP entry
> signals
> > > and nothing more.
> > >> (And instead of "exploration", you should use "Add artificial
> > > future bar" in the settings and run BACKTEST
> > >> with TOMMORROWS date to find out signals for tommorrow).
> > >>
> > >> Best regards,
> > >> Tomasz Janeczko
> > >> amibroker.com
> > >> ----- Original Message -----
> > >> From: "Mike" <sfclimbers@>
> > >> To: <amibroker@xxxxxxxxxxxxxxx>
> > >> Sent: Tuesday, September 04, 2007 7:00 PM
> > >> Subject: [amibroker] Re: How do I backtest placing a
restricted
> > > number of limit orders each night?
> > >>
> > >>
> > >> > Tomasz,
> > >> >
> > >> > You are missing the problem.
> > >> >
> > >> > Yes, setting a limit order is easy. The problem is that in
> real
> > > life
> > >> > the broker will *reserve the funds* necessary to fill a
limit
> > > order
> > >> > *at the time that the order is placed*, even if the order is
> > > never
> > >> > filled. If the limit is not reached, the funds will only
> become
> > >> > available again *after* the close of the bar.
> > >> >
> > >> > Using portfolio constraints, the sample that you have
provided
> > > can be
> > >> > made to ensure that only 10 orders are *filled*. But, it
> assumes
> > > that
> > >> > limit orders were *placed* for all setups. That is not
> realistic.
> > >> >
> > >> > So, if I have $50,000, I can only place 10 limit orders of
> $5,000
> > >> > each. If I receive more than 10 setups from the previous
bar,
> > > then I
> > >> > do not have enough funds to place orders for all of them and
> must
> > >> > choose the top 10 of 15.
> > >> >
> > >> > Since we can only place *some* limit orders, the trading
> system
> > > must
> > >> > recognize *which* limit orders were placed, and ignore the
> rest.
> > >> >
> > >> > To repeat, if I have only placed limit orders for the top 10
> > > setups,
> > >> > then if the limit is not reached for any of those 10, I will
> have
> > > 0
> > >> > positions filled. The price action of the remaining 5 is
> > >> > irrelevant. I could not afford to place orders on all 15, so
> my
> > >> > system must reflect that any fills of the remaining 5 *were
> never
> > >> > placed* and must be cancelled.
> > >> >
> > >> > Is there a better way to model this behavior?
> > >> >
> > >> > Thanks,
> > >> >
> > >> > Mike
> > >> >
> > >> > --- In amibroker@xxxxxxxxxxxxxxx, "Tomasz Janeczko"
<groups@>
> > >> > wrote:
> > >> >>
> > >> >> Solution was provided before. It does not require any
custom
> > >> > backtest code
> > >> >> and is actually easy.
> > >> >> I repeat:
> > >> >>
> > >> >> LimitPrice =
> > >> >> Buy = your original buy rule
> > >> >>
> > >> >> SetTradeDelays( 0, 0, 0, 0 ); // we use zero delays but we
> use
> > > Ref
> > >> > () to shift buy signal.
> > >> >>
> > >> >> Buy = Ref( Buy, -1 ) AND Low < LimitPrice; // this handles
> LIMIT
> > >> > order
> > >> >> BuyPrice = Min( Open, LimitPrice ); // this ensures
> limitprice
> > > is
> > >> > used for entry or the Open price if it is lower than limit
> > >> >>
> > >> >> SetBacktestMode( backtestRegularRaw ); // this makes sure
> that
> > >> > repeated signals occuring on many bars in sequence are not
> ignored
> > >> >>
> > >> >>
> > >> >> You don't need to do anything as convoluted as you are
> > > apparently
> > >> > doing in your formula
> > >> >> as the code ABOVE handles placing limit orders (which are
> only
> > >> > executed if
> > >> >> price penetrates your desired limit level).
> > >> >>
> > >> >> Best regards,
> > >> >> Tomasz Janeczko
> > >> >> amibroker.com
> > >> >> ----- Original Message -----
> > >> >> From: "Mike" <sfclimbers@>
> > >> >> To: <amibroker@xxxxxxxxxxxxxxx>
> > >> >> Sent: Tuesday, September 04, 2007 9:08 AM
> > >> >> Subject: [amibroker] Re: How do I backtest placing a
> restricted
> > >> > number of limit orders each night?
> > >> >>
> > >> >>
> > >> >> > Hi, I am submitting the following code for comment. I
> believe
> > >> > that I
> > >> >> > have a generic solution for the "fixed number of
> conditional
> > >> > orders
> > >> >> > on next bar" problem.
> > >> >> >
> > >> >> > Constructive criticism is welcomed. Please feel free to
> point
> > > out
> > >> > any
> > >> >> > bugs, inefficiencies, suggested enhancements, etc.
> > >> >> >
> > >> >> > If this is deemed valuable, I can clean up the formatting
> and
> > > add
> > >> > it
> > >> >> > to the files section.
> > >> >> >
> > >> >> > Mike
> > >> >> >
> > >> >> > Problem Statement:
> > >> >> > ------------------
> > >> >> > Need programatic support for simulating the placement of
a
> > > fixed
> > >> >> > number of prioritized *conditional* orders at the next
bar,
> in
> > >> >> > response to one or more favorable "setups" triggered by
the
> > >> > current
> > >> >> > bar, and constrained by the number of positions permitted
> by
> > > the
> > >> >> > strategy.
> > >> >> >
> > >> >> > Example:
> > >> >> > --------
> > >> >> > Consider a strategy that calls for the placement of limit
> > > orders
> > >> > at
> > >> >> > the next bar after recognizing one or more favorable
setups
> on
> > >> > the
> > >> >> > current bar. Assume that the strategy allows a maximum of
> only
> > > 10
> > >> >> > open positions at any given time, and that the setups are
> > >> > prioritized
> > >> >> > from most preferred (position 1) to least preferred
> (position
> > > 10).
> > >> >> >
> > >> >> > If on the first day of the strategy 20 favorable setups
> were
> > >> >> > recognized, then the strategy would call for placing
limit
> > > orders
> > >> > at
> > >> >> > the next bar for *only* the top 10 preferred setups
(since
> > > only
> > >> > 10
> > >> >> > positions are permitted and we can not know in advance
> whether
> > >> > any or
> > >> >> > all of the 10 orders would actually get filled).
> > >> >> >
> > >> >> > Similarly, if at some point after starting the strategy
we
> > > found
> > >> >> > ourself with 2 currently open positions and received 20
> > > setups,
> > >> > we
> > >> >> > would place 8 (10 - 2 = 8) limit orders for the top 8
> > > preferred
> > >> >> > setups.
> > >> >> >
> > >> >> > Complications
> > >> >> > -------------
> > >> >> > 1. Using PositionScore and position sizing is not
> sufficient
> > >> > since
> > >> >> > they do not recognize the allocation of funds commited to
> > >> >> > *conditional* order placements that do *not* get filled.
> > >> > Resulting
> > >> >> > code would typically continue to attempt to fill
allowable
> > >> > position
> > >> >> > count despite not having enough funds to cover all
possible
> > >> > setups.
> > >> >> >
> > >> >> > 2. Script execution for any given symbol does not have
> access
> > > to
> > >> > the
> > >> >> > PositionScore of the remaining symbols.
> > >> >> >
> > >> >> > 3. Custom backtester object does not have access to the
> > >> > PositionScore
> > >> >> > of any symbol that did *not* result in a generated trade
> > > signal
> > >> > (i.e.
> > >> >> > if a limit order was not met, the custom backtester would
> not
> > >> > have a
> > >> >> > signal object for that conditional placement, and thus
> would
> > > not
> > >> > have
> > >> >> > access to the PositionScore of the unsuccessful order).
> > >> >> >
> > >> >> > Solution
> > >> >> > --------
> > >> >> > 1. Generate a "composite" symbol for each allowable
> position
> > > of
> > >> > the
> > >> >> > strategy (e.g. for a strategy allowing a maximum of 10
open
> > >> >> > positions, geneare composites ~Position1,
~Position2, ...,
> > >> >> > ~Position10).
> > >> >> >
> > >> >> > 2. At each bar of each symbol, calculate a PositionScore
> for
> > > any
> > >> >> > conditional order based on the recognition of a setup on
> the
> > >> > previous
> > >> >> > bar (e.g. PositionScore for a limit order in response to
a
> > >> > recognized
> > >> >> > setup the bar before). Note that this is a PositionScore
> for
> > > the
> > >> >> > *conditional* order which *may or may not* have been
> filled.
> > > If
> > >> > no
> > >> >> > setup was recognized in the previous bar the
PositionScore
> > > would
> > >> > be
> > >> >> > zero.
> > >> >> >
> > >> >> > 3. Insert, in a sorted manner, the calculated
PositionScore
> > > into
> > >> > the
> > >> >> > appropriate composite, bumping down in a chain reaction
any
> > >> > current
> > >> >> > composite occupants as needed.
> > >> >> >
> > >> >> > For example; if the PositionScore for the current symbol
at
> > > the
> > >> >> > current bar was found to be less than the value held by
> > >> > ~Position1
> > >> >> > for that bar, the comparrison would next be made against
> > >> > ~Position2.
> > >> >> > If the PositionScore was found to be greater than the
value
> > > held
> > >> > by
> > >> >> > ~Position2 for that bar, then the value for that bar of
> > >> > ~Position2
> > >> >> > would be replaced (bumped) by PositionScore, and the
value
> > > that
> > >> > had
> > >> >> > been in ~Position2 would be moved down to ~Position3 for
> that
> > >> > same
> > >> >> > bar, bumping down any value held by ~Position3 in a chain
> > >> > reaction
> > >> >> > until a zero composite value was found (i.e. nothing to
> bump)
> > > or
> > >> > all
> > >> >> > composites had been updated.
> > >> >> >
> > >> >> > e.g. given:
> > >> >> >
> > >> >> > PositionScore[x] is 99 and;
> > >> >> >
> > >> >> > ~Position1[x] is 100
> > >> >> > ~Position2[x] is 50
> > >> >> > ~Position3[x] is 49
> > >> >> > ~Position4[x] is 0
> > >> >> > ...
> > >> >> > ~Position10[x] is 0
> > >> >> >
> > >> >> > Result after insertion would be:
> > >> >> >
> > >> >> > ~Position1[x] is 100
> > >> >> > ~Position2[x] is 99
> > >> >> > ~Position3[x] is 50
> > >> >> > ~Position4[x] is 49
> > >> >> > ~Position5[x] is 0
> > >> >> > ...
> > >> >> > ~Position10[x] is 0
> > >> >> >
> > >> >> > 4. Write custom backtester logic to calculate, at each
bar,
> > > how
> > >> > many
> > >> >> > open positions exist, and reset to 0 the PosSize of any
> Signal
> > >> > whose
> > >> >> > PositionScore is *less* than the PositionScore held by
the
> N-
> > > th
> > >> >> > composite, where N is calculated as max allowed positions
> > > minus
> > >> > the
> > >> >> > number of currently opened positions (e.g. 10 max
> positions -
> > > 2
> > >> > open
> > >> >> > positions = composite ~Position8). This emulates not
having
> > >> > placed
> > >> >> > orders for any but the top N preferred setups.
> > >> >> >
> > >> >> > 5. Leave to the native backtester all other decisions
> > > regarding
> > >> > enty
> > >> >> > into positions and tie-breaking of equal PositionScore.
> > >> >> >
> > >> >> > Advantages
> > >> >> > ----------
> > >> >> > 1. Works generically for any conditional strategy, Long
or
> > > Short*.
> > >> >> > 2. Works equally well for scale-in strategies.
> > >> >> > 3. Makes no assumptions regarding Buy/Sell rules.
> > >> >> > 4. Does not result in any phantom/artificial trades.
> > >> >> > 5. Does not generate any phantom/artificial commisions.
> > >> >> > 6. Does not depend on any backtester settings "tweaks".
> > >> >> > 7. PositionScore data is available at all times for
> additional
> > >> >> > analysis.
> > >> >> >
> > >> >> > * Backtester logic must be custom fit to your strategy,
but
> > >> >> > persistence of scores is generic to all.
> > >> >> >
> > >> >> > Disadvantages
> > >> >> > -------------
> > >> >> > 1. Slower execution resulting from heavy looping (loops N
> > > times
> > >> > more
> > >> >> > than alternative proposed in msg #113384, where N equals
> > > maximum
> > >> >> > allowed positions).
> > >> >> >
> > >> >> > For example; A strategy backtested 3 months over 7800+
> symbols
> > >> > using
> > >> >> > 10 allowed positions on a 1.4Ghz laptop with 1GB RAM
takes
> > > about
> > >> > 10
> > >> >> > minutes.
> > >> >> >
> > >> >> > 2. Code is more complex than alternative proposed in msg
> > > #113384.
> > >> >> >
> > >> >> > -----
> > >> >> > ----- Sample code snippets for your review (Long only)
> > >> >> > ----- I have left in _TRACE statements to see what's
> happening
> > >> >> > -----
> > >> >> >
> > >> >> > /*
> > >> >> > * Carry fixed number of positions, equally divided.
> > >> >> > */
> > >> >> > maxPositions = 10;
> > >> >> > PositionSize = -100/maxPositions;
> > >> >> > SetOption("MaxOpenPositions", maxPositions);
> > >> >> >
> > >> >> > /*
> > >> >> > * Custom backtester implementation to strip out orders
that
> in
> > >> >> > * reality would not have been placed due to a limitation
of
> > >> >> > * available capital to cover bids on all setups.
> > >> >> > *
> > >> >> > * Note: This implementation assumes Long positions only!
> > >> >> > */
> > >> >> > SetCustomBacktestProc("");
> > >> >> >
> > >> >> > if (Status("action") == actionPortfolio) {
> > >> >> > bo = GetBacktesterObject();
> > >> >> > bo.PreProcess();
> > >> >> >
> > >> >> > for (bar = 0; bar < BarCount; bar++) {
> > >> >> > openCount = 0;
> > >> >> >
> > >> >> > for (openPos = bo.GetFirstOpenPos();
> > >> >> > openPos;
> > >> >> > openPos = bo.GetNextOpenPos())
> > >> >> > {
> > >> >> > openCount++;
> > >> >> > }
> > >> >> >
> > >> >> > minPos = maxPositions - openCount;
> > >> >> > posScores = IIF(minPos,
> > >> >> > Foreign("~Position" + minPos, "X", 0),
> > >> >> > 9999); // Highest possible score!
> > >> >> >
> > >> >> > for (sig = bo.GetFirstSignal(bar);
> > >> >> > sig;
> > >> >> > sig = bo.GetNextSignal(bar))
> > >> >> > {
> > >> >> > if (sig.IsEntry() AND sig.IsLong()) {
> > >> >> > if (sig.PosScore < posScores[bar]) {
> > >> >> > /*_TRACE(StrFormat("Score %9.4f less than top %
> 1.0f
> > >> > scores
> > >> >> > of %9.4f at bar %5.0f, cancel signal for ", sig.PosScore,
> > > minPos,
> > >> >> > posScores[bar], bar) + sig.Symbol);*/
> > >> >> >
> > >> >> > // Order would not have been placed, cancel it
out.
> > >> >> > sig.PosSize = 0;
> > >> >> > }
> > >> >> > }
> > >> >> > }
> > >> >> >
> > >> >> > bo.ProcessTradeSignals(bar);
> > >> >> > }
> > >> >> >
> > >> >> > bo.PostProcess();
> > >> >> > }
> > >> >> >
> > >> >> > /*
> > >> >> > * For each bar following entry setup, persist
PositionScore
> > > into
> > >> > an
> > >> >> > * ordered list of Foreign symbols such that we may later
> have
> > >> > access
> > >> >> > * to the top scores during backtesting, regardless of
> whether
> > > a
> > >> >> > * concrete signal for the ranked symbol is actually
found.
> See
> > >> >> > * custom backtester method for filtering logic.
> > >> >> > *
> > >> >> > * For example; a 10 position, limit order strategy
> currently
> > >> > holding
> > >> >> > * 2 positions might place limit orders for only the top 8
> > > setups,
> > >> >> > * despite recognizing more than 8 candidate setups. This
> > > method
> > >> >> > * would sort the PositionScore of all candidate setups
into
> 10
> > >> >> > * foreign symbols, regardless of whether or not the limit
> > > order
> > >> > was
> > >> >> > * met. The backtester would then compare the
PositionScore
> of
> > > all
> > >> >> > * filled signals (i.e. all signals of the limit price
> having
> > > been
> > >> >> > * met), and cancel out those whose score was less than
the
> top
> > > 8
> > >> >> > * scores found in the Foreign symbols (i.e. cancel out
> signals
> > >> > for
> > >> >> > * those symbols upon which, in reality, a limit order
would
> > > never
> > >> >> > * actually have been placed).
> > >> >> > *
> > >> >> > * Note: This implementation leaves the responsibility of
> tie-
> > >> >> > * breaking to the backtester, when multiple symbols have
> the
> > > same
> > >> >> > * PositionScore for a limited number of available
> positions.
> > > The
> > >> >> > * symbol selected by the backtester may not be the one
for
> > > which
> > >> > an
> > >> >> > * order was actually placed in real life. But, the symbol
> > >> > selected
> > >> >> > * is guaranteed to at least have an equivalent
> PositionScore.
> > > Use
> > >> >> > * unique PosittionScore values, or trade in real life
using
> > > the
> > >> > same
> > >> >> > * tie-breaking logic that AmiBroker uses :)
> > >> >> > *
> > >> >> > * Note: This implementation assumes that PositionScore
will
> be
> > >> >> > * either zero, for bars not recognized as following order
> > >> > placement
> > >> >> > * criteria (i.e. no setup from previous bar), or a non
zero
> > >> > positive
> > >> >> > * number, for bars where order placement criteria has
been
> > > met. To
> > >> >> > * reiterate, this refers to order *placement* criteria
> (i.e.
> > >> > setup),
> > >> >> > * not order *fulfillment*.
> > >> >> > */
> > >> >> > procedure persistScores(scores) {
> > >> >> > local maxPositions; // Max positions allowed in portfolio
> > >> >> > local empty; // Array of zeros
> > >> >> > local bar; // Loop variable
> > >> >> > local score; // PositionScore of bar-th bar
> > >> >> > local pos; // Loop variable
> > >> >> > local composite; // Name of pos-th composite
> > >> >> > local posScores; // Scores persisted to composite
> > >> >> > local delta; // Delta between PositionScore and
> > > composite
> > >> >> > local affected; // Flag whether any deltas were added
> > >> >> >
> > >> >> > maxPositions = GetOption("MaxOpenPositions");
> > >> >> > empty = Cum(0);
> > >> >> >
> > >> >> > for (pos = 1; pos <= maxPositions; pos++) {
> > >> >> > /*_TRACE("Persist " + Name() + " to position " +
pos);*/
> > >> >> > composite = "~Position" + pos;
> > >> >> > AddToComposite(0, composite, "X", 1 + 2 + 4 + 8); //
> > >> > Initialize
> > >> >> > posScores = Foreign(composite, "X", 0); // Do not
fill
> > > holes!
> > >> >> > delta = empty;
> > >> >> > affected = false;
> > >> >> >
> > >> >> > for (bar = 0; bar < BarCount; bar++) {
> > >> >> > if (scores[bar]) {
> > >> >> > score = scores[bar];
> > >> >> >
> > >> >> > if (score > posScores[bar]) {
> > >> >> > /*_TRACE(StrFormat("Score %9.4f bumps down
> position %
> > >> > 1.0f
> > >> >> > score of %9.4f at bar %5.0f", score, pos, posScores[bar],
> > > bar));*/
> > >> >> >
> > >> >> > // Grab current best value and hold for next
> composite
> > >> >> > // iteratation, and calculate delta needed to
add
> to
> > >> >> > // this composite in order to make it equal new
> high
> > >> > score
> > >> >> >
> > >> >> > scores[bar] = posScores[bar];
> > >> >> > delta[bar] = score - posScores[bar];
> > >> >> > affected = true;
> > >> >> > }
> > >> >> > /*else if (posScores[bar]) _TRACE(StrFormat("Score
%
> > > 9.4f
> > >> >> > blocked by position %1.0f score of %9.4f at bar %5.0f",
> score,
> > >> > pos,
> > >> >> > posScores[bar], bar));*/
> > >> >> > }
> > >> >> > }
> > >> >> >
> > >> >> > if (affected) {
> > >> >> > AddToComposite(delta, composite, "X", 1 + 2 + 4 + 8);
> > >> >> > }
> > >> >> > }
> > >> >> >
> > >> >> > /*_TRACE("\n");*/
> > >> >> > }
> > >> >> >
> > >> >> > setup = ... // Some setup recognition
logic
> > >> >> > Buy = Ref(setup, -1) AND ... // Some conditional entry
logic
> > >> >> > PositionScore = IIF(Ref(setup, -1), ..., 0); // Some
score
> > > logic
> > >> > or 0
> > >> >> > Sell = ... // Some Sell logic
> > >> >> >
> > >> >> > persistScores(PositionScore);
> > >> >> >
> > >> >> > /*
> > >> >> > * Example of 5% dip limit conditional entry:
> > >> >> > * BuyPrice = min(Open, (Ref(Close, -1) * 0.95));
> > >> >> > * Buy = Ref(setup, -1) AND Low <= BuyPrice;
> > >> >> > */
> > >> >> >
> > >> >> > ------
> > >> >> > ------ End code snippets
> > >> >> > ------
> > >> >> >
> > >> >> > --- In amibroker@xxxxxxxxxxxxxxx, "ed2000nl"
<empottasch@>
> > > 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 amibroker@xxxxxxxxxxxxxxx, "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 amibroker@xxxxxxxxxxxxxxx, "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: amibroker@xxxxxxxxxxxxxxx
> > >> >> >> > > 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.
> > >> >> >> > >
> > >> >> >> >
> > >> >> >>
> > >> >> >
> > >> >> >
> > >> >> >
> > >> >> >
> > >> >> > Please note that this group is for discussion between
users
> > > only.
> > >> >> >
> > >> >> > To get support from AmiBroker please send an e-mail
> directly
> > > to
> > >> >> > SUPPORT {at} amibroker.com
> > >> >> >
> > >> >> > For NEW RELEASE ANNOUNCEMENTS and other news always check
> > > DEVLOG:
> > >> >> > http://www.amibroker.com/devlog/
> > >> >> >
> > >> >> > For other support material please check also:
> > >> >> > http://www.amibroker.com/support.html
> > >> >> >
> > >> >> > Yahoo! Groups Links
> > >> >> >
> > >> >> >
> > >> >> >
> > >> >> >
> > >> >> >
> > >> >>
> > >> >
> > >> >
> > >> >
> > >> >
> > >> > Please note that this group is for discussion between users
> only.
> > >> >
> > >> > To get support from AmiBroker please send an e-mail directly
> to
> > >> > SUPPORT {at} amibroker.com
> > >> >
> > >> > For NEW RELEASE ANNOUNCEMENTS and other news always check
> DEVLOG:
> > >> > http://www.amibroker.com/devlog/
> > >> >
> > >> > For other support material please check also:
> > >> > http://www.amibroker.com/support.html
> > >> >
> > >> > Yahoo! Groups Links
> > >> >
> > >> >
> > >> >
> > >> >
> > >> >
> > >>
> > >
> > >
> > >
> > >
> > > Please note that this group is for discussion between users
only.
> > >
> > > To get support from AmiBroker please send an e-mail directly to
> > > SUPPORT {at} amibroker.com
> > >
> > > For NEW RELEASE ANNOUNCEMENTS and other news always check
DEVLOG:
> > > http://www.amibroker.com/devlog/
> > >
> > > For other support material please check also:
> > > http://www.amibroker.com/support.html
> > >
> > > Yahoo! Groups Links
> > >
> > >
> > >
> > >
> > >
> >
>
Please note that this group is for discussion between users only.
To get support from AmiBroker please send an e-mail directly to
SUPPORT {at} amibroker.com
For NEW RELEASE ANNOUNCEMENTS and other news always check DEVLOG:
http://www.amibroker.com/devlog/
For other support material please check also:
http://www.amibroker.com/support.html
Yahoo! Groups Links
<*> To visit your group on the web, go to:
http://groups.yahoo.com/group/amibroker/
<*> Your email settings:
Individual Email | Traditional
<*> To change settings online go to:
http://groups.yahoo.com/group/amibroker/join
(Yahoo! ID required)
<*> To change settings via email:
mailto:amibroker-digest@xxxxxxxxxxxxxxx
mailto:amibroker-fullfeatured@xxxxxxxxxxxxxxx
<*> To unsubscribe from this group, send an email to:
amibroker-unsubscribe@xxxxxxxxxxxxxxx
<*> Your use of Yahoo! Groups is subject to:
http://docs.yahoo.com/info/terms/
|