A Better way to find Key Levels

What I was hoping to do is Consolidating Key Levels close to each other into one. This code somewhat works but really slows it down. Obviously because of the FOR loops. I was hoping to get a better way to identify "stronger" Key Levels based on the number of times it was "touched" using 1 minute timeframe and intraday.

function CheckNear( val1, val2, per )
{
	per = per / 100;
	nearIT = ( abs ( val1 - val2 ) ) / val2;
	result = IIf ( nearIT <= per, True, False );
	return result;
}

_SECTION_BEGIN("Study Space");

lo40 = L <= LLV( L, 40 );
//PlotShapes( lo40 * shapeSmallCircle, colorYellow, 0, L, -10 );
//"Total LLv = " + Sum( lo40, 150 );
//"valueWhen LOW = " + ValueWhen( lo40, L, 4 );
s = LastValue( Sum( lo40, 150 ) );

for( i = 1, loCnt = 0; i <= s ; i++ ) {
	for( ii = 1; ii <= s; ii++ ) {	
		if( CheckNear( LastValue( ValueWhen( lo40, L , i ) ), LastValue( ValueWhen( lo40, L, ii ) ), .5 )  ){
			loCnt[ i ]++;
			loVal[ i ] = ( LastValue( ValueWhen( lo40, L, i ) ) + LastValue( ValueWhen( lo40, L, ii ) ) ) / 2;
		}
	}
	if( loCnt[ i ] >= 2 ) {
		//_TRACE( "loCnt[ " + i + " ] = " + loCnt[ i ] + " **  loVal[ " + i + " ] = " + loVal[ i ] );	
		Plot( ValueWhen( L == loVal[ i ], loVal[ i ] ), "Support", colorAqua, styleLine | styleNoLabel );
	}		
}
_SECTION_END();
1 Like

Is this line correct?

You are adding up the last 150 array positions and using as the for() limit.

Anyway, I would do this on a very different way.
I would store all the levels on another array, using for(). I don't see any other way.
I would sort() this new array (that is not necessary in your code because your levels would be ascending or descending).
Run a for on the new array checking if they are near each other.

Can you try that on your own or some code would help?
I might have the time on this afternoon.

I would do something like this code.

It is not a final code, it is just to show the idea.
Please, take a look at the comments.

_SECTION_BEGIN( "Study Space 2" );
function CheckNear( val1, val2, per )
{
    per = per / 100;
    nearIT = ( abs( val1 - val2 ) ) / val2;
//    result = IIf( nearIT <= per, True, False ); // Wrong IIF() is for arrays, it is not a one-line IF()
    result = nearIT <= per;
    return result;
}


toGo = Param("(0=all) Last X Levels:", 30, 0, 1000);
if(toGO==0) toGO = BarCount-2;

Show = ParamToggle( "Show", "No|Yes", 0 );
if( Show )
{

//    lo40 = L <= LLV( L, 40 ); // You need better levels, this condition will be TRUE for a number of near candles
    lo40 = L <= LLV( L, 40 ) AND Ref( LLV( L, 5), 5 ) >= L; // This way L most be lower than the previous 40 but also lower than the next 5 bars, just one idea

    BarI = BarIndex();

Title = ""; // You can use Title as a Debug, good for fast and small verifications

    for( Total_Levels = 1; Total_Levels <= toGO; Total_Levels++ )
    {
        x1 = LastValue( ValueWhen( lo40, BarI, Total_Levels ) ); // Locate the previous Lo40 on a very fast way (and get its BarNumber)
        if( x1 == 0 ) break; // All Levels were scanned

        Levels_lo[Total_Levels-1] = Low[x1]; // Array Levels_lo will get all levels

//Title += "\n"+ (Total_Levels-1)+"  -  "+Levels_lo[Total_Levels-1];

    }
	Total_Levels--;

Title += "\n\nTotal Levels_H Gathered:" + Total_Levels;

//    Levels_lo = Sort( Levels_lo, 0, Total_Levels, 0 ); // Sort array in ascending order, not needed for your code. Right?
    
/*
Title = "";
    for( i = 0; i<Total_Levels ; i++ )
    {
Title += "\n"+ i +"  -  "+Levels_lo[i];

    }
*/    

	//
	// Let's check if the levels are near each other
	//
    
	Checked = 0;
	Checked_lo[0] = Levels_lo[0];

//Title += "\n"+Levels_lo[0];

    for( i = 1; i <= Total_Levels ; i++ )
    {
		if( CheckNear( Checked_Lo[Checked] , Levels_lo[i], 0.5 )  )
		{

//Title += "\n"+Checked+" Near:" + Checked_lo[Checked] + " and " + Levels_lo[i] + " ---> "+ ((Checked_lo[Checked] + Levels_lo[i]) / 2);
			Checked_lo[ checked ] = (Checked_lo[Checked] + Levels_lo[i]) / 2;
		}
		else
		{
//Title += "\n"+Checked+" Not Near:" + Checked_lo[Checked] + " and " + Levels_lo[i];
			Checked++;
			Checked_lo[ checked ] = Levels_lo[i];
		}
			
	}

//Title = "Checked:" + Checked + "   -  last:"+Checked_lo[Checked-1];

    for( i = 0; i <= Checked ; i++ )
    {
        Plot( Checked_lo[i], "", colorAqua, styleLine | styleNoLabel | styleNoRescale );
	}


}

_SECTION_END();

Your commented statement "Wrong IIF() is for arrays" is incorrect. IIf() function is polymorph. So it is for arrays as well as for numbers.

e.g.

var = Iif(element[ i ] > 0, 1, 0);// result is type number here

There is no loop required for that (custom array Levels_lo). Also ValueWhen being iterated thousands of times is much too slow. Instead look at SparseCompress and other additional functions.
Again... not any single loop required.


Rather use Gfx* functions here. Plot() is rather for arrays and you will get warning at 500 Plot() calls anyway.

Thanks for looking into my code.

s = LastValue( Sum( lo40, 150 ) );

It's suppose to just loop the number of LLVs found in 150 periods.

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