Static Variable value for some stocks missing

I have some computation that consumes large amount of time. In order to save time I store the processed value in static variables and persist. I call this value barScore . It is longest distance a line drawn from the given bar can travel (towards right) without intersection. This may not mean anything to you but in my world it has meaning. The meaning of barScore and it's computation has nothing to do with my problem. Every bar has two BarScore (s) each. One is BarScoreHH (High to High) and the other BarScoreLL (Low to Low). I create/store barscore for different timeframes with different variable names. So I add the interval() to the static variable name to differentiate.

Everything works perfectly when I work on one single timeframe (lets say 10 minutes) and in the same database. BarScores are generated, stored statically and persisted, retrieved everything works perfectly. I have a stock universe of 80 stocks and it works flawlessly. I can see that PersistVars.bin getting created and getting loaded on startup.
But the moment I change timeframe for example If i was working on 10 minutes earlier and now i switch to 20 minutes which means I ran my code on 20 minutes timeframe which in turn generated barscore for the said timeframe and stores/persists, it starts loosing values for the earlier 10 minutes timeframe. Some stocks still hold the value for 10 minutes but many stocks show value as 0. This happens to roughly 50% of my stocks. Some stocks lose data partially for example a stock may lose value from bar 500 to last bar. And some stocks lose value for all the bars. I have noticed that this also happens when i switch Database. For example lets say I was working on DB_Jan_March earlier and had created barscore for 80 stocks in timeframe 10 minutes and now i switch to DB_April_June and again create barscore in the same timeframe or some other timeframe and then later switch back to earlier DB (DB_Jan_March) i can see that many stocks have lost the barscore. I will reiterate that some stocks still hold the values but many have lost.
Below I am posting complete code that is runnable on copy paste.

_SECTION_BEGIN( "TestBarScoreNew" );
SetChartOptions( 0, chartShowArrows | chartShowDates | chartWrapTitle );
_N( Title = StrFormat( "{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}} ", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ) );
PlotOHLC( O, H, L, C, "Price", colorRed, styleBar , Null, Null, 0, 1, 1 );
Plot( BarIndex(), "Barindex", colorwhite, styleNoLine + styleNoLabel + styleNoRescale );
Plot( BarCount, "BarCount", colorwhite, styleNoLine + styleNoLabel + styleNoRescale );
_SECTION_END();

SetBarsRequired( sbrAll, sbrAll );
_TRACE( "!CLEAR!" );
global runmode;
dist = Param( "distance", 50, 1, 500, 1 );

timeframeBaseInSeconds = Interval();
InstrumentNameAndTFtext = Name() + "_interval_" + timeframeBaseInSeconds + "_";
maxSearchDistanceForBarScore = Min( dist, 100 );
finalSyntheticPrice = ( H + L ) / 2;

minSearchDistanceForBarScore = 2;
mapKey = ( dist - minSearchDistanceForBarScore );

function selectRunMode()
{
defaultRunMode = 0;
global txtAlongTheTrend, txtCounterTrend, txtNetEffect;
txtViewOnly = "View Only";
txtProcessing = "Processing";


global runModeViewOnly, runModeProcessing ;
runModeViewOnly = 1;
runModeProcessing = 2;


global runMode;
usrInput = ParamList( "Mode", txtViewOnly + "|" + txtProcessing, defaultRunMode );
runMode = IIf( usrInput == txtViewOnly, runModeViewOnly, IIf( usrInput == txtProcessing, runModeProcessing, 0 ) ) ;
}

function getEffectiveStartBarIndx()
{
    effStartBarIndx = Max( 0, BarCount - round( BarCount * timeframeBaseInSeconds / Max( timeframeBaseInSeconds, Interval() ) ) ) + 2;
    //_TRACE("getEffectiveStartBarIndx() BarCount="+BarCount +", timeframeBaseInSeconds="+timeframeBaseInSeconds+", Interval()="+Interval()+", effStartBarIndx="+effStartBarIndx);

    return( effStartBarIndx );
//return(10);

}

function calculateBarScore()
{
    if( Status( "actionex" ) != actionExAAParameters && Status( "actionex" ) != actionPortfolio )
    {
        startTime = Now( 5 );
        barHeight = H - L; //ATR( 5 );//
        thisTimeframeinseconds = Interval();
        thisTimeframeinMinutes = thisTimeframeinseconds / 60;
        InstrumentNameAndTFtext = Name() + "_interval_" + thisTimeframeinseconds + "_";
        sourceBarStartIndexBasedOnTimeframe = round( BarCount - Barcount / Max( 1, ( thisTimeframeinseconds / Max( 1, timeframeBaseInSeconds ) ) ) );
        barScoreComputationCompleteTillDistance = Nz( staticVarGet( InstrumentNameAndTFtext + "barScoreComputationCompleteTillDistance" ) );_TRACE("barScoreComputationCompleteTillDistance="+barScoreComputationCompleteTillDistance+", isnull(barScoreComputationCompleteTillDistance)="+isnull(barScoreComputationCompleteTillDistance));
        barScoreComputationCompleteTillDistanceInitial=barScoreComputationCompleteTillDistance;
        maxSearchDistanceEff = Max( 0, Min( maxSearchDistanceForBarScore, BarCount - BarIndex() - minSearchDistanceForBarScore ) );
        effStartBarIndex = getEffectiveStartBarIndx();
        barScoreComputationIncompleteCondition = barScoreComputationCompleteTillDistance < maxSearchDistanceEff && ( BarCount - BarIndex() -1) > maxSearchDistanceEff && maxSearchDistanceEff > effStartBarIndex && BarIndex()>=effStartBarIndex &&  BarIndex()<BarCount-1;_TRACE("barScoreComputationIncompleteCondition="+barScoreComputationIncompleteCondition);
        barScoreComputationIncompleteCondition[effStartBarIndex] = 1;
        SourceBarCounterStartValue = ValueWhen( barScoreComputationIncompleteCondition, BarIndex(), -1 ); 
        SourceBarCounterEndValue = ValueWhen( barScoreComputationIncompleteCondition && !Ref(barScoreComputationIncompleteCondition, 1), BarIndex(), -1); 
        SourceBarCounterStartValueScalar = SourceBarCounterStartValue[effStartBarIndex];
        SourceBarCounterEndValueScalar = SourceBarCounterEndValue[effStartBarIndex];
        _TRACE("1. SourceBarCounterStartValueScalar="+SourceBarCounterStartValueScalar+", isnull(SourceBarCounterStartValueScalar)="+isnull(SourceBarCounterStartValueScalar)+", SourceBarCounterEndValueScalar="+SourceBarCounterEndValueScalar+", isnull(SourceBarCounterEndValueScalar)="+isnull(SourceBarCounterEndValueScalar));
        //_TRACE("barScoreComputationIncompleteCondition="+barScoreComputationIncompleteCondition+", isnull(barScoreComputationIncompleteCondition)="+isnull(barScoreComputationIncompleteCondition)+", effStartBarIndex="+effStartBarIndex+", maxSearchDistanceEff="+maxSearchDistanceEff+", maxSearchDistanceForBarScore="+maxSearchDistanceForBarScore+", barScoreComputationCompleteTillDistance="+barScoreComputationCompleteTillDistance);

        if( IsNull( SourceBarCounterStartValueScalar ) || SourceBarCounterStartValueScalar == effStartBarIndex || SourceBarCounterStartValueScalar<=effStartBarIndex)
            SourceBarCounterStartValueScalar = BarCount;
            
        if( IsNull( SourceBarCounterEndValueScalar ) || SourceBarCounterEndValueScalar == effStartBarIndex ||SourceBarCounterEndValueScalar<SourceBarCounterStartValueScalar)
            SourceBarCounterEndValueScalar = BarCount;         
          

        barScoreComputationIsAlreadyCompleteForThisTimeFrame = SourceBarCounterStartValueScalar == BarCount;
        
           _TRACE("2. SourceBarCounterStartValueScalar="+SourceBarCounterStartValueScalar+", isnull(SourceBarCounterStartValueScalar)="+isnull(SourceBarCounterStartValueScalar)+", SourceBarCounterEndValueScalar="+SourceBarCounterEndValueScalar+", isnull(SourceBarCounterEndValueScalar)="+isnull(SourceBarCounterEndValueScalar)+", barScoreComputationIsAlreadyCompleteForThisTimeFrame="+barScoreComputationIsAlreadyCompleteForThisTimeFrame);

        //_trace("BarCount="+BarCount+", barScoreComputationIsAlreadyCompleteForThisTimeFrame="+barScoreComputationIsAlreadyCompleteForThisTimeFrame);
		//barScoreComputationIsAlreadyCompleteForThisTimeFrame=1;
        if( barScoreComputationIsAlreadyCompleteForThisTimeFrame )
            _trace( "barScore computation is ALREADY COMPLETE for all bars for instrument '" + Name() + "' upto SearchDistance of " + maxSearchDistanceForBarScore + " bars for interval " + thisTimeframeinMinutes + " minutes." );
        //else
        //_trace("SourceBarCounterStartValueScalar = "+SourceBarCounterStartValueScalar+", barScoreComputationIncompleteCondition="+barScoreComputationIncompleteCondition+", barScoreComputationCompleteTillDistance="+barScoreComputationCompleteTillDistance+", maxSearchDistanceEff="+maxSearchDistanceEff+", isnull(barScoreComputationCompleteTillDistance)="+isnull(barScoreComputationCompleteTillDistance));
        else
        {

            for( i = SourceBarCounterStartValueScalar; i < SourceBarCounterEndValueScalar; i++ ) //source bar
            {
                if( IsNull( barScoreComputationCompleteTillDistance[i] ) )
                    serD = minSearchDistanceForBarScore;
                else
                    serD = Max( minSearchDistanceForBarScore, barScoreComputationCompleteTillDistance[i] + 1 );

                //_TRACE( "...calculating bar score for bar "+i +" for dist "+serD+ " and onwards.");

                sourceBarHigh = high[ i ];
                sourceBarLow = Low[ i ];

                distCounterStartValue = Max( minSearchDistanceForBarScore, barScoreComputationCompleteTillDistance[i] + 1 );

                for( dist = distCounterStartValue; dist <= maxSearchDistanceEff[i] ; dist++ ) //Search Distance aka destination bar distance
                {
                    // the trendline is given by equation
                    //        y = ax + b;
                    //  where x would be (dist - x)
                    //             b would be high[ i ]
                    //             a would be (high[ dist ] - high[ i ] ) / (dist - i );

                    destBarIndex = i + dist;
                    destBarHigh = H[destBarIndex];
                    destBarLow = L[destBarIndex];

                    bsArraySuffixMappingToSearchDist =  dist - minSearchDistanceForBarScore ;

                    scoreForThisiDistPairHH = 0;

                    intersectionReachedForThisSynthPrice = 0;


                    for( k = 1; k < dist; k++ ) //intervening price bar between source and destination; k is the distance between sorce and intervening bar
                    {

                        cleanlineHH = 0;
                        interveningBarIndex = i + k;
                        interveningBarHigh = H[interveningBarIndex];

                        aHH = ( destBarHigh - sourceBarHigh ) / dist;
                        lineHH = aHH * k  + sourceBarHigh;    //value of line at bar (i+k)

                        if( interveningBarHigh <  lineHH && intersectionReachedForThisSynthPrice == 0 ) // line is clean
                        {
                            cleanlineHH = 1;
                            scoreForThisiDistPairHH = k;
                        }
                        else  //intersection found
                        {
                            intersectionReachedForThisSynthPrice = 1;

                            if( scoreForThisiDistPairHH == 0 && k == ( dist - 1 ) )
                                breakLoopSHH = 1;
                        }


                        matrixIndxOffset = 1;


                        a = staticVarGet( InstrumentNameAndTFtext + "bsHH_" + Max( 0, bsArraySuffixMappingToSearchDist - matrixIndxOffset ) );
                        bs =  Max( scoreForThisiDistPairHH,  a[i] );
                        bsHH = staticVarGet( InstrumentNameAndTFtext + "bsHH_" + bsArraySuffixMappingToSearchDist ) ;
                        bsHH[i] = bs;
                        staticVarSet( InstrumentNameAndTFtext + "bsHH_" + bsArraySuffixMappingToSearchDist,  bsHH, true );

                        //if( i == 38 && dist == 30)
                        //_TRACE( "i="+i+", dist="+dist+", s="+s+", k=" + k+ ", bsArraySuffixMappingToSearchDist=" + bsArraySuffixMappingToSearchDist + ", lineHH=" + lineHH + ", maxSearchDistanceEff=" + maxSearchDistanceEff[i] +", cleanlineHH="+cleanlineHH +", scoreForThisiDistPairHH="+scoreForThisiDistPairHH+", intersectionReachedForThisSynthPrice="+intersectionReachedForThisSynthPrice+", breakLoopSHH="+breakLoopSHH);


                        

                    }//end of loop k




                    bsArraySuffixMappingToSearchDist = dist - minSearchDistanceForBarScore ;

                    scoreForThisiDistPairLL = 0;

                    intersectionReachedForThisSynthPrice = 0;


                    for( k = 1; k < dist; k++ ) //intervening price bar between source and destination; k is the distance between sorce and intervening bar
                    {

                        cleanlineLL = 0;
                        interveningBarIndex = i + k;
                        interveningBarLow = L[interveningBarIndex];

                        aLL = ( destBarLow - sourceBarLow ) / dist;
                        lineLL = aLL * k  + sourceBarLow;    //value of line at bar (i+k)

                        if( interveningBarLow >  lineLL && intersectionReachedForThisSynthPrice == 0 ) // line is clean
                        {
                            cleanlineLL = 1;
                            scoreForThisiDistPairLL = k;
                        }
                        else  //intersection found
                        {
                            intersectionReachedForThisSynthPrice = 1;

                            if( scoreForThisiDistPairLL == 0 && k == ( dist - 1 ) )
                                breakLoopSLL = 1;

                        }


                        matrixIndxOffset = 1;


                        a = staticVarGet( InstrumentNameAndTFtext + "bsLL_" + Max( 0, bsArraySuffixMappingToSearchDist - matrixIndxOffset ) );
                        bs =  Max( scoreForThisiDistPairLL,  a[i] );
                        bsLL = staticVarGet( InstrumentNameAndTFtext + "bsLL_" + bsArraySuffixMappingToSearchDist ) ;
                        bsLL[i] = bs;
                        staticVarSet( InstrumentNameAndTFtext + "bsLL_" + bsArraySuffixMappingToSearchDist,  bsLL, true );

                        //if( i == 10 && dist == 30 )
                        //_TRACE( "i=" + i + ", dist=" + dist + ", k=" + k + ", s=" + s + ", bsArraySuffixMappingToSearchDist=" + bsArraySuffixMappingToSearchDist + ", lineLL=" + lineLL + ", maxSearchDistanceEff=" + maxSearchDistanceEff[i] + ", cleanlineLL=" + cleanlineLL + ", scoreForThisiDistPairLL=" + scoreForThisiDistPairLL + ", intersectionReachedForThisSynthPrice=" + intersectionReachedForThisSynthPrice + ", breakLoopSLL=" + breakLoopSLL );
						if (k==dist-1)
						{
						barScoreComputationCompleteTillDistance = staticVarGet( InstrumentNameAndTFtext + "barScoreComputationCompleteTillDistance" );
                        barScoreComputationCompleteTillDistance[i] = dist;
                        staticVarSet( InstrumentNameAndTFtext + "barScoreComputationCompleteTillDistance", barScoreComputationCompleteTillDistance, True );
                        }
                        
                    }//end of loop k

                }// end of loop dist
            }// end of loop i
        }// end if

			endTime = Now( 5 );
			runTime = round( DateTimeDiff( endTime, startTime ) ) ;

        if( !barScoreComputationIsAlreadyCompleteForThisTimeFrame )
            _TRACE( "...calculateBarScore run completed for Instrument '" + Name() + "' for interval " + thisTimeframeinMinutes + " minutes for SearchDistance of " + Min( maxSearchDistanceForBarScore, BarCount )  + " bars for barcount "
                    + ( BarCount - sourceBarStartIndexBasedOnTimeframe ) + " bars, in " + runTime + " seconds. Computation began from bar "+SourceBarCounterStartValueScalar+" . "
                    +writeif(barScoreComputationCompleteTillDistanceInitial>0, "barScore was already complete upto distance "+barScoreComputationCompleteTillDistanceInitial, ""));
    }// end if
}//end of function

function getBarScore( arrayFwdSearchDistance, barScoreType )
{

    timeframeinseconds = Interval();
    InstrumentNameAndTFtext = Name() + "_interval_" + timeframeinseconds + "_";
    retval = Null;

    for( dist = minSearchDistanceForBarScore; dist < ( maxSearchDistanceForBarScore ); dist++ )
    {

        mapKey = ( dist - minSearchDistanceForBarScore );
        retval = IIf( arrayFwdSearchDistance == dist,  iif( barScoreType == constScoreTypeHH, staticVarGet( InstrumentNameAndTFtext + "bsHH_" + mapKey ), staticVarGet( InstrumentNameAndTFtext + "bsLL_" + mapKey ) ) , retval );
    }

    return retval;
}

function displayBarScore()
{
bsHH = Nz( staticVarGet( InstrumentNameAndTFtext + "bsHH_" + mapKey ) );
bsLL = Nz( staticVarGet( InstrumentNameAndTFtext + "bsLL_" + mapKey ) );
//_Trace( "using matrix getBarScore(40)="+bs );
ATR10 = IIf( Cum( 1 ) > 10, ATR( 10 ), ATR( 1 ) );

for( i = 0; i < BarCount; i++ )
{
    PlotTextSetFont( "" + bsHH[i], "windings", 7, i , H[i] + Atr10[i] / 3, colorYellow );
    PlotTextSetFont( "" + bsLL[i], "windings", 7, i , L[i] - Atr10[i] / 3, colorYellow );
}
}


selectRunMode();
if( runMode == runModeProcessing )
    calculateBarScore();
    else
    _TRACE("in view mode");

displayBarScore();

Apply this on a chart of lets say 10 minutes. I have also provided 1 minute data for 100 odd stocks see below. Right click parameters select distance as 50 and mode as Processing. Hit Ok. This will start the processing. Once processing is complete it will say so in log window. Then go to parameters window again and switch to view only mode. The chart should look something like below.

The respective barscore is displayed on top and bottom of every bar.

Now switch to a different timeframe lets say 20 minutes. generate barscore and view using steps given above. And then switch back to 10 minutes. You will see that some stocks have lost their barscore. Why does this happen?

I am trying to troubleshoot the reason for missing values of static variables and seek your indulgence.
Thankyou.

Data

Strangely PersistVars.bin file size does not seem to exceed 5GB. I feel as new values enter old ones are being lost. Could this be antivirus doing its thing? Amibroker folder is added to exclusion list.

Static variables were never meant to store 5GB+ worth of data.

Static variables are NOT meant to replace database.

Static variables should not be abused by storing everything under the sun in them.

Maximum allowable file size of PersistVars.bin is 4GB

That is mainly dictated by the fact that certain older file systems like FAT32 that must be still supported have 4GB file size limit, but also by common sense as all static variables consume memory (RAM) constantly and if you go absurd you would start getting crashes / out of memory. RAM is much more needed for doing actual work / computations.

1 Like

Can you suggest me some way to store the values. I need to store and reuse the values because it takes enormously large time to calculate it. For example to calculate barscore for 1 minute data for 80 stocks for 1 month (20 days) it will take 25 hours. I need to calculate for every timeframe from 1 minute to 30 minutes (step of 1 minute). How can i do this?

https://www.amibroker.com/guide/afl/addtocomposite.html

2 Likes

Something is wrong with the code that you are using if it needs 25 hours.

I would seriously rethink/redesign the code that you are using. Use array processing, not loops. Normal execution time per-symbol is in sub-second range.

Anyway, you should be using database, not static variables.
And yes one of the ways is to use AddToComposite to create artificial symbols that store data.

1 Like

Actually you had advised me earlier to use loops. Distance travelled without intersection - #12 by Tomasz

My code uses 3 nested loops. I welcome any suggestion that can cut down on loops.

No, I did not advise you to use loops in AFL. You should re-read what I wrote about the code I gave you.

I wrote:

"You asked about possiblity to write in C++ and I provided you the code that would work with C++" Distance travelled without intersection - #14 by Tomasz

It would be useful if you read the responses AS THEY ARE, without manipulation.

1 Like

Thankyou Tomasz and awilson. Your response is very usefull to me. I shall start working on these suggestions and shall post back my findings here.
Thankyou very very much.

I have one question. In my case I suppose I would need one composite symbol for every Symbols_interval pair to store barscore. Right? So For example if i have 5 instruments (aaa, bbb, ccc, ddd, eee) and i wish to run my code for 3 timeframes (lets say 1min, 5min, 10min) Then I need to create below 5 X 3 = 15 composite instruments namely
~aaa1min
~aaa5min
~aaa10min
~bbb1min
~bbb5min
~bbb10min
~ccc1min
~ccc5min
~ccc10min
~ddd1min
~ddd5min
~ddd10min
~eee1min
~eee5min
~eee10min
I can store barScoreHH in filed "H" and barScoreLL in field "L".
Is my understanding correct?

You can use all fields Open, High, Low, Close, Volume, OpenInterest and Aux1 and Aux2.
So there are 8 arrays per symbol available.

1 Like

Sometimes it just amazes me how i overlook basic stuff. After switching to array what took 25 Hours is just taking 7 minutes. below is my new code

        for( distanceCounter = distCounterStartValue; distanceCounter <= Dist; distanceCounter++ )
            {
                intersectionReachedHH = 0;
                intersectionReachedLL = 0;
                sourceBarHigh = H;
                destBarHigh = Ref( H, distanceCounter );
                sourceBarLow = L;
                destBarLow = Ref( L, distanceCounter );
                aHH = ( destBarHigh - sourceBarHigh ) / distanceCounter;
                aLL = ( destBarLow - sourceBarLow ) / distanceCounter;
                distanceIdentifier=distanceCounter;//Max(0, distanceCounter - minSearchDistanceForBarScore);

                for( InterveaningBarCounter = 1; InterveaningBarCounter < distanceCounter; InterveaningBarCounter++ )
                {
                    lineHHAtInterveaningBar = aHH * InterveaningBarCounter  + sourceBarHigh;    //value of line_HH at bar (i+k)
                    lineLLAtInterveaningBar = aLL * InterveaningBarCounter  + sourceBarLow;    //value of line_LL at bar (i+k)
                    intersectionReachedHH = intersectionReachedHH || lineHHAtInterveaningBar <= Ref( H, InterveaningBarCounter );
                    intersectionReachedLL = intersectionReachedLL || lineLLAtInterveaningBar >= Ref( L, InterveaningBarCounter );

                    VarSet( "bsHH_" + distanceIdentifier, IIf( !distanceIsMoreThanBarCount && !intersectionReachedHH && lineHHAtInterveaningBar > Ref( H, InterveaningBarCounter ), 
                    InterveaningBarCounter, IIf(distanceIdentifier==0, 0, Nz( Varget( "bsHH_" + ( distanceIdentifier - 1 ) ) ) ) ) );
                    VarSet( "bsLL_" + distanceIdentifier, IIf( !distanceIsMoreThanBarCount && !intersectionReachedLL && lineLLAtInterveaningBar < Ref( L, InterveaningBarCounter ), 
                    InterveaningBarCounter, IIf(distanceIdentifier==0, 0, Nz( Varget( "bsLL_" + ( distanceIdentifier - 1 ) ) ) ) ) );


                }

                AddToComposite( VarGet( "bsHH_" + distanceIdentifier ), NameCompositeInstrumentForBarScore + "_Dist_" + distanceIdentifier, "1", flagForAddToComposite );
                AddToComposite( VarGet( "bsLL_" + distanceIdentifier ), NameCompositeInstrumentForBarScore + "_Dist_" + distanceIdentifier, "2", flagForAddToComposite );

				//_TRACE("bsHH_"+distanceCounter+"="+VarGet("bsHH_"+distanceCounter));
				//_TRACE("bsLL_"+distanceCounter+"="+VarGet("bsLL_"+distanceCounter));


            }

            if( InterveaningBarCounter == distanceCounter - 1 )
                AddToComposite( distanceCounter - 1, NameCompositeInstrumentForBarScore + "_BSCompleteTillSD", "V", flagForAddToComposite );

3 questions.

  1. The below code raises "warning 512 Calling Foreign() or SetForeign() too many times (in a loop or in repeated code) is very inefficient". My intention below is that after composites are populated I copy all of them into staticVariables (Non persistent) and thereon only refer to the staticVariables in my code and avoid calling Foreign().
for( searchDistanceCounter = minSearchDistanceForBarScore; searchDistanceCounter <= maxSearchDistanceForBarScore; searchDistanceCounter++ )
    {
		distanceIdentifier=searchDistanceCounter;//Max(0, searchDistanceCounter - minSearchDistanceForBarScore);
        //_TRACE("maxSearchDistanceForBarScore="+maxSearchDistanceForBarScore+", searchDistanceCounter="+searchDistanceCounter+", Foreign( NameCompositeInstrumentForBarScore + _Dist_ + searchDistanceCounter, 1 ) ="+Foreign( NameCompositeInstrumentForBarScore + "_Dist_" + searchDistanceCounter, "1" ) );
        StaticVarSet( Name()  + "_interval_" + timeframeBaseInSeconds + "_bsHH_" + distanceIdentifier, Foreign( NameCompositeInstrumentForBarScore + "_Dist_" + distanceIdentifier, "1" ), persistStaticVariable, cmAlways );
        StaticVarSet( Name() + "_interval_" + timeframeBaseInSeconds + "_bsLL_" + distanceIdentifier, Foreign( NameCompositeInstrumentForBarScore + "_Dist_" + distanceIdentifier, "2" ), persistStaticVariable, cmAlways );
    }

    StaticVarSet( Name() + "_interval_" + timeframeBaseInSeconds + "_BSCompleteTillSD", Foreign( NameCompositeInstrumentForBarScore + "_BSCompleteTillSD", "V" ), persistStaticVariable, cmAlways );
  1. I use below flag in addToComposite(). But I have noticed that on portfolio backtest the composites are not getting generated. I have to explicitly run a scan to populate the composites and then run the backtest. What can i do such that composites get generated on portfolio backtest.
        flagForAddToComposite = atcFlagDefaults + atcFlagCompositeGroup + atcFlagEnableInBacktest + atcFlagEnableInExplore + atcFlagEnableInPortfolio;

AddToComposite( VarGet( "bsHH_" + distanceIdentifier ), NameCompositeInstrumentForBarScore + "_Dist_" + distanceIdentifier, "1", flagForAddToComposite );
                AddToComposite( VarGet( "bsLL_" + distanceIdentifier ), NameCompositeInstrumentForBarScore + "_Dist_" + distanceIdentifier, "2", flagForAddToComposite );

  1. Is there a way to create the composites from chart indicator run? Like when we apply an afl on a chart at that time can we trigger a addToComposite()?

Using the right flag did the trick. question 2 is answered.

flagForAddToComposite = atcFlagDefaults  + atcFlagEnableInBacktest + atcFlagEnableInExplore + atcFlagEnableInPortfolio;
  1. I don't know how many times you call it. The answer to every question is "it depends".
    Don't assume - measure. Use GetPerformanceCounter and measure. Premature optimization is the root of all evil as Donald Knuth once said.

  2. and 3. is answered in The Great User manual: AFL Function Reference - ADDTOCOMPOSITE

1 Like

Thanks Tomasz. For ATC to work at indicator (chart) level we must use the flag atcFlagEnableInIndicator. Somehow I was not able to see it in the help article. Thanks again.

I will use GetPerformanceCounter and measure for 1. and shall post back the results here.

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