AFL to draw Trendline Between Previous day High and Previous day Low

Hi,
I am a geometry based day trader and would like to plot the Right Extended Trend line between Previous day’s High and Previous day’s Low.
Since being very beginner to AFL,I am struggling to make it possible using the syntax LINEARRAY and BARINDEX.

I tried in many ways with my little Knowledge but in vain.
I would be grateful if someone can help me to get it done.

Thanks and Regards,
Gloria Filamino

Assuming that you are using intraday chart, if you wish to do so for all days then the code would be:

prevdayH = TimeFrameGetPrice( "H", inDaily, -1 );
prevdayL = TimeFrameGetPrice( "L", inDaily, -1 );

Plot( prevDayH, "PrevH", colorRed );
Plot( prevDayL, "PrevL", colorGreen );

Plot( C, "Price", colorDefault, styleCandle );

If you want to do this just for very last day and extend the line past the last bar then:

prevdayH = TimeFrameGetPrice( "H", inDaily, -1 );
prevdayL = TimeFrameGetPrice( "L", inDaily, -1 );

prevdayH = LastValue( prevdayH );
prevdayL = LastValue( prevdayL );

DayChange = DateNum() != Ref( DateNum(), -1 );
lastDayBegin = LastValue( ValueWhen( DayChange, BarIndex() ) );

extension = 500; // how many bars to right extend

GfxSetCoordsMode( 1 );
GfxSelectPen( colorRed );
GfxMoveTo( lastDayBegin, prevDayH );
GfxLineTo( lastDayBegin + extension, prevDayH );
GfxMoveTo( lastDayBegin, prevDayL );
GfxLineTo( lastDayBegin + extension, prevDayL );

Plot( C, "Price", colorDefault, styleCandle );

As you can see the power of array processing makes doing things for all bars at once simpler.

6 Likes

Thanks for quick reply Mr.Tomasz.
What I wanted was trendline between previous day and previous day low.
But Provided afl plots horizontal lines for previous day high and low.
It would be helpful if I can get the code for plotting trendline between previous day high and previous day low.
Thanks and Regards,
Gloria Filamino

Hello and welcome to the forum.
Until Tomasz answer.
I was thinking to ask you, when you said between, do you mean the average between High Low?
If you say Yes!!. Then you can ADD these lines in Tomasz afl.

AveragePrevHL= (prevdayH + prevdayL)/2;   // average of previous day High Low
GfxMoveTo( lastDayBegin, AveragePrevHL );
GfxLineTo( lastDayBegin + extension, AveragePrevHL );
1 Like

No it wasn’t “quick reply”, it was elaborate reply. In case you did not notice someone spent time writing formula for you. You were quick to ask question that was not formulated carefully and clearly enough. If you for example provided picture of what you are after you would save lot of guessing.

If you want automatically drawn trendline that connects previous’ day high with previous day low with right extension the formula is as follows.

Please note that we will NOT write every formula you ask for because formula writing is NOT free. It costs $80-$120 per hour depending on complexity.

Plot( Close, "Price", colorDefault, styleCandle );

dn = DateNum();
lastDay = LastValue( dn );

newDay = dn != Ref( dn, -1 );

dhh = ValueWhen( dn < lastDay, HighestSince( newDay, High ) );
dh = ValueWhen( dn < lastDay, HighestSinceBars( newDay, High ) );
dll = ValueWhen( dn < lastDay, LowestSince( newDay, Low ) );
dl = ValueWhen( dn < lastDay, LowestSinceBars( newDay, Low ) );

dhh = LastValue( dhh );
dh = LastValue( dh );
dll = LastValue( dll );
dl = LastValue( dl );

bi = BarIndex();
off = LastValue( BarsSince( newDay ) );

xlow = BarCount - off - dl;
xhigh = BarCount - off - dh;

Plot( dhh , "dhh", colorGreen );
Plot( dll , "dll", colorRed);
//Plot( bi == xhigh, "dh", colorGreen, styleOwnScale );
//Plot( bi == xlow, "dl", colorRed, styleOwnScale);

GfxSetCoordsMode( 1 );
GfxSelectPen( colorYellow, 2 );

// normal trendline
GfxMoveTo( xlow, dll );
GfxLineTo( xhigh, dhh );

// to draw extended line you need to calculate slope
slope = ( dhh - dll ) / (xhigh - xlow + 1e-9 );
// and draw extension
GfxLineTo( xhigh + off, dhh +  off * slope );
9 Likes

Sorry for late reply.
Thanks a lot for helping me Mr.Tomasz.
You have provided what exactly I wanted.
Thanks again

Thanks and Regards.
Gloria Filamino.

i remembered this question and wanted to check if there would be some significance lining up yesterdays high and low. I do not see it.

below my code that lines up the high and low of the day and extends it into the next day. Few small errors still in there but I do not see the significance in lining them up. Code below

// code assumes your working with intraday data (e.g. 5min data)
// 10/2017, emp

newDay = DateNum() != Ref( DateNum(), -1 );
bi = BarIndex();
fvb = FirstVisibleValue( bi );
lvb = LastVisibleValue( bi );

highOfDay = TimeFrameGetPrice( "H", inDaily );
lowOfDay = TimeFrameGetPrice( "L", inDaily );

lbx = ValueWhen( newDay, bi );
lbx0 = ValueWhen( newDay, bi, 0 );
ph1 = ValueWhen( highOfDay == H, H );
px1 = ValueWhen( highOfDay == H, bi );
tl1 = ValueWhen( lowOfDay == L, L );
tx1 = ValueWhen( lowOfDay == L, bi );

SetChartBkColor( ColorRGB( 0, 0, 0 ) );
Plot( Close, "Price", colorDefault, styleCandle, Null, Null, 0, 0, 1 );
Plot( newday, "", colorDarkBlue, styleHistogram | styleOwnScale | styleNoLabel | styleNoRescale, 0, 1, 0, 0, 5 );
Plot( highOfDay, "", colorGreen, styleLine, Null, Null, 0, 1, 1 );
Plot( lowOfDay, "", colorRed, styleLine, Null, Null, 0, 1, 1 );

GfxSetZOrder( -1 );
GfxSetCoordsMode( 1 );

cnt = 0; // count number of visible days

for( i = lvb; i > fvb; i-- )
{
    idx = lbx[ i ];

    if( IsEmpty( idx ) ) break;

    idx = lbx[ i ];

    hv = ph1[ idx ];
    hx = px1[ idx ];
    lv = tl1[ idx ];
    lx = tx1[ idx ];
    slope = ( hv - lv ) / ( hx - lx );

    if( hx < lx )
        line = LineArray( hx, hv, lx, lv );
    else
        line = LineArray( lx, lv, hx, hv );

    Plot( IIf( line, line, Null ), "", colorYellow, styleLine | styleNoLabel | styleNoRescale, Null, Null, 0, 0, 1 );

    x1 = Max( hx, lx );

    if( IsEmpty( x1 ) ) break;
    else
    {
        x2 = idx;
        dx = x2 - x1;
        y1 = line[ x1 ];
        y2 = y1 + dx * slope;

		// extension inside same day
        GfxSelectPen( colorYellow, 1, 1 );
        GfxMoveTo( x1, y1 );
        GfxLineTo( x2, y2 );

        // extension into next day
        x1 = idx;
        if( IsEmpty( lbx0[ idx ] ) OR lbx0[ idx ] <= idx )
        {
			x2 = BarCount - 1;
        }
        else
        {
			x2 = lbx0[ idx ];
        }
        dx = x2 - x1;

        y1 = y2;

        y2 = y1 + dx * slope;
        GfxSelectPen( colorViolet, 1, 1 );
        GfxMoveTo( x1, y1 );
        GfxLineTo( x2, y2 );
    }

    i = lbx[ idx ];
    cnt++;
}

"cnt: " + cnt;

should look like this

es

3 Likes

little update, it is about getting it technically correct more than anything else. Seems to be technically correct now

// in reply to: http://forum.amibroker.com/t/afl-to-draw-trendline-between-previous-day-high-and-previous-day-low/2445
// code assumes your working with intraday data (e.g. 5min data), 10/2017, E.M.Pottasch

lineWidth = Param( "Linewidth", 1, 1, 10, 1 );
zorder = Param( "Zorder", 1, -2, 2, 1 );

dn = DateNum();
newDay = dn != Ref( dn, -1 );
bi = BarIndex();
fvb = FirstVisibleValue( bi );
lvb = LastVisibleValue( bi );

highOfDay = TimeFrameGetPrice( "H", inDaily );
lowOfDay = TimeFrameGetPrice( "L", inDaily );

lbx1 = ValueWhen( newDay, bi );
lbx0 = ValueWhen( newDay, bi, 0 );
ph1 = ValueWhen( highOfDay == H, H );
px1 = ValueWhen( highOfDay == H, bi );
pdd1 = ValueWhen( highOfDay == H, dn );
tl1 = ValueWhen( lowOfDay == L, L );
tx1 = ValueWhen( lowOfDay == L, bi );
tdd1 = ValueWhen( lowOfDay == L, dn );

SetChartBkColor( ColorRGB( 0, 0, 0 ) );
Plot( Close, "Price", colorDefault, styleCandle, Null, Null, 0, 0, 1 );
Plot( newday, "", colorDarkBlue, styleHistogram | styleOwnScale | styleNoLabel | styleNoRescale, 0, 1, 0, 0, 5 );
Plot( highOfDay, "", colorGreen, styleLine, Null, Null, 0, 1, 1 );
Plot( lowOfDay, "", colorRed, styleLine, Null, Null, 0, 1, 1 );

GfxSetZOrder( zorder );
GfxSetCoordsMode( 1 );

cnt = 0; // count number of visible days

for( i = lvb; i > fvb; i-- )
{
    idx = lbx1[ i ];

    if( IsEmpty( idx ) ) break;

    if( pdd1[ idx ] > tdd1[ idx ] )
    {
        hv = ph1[ idx - 1 ];
        hx = px1[ idx - 1 ];
        lv = tl1[ idx ];
        lx = tx1[ idx ];
    }
    else
        if( pdd1[ idx ] < tdd1[ idx ] )
        {
            hv = ph1[ idx ];
            hx = px1[ idx ];
            lv = tl1[ idx - 1 ];
            lx = tx1[ idx - 1 ];
        }
        else
            if( pdd1[ idx ] == tdd1[ idx ] )
            {
                hv = ph1[ idx ];
                hx = px1[ idx ];
                lv = tl1[ idx ];
                lx = tx1[ idx ];
            }

    slope = ( hv - lv ) / ( hx - lx );

    if( hx < lx )
        line = LineArray( hx, hv, lx, lv );
    else
        line = LineArray( lx, lv, hx, hv );

    Plot( IIf( line, line, Null ), "", colorYellow, styleLine | styleNoLabel | styleNoRescale, Null, Null, 0, zorder, lineWidth );

    x1 = Max( hx, lx );

    if( IsEmpty( x1 ) ) break;
    else
    {
        x2 = idx;
        dx = x2 - x1;
        y1 = line[ x1 ];
        y2 = y1 + dx * slope;

        // extension inside same day (dashed yellow)
        GfxSelectPen( colorYellow, lineWidth, 1 );
        GfxMoveTo( x1, y1 );
        GfxLineTo( x2, y2 );

        // extension into next day (dashed violet)
        x1 = idx;

        if( IsEmpty( lbx0[ idx ] ) OR lbx0[ idx ] <= idx )
        {
            x2 = BarCount - 1;
        }
        else
        {
            x2 = lbx0[ idx ];
        }

        dx = x2 - x1;

        y1 = y2;

        y2 = y1 + dx * slope;
        GfxSelectPen( colorViolet, lineWidth, 1 );
        GfxMoveTo( x1, y1 );
        GfxLineTo( x2, y2 );
    }

    i = lbx1[ idx ];
    cnt++;
}

"cnt: " + cnt;
5 Likes

expanding a bit on this same topic I post a cool little tool that extends a LSF (Least Squares Fit) calculated over certain time segment. Default is 1 segment, e.g. 1 day but the number can be set in Param window. It is actually intended for intraday price prediction assuming that yesterdays intraday trend continues today. The blue lines border the range where the price is expected to go, based on yesterdays trend. The blue lines are the lines you need to use for trading system development and they are stored in the arrays FitFinalExt, TopFinalExt and BotFinalExt. I did not add backtesting functionality in this version but was not able myself yet to make anything anywhere close to returning something decent. If you figure out some winning strategy send me an email, I particularly like those +500% per year systems :beer:

/*
LSF Gadget, E.M.Pottasch, 10/2017

Calculates Least Squares Fit (LSF) over chosen time Segment / Interval (Day / Week / Month / Year)
The LSF is displayed in light Grey. The extension of the LSF (light blue) is displayed in the next 
time segment and is supposed to function as the non-repainting indicator or price predictor.

The idea behind it is that yesterday's trend might continue today. Or if you set the "shft"
parameter at 1 then the hope is that the trend of the past 2 days (or 2 time segments) continues
today (or in the current time segment).

The extension of the fit is the price "predictor" and is stored in the arrays FitFinalExt, TopFinalExt, 
BotFinalExt and can therefor be used for trading system developemnt
*/

sep = ParamList( "Separator Interval", "Day|Week|Month|Year", 0 );
order = Param( "Order", 1, 1, 8, 1 ); // order of LSF
clevel = Param( "Confidence Level", 2, 1, 3, 0.1 ); // standard deviation or width of channel
shft = Param( "Number of Time Segments for Trend calculation", 0, 0, 10, 1 ); // adds Time Segments for LSF calculation
maxpat = Param( "Maximum Number of Channels (Interval Segments)", 10, 0, 100, 1 ); // only has display purpose, by default max 10 patterns 
moveback = Param( "Move Channel Pattern Back (Interval Segment)", 0, 0, 10, 1 ); // only has display purpose, move displayed patterns back

dif = 0;
Buy = Sell = Short = Cover = BuyPrice = SellPrice = ShortPrice = CoverPrice = 0;
Fit = Top = Bot = FitExt = TopExt = BotExt = Null;
FitFinalExt = TopFinalExt = BotFinalExt = Null;
FitFinal = TopFinal = BotFinal = Null;

switch( sep )
{
case "Day":
    dn = Day();
    dn1 = inDaily;
    break;

case "Week":
    dw = DayOfWeek();
    newWeek = dw < Ref( dw, -1 );;
    newYear = Year() != Ref( Year(), -1 );
    dn = weekNumber = Sum( newWeek, BarsSince( newYear ) + 1 );
    dn1 = inWeekly;
    break;

case "Month":
    dn = Month();
    dn1 = inMonthly;
    break;

case "Year":
    dn = Year();
    dn1 = inYearly;
    break;
}

separator = dn != Ref( dn, -1 );

bi = BarIndex();
fvb = FirstVisibleValue( bi );
lvb = LastVisibleValue( bi );

for( i = 0; i <= 2 + shft; i++ )
{
    VarSet( "lbx" + i, ValueWhen( separator, bi, i ) );
}

prc = ( H + L ) / 2;
sd = 0;
Ext = lbx0 - lbx1;
Ext = IIf( Ext == 0 AND lbx1 == lbx0 AND lbx1 > 0 AND lbx0 > 0, BarCount - 1 - lbx1, Ext );

function get_y( eb, bars )
{
    fb = eb - bars;
    yy = Matrix( bars + 1, 1, 0 );

    yy = MxSetBlock( yy, 0, bars, 0, 0, Ref( prc, fb ) );

    return yy;
}

function get_x( eb, bars )
{
    xx = Matrix( bars + 1, order + 1, 1 );
    x = BarIndex() - bars / 2;

    for( j = 1; j <= order; j++ )
    {
        xx = MxSetBlock( xx, 0, bars, j, j, x ^ j );
    }

    return xx;
}

function calculateCoefficients( eb, bars )
{
    xx = get_x( eb, bars );
    yy = get_y( eb, bars );
    xxt = MxTranspose( xx );
    aa = MxSolve( xxt @ xx, xxt ) @ yy;

    return aa;
}

function calculateFit( eb, bars, Extend )
{
    Fit = FitExt = Null;

    lb = eb;
    fb = eb - bars;

    x = BarIndex() - bars / 2;

    // calculate coefficients
    aa = calculateCoefficients( eb, bars );

    // store the fit in Fit
    for( i = fb; i <= lb; i++ )
    {
        Fit[i] = aa[0][0];

        for( j = 1; j <= order; j++ )
        {
            Fit[i] += aa[j][0] * x[ i - fb ] ^ j;
        }
    }

    // calculate standard deviation
    sdp = 0;

    for( i = fb; i <= lb; i++ )
    {
        sdp = sdp + ( prc[i] - Fit[i] ) ^ 2;
    }

    sd = sqrt( sdp / ( bars - 2 ) ); // devide by ( bars - 2 ) corresponding to StdErr function

    Top = Fit + sd * clevel;
    Bot = Fit - sd * clevel;

    // Extended fit
    for( i = lb + 1; i <= Min( BarCount - 1, lb + Extend ); i++ )
    {
        FitExt[i] = aa[0][0];

        for( j = 1; j <= order; j++ )
        {
            FitExt[i] += aa[j][0] * x[ i - fb ] ^ j;
        }
    }

    TopExt = FitExt + sd * clevel;
    BotExt = FitExt - sd * clevel;
}

function doCalculation( fb, lb )
{

    cnt = 0; // count number of visible periods
    Extend = Ext[lb];

    for( i = lb; i > fb; i-- )
    {
        if( !separator[i] )
        {
            hh = VarGet( "lbx" + ( 1 + shft ) );
            eb = i;
            sb = hh[i];

            jmp = lbx1[i];

            bars = eb - sb + 0;

            if( IsEmpty( bars ) ) break;

            calculateFit( eb, bars, Extend );

            FitFinalExt = IIf( !IsEmpty( FitExt ), FitExt, FitFinalExt );
            TopFinalExt = IIf( !IsEmpty( TopExt ), TopExt, TopFinalExt );
            BotFinalExt = IIf( !IsEmpty( BotExt ), BotExt, BotFinalExt );

            FitFinal = IIf( !IsEmpty( Fit ), Fit, FitFinal );
            TopFinal = IIf( !IsEmpty( Top ), Top, TopFinal );
            BotFinal = IIf( !IsEmpty( Bot ), Bot, BotFinal );

            if( Status( "Action" ) == actionIndicator ) // control the display of the channels in here
            {
                if( cnt >= moveback AND( cnt <= maxpat + moveback ) )
                {
                    line = Null;
                    line = IIf( !IsEmpty( Top ), Top, line );
                    Plot( line, "", ColorRGB( 90, 90, 90 ), styleLine | styleNoLabel | styleNoRescale, Null, Null, 0, 0, 1 );
                    line = IIf( !IsEmpty( Bot ), Bot, line );
                    Plot( line, "", ColorRGB( 90, 90, 90 ), styleLine | styleNoLabel | styleNoRescale, Null, Null, 0, 0, 1 );
                    line = IIf( !IsEmpty( Fit ), Fit, line );
                    Plot( line, "", ColorRGB( 50, 50, 50 ), styleDashed | styleNoLabel | styleNoRescale, Null, Null, 0, 0, 1 );
                }

                if( cnt > moveback  AND( cnt <= maxpat + moveback ) )
                {
                    line = Null;
                    line = IIf( !IsEmpty( TopExt ) AND TopExt, TopExt, line );
                    Plot( line, "", ColorRGB( 0, 250, 250 ), styleLine | styleNoLabel | styleNoRescale, Null, Null, 0, 0, 2 );
                    line = IIf( !IsEmpty( BotExt ) AND BotExt, BotExt, line );
                    Plot( line, "", ColorRGB( 0, 250, 250 ), styleLine | styleNoLabel | styleNoRescale, Null, Null, 0, 0, 2 );
                }
            }
        }
        else
        {
            jmp = i;
        }

        i = jmp;
        Extend = Ext[i];
        cnt++;
    }
}

if( Status( "Action" ) == actionIndicator )
{
    dif = int( lvb - fvb );
    SetBarsRequired( dif * 2, dif * 2 );

    SetChartBkColor( colorBlack );
    SetChartOptions( 1, chartShowDates, chartGridMiddle, 0, 0, 0 );
    SetBarFillColor( IIf( C > O, ColorRGB( 0, 75, 0 ), IIf( C <= O, ColorRGB( 75, 0, 0 ), colorLightGrey ) ) );
    Plot( C, "", IIf( C > O, ColorRGB( 0, 255, 0 ), IIf( C <= O, ColorRGB( 255, 0, 0 ), colorLightGrey ) ), 64, Null, Null, 0, 0, 1 );
    Plot( separator, "", colorDarkBlue, styleHistogram | styleOwnScale | styleNoLabel | styleNoRescale, 0, 1, 0, -2, 5 );

    doCalculation( fvb, lvb );

    PlotShapes( IIf( Buy, shapeUpArrow, shapeNone ), colorDarkGreen, 0, L, -15 );
    PlotShapes( IIf( Buy, shapeSmallCircle, shapeNone ), colorWhite, 0, BuyPrice, 0 );
    PlotShapes( IIf( Sell, shapeDownArrow, shapeNone ), colorRed, 0, H, -15 );
    PlotShapes( IIf( Sell, shapeSmallCircle, shapeNone ), colorwhite, 0, SellPrice, 0 );
    PlotShapes( IIf( Short, shapeSmallDownTriangle, shapeNone ), colorRed, 0, H, IIf( Short AND Sell, -30, -15 ) );
    PlotShapes( IIf( Short, shapeSmallCircle, shapeNone ), colorWhite, 0, ShortPrice, 0 );
    PlotShapes( IIf( Cover, shapeSmallUpTriangle, shapeNone ), colorDarkGreen, 0, L, IIf( Cover AND Buy, -30, -15 ) );
    PlotShapes( IIf( Cover, shapeSmallCircle, shapeNone ), colorwhite, 0, CoverPrice, 0 );
}
11 Likes

Thanks a Lot empottasch,
Though the code is beyond my knowledge of understanding,I still need to thank you for the supreme effort you have put for my request,
Heartfelt Thanks.

Gloria Filamino

2 Likes