Scale in failure due to failure of detecting the first trade

Hi all, I am designing a short strategy which has a 2-steps entry. The first entry is when RSI < 40 and VHSI < 30 (The volatility index of Hang Seng Index), using only 50% of equity. Then, I would like when only the first entry has been entered, and RSI < 40 with VHSI > 30, then I will enter another trade with the remaining 50% of equity. All positions will be covered when meeting the "Cover" criteria.

However, I am not able to debug why the ScaleinEntry will be entered earlier than InitialEntry. It seems like the InitialEntry and ScaleinEntry are independent signal in my codes. I used the exploration function and saw the above phenomenon happened. For example, on 27/3/2001, there was a short action(ScaleInEntry) and without previous InitialEntry done. Could someone point me where I did wrong? Thanks.

image

MaxPos = 2;
SetOption("InitialEquity",1000000);
SetOption("MaxOpenPositions",MaxPos);

RSI_display = RSIa(Close,5);
EMA_display = EMA(Close,50);

RSI_param = 5;
RSI_threshold = 40;
EMA_param = 50;



VHSI = Foreign("VHSI","Close");
marketpanic = VHSI > 30
notmarketpanic = NOT marketpanic;

Entry1 = RSI(RSI_param) < 40 AND notmarketpanic;
Entry2 = RSI(RSI_param) < 40 AND marketpanic;

SL_above_previous_high = Ref(High,-1) * 1.02;
ExitSignal = H > SL_above_previous_high;

Entry2 = ExRem(Entry2, ExitSignal);

InitialEntry = Entry1;
ScaleInEntry = Entry2;

Short = IIf(InitialEntry, 1, IIf(ScaleInEntry, sigScaleIn,0));

Cover = ExitSignal;
CoverPrice = IIf(Cover==1, Max(O, Ref(High,-1)*1.03), C);

ApplyStop(stopTypeLoss,	stopModePercent,3,1);
         
ApplyStop( stopTypeNBar, stopModeBars,Optimize( "num of days to stop",17,5,30,1 ),1);

//ApplyStop( stopTypeTrailing, stopModePercent, SL_above_previous_high ,1);

ApplyStop( stopTypeProfit, stopModePercent, 20,1);



//Position sizing
EntryPosSize1 = 50; //Size for first entry
EntryPosSize2 = 50; //Size for second entry
PosSize = (Entry1 * EntryPosSize1) + (Entry2 * EntryPosSize2);
SetPositionSize(PosSize,spsPercentOfEquity);

You first need to detect whether you are between Entry1 and the ExitSignal before you trigger Entry2.

Study the Connors TPS strategy code in the knowledgebase which contains the logic you need.

Thank you MacAllan. I saw there are codes as following:

FirstEntry = CloseAboveLongTermMA AND MultipleDayLowRSI;
InFirstPos = Flip(FirstEntry, Sell);
FirstTrigger = ExRem(InFirstPos, Sell);

I searched for Flip and ExRem functions and the effect seems to be a reversal. I assume there is a reason to use the above codes instead of FirstTrigger = ExRem(FirstEntry, Sell) but I do not know why.

It's being done that way due to the entry signal being a state signal rather than an impulse.

Consider the bars where this might be true:
FirstEntry = RSI(RSI_param) < 40 AND notmarketpanic;

You may get a string of bars where it's satisfied, then it's not for a few bars, then it is again for another series of bars. This is known as a "state signal".

ExRem(FirstEntry, Sell);
would only find the latest occurrence where FirstEntry was false then true, and use that as its starting point. This may be some time after the initial entry you want to find.

Flip(FirstEntry, Sell);
will find the first time FirstEntry was true following any previous Sell, and mark all bars forward until it hits a Sell as True, thus isolating all the bars your initial position would be open.

Now, to what TPS is doing:

FirstEntry = CloseAboveLongTermMA AND MultipleDayLowRSI;
InFirstPos = Flip(FirstEntry, Sell);
FirstTrigger = ExRem(InFirstPos, Sell);

Using Flip in the TPS context, finds all the bars the initial trade is open. ExRem-ing that then isolates the initial bar where that entry occurred.

Further reading at the links below:

3 Likes

Thank you for your informative sharing. Now I realized the need for saving the first entry and the period of holding positions in two variables.

Then for the last part, I saw a code statement like:

PositionScore = PositionScore = 100 - CurrentRSI ;  // favour low RSI

Is it a typo?

It's syntactically correct, but it does seem like needless duplication.

1 Like

I just tried writing the codes for my 2-steps entry following the codes of TPS, but it seems the second trade will still be triggered before the entering of the first trade. I used the exploration to confirm this.

SecondEntry

Could you please take a look at my codes if possible?

//Backtesting Only Code will not plot any signals
_SECTION_BEGIN("Simple RSI Momentum Long Only Strategy");
SetTradeDelays(0,0,0,0);


//Trading Logic
MaxPos = 2;
MaxPositionSizePercent = 100;
SetOption("InitialEquity",1000000);
SetOption("MaxOpenPositions",MaxPos);

VHSI = Foreign("VHSI","Close");
marketpanic = VHSI > Optimize("VHSI",28,10,40,1);
notmarketpanic = NOT marketpanic;

RSI_param = 5;
RSI_threshold = 40;
EMA_param = 50;
trailing_stop = 1.02;
time_stop = 17;
initial_stop = 3;


FirstScaleIn = 0.5;
SecondScaleIn = 0.5;

SL_above_previous_high = Ref(High,-1) * trailing_stop;
Cover = H > SL_above_previous_high;
CoverPrice = IIf(Cover==1, Max(O, Ref(High,-1)*trailing_stop), C);
//CoverPrice = Max(0, Ref(High,-1)*1.02);

BarsSinceCover = BarsSince(Cover);

FirstEntry = RSI(RSI_param) < RSI_threshold and Ref(RSI(RSI_param),-1) > RSI_threshold and (EMA(Close,EMA_param) < ref(EMA(Close,EMA_param),-1)) AND notmarketpanic;
InFirstPos = Flip(FirstEntry, Cover);
FirstTrigger = ExRem(InFirstPos, Cover);
BarsSinceFirstTrigger = BarsSince(FirstTrigger);
FirstTriggerPrice = IIf(BarsSinceFirstTrigger < BarsSinceCover, Ref(C,-BarsSinceFirstTrigger),0);

SecondEntry = RSI(RSI_param) < RSI_threshold and Ref(RSI(RSI_param),-1) > RSI_threshold and (EMA(Close,EMA_param) < ref(EMA(Close,EMA_param),-1)) AND marketpanic;
InSecondPos = Flip(SecondEntry,Cover);
SecondTrigger = ExRem(InSecondPos,Cover);
BarsSinceSecondTrigger = BarsSince(SecondTrigger);
SecondTriggerPrice = IIf(BarsSinceSecondTrigger < BarsSinceCover, Ref(C,-BarsSinceSecondTrigger), 0);


//---
// Trade signals
//---

if( FirstScaleIn + SecondScaleIn == 1.0 )
{
  //PositionScore = PositionScore = 100 - CurrentRSI ;  // favour low RSI

  Short = IIf( FirstTrigger, 1, 
             IIf( SecondTrigger, sigScaleIn, 0  ) );

  SetPositionSize(IIf( FirstTrigger, MaxPositionSizePercent*FirstScaleIn,MaxPositionSizePercent*SecondScaleIn), IIf( Short > 0, spsPercentOfEquity, spsNoChange ) );

  Cover = ExRem(Cover,Short);
}




ApplyStop(stopTypeLoss,	stopModePercent,initial_stop,1);
         
ApplyStop( stopTypeNBar, stopModeBars,time_stop,1);

//ApplyStop( stopTypeTrailing, stopModePercent, SL_above_previous_high ,1);

ApplyStop( stopTypeProfit, stopModePercent, 20,1);

//Equity(1,-1);

SetStopPrecedence( stopTypeLoss,  stopTypeTrailing, stopTypeNBar, stopTypeProfit );

//Position Size
//PositionSize = MarginDeposit = 1;

_SECTION_END();

PlotShapes(Cover*shapeUpArrow,colorGreen,0,Low);
PlotShapes(Short*shapeDownArrow,colorRed,0,High);

Plot( Close,"Price",colorBlack,styleBar);
Plot(SL_above_previous_high , "trailing stop line", colorRed );


//SetPositionSize( 50, spsPercentOfEquity );
//SetPositionSize( 50, spsPercentOfPosition * ( Buy == sigScaleOut ) ); // scale out 50% of position

Filter = 1;
AddColumn(VHSI,"VHSI_param",1.2);
AddColumn(ShortPrice,"ShortPrice",1.2);
AddColumn(CoverPrice,"CoverPrice",1.2);
AddColumn(Short,"Short Signal",1.2);
AddColumn(Cover,"Cover Signal",1.2);
AddColumn(FirstTrigger,"FirstTrigger",1.2);
AddColumn(InFirstPos,"InFirstPos",1.2);
AddColumn(SecondTrigger,"SecondTrigger",1.2);
AddColumn(InSecondPos,"InSecondPos",1.2);

Scaling-in is explained here in detail:
https://www.amibroker.com/guide/h_pyramid.html

1 Like

If you only want to enter the second position when the first position is open, you need that condition in the definition of SecondEntry. I don't see any reference to it in your code.

You should go back and study the TPS code again.

Clue...
image

1 Like

Got it, thanks!

I should have changed to:

SecondEntry = RSI(RSI_param) < RSI_threshold and Ref(RSI(RSI_param),-1) > RSI_threshold and (EMA(Close,EMA_param) < ref(EMA(Close,EMA_param),-1)) and marketpanic AND InFirstPos AND Ref(InFirstPos,-1);;

Hi MacAllan, sorry to bother you again. I tried to add the codes you hinted (I assume I am right at the moment) and Equity(1,-1) to show which stop mechanism was triggered during backtesting. However, on 7/6/2021 as shown in the photo, as the cover signal has been initiated on that day, the function

Exrem(InFirstPos, Cover)

should be initiated and make the InFirstPos as 0 from that point onwards, but it still keeps as 1 going on. Can you help point me which I went wrong please?

InFirstPos

I don't see that line of code in the listing you posted above.

I'd say the output of InFirstPos in the Explore looks like it's the result of a Flip function, not ExRem

You may want to spend a bit of time studying this post, to learn how to troubleshoot your own code.

Sorry for my confusion. I wrote it in on the third code line. Let me try on your link first.

FirstEntry = RSI(RSI_param) < RSI_threshold and Ref(RSI(RSI_param),-1) > RSI_threshold and (EMA(Close,EMA_param) < ref(EMA(Close,EMA_param),-1)) AND notmarketpanic;
InFirstPos = Flip(FirstEntry, Cover);
FirstTrigger = ExRem(InFirstPos, Cover);
BarsSinceFirstTrigger = BarsSince(FirstTrigger);
FirstTriggerPrice = IIf(BarsSinceFirstTrigger < BarsSinceCover, Ref(C,-BarsSinceFirstTrigger),0);

I have written InTrade = Flip( Short, Cover ); so I assume the InTrade value will become 0 on 28/12/2021 as there is a cover signal becoming True on that day, but the InTrade value has lasted for a few more days as 1 before got set back to 0. Does anyone have any idea? I have read through the debug guideline but still unable to find what had happened.
image

This topic was automatically closed 100 days after the last reply. New replies are no longer allowed.