[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [amibroker] a JScript replacing Metastocks PREV



PureBytes Links

Trading Reference Links

Stefan,

Thank you ofr your valuable post.
Just one note: there are also other functions
that allow recursive-type calculations.

Cum() is excellent example and it makes OBV re-implementation
much easier:

addvol = IIF( Close > Ref( Close, -1 ), Volume,
IIF( Close < Ref( Close, -1 ), -Volume, 0 ) );

/* cumulative sum is simple */
obvreplacement = CUM( addvol ); 

Also other functions use indirectly previous value.

For example your 
foo_today = Max(foo_yesterday,anothervalue).

in AFL is called: Highest( array ), HighestSince( condition, array )

Anyway nice article.

Best regards,
Tomasz Janeczko
amibroker.com
----- Original Message ----- 
From: <elstephel@xxxx>
To: <amibroker@xxxxxxxxxxxxxxx>
Sent: Wednesday, October 02, 2002 12:41 AM
Subject: [amibroker] a JScript replacing Metastocks PREV


> Hello,
> 
> Some newbies in this group (like me) have problems accessing past 
> data. Normally one would use the Ref() function of AFL, but this 
> doesn't work from within a definition like follows:
> 
> foo_today = func(foo_yesterday, anothervalue1, anothervalue2,...)
> 
> The workaround offered in these cases is the usage of the AMA2 
> function of AFL, since there is no PREV function like in 
> Metastock. Unfortunately the AMA2 function is not sufficient in 
> some cases, but - thanks to JScript and VBScript in AB - there is 
> an other way. In this text I want to decribe, how referencing past 
> data from within a functions definition can be done by using 
> JScript. I will explain it using two examples, a on balance volume 
> and a ATR based trailing stop.
> 
> Assumed you know the definiton of the OBV: How would you code it in 
> AFL? Simply writing OBV()? Right, but we cannot learn anything 
> from that, so let's get on to the next possibility using the AMA2 
> function:
> 
> OBV = AMA2(Volume,IIf(Close>Ref(Close,-1),1,IIf(Close<Ref(Close,-
> 1),-1,0)),1);
> 
> This function works as follows: The Volume is firstly multiplied 
> with an factor (+1,-1 or 0) depending on the close price change. 
> The result is added to the yesterdays OBV value (which is 
> multiplied before with the "1" on the far right). But this 
> yesterdays OBV value is not "known" anyhow to the AMA2 function, it 
> is again calculated by evaluating the first two arguments of the 
> AMA2 function but therfore the OBV of the preceding day is needed. 
> So this calculated as well and so on.... This way the AMA2 
> function recalculates the OBV from the last bar back to the first. 
> (For an in depth explaination of the AMA2 function please refer to 
> the AB help files.)
> 
> Ok, this construction works, but honestly, this looks a bit 
> strange, because the On Balance Volume has nothing to do with an 
> "Adapting Moving Avarage". Well, its a workaround like so many in 
> AB. It's not easy to see for a newbie.
> 
> Here comes, how this calculation can be done using JScript: In 
> JScript it is possible calculate the OBV values using a "for" loop 
> from the first to the last bar. This is the opposite direction of 
> how it's calculated by the AMA2 function. This difference is not 
> importend in this OBV example but can be very crucial (see 2nd 
> example). Please read the comments in the following code:
> 
> //ON BALANCE VOLUME with JScript
> 
> EnableScript("jscript");
> 
> <%
> 
> //Close and Volume are required to calculate the OBV
> //transfer Volume and Close from AFL into JScript
> Vol = VBArray(AFL("Volume")).toArray();
> Clo = VBArray(AFL("Close")).toArray();
> 
> //create an empty OBV-Array and initiate the first value
> jsOBV = new Array();
> jsOBV[0]=Vol[0];
> 
> //calculating OBV-Data in a loop
> for(i=1;i<Clo.length;i++){
> 
> if(Clo[i]>Clo[i-1]){
> jsOBV[i]=jsOBV[i-1]+Vol[i];}//adding Volume to yesterdays OBV
> else{
> if(Clo[i]<Clo[i-1]){
> jsOBV[i]=jsOBV[i-1]-Vol[i];}//substracting Volume from 
> yesterdays OBV
> else{
> jsOBV[i]=jsOBV[i-1];}//OBV not changed
> }
> }
> 
> //transfer jsOBV back to AFL
> AFL("myOBV")= jsOBV;
> %>
> 
> Plot(myOBV,"myOBV",colorRed,styleDots+styleNoLine);
> Plot(OBV(),"OBV",colorBlue,styleLine);
> 
> Attached you find a picture of this AFL code. the blue line is the 
> plot of the AFL-OBV() function, the red dots were calculated using 
> JScript.
> 
> Yes, you are right: the code is very long and it makes no sense 
> creating the OBV that way. This was only to show you the general 
> principle of coding recursive functions: (1) Create an (empty) 
> array, (2) [optional] initiate the first value and (3) run a loop 
> to calculate the remaining values of the array. The point is, that 
> this methology is more powerful than using the AMA2 function 
> because the calculation is done from the first to the last bar. 
> This direction makes it possible that a value is calculated based 
> on the REAL preceding value (not so in AMA2). 
> 
> AMA2 can (and should) be used for "ordinary" calculations like +-
> */. But try to use it in the following formula:
> 
> foo_today = Max(foo_yesterday,anothervalue).
> 
> I was not successful but that was part of my attempt to create ATR 
> based trailing stops. I wanted them to be calculated as follows. 
> Initially the distance from the close price to the stop should be 
> say 3*ATR(9): Close+3*ATR(9) for the short stop and Close-3*ATR(9) 
> for the long stop. The short stop will only be shifted towards 
> lower prices, except it gets broken by the close price. Vice versa, 
> the long stop will only be increased, except it gets broken by the 
> close.
> 
> I think it is impossble to code that in "pure" AFL. (I'd be curious 
> to see the opposite proven. Anyone?) The reason, I think, is that 
> there are two comparing conditions to be included in the AMA2 
> function: was the stop of yesterday broken? and is the todays stop 
> higher/lower than yesterdays? So my approach was using JScript. 
> Please read the comments in the following code:
> 
> //ATR BASED STOPS with JScript
> 
> EnableScript("jscript");
> 
> //first the raw stop functions are defined
> //based on ATR-depending distance to the close price
> multiplier = 3;
> Len = 5;
> range = multiplier*ATR(Len);
> rawlongstop=C-range; //raw long stop
> rawshortstop=C+range; //raw short stop
> 
> //two JScript functions for the stops are defined
> <%
> //function for the longstop
> function f_longstop(rawstop,baseprice,Length){
> 
> //"importing" the AFL functions into JScript
> Len = AFL(Length);
> Ls=VBArray(AFL(rawstop)).toArray();
> bp = VBArray(AFL(baseprice)).toArray();
> 
> //the stop is calculated in the loop
> for(i=Len+1;i<Ls.length;i++){
> if(bp[i]>=Ls[i-1]){Ls[i]=Math.max(Ls[i],Ls[i-1]);}
> }
> 
> return Ls;
> }
> 
> //function for the shortstop
> function f_shortstop(rawstop,baseprice,Length){
> //"importing" the AFL functions into JScript
> Len = AFL(Length);
> Ss=VBArray(AFL(rawstop)).toArray();
> bp = VBArray(AFL(baseprice)).toArray();
> 
> //the stop is calculated in the loop
> for(i=Len+1;i<Ss.length;i++){
> if(bp[i]<=Ss[i-1]){Ss[i]=Math.min(Ss[i],Ss[i-1]);}
> }
> 
> return Ss;
> }
> %>//End of JScript
> 
> //call the JScript functions to create the AFL stop arrays
> script = GetScriptObject();
> longstop = script.f_longstop("rawlongstop","Close","Len");
> shortstop = script.f_shortstop("rawshortstop","Close","Len");
> //End of stop calculations
> 
> //A simple trading system is included
> //to color the price plot. Since it is a trend following system,
> //it will cause losses in non trending markets. 
> //Please don't apply.
> Buy=C>Ref(shortstop,-1);
> Sell= C<Ref(longstop,-1);
> 
> Buy=ExRem(Buy,Sell);
> Sell=ExRem(Sell,Buy);
> 
> Short=Sell;
> Cover=Buy;
> 
> poslong=Flip(Buy,Sell);//position is long
> posshort=Flip(Short,Cover);//position is short
> 
> Plot(shortstop,"ShortStop",colorLightOrange,styleDots+styleNoLine);
> Plot(longstop,"LongStop",colorBlue,styleDots+styleNoLine);
> Plot(C,"Close",IIf(poslong,colorGreen,IIf
> (posshort,colorRed,colorBlack)),styleBar);
> 
> 
> Attached you find a image of that code applied. The price bars were 
> colored green and red indicating the long or short market 
> position. The orange dots represent the short stop, wich is only 
> applied if the price bars are red. Vice versa the blue dots 
> represent the long stop that gets only applied in the long position 
> (green).
> 
> Again, the two JSCript functions follow the above mentioned basic 
> principle: first the arrays were defined (Ls=... and Ss=...). The 
> Initiation was already done by the preciding AFL code 
> (rawlongstop=... and rawshortstop=...), so there was no need to do 
> it again in the JScript section, and second the loops were run to 
> create the remaining data.
> 
> Finally pretty easy. In addition, I was really surprised by the 
> execution speed. I expected it to be a bit slower because of the 
> JScript sections in the code, but it was not. Just a mouse click 
> and it is there even with long histories (^DJI back to 1930).
> 
> I hope that I could show you an other way to prgramm recursive 
> formulas in AB. Give the scripting languages a try, they make AB 
> very powerful.
> 
> Best regards,
> 
> Stephan
> 
> 
> Post AmiQuote-related messages ONLY to: amiquote@xxxxxxxxxxxxxxx 
> (Web page: http://groups.yahoo.com/group/amiquote/messages/)
> 
> Check group FAQ at: http://groups.yahoo.com/group/amibroker/files/groupfaq.html 
> 
> Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/ 
> 
>