Automatic Bands

Quite often you see a code where buys occur when the price goes below a bottom Bollinger Band or shifted moving average band and the sell is when price hits the top band. In an uptrend, they bands will typically fall below the prices and in a downtrend the bands occur above the prices.

What I'd like to do is have the bands be able to "see" if they are above the price channel and to make automatic adjustments. What I'd like to do is count how many bars it has been since the high price has crossed above the top band and then use that number to keep pushing the top band down until the price hits it.

I have this code started here:

MiddleLine = MA(C,5);
Shift = ATR(5);

TopBand = MiddleLine + 0.5*Shift;
TopHit = High > TopBand;
SinceTopHit = BarsSince(TopHit);
TopBandModified = MiddleLine + 0.5*Shift - 0.1*SinceTopHit*Shift;
//TopBandModified goes a little lower each time the high doesn't cross the TopBand
//Is it possible to have the TopBandModified go lower each time the high doesn't cross the TopBandModified itself?

Plot( C, "Price", colorDefault, styleCandle );
Plot(TopBandModified,"TopBandModified", colorBlue, styleLine|styleThick);
Plot(MiddleLine, "MiddleLine", colorwhite, styleDashed); 
Plot(TopBand,"TopBand", colorBlue, styleDashed);
Plot(SinceTopHit,"SinceTopHit",colorYellow,styleLine|styleOwnScale);

The shortcoming in my code is that it has to use a separate "TopBand" to calculate the BarsSince the high crossed above. I'd like to use the BarsSince the high has crossed above the "TopBandModified" itself. Does it make sense what I'm asking? Is it possible to do it?

Perhaps this illustration will better explain what I'd like to do.

Untitled

@Marcel: I think this falls into the category of "self referencing" formulas, and therefore would probably require a loop to calculate TopBandModified in the way that you have suggested. See this post: Doubt when using self referencing

3 Likes

I made a code with a loop, with top and bottom bands that keep moving closer to the bars until they cross the high or low. I tested a few variations of it but I couldn't find any particular advantage over just trading a system that buys and sells on a normal pair of moving average channels.

SetOption( "AllowSameBarExit", False );
settradedelays( 0, 0, 0, 0 );//zero delay, trades on open or a limit order, but uses yesterday's data to prevent future data leak

AverageRange = ATR( 10 );
CenterLine = LinearReg( Close, 10 );

TopLine = CenterLine + 1 * AverageRange;
BottomLine = CenterLine - 1 * AverageRange;

DelayedTopLine = Ref( TopLine, -1 );//delays calculation of top and bottom line by one bar to prevent future data leak
DelayedBottomLine = Ref( BottomLine, -1 );

TopHit = 0;
SinceTopHit = 0;
ShiftedTopLine = DelayedTopLine;

BottomHit = 0;
SinceBottomHit = 0;
ShiftedBottomLine = DelayedBottomLine;

for( i = 1; i < BarCount; i++ )
{
    TopHit[i] = High[i - 1] > ShiftedTopLine[i - 1];

    if( TopHit[i] == 1 )
    {
        SinceTopHit[i] = 0;
    }
    else
    {
        SinceTopHit[i] = SinceTopHit[i - 1] + 1;
    }

    ShiftedTopLine[i] =  ShiftedTopLine[i] - 0.1 * SinceTopHit[i];

    BottomHit[i] = Low[i - 1] < ShiftedBottomLine[i - 1];

    if( BottomHit[i] == 1 )
    {
        SinceBottomHit[i] = 0;
    }
    else
    {
        SinceBottomHit[i] = SinceBottomHit[i - 1] + 1;
    }

    ShiftedBottomLine[i] =  ShiftedBottomLine[i] + 0.1 * SinceBottomHit[i];
}

Buy = Cross( ShiftedBottomLine, Low );
BuyPrice = Min( Open, ShiftedBottomLine );

Sell = Cross( High, ShiftedTopLine );
SellPrice = Max( Open, ShiftedTopLine );
Short = Cover = 0;

SetChartOptions( 1, chartShowArrows | chartShowDates );
_N( Title = StrFormat( "{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) \n{{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ) );
Plot( C, "Price", colorDefault, styleCandle );

Plot( TopLine, "TopLine", colorWhite, styleLine | styleDashed );
Plot( DelayedTopLine, "DelayedTopLine", colorYellow, styleLine | styleDashed );
Plot( ShiftedTopLine, "ShiftedTopLine", colorYellow, styleLine | stylethick );
PlotShapes( Ref( TopHit, 1 )*shapeUpTriangle, colorYellow, 0, ShiftedTopLine );
Plot( CenterLine, "CenterLine", colorwhite, styleLine | styleDashed );
Plot( BottomLine, "BottomLine", colorWhite, styleLine | styleDashed );
Plot( DelayedBottomLine, "DelayedBottomLine", colorBlue, styleLine | styleDashed );
Plot( ShiftedBottomLine, "ShiftedBottomLine", colorBlue, styleLine | stylethick );
PlotShapes( Ref( BottomHit, 1 )*shapeDownTriangle, colorBlue, 0, ShiftedBottomLine );