How to write a custom trail stop?

I'm going to write a custom trail stop, but have no clue how to reset a variable to false when using valueWhen.

open0 = TimeFrameGetPrice("O", inDaily, -1); //previous day open
close0 = TimeFrameGetPrice("C", inDaily, -1); //previous day close

v1 = ValueWhen(TimeNum() == 93000, O);
v2 = ValueWhen(TimeNum() == 94500, C);

BuySignal = v2 - v1 > 30 && v1 > close0 && open0 > close0;
Buy = Ref(BuySignal, -1);

	sell only if Close is greater than last day's open and 
	after breaking, falling down and crossing under the moving average.
	But I don't know how to reset hit to false after exiting from the market.
hit = ValueWhen(Cross(Close, open0), 1);
ma60 = MA(Close, 60);
SellSignal = hit && Cross(ma60, Close);
Sell = Ref(SellSignal, -1) || TimeNum() == 160000;

Firstly, you are dealing with Arrays not numeric variable, so you need to think accordingly.

Referring to my line above, and this query of yours,

Its supposed to be done like this

buy = ExRem( buy, sell );
sell = ExRem( sell, buy ); 

So you can ExRem() hit with whichever corresponding condition that compliments it.

hit = ExRem( hit, false );     // This is one way, false or 0
1 Like

Hi travick,

Thanks so much for your kind help. I will try it later.

Hi travick,

Seems ExRem didn't work well under this situation since it just keeps the first occurrence. But what I need is to keep the value until exiting from the market. It should look like:

hit = ValueWhen(Cross(Close, open0) && marketposition != 0, 1);
hit = 0 after exiting from the market;

But there is no marketposition in AB, and no non-array variable to keep the status.

In that case you need to use Flip

This works like a latch, so once set to 1 when Buy occurs, Array will stay 1, until you Flip with with Sell and set it to 0.
This is like a state.

Hi travick,
Thanks. flip works well for resetting the status of hip to False. Now there is new problem with circular referencing. Here is the code. Could you please give a clue how to address it? Thanks again.


Sell = False;
hit = Flip( Cross(Close, open0), Sell );
ma60 = MA(Close, 60);
SellSignal = hit && Cross(ma60, Close);
Sell = Ref(SellSignal, -1) || TimeNum() == 160000;
Sell = ExRem(Sell, Buy);

In above code, I have to put Sell = False; at the top because hit assignment refers to Sell , and Sell needs to refer to the status of hit , but hit assignment has no way to know the latest status of Sell since Sell got updated below hit assignment. So even if flip works, it doesn't solve my problem.

Actually, I just bought the professional edition 2 days ago. Now I just regret because array programming is so troublesome. Such a simple problem could be easily solved in ordinary programming languages. Even if in MultiCharts, it could be easily solved by global variables.

You just have to get accustomed and it usually won't take long. 2 days since your purchase is a very short time.
Vector (or Array) Processing is actually required in such applications. If you are a programmer in any language, you'll pick it up in no time.

Now, for the code:

Sell = 0;   // 0 and False are the same
hit = Flip( Buy, Sell );    // Returns 1 when Buy signal appears and stays 1
ma60 = MA(Close, 60);
SellSignal = hit && Cross( ma60, Close);    // Intrade and price goes below ma60
Sell = Ref(SellSignal, -1) || TimeNum() == 160000; // Sell signal

// Now in general programing, you check if SELL occurred
// and set hit = 0;   // Reset

// But in Array processing, hit on the new bar after a SELL is already 0 because
// earlier Flip is for all bars 

Buy  = ExRem(Buy, Sell);
Sell = ExRem(Sell, Buy);

if you want to learn, just use a for() loop and use TRACE() so see how each array index populates.
The Trace tab in Log window will help a lot "to see" inside the array

You access any array like this:

bc = Barcount - 1;
_TRACEF("%g", C[bc] );


|| TimeNum() == 160000;
|| TimeNum() >= 160000;    // This is guaranteed

See any difference if a tick got skipped etc ?


Hi travick,
I've tried your code on a symbol, and seems hit always stays 1 and never be reset to 0 even if Sell is true.
For debugging, I'd like to use exploration to view the array values since it's most convenient and useful tool debugging, much better than built-in debugger with limitation.
Please refer to the image below, you can see hit stayed 1 even if Sell turns to true.
array exploration
I can understand why hit stayed 1 because the code is executed sequentially, and hit are evaluated after Sell = 0; and before Sell = Ref(SellSignal, -1) || TimeNum() == 160000;, which will not affect the value of hit. I have no idea to solve such problem at all.

The Classic by @Tomasz

And the Gems by @fxshrat


My bad, this happened when I copy pasted your code with mine in editing.

Move the Flip code to after the SELL code line.

This is a nice way to start with using visual method for debugging.

hit =0;
hit = Flip(Buy,Sell);
for (i= BarCount -1; i > BarCount -100; i--)
	_TRACEF("%g=%g",i ,hit[i]);

This is the simplest way to visualize, I have different buy and sell conditions.

Hehe, its logical, isn't it? How do you Flip Sell before it has even been computed :slight_smile:
just move it to after the SELL code.

And same with Buy, in your exploration output, the Bar that is True will be 1, the rest will be 0.
Not a state, but an impulse.


The Classic by @Tomasz

By the way, this is essentially the same code you get from the "Trailing Stop Loop", one of the many Code Snippets that are, by default, pre-installed in the Formula Editor:


I wonder how many users actually employ this productivity feature of the editor; using the default snippets is already a good thing, but learning how to add your own code (as explained in the above-linked document) is a very efficient way to avoid retyping boilerplate code.
Especially, if you get the habit to do it each time you see a brilliant code solution in this forum!


Excellent advice @beppe. Code snippets are (unfortunately) one of most overlooked features.


Thanks a lot @beppe. I modified the code snippets and made it work with my situation.
@travick flip doesn't work with my case. But anyway, thank you again.

1 Like