logo
Welcome Guest! To enable all features please Login or Register.

Notification

Icon
Error

Options
Go to last post Go to first unread
HolyGrail  
#1 Posted : Thursday, May 27, 2010 2:24:52 PM(UTC)
HolyGrail

Rank: Member

Groups: Registered, Registered Users
Joined: 5/27/2010(UTC)
Posts: 13
Location: Norton, Ohio

Folks, Hello - first poster here. I am trying to convert TradeStation EL to MFL. I finally found the Cum(1) trick to identify the first bar on a chart, but I still fail at something that should be simple. The goal is to write a formula for an indicator that will, on day #1, set a variable (Trigger) to its initial value, but on subsequent days just start with the previous day's value, kind of like a cumulative, rolling value. Here's the code: BarCount := Cum(1); Trigger := If(BarCount = 1, ((HIGH - LOW) / 2) + LOW, Ref(Trigger, -1)); Trigger; If you run this, nothing shows up, and no error message appears either. But if I replace the "else" code with a constant, it shows up and acts fine with a different value on day #1 like I want, like this: BarCount := Cum(1); Trigger := If(BarCount = 1, ((HIGH - LOW) / 2) + LOW, 86 {swapped the code for a constant}); Trigger; Any of you MFL gurus see what I am doing wrong? TIA.
johnl  
#2 Posted : Thursday, May 27, 2010 7:15:13 PM(UTC)
johnl

Rank: Advanced Member

Groups: Registered, Registered Users
Joined: 11/7/2005(UTC)
Posts: 602

Will:

a1:=((H-L)/2)+L;
a2:=Ref(a1,-1);
a2

work?


mstt  
#3 Posted : Thursday, May 27, 2010 8:02:06 PM(UTC)
mstt

Rank: Advanced Member

Groups: Registered, Registered Users, Subscribers
Joined: 7/25/2005(UTC)
Posts: 1,042

Was thanked: 57 time(s) in 54 post(s)

Hi HG

The reason for your first attempt failing is that you're referncing a variable at the same time as you're creating it. This is a no-no in MetaStock. The solution is to replace Ref(Trigger,-1) with PREV, a function that references this variable's PREVious value (as on the previous bar) for use in calculating the current value. Generally bar one would return a zero rather than what you want for the simple reason that there is no PREV value for bar one.

Checking your code, you're in danger of losing plot's for the first two bars and then having the third bar start from zero. N/A results (no plot) are the bane of just about every MS programmer on the planet so it's something that you need to get used to. There are solutions for many of the problems you'll run into but those solutions are seldom intuitive, even for an experienced user.

I've found that a good way to deal with N/A bars is to cycle my data array through the Forum DLL Sum function which replaces N/A with zero. After that you can doctor the data array ( but not using PREV or Ref() or Cross() or any other function that immediately introduces another N/A) so as to replace zero with a preferred value, such as ((H-L)/2)+L).

I'm not sure if this is the sort of thing that you're aiming for but here's my take on how you could begin to reorganise your code. The last line separates out the zero plot and replaces it with N/A. That prevents the plot from distorting the price plot if price and indicator use the same scale.

BarCount:= Cum(1);
Trigger:=If(BarCount=2,PREV,Ref(((H-L)/2)+L,-1));
ValueWhen(1,Trigger>0,Trigger);

However, If all you want to do is plot the previous bars value of ((H-L)/2)+L then the use of a single ValueWhen() function should do the trick.

ValueWhen(2,1,((H-L)/2)+L);

This could also be written as Ref(((H-L)/2)+L,-1) but I tend to use ValueWhen() for generating delays because it's less prone to introduce additional N/A results once triggered. Explaining how that happens is difficult but nevertheless true.

Hope this helps.

Roy

HolyGrail  
#4 Posted : Thursday, May 27, 2010 8:26:12 PM(UTC)
HolyGrail

Rank: Member

Groups: Registered, Registered Users
Joined: 5/27/2010(UTC)
Posts: 13
Location: Norton, Ohio

Roy, That gets it all right! Thank you. The new code: BarCount := Cum(1); Trigger := If(BarCount = 1, ((HIGH - LOW) / 2) + LOW, PREV); I only posted a small tidbit of code, as it was the concept I needed to focus on. I have many more spots in my EL code that "assume" previous day values, so this will be more of a haul to convert than I anticipated. Many thanks for the detail you took the time to produce!
HolyGrail  
#5 Posted : Friday, May 28, 2010 12:43:50 AM(UTC)
HolyGrail

Rank: Member

Groups: Registered, Registered Users
Joined: 5/27/2010(UTC)
Posts: 13
Location: Norton, Ohio

Roy, Looks like I got happy too soon. PREV doesn't work at all like I thought, and Ref(A, -1) isn't much better. WOW - this shouldn't be this hard. A while ago you posted this code when helping others with PREV:
X:=H-3*ATR(10);
If(PREV<l,Max(X,PREV),X);
I think if I could understand this code, it might shed light on my situation. You have 2 PREVs in the same line of code! Does PREV refer to X in this case (the PREVious assignment statement? Does it refer to that single line of code, but on the previous day's running? I was thinking that PREV refered to the FINAL assignment of a given variable, but clearly that's not true. ie - I assign A to 1, change it to 3, the next day I PREV it and I should get 3. Nope. Grown men DO cry, I am about to prove it...
HolyGrail  
#6 Posted : Friday, May 28, 2010 12:57:47 AM(UTC)
HolyGrail

Rank: Member

Groups: Registered, Registered Users
Joined: 5/27/2010(UTC)
Posts: 13
Location: Norton, Ohio

The code I was mentioning has a "less than" in it and it isn't showing correctly. I'll try to paste code here again replacing it with the web safe symbol.. X:=H-3*ATR(10); If(PREV<L,Max(X,PREV),X); I think if I could understand this code of yours, it might shed light on my situation. You have 2 PREVs in the same line of code! Does PREV refer to X in this case (the PREVious assignment statement? Does it refer to that single line of code, but on the previous day's running? I was thinking that PREV refered to the FINAL assignment of a given variable, but clearly that's not true. ie - I assign A to 1, change it to 3, the next day I PREV it and I should get 3. Nope.
mstt  
#7 Posted : Friday, May 28, 2010 2:14:24 AM(UTC)
mstt

Rank: Advanced Member

Groups: Registered, Registered Users, Subscribers
Joined: 7/25/2005(UTC)
Posts: 1,042

Was thanked: 57 time(s) in 54 post(s)

Hi HG

PREV refers to the value of the variable currently being defined as on the previous bar. It makes no difference to the calculation whether the variable is named or unnamed.

I like to think of MetaStock as purely sequencial language - everything happens in a very orderly fashion. An indicator executes each variable in sequence on bar one, and then repeats the process on bar two and so on. If the same code was being used in all columns of an exploration processing would start in columb B after completing bar one of column A, and so on. When that security was scanned completely the whole process would begin again with the next security, line 1, bar 1 column A. Maybe it doesn't work this way but believing that it does has helped me solve a number of thorny problems over the year, like why some practices are acceptable and others are not.

The one one situation where MetaStock deviates slightly from the normal sequence is when PREV is used. It doesn't permit a jump to a variable out of sequence but it does allow a look back to the previous bars value or result that the current variable generated and use that information to determine a result for the bar (and variable) currently being processed.

You were spot on when you wrote the original line of code using Ref(Trigger,1), except that Metastock generally does not allow you to use any variable that has not already been defined for the bar currently being processed. PREV does and is exactly what you assumed was true for Ref(Trigger,1), but it's legal and MetaStock fakes the first value (usually with zero as far as I can work out) and then goes on from there. PREV is not a difficult concept so don't get hung up on it - it just returns the previous bars value of the variable currently being defined.

The code of mine that you're referring to is a slightly mangled trailing stop. X defines how far the trail should hang below the current HIGH. I'm changing it around a little so that hopehully it doesn't get mangled. Yep. that looks OK in Preview mode.

X:=H-3*ATR(10);
If(L>PREV,Max(X,PREV),X);

What the second line says is: If L is greater than the previous value of the stop set a new stop level for the higher of X or PREVious value (move the stop up or keep it the same), otherwise {else} reposition the stop downwards to start a new ascent because of L having just breached the stop.

Plot this code as a ew indicator on a chart that's trenind upwards quite smoothly and you'll quickly see how it works. Plot it with the result of the second line delayed by one bar and you'll see very clearly where the stop is breached and it's forced to reposition at a lower price.

X:=H-3*ATR(10);
Y:=If(L>PREV,Max(X,PREV),X);
Ref(Y,-1);

So in this simple trailing stop PREV is first being used to decide if the stop has been breached or not, then if the stop has not been breached PREV is used to maintain at least the exiting price level. With nested If() functions we could make a number of other deciions if we wanted to.

One problem that shows up with this type of stop construction, where the X variable refers to the current bar rather than the previous bar, (it isn't delayed) is that a large sudden rise will trigger the stop. Delaying X prevents this rather unusual but quite possible problem.

Hope this helps.

Roy

HolyGrail  
#8 Posted : Friday, May 28, 2010 12:46:27 PM(UTC)
HolyGrail

Rank: Member

Groups: Registered, Registered Users
Joined: 5/27/2010(UTC)
Posts: 13
Location: Norton, Ohio

Roy, If I understand your post and my small tests, I think I am hosed. I need too much flexiibility with this variable. Check out this process flow chart which lays out the need: If for "beginning trigger" I use...
BarCount := Cum(1); {track bars so we can locate bar #1}
Trigger := If(BarCount = 1, ((HIGH - LOW) / 2) + LOW, PREV); 
...then "Beginning Trigger" will NEVER be anything except ((HIGH - LOW) / 2) + LOW. It is set that way on bar #1 and PREV evaluates to that value on all subsequent bars since it picks up the value "currently being defined as on the previous bar". This is what you've been telling me but I finally get it. But that is why I am hosed! Similar to a stop, the previous day's FINAL value of Trigger needs to be evaluated against the current Close to determine if trigger needs to change. If it does, it is RE-assigned a new value, which needs passed to the next day. AArgh...any thoughts? I'm going to look at your ValueWhen() thoughts in the meantime. Thanks again - you're holding me up in this battle.
Users browsing this topic
Guest (Hidden)
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.