Swing High / Swing Low AFL Code

Dear PanoS;
Good Morning
and thanks for directing to afl "Automatic support and resistance lines9 …"

With this AFL, The swing high and low are plotted on the chart.

To get buy & sell signals as & when latest price breaks-out this level I tried to add
Buy = Close >hv;
Sell = Close < lv;
But error received as
Error 29:Variable "hv" used without having been initialized.
Error 29:Variable "lv" used without having been initialized.

image

So, I will be thankful if you please advice me how to generate signals /alarms as & when latest price breaks-out this level in Intraday chart.
Thanks...
Rao.

@rao
Your code doesn’t know the meaning of “hv & lv”…. that’s why throwing error.

Dear Fossil;
Hi.
So please advice, how to resolve it..
Thanks.

@rao
http://forum.amibroker.com/t/how-to-avoid-error-29-variable-used-without-having-been-initialized/996

Hello @rao
That is true as @Fossil said, it is easy to find where is this error, in your AFL code.
But always if you find any difficulty’s this forum is open to help you, drop your code here and we will see what extras you need.
Thank you

Dear Panos;
good evening.

Please find herewith the AFL code;

// define reusable function
function SupResLevels( bars, colorUp, ColorDn )
{
bi = BarIndex();
lvbi = LastValue( bi );

// return HHV value only for bars starting from the bar where HHV level was established
hv = IIf( bi >= lvbi - LastValue( HHVBars( High, bars ) ), LastValue( HHV( High, bars ) ), Null );

// the same approach for LLV
lv = IIf( bi >= lvbi - LastValue( LLVBars( Low, bars ) ), LastValue( LLV( Low, bars ) ), Null );

// plot levels
Plot( hv, "hv", colorUp, styleDashed );
Plot( lv, "lv", ColorDn, styleDashed );

}

// price plot
Plot( Close, "Close", colorDefault, styleBar );

// call function with various parameters
SupResLevels( 10, colorGreen, colorRed );
SupResLevels( 50, colorGreen, colorRed );

Buy = Close > hv;
Sell = Close < lv;

This code is giving error 29 as mentioned earlier.

Please help me to resolve as I like to get buy & sell signals generated in Intraday chart or in daily chart after running this scanner.

Thanks.

Hello
For your Question. The Hv and Lv are INSIDE the Function and you have to call your BUY with a different way.

I am going to give you another code to play little bit with it. I wrote the Buy condition with the Cross(). Also as I saw you are interest for scanner and I wrote few lines for exploration to start with.

Just remember this SUPPORT AND RESISTANCE version uses moving Avarage instead of pivots. There are many different S&R versions on the Net that you can find. I choose this one as I believe will keep you busy.

// You can also use other condition for buy/sell like a macd() for example
// System use MACD for Buy, Sell signals
 Buy = Cross(MACD(), Signal());
 Sell = Cross(Signal(), MACD());

So here is the exercise code. @rao I hope you will enjoy :wink:

_SECTION_BEGIN("SUPPORT AND RESISTANCE (using moving Avarage)");

LB= Param("Back Periods HH,LL",10,0.25,30,0.25);
R=ValueWhen(Cross(MA(C,LB),C),HHV(H,LB),1);
S=ValueWhen(Cross(C,MA(C,LB)),LLV(L,LB),1);
SupResInclude = ParamToggle("SUPPORT AND RESISTANCE","HIDE|SHOW",1);

if( SupResInclude )
{
    Plot( R, "Resistant", colorGreen, 24 );
    Plot( s, "Support", colorRed, 24 );
}



// it is better to use Cross(Close ,R) Than Buy = Close > R 
 Buy= Cross(Close ,R);  
 Sell = Cross(S ,Close);  

// Plot arrows on the chart
shape = Buy * shapeUpArrow + Sell * shapeDownArrow;
PlotShapes( shape, IIf( Buy, colorGreen, colorRed ), 0, IIf( Buy, Low, High ) );
// price plot
Plot( C, "Close", colorDefault, stylebar );

if( ParamToggle("Plot Mov Average ?", "No|Yes" ) ) Plot( MA(C,LB), "Mov", colorred, styleline );


//-- Code For Exploration
if( Status( "Action" ) == actionExplore )
{
  Filter= Buy OR sell;  // short or Cover (you need to add in the filter later on)
  ColGreen = IIf(Buy,colorGreen, colorDefault);
    SetOption( "NoDefaultColumns", True );
    AddtextColumn( Name(), "Symbol", 1, colorDefault, ColGreen, 70 );
    AddColumn( DateTime(), "Date / Time", formatDateTime , colorDefault, colorDefault, 150 );
    AddColumn( BUY, "BUY", 1, colorDefault, colorDefault, 35 );
    AddColumn( SELL, "SELL", 1, colorDefault, colorDefault, 35 );
}

_SECTION_END();

SandR

3 Likes

@rao

more in general, I suggest you review this part of the AmiBroker guide User-definable functions, procedures. Local/global scope.

It is crucial to correctly understand the "scope" of variables and how this relates to their use in user-defined functions.

Due to the fact that AFL does not require to declare variables the decision, whenever given variable is treated as local or global, is taken depends on where it is FIRST USED.
If given identifier appears first INSIDE function definition - then it is treated as a LOCAL variable.
If given identifier appears first OUTSIDE function definition - then it is treated as a GLOBAL variable.
This default behavior can be however overridden using global and local keywords (introduced in 4.36) - see example 2.

A very powerful and useful feature recently introduced in AmiBroker 6.25 Beta allows also to use functions passing variables by reference but this is a more advanced topic that you should study only when you are entirely comfortable with the above concepts.

2 Likes

@rao

function SupResLevels( bars, colorUp, ColorDn )
{
...........
...........
VarSet ("Highvalue",hv);
VarSet ("Lowvalue",lv);
return;
}
...........
...........
VarGet("Highvalue");
VarGet("Lowvalue");

Moderator comment: this is wrong because VarSet should only be used for DYNAMIC variables, i.e. variables with dynamically constructed identifiers. For all other uses you should use normal variables and DECLARE them to have them global.

If you want hv and lv to be visible OUTSIDE the function where they first appeared, you need to DECLARE them as global.

function SupResLevels( bars, colorUp, ColorDn )
{
  global hv, lv; // DECLARATION REQUIRED 
  ....
}
// hv and lv would be visible outside the function because they are declared global
4 Likes

Dear PanoS,

I tried your posted exercise code . The plotting is ok BUT after scanning / exploration nothing came out. The result is showing zero.

Thanks.

If you prefer to avoid globals and want to "simulate" multiple return values from a function it is possible to use the technique explained in this KB article:

A function with multiple return values

As said before, a recent beta AmiBroker introduced the "true" feature to pass parameters by reference.

Re this new feature I have a question for @Tomasz.

For testing purposes, I modified the Automatic support and resistance lines passing to the SupResLevels( ) function the 2 last params by reference (..., byRef1, byRef2)

Here is my modified code sample that works properly:

// requirements
Version( 6.27 );

function SupResLevels( bars, colorUp, ColorDn, byRef1, byRef2 )
{
	bi = BarIndex();
    lvbi = LastValue( bi );

	// return HHV value only for bars starting from the bar where HHV level was established
    hv = IIf( bi >= lvbi - LastValue( HHVBars( High, bars ) ), LastValue( HHV( High, bars ) ), Null );

    // the same approach for LLV
    lv = IIf( bi >= lvbi - LastValue( LLVBars( Low, bars ) ), LastValue( LLV( Low, bars ) ), Null );

    // plot levels
    Plot( hv, "hv", colorUp, styleDashed | styleThick);
    Plot( lv, "lv", ColorDn, styleDashed | styleThick );

	// Assing calculated local arrays to param passed by ref
    byRef1 = hv;
    byRef2 = lv;
}

// price plot
Plot( Close, "By Ref: USING Local Vars - Close", colorDefault, styleBar );

// call function with various parameters
SupResLevels(  20, colorBrightGreen, colorRed, &hv1, &lv1 );
SupResLevels( 100, colorBrightGreen, colorRed, &hv2, &lv2 );

// Exploration
Filter = 1;
AddColumn( C, "Close" );
AddColumn( hv1, "HV1" );
AddColumn( lv1, "LV1" );
AddColumn( hv2, "HV2" );
AddColumn( lv2, "LV2" );
SetSortColumns(1); // sort by ticker

But, if I modify the code in the following way - NOT using local variables inside the function but doing the calculations directly to the passed by ref parameters - the main procedure arrays are filled with correct values (as it is possible to verify step by step with the debugger or using the exploration), but there is NO PLOTTING of the res/sup lines inside the function (and no warning or error messages).

// requirements
Version( 6.27 );

function SupResLevels( bars, colorUp, ColorDn, byRef1, byRef2 )
{
	bi = BarIndex();
    lvbi = LastValue( bi );

    // return HHV value only for bars starting from the bar where HHV level was established
    byRef1 = IIf( bi >= lvbi - LastValue( HHVBars( High, bars ) ), LastValue( HHV( High, bars ) ), Null );

    // the same approach for LLV
    byRef2 = IIf( bi >= lvbi - LastValue( LLVBars( Low, bars ) ), LastValue( LLV( Low, bars ) ), Null );

    // plot levels
    Plot( byRef1, "hv", colorUp, styleDashed | styleThick); // NO PLOT!
    Plot( byRef2, "lv", ColorDn, styleDashed | styleThick); // NO PLOT!
}

// price plot
Plot( Close, "By Ref: NO Local Vars - Close", colorDefault, styleBar );

// call function with various parameters
SupResLevels(  20, colorBrightGreen, colorRed, &hv1, &lv1 );
SupResLevels( 100, colorBrightGreen, colorRed, &hv2, &lv2 );

// Exploration
Filter = 1;
AddColumn( C, "Close" );
AddColumn( hv1, "HV1" );
AddColumn( lv1, "LV1" );
AddColumn( hv2, "HV2" );
AddColumn( lv2, "LV2" );
SetSortColumns(1); // sort by ticker

Here is what I see on my screen:

image

If possible, I would like to understand what is the reason for this different behavior.

(Test was done using AmiBroker 6.27.1 Beta - 64 Bits)

2 Likes

Dear @rao
I have to remind you that «exercise code» contain parameters.
You can right click over chart pane and select "Parameters" or press Ctrl+R allows to change chart parameters.
Now depend of the time frame you are looking your chart, most of the time YOU HAVE to adjust the parameters according to your needs – strategy.
Exactly the same parameters you have to declare TYPE when you are try to run scan or exploration. Otherwise you are going to have deferent results.

I bet that was your problem.
i try to avoid that and this is the reason that i include parameter window in my photo.

P.S aslo just remeber that i left alot of room for you to edit this code. as the SELL contition is not corect.... you must write your sell strategy...

EDIT:
Do not forget also the Backtester window settings, special where is the Periodicity tab

hello @beppe

beppe I have a question also here. I have the feeling that, the only AB coder use the character "&" is you, (you are put the "And" In some place of the code that personaly I would never realize to use it) and I would like to tell me the reason.
& Bit-wise "And"
I saw “&” In some places of your codes that really surprise me :heart_eyes:

// call function with various parameters
SupResLevels( 20, colorBrightGreen, colorRed, &hv1, &lv1 );

I think this is look like a newbuy question. :sunglasses:

@PanoS

it is the syntax to pass parameters by reference introduced in AmiBroker 6.25.0 Beta

CHANGES FOR VERSION 6.25.0 (as compared to 6.22.0)
...
9. AFL: New feature: Passing arguments as reference (allows modification of arguments passed – easy way to return multiple values), to pass by reference use & (address-of) operator before variable identifier
....

It is a feature that was further improved in the more recent Betas.

1 Like

Ahhha. I was really missing that bit. Thank you

In addition to the above, it is important to note that this syntax SHOULD NOT BE CONFUSED WITH THE BITWISE OPERATOR since in this case, it is directly used as a prefix to the variable names (no spaces).

In short, one of the main advantages using functions arguments by reference is that the referenced variables are directly modified, and as such, there is no duplication of such variables in memory.
This is useful, especially when dealing with huge arrays/ matrixes of data.

Another common usage is to simulate/mimic functions that will return multiple values (a feature that is available in some programming langages

Up to the said Beta, AmiBroker allowed passing arguments ONLY by value (but passing variables by names as in the linked KB article was a nice trick to circumvent this limitation)

Googling "passing by value vs passing by reference" will find many pages that explain the difference in detail: it is a standard feature in many programming languages.

Re how this feature is implemented in AmiBroker (and/or caveats using it) is something that @Tomasz only can adequately address!

4 Likes

With reference to the above, some users might be interested in additional info about different operators ( OR = || , AND = && ), bitwise operators and separators (inside the string - " I " ) used in AFL. It has been discussed in this thread:

A needed clarification

In my posted code the function call that pass arguments per reference could also be written in such a way:

// call function with various parameters
SupResLevels(  20, colorBrightGreen, colorRed, &   hv1, &    lv1 );
SupResLevels( 100, colorBrightGreen, colorRed, & hv2, & lv2 );

(with one or more SPACE/s between the & and the variable name)

The code works in the same way. since Amibroker (at least in this Beta) ignores the spaces.
Personally, I prefer to use the ampersand symbol (&) directly attached to the variables names.

The & when used as a BITWISE operator requires 2 operands.

1 Like

Thank you, Mr. PanoS.

I got it. Sorry for teoubling u.

Thanks...