Problem of referencing (with even better example)

I had posted two thread before this related to problem of referencing [ref( )] in arrays. But unfortunately i was not able to get my point across. This time around I have come with the right example that pin points my concern. Below is the code for a simple ABCD pattern that is expanding in price length such as Leg A is smallest, Leg B is larger than Leg A, Leg C is larger than Leg B and Leg D is Larger than Leg C. See the chart below
LT

below is the working code that you can copy paste and run. It works perfectly well with the for loop and my aim is to remove this for loop. Below is the 1 minute data a file that you could use to run this code.
https://filebin.net/aghel9p3mjj5e7qs/LT082021.csv

_TRACE( "!CLEAR!" );
_N( Title = StrFormat( "{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}} ", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ) );
SetChartOptions( 0, chartShowArrows | chartShowDates | chartWrapTitle );
PlotOHLC( O, H, L, C, "Close", colorRed, styleBar , Null, Null, 0, 1, 1 );


patternLengthMax = 30;

BarRefLeg_0 = BarRefLeg_A = BarRefLeg_B = BarRefLeg_C = BarRefLeg_D = 0;
high_0 = Low_A = High_B = Low_C = High_D = 0;

BarRefLeg_C = LLVBars( L, patternLengthMax );
Low_C = Ref( L, -BarRefLeg_C );

BarRefLeg_D = HHVBars( H, patternLengthMax );
High_D = Ref( H, -BarRefLeg_D );

//can you get rid of this loop?
for( i = 0; i <= patternLengthMax; i++ )
{
    BarRefLeg_B = IIf( i == BarRefLeg_C, Ref( HHVBars( H, Ref( patternLengthMax - BarRefLeg_C, i ) ), -i ) + BarRefLeg_C, BarRefLeg_B );
    BarRefLeg_A = IIf( i == BarRefLeg_B, Ref( LLVBars( L, Ref( patternLengthMax - BarRefLeg_B, i ) ), -i ) + BarRefLeg_B, BarRefLeg_A );
    BarRefLeg_0 = IIf( i == BarRefLeg_A, Ref( HHVBars( H, Ref( patternLengthMax - BarRefLeg_A, i ) ), -i ) + BarRefLeg_A, BarRefLeg_0 );
}


High_B = Ref( H, -BarRefLeg_B );
Low_A = Ref( L, -BarRefLeg_A );
High_0 = Ref( H, -BarRefLeg_0 );


_TRACE( "BarRefLeg_0=" + BarRefLeg_0 + ", BarRefLeg_A=" + BarRefLeg_A + ", BarRefLeg_B=" + BarRefLeg_B + ", BarRefLeg_C=" + BarRefLeg_C + ", BarRefLeg_D=" + BarRefLeg_D );


patternFound = BarRefLeg_0 > BarRefLeg_A && BarRefLeg_A > BarRefLeg_B && BarRefLeg_B > BarRefLeg_C && BarRefLeg_C > BarRefLeg_D && BarRefLeg_0 <= patternLengthMax && BarRefLeg_D>0
               && high_0 > Low_A && Low_A < High_B && High_B > Low_C && Low_C < High_D && Low_C < Low_A && High_D > High_B && High_B > high_0;

atrBar = ATR( 5 )*0.75;

//Plot
PlotShapes( IIF( patternFound, shapeSmallSquare, shapeNone ), colorYellow );

for( i = 0; i < BarCount; i++ )
{
    if( patternFound[i] )
    {
        PlotText( "0", i - BarRefLeg_0[i] , H[ i - BarRefLeg_0[i] ] + atrBar[i - BarRefLeg_0[i]], coloryellow );
        PlotText( "A", i - BarRefLeg_A[i] , L[ i - BarRefLeg_A[i] ] - atrBar[i - BarRefLeg_A[i]], coloryellow );
        PlotText( "B", i - BarRefLeg_B[i] , H[ i - BarRefLeg_B[i] ] + atrBar[i - BarRefLeg_B[i]], coloryellow );
        PlotText( "C", i - BarRefLeg_C[i] , L[ i - BarRefLeg_C[i] ] - atrBar[i - BarRefLeg_C[i]], coloryellow );
        PlotText( "D", i - BarRefLeg_D[i] , H[ i - BarRefLeg_D[i] ] + atrBar[i - BarRefLeg_D[i]], coloryellow ); 
    }
}

//exploration
Filter = 1;

AddColumn(  BarRefLeg_0, "BarRefLeg_0");
AddColumn(  BarRefLeg_A, "BarRefLeg_A");
AddColumn(  BarRefLeg_B, "BarRefLeg_B");
AddColumn(  BarRefLeg_C, "BarRefLeg_C");
AddColumn(  BarRefLeg_D, "BarRefLeg_D");

In what way is this substantially different than your previous examples? Have you tried the previously provided solution? If that solution does not work, please demonstrate HOW it does not work. What exactly is the concern that you believe you are pin-pointing?

In my previous example barRefLeg_B was scalar. In this example it is an array. As to how the solution provided by you to my previous question is wrong I have clearly described it in that thread.

I spent a lot of time creating and trying to explain the previous solution to you, and you chose to reject it. Nothing in your previous thread was "clearly described"... you simply said that you didn't understand the output you were getting. Now you want to start over, with no additional information about your goal or how you're falling short of that goal. Perhaps someone else on the forum will have the patience to figure out what you want.

2 Likes

matt see the below illustration explaining the mistake in your code see below. I feel you are taking things personaly. If your solution is wrong then it is wrong no matter how long you spent on it.

stmt1

stmt2

stmt3

@Tomasz can you please intervene. Matt has effectively killed this thread.

Quite frankly, I don't see the point of the whole thing either. Your loop is executing just 30 times (NOT for all bars) - it is fixed and does not depend on number of bars in total. Formula complexity therefore is O(n), not O(n^2), which makes it pointless to spend time "optimizing" it, except for maybe moving loop invariants outside of the loop. Plus, I also seem to be lacking the understanding why Matt's response wasn't accepted by you.

2 Likes

Yes, but this is just an example. In my afl there are several thousand lines within the for loop. None of those lines are loop invariants, that means i cannot place them outside the loop.

Matt's solution (see my previous thread) overlooks the basic principles of arrays. Is he serious?
Let me explain this again.

  1. Lets assume we are at patternFound bar.

  2. We wish to compute BarRefLeg_B. Leg_B is the low between Leg_A and Leg_C. So first we hop to Leg_C and the compute the LLVBars between it and Leg_0. i.e

BarRefLeg_B = Ref(LLVBars(L, Ref(BarRefLeg_0-BarRefLeg_C, BarRefLeg_C)), -BarRefLeg_C) + BarRefLeg_C;

Idea is right but implementation is WRONG! Continue reading to know why it is WRONG.

  1. Note that the outer ref( ) goes back BarRefLeg_C bars and then the inner ref () moves forward BarRefLeg_C bars.

  2. But how can this work????? the inner Ref( ) is operating on Leg_C bar that does not have the correct value of BarRefLeg_C, so how can it move forward BarRefLeg_C bars? The correct value of BarRefLeg_C is in patternFound Bar not in Leg_C bar.

Do you get it? It's so basic why is this so hard to understand?

@AlgoEnthusiast, apparently, most of the users of this forum are either not interested in the pattern-based strategy you are evaluating, don't understand what you want to achieve1, are unable to provide a different solution or at least don't want to! 2

Personally, I think it is useless to insist.

In the absence of a better solution, since your formula contains extra lines, the only advice I can give is to evaluate if the loop in question can be encapsulated in a plugin written in C (via the ADK) to speed up its execution.

1) I belong to this category - I tried your example code - and I see many overlapping and/or incomplete patterns.
2) Alternatively, you can always look for someone who provides Amibroker's coding services who, if they understand your requirements, will do it for a fee.

1 Like

You are partly right. The scenario presented is the problem of referencing that arises due to AFL style of coding. And there is a simple solution which I have presented to @tomasz. i.e. CallingBar ().
It is generic function and can be used in variety of places unlike barsSinceCompare() which is specific and not as usable.

It is pointless. I explained to you already that your suggestion is fundamentally flawed. You don't understand how AFL works. It works for entire array / vector at once - in ONE STEP for entire vector, not for one bar. There is no such thing conceptually as "calling bar" in vector functions. The process is NOT serial, it is PARALLEL. If you want to process single bar at a time, you write a loop. Loops are provided for that purpose and your Callingbar would be just bar[ i ] in the loop (where i is the bar index - loop counter) Understanding how AFL works

2 Likes

It is very much on the point. I will prove it to you soon enough with evidence. Btw, what did you think of matt's solution?

@Tomasz I have re-Written the code using function currentBar( ). CallingBar( ) or CurrentBar ( ) is same thing. This is how it would resolve. Row in green background is the traditional way Ref( ) resolves and if you implement CurrentBar ( ) it will resolve as mentioned in pink bar. the Ref() functon would have to be altered to pick up currentBar( ) keyword while code parsing and resolve accordingly.

Currentbar

the code will modify to as below. Notice the loop is gone

_TRACE( "!CLEAR!" );
_N( Title = StrFormat( "{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}} ", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ) );
SetChartOptions( 0, chartShowArrows | chartShowDates | chartWrapTitle );
PlotOHLC( O, H, L, C, "Close", colorRed, styleBar , Null, Null, 0, 1, 1 );


patternLengthMax = 30;

BarRefLeg_0 = BarRefLeg_A = BarRefLeg_B = BarRefLeg_C = BarRefLeg_D = 0;
high_0 = Low_A = High_B = Low_C = High_D = 0;

BarRefLeg_C = LLVBars( L, patternLengthMax );
Low_C = Ref( L, -BarRefLeg_C );

BarRefLeg_D = HHVBars( H, patternLengthMax );
High_D = Ref( H, -BarRefLeg_D );



    BarRefLeg_B = Ref( HHVBars( H, CurrentBar( patternLengthMax - BarRefLeg_C ) ), -BarRefLeg_C ) + BarRefLeg_C;
    BarRefLeg_A = Ref( LLVBars( L, CurrentBar( patternLengthMax - BarRefLeg_B) ), -BarRefLeg_A ) + BarRefLeg_B;
    BarRefLeg_0 = Ref( HHVBars( H, CurrentBar( patternLengthMax - BarRefLeg_A) ), -BarRefLeg_0 ) + BarRefLeg_A;



High_B = Ref( H, -BarRefLeg_B );
Low_A = Ref( L, -BarRefLeg_A );
High_0 = Ref( H, -BarRefLeg_0 );


_TRACE( "BarRefLeg_0=" + BarRefLeg_0 + ", BarRefLeg_A=" + BarRefLeg_A + ", BarRefLeg_B=" + BarRefLeg_B + ", BarRefLeg_C=" + BarRefLeg_C + ", BarRefLeg_D=" + BarRefLeg_D );


patternFound = BarRefLeg_0 > BarRefLeg_A && BarRefLeg_A > BarRefLeg_B && BarRefLeg_B > BarRefLeg_C && BarRefLeg_C > BarRefLeg_D && BarRefLeg_0 <= patternLengthMax && BarRefLeg_D>0
               && high_0 > Low_A && Low_A < High_B && High_B > Low_C && Low_C < High_D && Low_C < Low_A && High_D > High_B && High_B > high_0;

atrBar = ATR( 5 )*0.75;

//Plot
PlotShapes( IIF( patternFound, shapeSmallSquare, shapeNone ), colorYellow );

for( i = 0; i < BarCount; i++ )
{
    if( patternFound[i] )
    {
        PlotText( "0", i - BarRefLeg_0[i] , H[ i - BarRefLeg_0[i] ] + atrBar[i - BarRefLeg_0[i]], coloryellow );
        PlotText( "A", i - BarRefLeg_A[i] , L[ i - BarRefLeg_A[i] ] - atrBar[i - BarRefLeg_A[i]], coloryellow );
        PlotText( "B", i - BarRefLeg_B[i] , H[ i - BarRefLeg_B[i] ] + atrBar[i - BarRefLeg_B[i]], coloryellow );
        PlotText( "C", i - BarRefLeg_C[i] , L[ i - BarRefLeg_C[i] ] - atrBar[i - BarRefLeg_C[i]], coloryellow );
        PlotText( "D", i - BarRefLeg_D[i] , H[ i - BarRefLeg_D[i] ] + atrBar[i - BarRefLeg_D[i]], coloryellow ); 
    }
}

//exploration
Filter = 1;

AddColumn(  BarRefLeg_0, "BarRefLeg_0");
AddColumn(  BarRefLeg_A, "BarRefLeg_A");
AddColumn(  BarRefLeg_B, "BarRefLeg_B");
AddColumn(  BarRefLeg_C, "BarRefLeg_C");
AddColumn(  BarRefLeg_D, "BarRefLeg_D");

Your formula is missing CurrentBar function definition. Write that function yourself. You can't? Its because the idea is flawed (not realisable).

Yes CurrentBar ( ) is not an atomic function. It has to be read along with the outer Ref ( ). And hence Ref() logic has to be altered a tad bit. :grimacing:

@Tomasz yes it is true that some changes would have to be made to the way code is parsed but it will add a world of value to AB. So many loops can be done away with.


Ref( CurrentBar( H ), -10) == H
Ref(Ref(Ref( CurrentBar( H ), -10), -50), 20) == H
CurrentBar ( H ) == H

The basic logic should be that whenever CurrentBar ( ) is encountered the current bar value should be taken irrespective of the outer ref ( ).

Please consider my proposal with an open mind. :pray:t3::relieved:

So, you know perfectly well that this idea is NOT realisable using VECTOR processing. Giving up vector processing is POINTLESS because it would slow processing BarCount-number of times. Just use loops, they are effectively much FASTER than your suggestion would be (as it essentially means re-executing entire formula BarCount-number of times)

The suggestion is essentially as evil as super-slow MS PREV, see Convert Metastock indicator to AFL - #4 by Tomasz

2 Likes

@Tomasz i accept your opinion but can we think of ways on how to achieve this. Ultimately every loop eliminated will only make things better.
I would like to takea look at barsSinceCompare( ) source-code.