Australian (ASX) Stock Market Forum

Amibroker FAQ

Hi All,

Been a little quite around here. How about a trading system topic.
I have no problem with using a short-entry signal to exit a long position. However, that does not always mean that I'm looking to get short. Even though the signal was indeed a short-entry, are those best taken after the long-system has exited via its own signal (long-exit)?

Of course I could have phrased the question with using long-exits to close a short position, but do they behave in a similar fashion? Perhaps the topic is more philosophical than quantitative. While I view the long and short systems a being quite separate, there is interaction that must be considered.

What are your ideas, thoughts and experiences in this regard?

Later,
RutheezKey
 
Hi RutheezKey --

In many issues, including stock shares, equity indexes, and equity ETFs, profitable long trades have different characteristics than profitable short trades. Short trades are shorter in number of bars with steeper price change than long trades.

Other issues, such as currencies and some commodities, are more symmetric.

We can study the characteristics of ideal trades by applying a zigzag indicator to the price series. Zigzag connects perfect bottoms with perfect tops. It looks into the future as it identifies the top bar and bottom bar, so it cannot be used as an indicator for live trading. But it is useful for study of historical data.

The technique is:
Apply a zigzag.
Buy at the bottom.
Sell at the top.
Short at the top.
Cover at the bottom.
Analyze the trades from each category.

If the data series is not symmetric, then the model should not attempt to force symmetric behavior. That is, the rules and parameters used to identify the top should be different than the rules and parameters used to identify the bottom. Allow the rules to adapt to the behavior of the data.

There are significant advantages (simpler, smaller, more easily understood, fewer components, faster, less distraction, etc) to developing trading systems that completely separate long from short. Have one system (a system is a model plus data) to enter and exit long positions, a separate one to enter and exit short positions. Whether the long exit always picks the same bar and price as the short entry is not important, provided each system is well developed and passes validation tests.

Best regards,
Howard
 
Hi Howard,

Thanks for your input. For the past many years, I've kept the long and short systems separate--- since their behavior is so frequently unique. Lately, I've been more interested in making my trading life simpler( single account, single system, single code-updates, etc.). This is why I began to view the short-exits as being part of the long strat. Sure, the total number of patterns may not be much different in the end, but the code will all be in one place;~).

Later,
RutheezKey
 
In analysis you set the from-to-date on the from screen. Is there a way to embed this within the AFL?

e.g

SetOption(RangeFromDate = 01/12/2014);
SetOption(RangeToDate = "31/12/2014");

I've not been able to find away to do this. I have a number of back tests that I am running from differing dates.
 
In analysis you set the from-to-date on the from screen. Is there a way to embed this within the AFL?

e.g

SetOption(RangeFromDate = 01/12/2014);
SetOption(RangeToDate = "31/12/2014");

I've not been able to find away to do this. I have a number of back tests that I am running from differing dates.

By "embed this..." do you mean calling the from-to setting?
If so then see Status() function in AB help and check available status codes. It's there.

If you mean setting from-to via AFL then use a condition (DateNum() range) to be added to Buy/Sell/Short/Cover variables.

Besides you can save your work to project files (.apx). Those project files save your AFL plus all backtest settings.
 
By "embed this..." do you mean calling the from-to setting?
If so then see Status() function in AB help and check available status codes. It's there.

If you mean setting from-to via AFL then use a condition (DateNum() range) to be added to Buy/Sell/Short/Cover variables.

Besides you can save your work to project files (.apx). Those project files save your AFL plus all backtest settings.


Thanks for that. :)

I have incorporated the DateNum() into my filter:

Code:
Filter =  EMA( C, FastMALength ) > EMA( C, SlowMALength ) A AND DateNum() >= 1150218 AND DateNum() <= 1150630;
RestorePriceArrays();

Thanks for your help.

I have also done a project file (.apx) but still need to see how best to use.
 
Hi,

From what I've read, I thought if I define the BuyPrice, SellPrice, etc. in the code that the backtester would use those arrays (instead of the BT settings). This is not what I am experiencing. Perhaps someone could provide me with the answer to what I am missing.

Thanks!
 
Hi,

From what I've read, I thought if I define the BuyPrice, SellPrice, etc. in the code that the backtester would use those arrays (instead of the BT settings). This is not what I am experiencing. Perhaps someone could provide me with the answer to what I am missing.

Thanks!

Hi RutheezKey --

Your understanding is correct.

BuyPrice, and the other execution prices, can be set in settings.

They can also be set in the afl code, and almost always are. Typically there will be a statement near the top of the program such as:
BuyPrice = Close;
This assigns the value of the closing price of each bar to the variable BuyPrice, which is also an array with a value for each bar.

Then, as each bar is processed to compute indicators and check rules, the Buy and Sell arrays receive values of True (numerically 1 -- actually any value other than zero) for those bars when the Buy or Sell signal is generated. If you are using stop orders or limit orders, it is your responsibility to set BuyPrice to the price at which you want execution. The statement pair looks something like this:

if xxx
{
Buy = True;
BuyPrice = 0.99*Ref(C,-1);
}

This stores a new value in the BuyPrice array for those specific elements, overriding the previously stored value of the close.

[That code example is intended to illustrate the sequence and assignment. It is almost certainly not what you want to use. In order for it to actually work, some additional code is required.]

To debug your program, dumb it down by commenting out unnecessary code so that it is easy to see what price is being stored in BuyPrice. Then run the system on a single issue (not a list), and check the Trade List after a Backtest. You should see the execution prices being those you requested. If not, check your code. The problem will be in your code, not in AmiBroker.

Best,
Howard
 
Hi Howard,
I admire your love of teaching!

Here is what I've got (after Buy/Sell/Short/Cover signal generation):
The signals are designed to force closure of existing positions(e.g. short signal triggers sell signal). Basic action is to enter the trade at the open and exit at the close. Reversals execute both trades at the open.

BuyPrice = ValueWhen( Buy, Open, 1 );
ShortPrice = ValueWhen( Short, Open, 1 );

SellPrice = ValueWhen( Sell, IIf( Short AND Sell, Open, Close ), 1 );
CoverPrice = ValueWhen( Cover, IIf( Buy AND Cover, Open, Close ), 1 );

I can plot the signal-flags and execution-values just fine......and they align as desired. It's just that the backtest report is following the backtest settings instead of my defined arrays.

Thanks for your help, Howard.

Later,
RutheezKey
 
I should add, in no way did I mean to imply that something was wrong with AB...I'm a large fan. More simply, I thought there might be a function/statement that was designed to direct the program to bypass the backtest settings.
 
Hi RutheezKey --

The syntax used -- ValueWhen rather than Ref -- is unusual. It may be that the BuyPrice value you are computing is being assigned to a bar other than the one you planned it to be, leaving the BuyPrice at the bar you you wanted to change still having the value set by an earlier assignment or the Settings screen.

If the problem you originally described still exists, try rewriting the statements using Ref rather than ValueWhen.

I find it helpful to draw a diagram of the bar chart. Put a star at the point everything that is necessary to generate the signal and compute the desired price is known. This would typically be at the close of a bar or at the open of a bar. Then, from the perspective of all the conditions at the star, describe the relationship of prices, indicators, rules, and signals. This will help detect conditions that cannot be met in real trading, if there are any. Then write the AmiBroker code that assigns values to Buy and BuyPrice. If all the references are to the current bar or previous bar, I prefer Ref to ValueWhen for clarity.

Best,
Howard
 
Hi Howard,

I'm using AFL (not index loop). I used ValueWhen so the array, in the time space between consecutive signals(single-bar-flags), would contain the execution price at the previous flag. I'm happy that it's "unusual", since that fits most folks description of me ;~)

Thanks for your help.......Later!
 
Hi RutheezKey --

You already know this, but for the benefit of others ---

Whether the code uses explicit looping or array assignments is not a factor in setting BuyPrice.

I am glad you are getting this figured out.

Best,
Howard
 
Can someone see where my problem is with the following code. My problem is running the afl that the actual trade delay is coming from my backtest settings which has a default to buy price at close.

The AFL code in theory sets the trade delay to buy at open the following day.

Code:
MaxPositions = 4;
SetOption("MaxOpenPositions", MaxPositions  );
SetOption("WorstRankHeld", MaxPositions + 2 );
SetOption("InitialEquity",15000);
SetPositionSize( 100 / MaxPositions, spsPercentOfEquity ); 

// trade on next day open
BuyPrice = Open;
SetTradeDelays( 1, 1, 1, 1 );

SetBacktestMode( backtestRotational );

Filter =  DateNum() >= 1150514 AND DateNum() <= 1150630;
RestorePriceArrays();


PositionScore = Iif( Filter, 10000 - ROC( C, 252 ), 0 );

StaticVarSet( Name() + "Score", 10000 - ROC( C, 252 ) );

SetCustomBacktestProc("");
if ( Status( "action" ) == actionPortfolio )
{
    bo = GetBacktesterObject();
    bo.backtest( 1 );

    // closed trades
    for ( trade = bo.GetFirstTrade(); trade; trade = bo.GetNextTrade() )
    {   // two additional columns
        trade.addcustomMetric( "Score@entry", Lookup( StaticVarget( trade.symbol + "Score" ), trade.EntryDateTime ) );
        trade.addcustomMetric( "Score@exit", Lookup( StaticVarget( trade.symbol + "Score" ), trade.ExitDateTime ) );
    }
    
    // open trades
    for ( trade = bo.GetFirstOpenPos(); trade; trade = bo.GetNextOpenPos() )
    {   // two additional columns
        trade.addcustomMetric( "Score@entry", Lookup( StaticVarget( trade.symbol + "Score" ), trade.EntryDateTime ) );
        trade.addcustomMetric( "Score@exit", Lookup( StaticVarget( trade.symbol + "Score" ), trade.ExitDateTime ) );
    }


    bo.listTrades();
}

When I change the buyprice to open in the parameters it works as I want.
 
Can someone see where my problem is with the following code. My problem is running the afl that the actual trade delay is coming from my backtest settings which has a default to buy price at close.

The AFL code in theory sets the trade delay to buy at open the following day.

Code:
MaxPositions = 4;
SetOption("MaxOpenPositions", MaxPositions  );
SetOption("WorstRankHeld", MaxPositions + 2 );
SetOption("InitialEquity",15000);
SetPositionSize( 100 / MaxPositions, spsPercentOfEquity ); 

// trade on next day open
BuyPrice = Open;
SetTradeDelays( 1, 1, 1, 1 );

SetBacktestMode( backtestRotational );

Filter =  DateNum() >= 1150514 AND DateNum() <= 1150630;
RestorePriceArrays();


PositionScore = Iif( Filter, 10000 - ROC( C, 252 ), 0 );

StaticVarSet( Name() + "Score", 10000 - ROC( C, 252 ) );

SetCustomBacktestProc("");
if ( Status( "action" ) == actionPortfolio )
{
    bo = GetBacktesterObject();
    bo.backtest( 1 );

    // closed trades
    for ( trade = bo.GetFirstTrade(); trade; trade = bo.GetNextTrade() )
    {   // two additional columns
        trade.addcustomMetric( "Score@entry", Lookup( StaticVarget( trade.symbol + "Score" ), trade.EntryDateTime ) );
        trade.addcustomMetric( "Score@exit", Lookup( StaticVarget( trade.symbol + "Score" ), trade.ExitDateTime ) );
    }
    
    // open trades
    for ( trade = bo.GetFirstOpenPos(); trade; trade = bo.GetNextOpenPos() )
    {   // two additional columns
        trade.addcustomMetric( "Score@entry", Lookup( StaticVarget( trade.symbol + "Score" ), trade.EntryDateTime ) );
        trade.addcustomMetric( "Score@exit", Lookup( StaticVarget( trade.symbol + "Score" ), trade.ExitDateTime ) );
    }


    bo.listTrades();
}

When I change the buyprice to open in the parameters it works as I want.

See info here http://amibrokerforum.proboards.com/thread/54/trade-prices-code
 
You can save project files (which are not ABS but APX files. ABS files save backtest settings only). Those APX files save your AFL and all your analysis settings (backtest and analysis toolbar settings) to a whole project.
 
Top