2 actions at the same bar

//Initializing the Variables
STP_Sc = 2*ticksize; //Size of the ScaleIn point (2 ticks below entryprice)
STP_L = 2*Ticksize; //Size of the StopLoss point (2 ticks below ScaleIn Price)
STP_G = 10*Ticksize; // Size of the TakeProfit point (10 tics above entryprice)
Bought = 0; // Just a variable to tell if there is an OpenPosition
Price_of_buy = 0; // The EntryPrice
Profit = 0; // The actual StopGain Price
ScaleIn = 0; // The actual ScaleIn EntryPrice
Price_of_stoploss = 0; // The actual StopLoss Price
Stage = 0; // 0 = didnt touch the ScaleIn, 1 = touched the ScaleIn

//Initializing the loop

for( i = 0; i < BarCount; i++ ) 
{ 
    if( Price_of_buy == 0 AND Buy[ i ] )  //If no openpositions and buy is true
    { 
     //Filling the Variables
       Bought = 1 ;
       Price_of_buy = BuyPrice[ i ]; 
       ScaleIn = BuyPrice[ i ] - STP_Sc;
       Price_of_stoploss  = BuyPrice[ i ] - STP_Sc - STP_L;
       Profit = BuyPrice[i] + STP_G;
       
       // Here we start with the conditions at the ENTRY BAR (THE SAME BAR)!

       if(Low[ i ] <= ScaleIn) //If the low touches the ScaleIn price, I want it to Buy another contract

            {
                Buy[ i ] = sigScaleIn; 
                Sell[ i ] = 0; // mark appropriate exit code (I think this is redundant here, right? Yes, I got it from the Amibroker Examples)
                buyPrice[i] = ScaleIn;
                Stage = 1;

/* 
So the backtest would buy at this price. And thats what I want. But... I also want it to make another test at the same bar AFTER the ScaleIn Buy. I want to see if the low touched the Stoploss price! If it touched, I want it to exit the 2 contracts. Lets continue the code. 
*/
	
	if( Low[i] <= Price_of_stoploss ) //Notice that this next if is NESTED (an IF inside an IF)
                {
		Buy[ i ] = 0; 
		Sell[ i ] = 1; // mark appropriate exit code 
		SellPrice[i] = Price_of_stoploss ;
		Stage = 0; //reset
		Price_of_buy = 0; // reset 
		Price_of_stoploss  = 0;
		Bought = 0;
		Profit = 0;
		ScaleIn = 0;
                }
              }

Ok. Here is how I THINK the Array table would look like to the Amibroker Backtest AFTER THE FIRST IF (The scalein buy):

Buy = 1
Sell = 0

This is how I THINK the ARRAY table after the second IF executed would be:

Buy = 0
Sell = 1

So, at the same bar, both of the conditions would be executed? In my tests its Always the second array table that is execute: it makes a sell at the StopLoss Price, escaping the ScaleIn Part. But, it there is no StopLoss touch, the ScaleIn is executed perfectly.

So my theory is that the second IF subscribe the first and only the “last condition met” is executed by the backtester. Please, correct me if im wrong. Im just a noob.

And my question is: how do i code it so both actions (ScaleIn and StopLoss) are executed by the backtester if they happen at the same bar?

Thanks!!!

The simple code below needs to be tuned as per your requirements. But you will get the idea, what to do!

//Using For-Loop to generate Buy/Sell Signal instead of using ExRem
_SECTION_BEGIN( "For-Loop Buy/Sell" );
	 //A Simple Demo strategy
	 Per = Param( "Periods", 15, 3, 144, 1 );	 
	 HigherHighs = HHV( H, Per );
	 LowerLows = LLV( L, Per );	 
	 _Buy = Cross( H, Ref( HigherHighs, -1 ) );
	 _Short = Cross( Ref( LowerLows, -1 ), L );	 
	 
	 //Array Initialization
	 Buy = Sell = Short = Cover = Null;
	 LongFlag = ShortFlag = 0; //Simple Flag arrays to identify whether in a Long or Short position
	 
	 //Using Loop to generate signals
	 for( i = 0; i < BarCount; i++ )
	 {
		 //Long Positions
		 if( _Buy[ i ] AND LongFlag == 0 )
		 {
			 Buy[ i ] = 1;
			 LongFlag = 1;  //To record that we are in Long position
		 }		 
		 if( _Short[ i ] AND LongFlag == 1 )
		 {
			 Sell[ i ] = 1;  //Selling-off the Long position
			 LongFlag = 0;   //Reseting LongFlag back to False, to denote that we are no longer in "Long" position
		 }
		 
		 //Short Positions
		 if( _Short[ i ] AND ShortFlag == 0 )
		 {
			 Short[ i ] = 1;
			 ShortFlag = 1;	  //To record that we are in Short position
		 } 
		 if( _Buy[ i ] AND ShortFlag == 1 )
		 {
			 Cover[ i ] = 1;  //Covering the Short position
			 ShortFlag = 0;   //Reseting ShortFlag back to False, to denote that we are no longer in "Short" position
		 }
	 }
	 
	 //Plotting
	 Plot( C, "", colorDefault, styleBar | styleThick );
	 Plot( HigherHighs, "Highs", colorDarkGreen );
	 Plot( LowerLows, "Lows", colorBrown );
	 
	 PlotShapes( IIf( Buy, shapeUpArrow, shapeNone ), colorBrightGreen, 0, L, -30 ); //Long Entry
	 PlotShapes( IIf( Sell, shapeSmallDownTriangle, shapeNone ), colorBrown, 0, H, -15 ); //Long Exit
	 
	 PlotShapes( IIf( Short, shapeDownArrow, shapeNone ), colorRed, 0, H, -30 ); //Short Entry
	 PlotShapes( IIf( Cover, shapeSmallUpTriangle, shapeNone ), colorDarkGreen, 0, L, -15 ); //Short Exit
_SECTION_END();

Thread Link

2 Likes

So what youre saying is that if I put like this (general concept):

IF Buy
{
Variables
Bought = 1;
}

IF Bought = 1 and low[i] <= ScaleIn
{
Buy = sigScaleIn
Stage = 1
}

IF Stage = 1 and low<=StopLoss
{
Sell =1
reset variables..
}

.
.
.
.
It will execute both ScaleIn and StopLoss at the same bar?

Thanks!

This is what I would do, to avoid or compensate for logic clash of two factors at same bar. There might be other efficient methods too which I am not aware of yet!

Using Flags determine the state of a trade explicitly, then, accordingly set your rules for ScaleIn/Out or TSL for each state respectively:

One more suggestion would be to first logically trace such bar (situation) off your database - as per your set trading rules - using Exploration as discussed in KB article - Debugging techniques – Part 1 – Exploration (also read How do I debug my formula?). Then continue testing until you are satisfied with the results!

Hello friends.

Well, I thought of a solution for my problem, but my limited knowledge at the moment is not enough to put it in action.

My code, as shown in the Original Post, is a loop. When it buys, if in the same bar the low reaches the ScaleIn Price, it will enter a second position. But what happens in the arrays is this:

Code...

Buy = 1;
BuyPrice = PriceA;

Loop...

Low < ScaleIn Price is true...

Buy = sigScaleIn;
BuyPrice = PriceB;

Note that when the sigScaleIn activates at the same bar, it just changes original BuyPrice to the ScaleIn's BuyPrice, and enters only 1 share.

The solution I came with is to, when it happens at the same bar, instead of the ScaleIn entering only 1 share, it would enter 2 shares, and i would put the buyprice at the "average entry price", so it would all be ok. But remember: that would be only for the first bar.

But i dont know how to put 2 shares in case of scalein in the first bar and 1 share in case of scalein from the second bar on.

Does anyone have any light?

Hello,

I also built an afl where I had several trades happening inside the same bar.
I also followed the same approach, and I calculated the average entry price. (just make sure that you don't make assumptions about price timming inside that bar. For example what happens first : the first buy signal or the scalein signal)
For position size, you can follow the same approach, and define a variable inside your loop which defines the trade size and then use that in SetPositionSize Function.
Something like this:

//initialize variable
tradesize=0;
IF scale in condition....
{
Buy[i] = 1;
Stage = 1;
tradesize[i]=2 ; // instead of 1
}

//outside loop
Setpositionsize(tradesize,spsShares);
1 Like

Here is an additional template that might be useful (provided by @aron in old yahoo groups).
The code below is what I used to "emulate" the concept of "pending orders".
Since you don't need to keep track of which orders were already filled or not, you can simplify it, but I think it is helpful just to get the idea on how you can approach it, including the position size part.

Sell = short = Cover = pos = 0;
Buy = 1;

increment = 100 * TickSize ;
orders = 5;
PositionSize  = 10000;

for( i = 0 ; i < BarCount ; i ++ )
{
    if( pos )
    {
      
        count = 0;
        for( n = 1 ; n <= orders ; n ++ )
        {
            if( order[n] )
            {
                if( High [i] > order [n] )
                {
                    Buy [i] = sigScaleIn;
                    count ++;
                    order[n] = 0; // executed
                }
            }
        }

        PositionSize [i] = count * 10000;
    }
    else
    {
        if( Buy [i] )
        {
            order = Null ;

            for( n = 1 ; n <= orders  ; n ++ )
            {
                order [n] = Close [i] + n * increment;
            }

            pos  = True; 
        }
    }
}
1 Like