How to get the most traded area value of previous day intraday data

good one , but still struggling to get those values in exploration window

i do not really see why you want to use the exploration but when trying to make it you had me puzzled there :thinking: for a moment. I used static variables to solve it, however not sure why I need to use them.

I add the adjusted code because I changed the chart setting a bit, added few params.

1 remark: I hard coded the TickSize but you can also comment that out when you have set the TickSize in the Information window.

if anyone reading this (will also ask elsewhere). My capital letter A is not working in the Amibroker editor, it is working fine elsewhere. Anyone have this problem? Although I do not have the problem on my laptop so must be on my side but only seems to show up in the Amibroker editor.

// in reply to: http://forum.amibroker.com/t/how-to-get-the-most-traded-area-value-of-previous-day-intraday-data/2472
// code assumes your working with intraday data (e.g. 5min data)
// Value area calculation: http://onlinelibrary.wiley.com/doi/10.1002/9781118659724.app1/pdf
// !!!! TickSize is hardcoded in code. You need to adjust for, according to contract specifics.
// E.M.Pottasch (10/2017)

TickSize = 0.25; // <<<<==== adjust yourself

volumeValuearea = Param( "Volume Value area (%)", 0.7, 0, 1, 0.01 );
showVolume = ParamToggle( "Show Volume", "No|Yes", 0 );
showHL = ParamToggle( "Show High/Low boundaries", "No|Yes", 0 );
showVal1 = ParamToggle( "Show Value area inside same day", "No|Yes", 0 );
showVal0 = ParamToggle( "Show Value area projected into the next day", "No|Yes", 1 );

Title = Name() + "   Volume area (%): " + volumeValuearea * 100;

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

valueHigh1 = valueLow1 = Null;
valueHigh0 = valueLow0 = Null;
highOfDay = TimeFrameGetPrice( "H", inDaily );
lowOfDay = TimeFrameGetPrice( "L", inDaily );

lbx2 = ValueWhen( newDay, bi, 2 );
lbx1 = ValueWhen( newDay, bi, 1 );
lbx0 = ValueWhen( newDay, bi, 0 );

SetChartOptions( 0, chartShowDates );
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, -2, 5 );

if( showHL )
{
    Plot( highOfDay, "", colorGreen, styleDots | styleNoLine | styleNoRescale, Null, Null, 0, 0, 1 );
    Plot( lowOfDay, "", colorRed, styleDots | styleNoLine | styleNoRescale, Null, Null, 0, 0, 1 );
}

GfxSetZOrder( -4 );
GfxSetCoordsMode( 1 );

cnt = 0; // count number of visible days

for( i = lvb; i > fvb; i-- )
{
    idx0 = lbx0[ i ];
    idx1 = lbx1[ i ];
    idx2 = lbx2[ i ];

    if( IsEmpty( idx1 ) ) break;

    bins = int( ( highOfDay[ idx1 - 1 ] - lowOfDay[ idx1 - 1 ] ) / TickSize );
    mx = PriceVolDistribution( H, L, V, bins, False, idx2, idx1 );
    bins = MxGetSize( mx, 0 );
    //_trace( "bins: " + bins );

    dx = idx1 - idx2;

    mxVolBinIdx = 0;
    mxVol = 0;
    totVol = 0;

    for( j = 0; j < bins; j++ )
    {
        price = mx[ j ][ 0 ]; // price level
        relvolume = mx[ j ][ 1 ]; // relative volume 0..1
        relbar = relvolume * dx;

        if( showVolume )
        {
            GfxSelectPen( ColorRGB( 80, 0, 0 ), 1, 0 );
            GfxMoveTo( idx2, price );
            GfxLineTo( idx2 + relbar, price );
        }

        if( relvolume > mxVol )
        {
            mxVol = relvolume;
            mxVolBinIdx = j;
        }

        totVol = totVol + relvolume;
    }

    // calculate Volume Value area
    mxih = mxil = mxVolBinIdx;
    tvol = mx[ mxVolBinIdx ][ 1 ];

    for( j = 0; j < bins; j++ )
    {
        if( mxih + 2 < bins AND mxil - 2 >= 0 )
        {
            relvolumeh = mx[ mxih + 1 ][ 1 ] + mx[ mxih + 2 ][ 1 ];
            relvolumel = mx[ mxil - 1 ][ 1 ] + mx[ mxil - 2 ][ 1 ];

            if( relvolumeh > relvolumel )
            {
                mxih = mxih + 2;
                tvol = tvol + relvolumeh;
            }
            else
                if( relvolumeh < relvolumel )
                {
                    mxil = mxil - 2;
                    tvol = tvol + relvolumel;
                }
                else
                    if( relvolumeh == relvolumel )
                    {
                        mxih = mxih + 2;
                        mxil = mxil - 2;
                        tvol = tvol + relvolumeh + relvolumel;
                    }
        }
        else
            if( mxih + 2 >= bins AND mxil - 2 >= 0 )
            {
                relvolumel = mx[ mxil - 1 ][ 1 ] + mx[ mxil - 2 ][ 1 ];
                mxil = mxil - 2;
                tvol = tvol + relvolumel;
            }
            else
                if( mxih + 2 < bins AND mxil - 2 < 0 )
                {
                    relvolumeh = mx[ mxih + 1 ][ 1 ] + mx[ mxih + 2 ][ 1 ];
                    mxih = mxih + 2;
                    tvol = tvol + relvolumeh;
                }

        if( ( tvol / totVol ) > volumeValuearea ) break;
    }

    priceh = mx[ mxih ][ 0 ];
    pricel = mx[ mxil ][ 0 ];
    x1 = idx2;
    x2 = idx1;
    line = LineArray( x1, priceh, x2, priceh );
    valueHigh1 = IIf( line, line, valueHigh1 );
    line = LineArray( x1, pricel, x2, pricel );
    valueLow1 = IIf( line, line, valueLow1 );

    // draw into next day
    if( cnt > 0 )
    {
        x1 = idx1;
        x2 = idx0;
        line = LineArray( x1, priceh, x2, priceh );
        valueHigh0 = IIf( line, line, valueHigh0 );
        line = LineArray( x1, pricel, x2, pricel );
        valueLow0 = IIf( line, line, valueLow0 );

    }
    else
        if( cnt == 0 )
        {
            x1 = idx2;
            x2 = BarCount - 1;
            line = LineArray( x1, priceh, x2, priceh );
            valueHigh0 = IIf( line, line, valueHigh0 );
            line = LineArray( x1, pricel, x2, pricel );
            valueLow0 = IIf( line, line, valueLow0 );
        }

    i = lbx1[ idx1 ];
    cnt++;

    StaticVarSet( "vh", valueHigh0 );
    StaticVarSet( "vl", valueLow0 );
}

if( showVal1 )
{
    Plot( valueHigh1, "", ColorRGB( 0, 250, 250 ), styleDots | styleNoLine | styleNoRescale, Null, Null, 0, -3, 1 );
    Plot( valueLow1, "", ColorRGB( 0, 250, 250 ), styleDots | styleNoLine | styleNoRescale, Null, Null, 0, -3, 1 );
}

if( showVal0 )
{
    Plot( valueHigh0, "", ColorRGB( 250, 250, 0 ), styleDots | styleNoLine | styleNoRescale, Null, Null, 0, -3, 1 );
    Plot( valueLow0, "", ColorRGB( 250, 250, 0 ), styleDots | styleNoLine | styleNoRescale, Null, Null, 0, -3, 1 );
    PlotOHLC( valueLow0, valueLow0, valueHigh0, valueHigh0, "", ColorRGB( 15, 15, 0 ), styleCloud | styleNoRescale, Null, Null, 0, -5, 1 );
}

Filter = Nz( StaticVarGet( "vh" ) ) OR Nz( StaticVarGet( "vl" ) );
AddColumn( Nz( StaticVarGet( "vh" ) ), "Upper Boundary Volume Value area", 1.2, colorWhite, colorRed, -1 );
AddColumn( Nz( StaticVarGet( "vl" ) ), "Lower Boundary Volume Value area", 1.2, colorWhite, colorGreen, -1 );
3 Likes

Awsome work emPottasch, we get the 70% area of previous day in current day, how to get the the value of day before yesterday in current day land in exploration
thanks:kissing_heart:

I think it would be best to make 2 separate arrays for that, unless of course in the next mail you send you want the day before that in the current day :smiley:

basically you define 2 arrays to hold this data and then in the section below “// draw into next day” you fill them up.

so you have to indicate the start and end index.

try yourself first

1 Like

will try my best thanks a ton empottasch

The reason is simple:

FirstVisibleValue() and LastVisibleValue() are chart functions not analysis functions (just like their name say “…Visible…”). In analysis both would return zero.

// Trace will return two times zero output for each value if applying in ANALYSIS.
// Reason: They are CHART functions. There is no visible area in Analysis.
// For analysis alternatively to static vars you may use Status() function codes.
bi = BarIndex();
_TRACEF( "fvb: %g, lvb: %g", FirstVisibleValue(bi), LastVisibleValue(bi));
2 Likes

thanks fx, didn’t know that, haven’t use the exploration myself much. Will adapt the code for that

added few things

  • the “point of control”
  • also when the volume area is set to 100% the blue lines should overlap with the day High/Low. It didnt do this always because the value area is calculated in steps of 2. Now I check if singles are left.
  • then added function so that exploration and indicator mode can be fed with different numbers. It works but exploration mode is slow maybe partially because in the function itself I also plot stuff. So this should be programmed differently in the next version :smiley: but indicator mode works fine
// in reply to: http://forum.amibroker.com/t/how-to-get-the-most-traded-area-value-of-previous-day-intraday-data/2472
// code assumes your working with intraday data (e.g. 5min data)
// Value area calculation: http://onlinelibrary.wiley.com/doi/10.1002/9781118659724.app1/pdf
// !!!! TickSize is hardcoded in code. You need to adjust for, according to contract specifics.
// E.M.Pottasch (10/2017)

TickSize = 0.25; // <<<<==== adjust yourself

volumeValuearea = Param( "Volume Value area (%)", 0.7, 0, 1, 0.01 );
showVolume = ParamToggle( "Show Volume", "No|Yes", 0 );
showHL = ParamToggle( "Show High/Low boundaries", "No|Yes", 0 );
showVal1 = ParamToggle( "Show Value area inside same day", "No|Yes", 0 );
showVal0 = ParamToggle( "Show Value area projected into the next day", "No|Yes", 1 );
showPOC = ParamToggle( "Show Point Of Control (POC)", "No|Yes", 1 );

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

valueHigh1 = valueLow1 = Null;
valueHigh0 = valueLow0 = Null;
pointOfControl = Null;
highOfDay = TimeFrameGetPrice( "H", inDaily );
lowOfDay = TimeFrameGetPrice( "L", inDaily );

lbx2 = ValueWhen( newDay, bi, 2 );
lbx1 = ValueWhen( newDay, bi, 1 );
lbx0 = ValueWhen( newDay, bi, 0 );

function calculateVolumeValueArea( fb, lb )
{
    GfxSetZOrder( -4 );
    GfxSetCoordsMode( 1 );

    cnt = 0; // count number of visible days

    for( i = lb; i > fb; i-- )
    {
        idx0 = lbx0[ i ];
        idx1 = lbx1[ i ];
        idx2 = lbx2[ i ];

        if( IsEmpty( idx1 ) ) break;

        bins = int( ( highOfDay[ idx1 - 1 ] - lowOfDay[ idx1 - 1 ] ) / TickSize );
        mx = PriceVolDistribution( H, L, V, bins, False, idx2, idx1 );
        bins = MxGetSize( mx, 0 );
        //_trace( "bins: " + bins );

        dx = idx1 - idx2;

        mxVolBinIdx = 0;
        mxVol = 0;
        totVol = 0;

        for( j = 0; j < bins; j++ )
        {
            price = mx[ j ][ 0 ]; // price level
            relvolume = mx[ j ][ 1 ]; // relative volume 0..1
            relbar = relvolume * dx;

            if( showVolume )
            {
                GfxSelectPen( ColorRGB( 80, 0, 0 ), 1, 0 );
                GfxMoveTo( idx2, price );
                GfxLineTo( idx2 + relbar, price );
            }

            if( relvolume > mxVol )
            {
                mxVol = relvolume;
                mxVolBinIdx = j;
            }

            totVol = totVol + relvolume;
        }

        // calculate Volume Value area
        mxih = mxil = mxVolBinIdx;
        tvol = mx[ mxVolBinIdx ][ 1 ];
        pricePOC = mx[ mxVolBinIdx ][ 0 ];

        for( j = 0; j < bins; j++ )
        {
            if( mxih + 2 < bins AND mxil - 2 >= 0 )
            {
                relvolumeh = mx[ mxih + 1 ][ 1 ] + mx[ mxih + 2 ][ 1 ];
                relvolumel = mx[ mxil - 1 ][ 1 ] + mx[ mxil - 2 ][ 1 ];

                if( relvolumeh > relvolumel )
                {
                    mxih = mxih + 2;
                    tvol = tvol + relvolumeh;
                }
                else
                    if( relvolumeh < relvolumel )
                    {
                        mxil = mxil - 2;
                        tvol = tvol + relvolumel;
                    }
                    else
                        if( relvolumeh == relvolumel )
                        {
                            mxih = mxih + 2;
                            mxil = mxil - 2;
                            tvol = tvol + relvolumeh + relvolumel;
                        }
            }
            else
                if( mxih + 2 >= bins AND mxil - 2 >= 0 )
                {
                    relvolumel = mx[ mxil - 1 ][ 1 ] + mx[ mxil - 2 ][ 1 ];
                    mxil = mxil - 2;
                    tvol = tvol + relvolumel;
                }
                else
                    if( mxih + 2 < bins AND mxil - 2 < 0 )
                    {
                        relvolumeh = mx[ mxih + 1 ][ 1 ] + mx[ mxih + 2 ][ 1 ];
                        mxih = mxih + 2;
                        tvol = tvol + relvolumeh;
                    }

            // handle uneven bars left
            if( mxih + 2 >= bins AND mxil - 2 < 0 )
            {
                if( mxih + 1 < bins )
                {
                    relvolumeh = mx[ mxih + 1 ][ 1 ];
                    mxih = mxih + 1;
                    tvol = tvol + relvolumeh;
                }

                if( mxil - 1 >= 0 )
                {
                    relvolumel = mx[ mxil - 1 ][ 1 ];
                    mxil = mxil - 1;
                    tvol = tvol + relvolumel;
                }
            }

            if( ( tvol / totVol ) > volumeValuearea ) break;
        }

        priceh = mx[ mxih ][ 0 ];
        pricel = mx[ mxil ][ 0 ];
        x1 = idx2;
        x2 = idx1;
        line = LineArray( x1, priceh, x2, priceh );
        valueHigh1 = IIf( line, line, valueHigh1 );
        line = LineArray( x1, pricel, x2, pricel );
        valueLow1 = IIf( line, line, valueLow1 );

        // draw into next day
        if( cnt > 0 )
        {
            x1 = idx1;
            x2 = idx0;
            line = LineArray( x1, priceh, x2, priceh );
            valueHigh0 = IIf( line, line, valueHigh0 );
            line = LineArray( x1, pricel, x2, pricel );
            valueLow0 = IIf( line, line, valueLow0 );

            line = LineArray( x1, pricePOC, x2, pricePOC );
            pointOfControl = IIf( line, line, pointOfControl );
        }
        else
            if( cnt == 0 )
            {
                x1 = idx2;
                x2 = BarCount - 1;
                line = LineArray( x1, priceh, x2, priceh );
                valueHigh0 = IIf( line, line, valueHigh0 );
                line = LineArray( x1, pricel, x2, pricel );
                valueLow0 = IIf( line, line, valueLow0 );

                line = LineArray( x1, pricePOC, x2, pricePOC );
                pointOfControl = IIf( line, line, pointOfControl );
            }

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

if( Status( "Action" ) == actionIndicator )
{
    Title = Name() + "   Volume area (%): " + volumeValuearea * 100;

    SetChartOptions( 0, chartShowDates );
    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, -2, 5 );

    if( showHL )
    {
        Plot( highOfDay, "", colorGreen, styleDots | styleNoLine | styleNoRescale, Null, Null, 0, 0, 1 );
        Plot( lowOfDay, "", colorRed, styleDots | styleNoLine | styleNoRescale, Null, Null, 0, 0, 1 );
    }

    calculateVolumeValueArea( fvb, lvb );

    if( showVal1 )
    {
        Plot( valueHigh1, "", ColorRGB( 0, 250, 250 ), styleDots | styleNoLine | styleNoRescale, Null, Null, 0, -3, 1 );
        Plot( valueLow1, "", ColorRGB( 0, 250, 250 ), styleDots | styleNoLine | styleNoRescale, Null, Null, 0, -3, 1 );
    }

    if( showVal0 )
    {
        Plot( valueHigh0, "", ColorRGB( 250, 250, 0 ), styleDots | styleNoLine | styleNoRescale, Null, Null, 0, -3, 1 );
        Plot( valueLow0, "", ColorRGB( 250, 250, 0 ), styleDots | styleNoLine | styleNoRescale, Null, Null, 0, -3, 1 );
        PlotOHLC( valueLow0, valueLow0, valueHigh0, valueHigh0, "", ColorRGB( 10, 10, 0 ), styleCloud | styleNoRescale, Null, Null, 0, -5, 1 );
    }

    if( showPOC )
    {
        Plot( pointOfControl, "", ColorRGB( 250, 0, 250 ), styleDots | styleNoLine | styleNoRescale, Null, Null, 0, -3, 1 );
    }
}

if( Status( "Action" ) == actionExplore )
{
    calculateVolumeValueArea( 0, BarCount - 1 );

    Filter = Nz( valueHigh0 ) OR Nz( valueLow0 );
    AddColumn( Nz( valueHigh0 ), "Upper Boundary Volume Value area", 1.2, colorWhite, colorRed, -1 );
    AddColumn( Nz( valueLow0 ), "Lower Boundary Volume Value area", 1.2, colorWhite, colorGreen, -1 );
}
4 Likes

found a little error and added plotting of the volume in the last segment

the code between the if(cnt == 0)

can be replaced with:

            if( cnt == 0 )
            {
                x1 = idx1;
                x2 = BarCount - 1;
                line = LineArray( x1, priceh, x2, priceh );
                valueHigh0 = IIf( line, line, valueHigh0 );
                line = LineArray( x1, pricel, x2, pricel );
                valueLow0 = IIf( line, line, valueLow0 );

                line = LineArray( x1, pricePOC, x2, pricePOC );
                pointOfControl = IIf( line, line, pointOfControl );

                // draw volume current day
                if( showVolume )
                {
                    bins = int( ( highOfDay[ x2 ] - lowOfDay[ x2 ] ) / TickSize );
                    mx = PriceVolDistribution( H, L, V, bins, False, x1, x2 );
                    bins = MxGetSize( mx, 0 );
                    //_trace( "bins: " + bins + " x1: " + x1 + " x2: " + x2  );

                    dx = x2 - x1;

                    for( j = 0; j < bins; j++ )
                    {
                        price = mx[ j ][ 0 ]; // price level
                        relvolume = mx[ j ][ 1 ]; // relative volume 0..1
                        relbar = relvolume * dx;

                        GfxSelectPen( ColorRGB( 80, 0, 0 ), 1, 0 );
                        GfxMoveTo( x1, price );
                        GfxLineTo( x1 + relbar, price );
                    }
                }
            }
1 Like

got a PM from Panos telling me about this: http://centerworldinvestment.blogspot.be/2016/04/re-amibroker-amibroker-6130-beta_27.html

so added that to the code.

Will leave it at that unless I get suggestions or mistakes and will correct for it. I do not really see why one needs an exploration with this but the way I solved it does not seem very good. So anyone who can do this more efficiently please show me how :slight_smile:

// in reply to: http://forum.amibroker.com/t/how-to-get-the-most-traded-area-value-of-previous-day-intraday-data/2472
// code assumes your working with intraday data (e.g. 5min data)
// Value area calculation: http://onlinelibrary.wiley.com/doi/10.1002/9781118659724.app1/pdf
// !!!! TickSize is hardcoded in code. You need to adjust for, according to contract specifics.
// E.M.Pottasch (10/2017)

// possible strategies (did not test any myself)
// - 80% rule: https://marketdelta.com/wp-content/uploads/Strategy-80PercentRule.pdf
// - 

// TickSize = 0.25; // <<<<==== adjust yourself

volumeValuearea = Param( "Volume Value area (%)", 0.7, 0, 1, 0.01 );
showVolume = ParamToggle( "Show Volume", "No|Yes", 1 );
showHL = ParamToggle( "Show High/Low boundaries", "No|Yes", 0 );
showVal1 = ParamToggle( "Show Value area inside same day", "No|Yes", 0 );
showVal0 = ParamToggle( "Show Value area projected into the next day", "No|Yes", 1 );
showPOC = ParamToggle( "Show Point Of Control (POC)", "No|Yes", 1 );
vai = Param( "Volume Value area Color Intensity", 15, 0, 254, 1 );

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

valueHigh1 = valueLow1 = Null;
valueHigh0 = valueLow0 = Null;
pointOfControl = Null;
highOfDay = TimeFrameGetPrice( "H", inDaily );
lowOfDay = TimeFrameGetPrice( "L", inDaily );

lbx2 = ValueWhen( newDay, bi, 2 );
lbx1 = ValueWhen( newDay, bi, 1 );
lbx0 = ValueWhen( newDay, bi, 0 );

function calculateVolumeValueArea( fb, lb )
{
    GfxSetZOrder( -4 );
    GfxSetCoordsMode( 1 );

    cnt = 0; // count number of visible days

    for( i = lb; i > fb; i-- )
    {
        idx0 = lbx0[ i ];
        idx1 = lbx1[ i ];
        idx2 = lbx2[ i ];

        if( IsEmpty( idx1 ) ) break;

        bins = int( ( highOfDay[ idx1 - 1 ] - lowOfDay[ idx1 - 1 ] ) / TickSize );
        mx = PriceVolDistribution( H, L, V, bins, False, idx2, idx1 );
        //bins = MxGetSize( mx, 0 );
        //_trace( "bins: " + bins );

        dx = idx1 - idx2;

        mxVolBinIdx = 0;
        mxVol = 0;
        totVol = 0;

        for( j = 0; j < bins; j++ )
        {
            price = mx[ j ][ 0 ]; // price level
            relvolume = mx[ j ][ 1 ]; // relative volume 0..1
            relbar = relvolume * dx;

            if( showVolume )
            {
                GfxSelectPen( ColorRGB( 80, 0, 0 ), 1, 0 );
                GfxMoveTo( idx2, price );
                GfxLineTo( idx2 + relbar, price );
            }

            if( relvolume > mxVol )
            {
                mxVol = relvolume;
                mxVolBinIdx = j;
            }

            totVol = totVol + relvolume;
        }

        // calculate Volume Value area
        mxih = mxil = mxVolBinIdx;
        tvol = mx[ mxVolBinIdx ][ 1 ];
        pricePOC = mx[ mxVolBinIdx ][ 0 ];

        for( j = 0; j < bins; j++ )
        {
            if( mxih + 2 < bins AND mxil - 2 >= 0 )
            {
                relvolumeh = mx[ mxih + 1 ][ 1 ] + mx[ mxih + 2 ][ 1 ];
                relvolumel = mx[ mxil - 1 ][ 1 ] + mx[ mxil - 2 ][ 1 ];

                if( relvolumeh > relvolumel )
                {
                    mxih = mxih + 2;
                    tvol = tvol + relvolumeh;
                }
                else
                    if( relvolumeh < relvolumel )
                    {
                        mxil = mxil - 2;
                        tvol = tvol + relvolumel;
                    }
                    else
                        if( relvolumeh == relvolumel )
                        {
                            mxih = mxih + 2;
                            mxil = mxil - 2;
                            tvol = tvol + relvolumeh + relvolumel;
                        }
            }
            else
                if( mxih + 2 >= bins AND mxil - 2 >= 0 )
                {
                    relvolumel = mx[ mxil - 1 ][ 1 ] + mx[ mxil - 2 ][ 1 ];
                    mxil = mxil - 2;
                    tvol = tvol + relvolumel;
                }
                else
                    if( mxih + 2 < bins AND mxil - 2 < 0 )
                    {
                        relvolumeh = mx[ mxih + 1 ][ 1 ] + mx[ mxih + 2 ][ 1 ];
                        mxih = mxih + 2;
                        tvol = tvol + relvolumeh;
                    }

            // handle uneven bars left
            if( mxih + 2 >= bins AND mxil - 2 < 0 )
            {
                if( mxih + 1 < bins )
                {
                    relvolumeh = mx[ mxih + 1 ][ 1 ];
                    mxih = mxih + 1;
                    tvol = tvol + relvolumeh;
                }

                if( mxil - 1 >= 0 )
                {
                    relvolumel = mx[ mxil - 1 ][ 1 ];
                    mxil = mxil - 1;
                    tvol = tvol + relvolumel;
                }
            }

            if( ( tvol / totVol ) >= volumeValuearea ) break;
        }

        priceh = mx[ mxih ][ 0 ];
        pricel = mx[ mxil ][ 0 ];
        x1 = idx2;
        x2 = idx1;
        line = LineArray( x1, priceh, x2, priceh );
        valueHigh1 = IIf( line, line, valueHigh1 );
        line = LineArray( x1, pricel, x2, pricel );
        valueLow1 = IIf( line, line, valueLow1 );

        // draw into next day
        if( cnt > 0 )
        {
            x1 = idx1;
            x2 = idx0;
            line = LineArray( x1, priceh, x2, priceh );
            valueHigh0 = IIf( line, line, valueHigh0 );
            line = LineArray( x1, pricel, x2, pricel );
            valueLow0 = IIf( line, line, valueLow0 );

            line = LineArray( x1, pricePOC, x2, pricePOC );
            pointOfControl = IIf( line, line, pointOfControl );
        }
        else
            if( cnt == 0 )
            {
                x1 = idx1;
                x2 = BarCount - 1;
                line = LineArray( x1, priceh, x2, priceh );
                valueHigh0 = IIf( line, line, valueHigh0 );
                line = LineArray( x1, pricel, x2, pricel );
                valueLow0 = IIf( line, line, valueLow0 );

                line = LineArray( x1, pricePOC, x2, pricePOC );
                pointOfControl = IIf( line, line, pointOfControl );

                // draw volume current day
                if( showVolume )
                {
                    bins = int( ( highOfDay[ x2 ] - lowOfDay[ x2 ] ) / TickSize );
                    mx = PriceVolDistribution( H, L, V, bins, False, x1, x2 );
                    //bins = MxGetSize( mx, 0 );
                    //_trace( "bins: " + bins + " x1: " + x1 + " x2: " + x2  );

                    dx = x2 - x1;

                    for( j = 0; j < bins; j++ )
                    {
                        price = mx[ j ][ 0 ]; // price level
                        relvolume = mx[ j ][ 1 ]; // relative volume 0..1
                        relbar = relvolume * dx;

                        GfxSelectPen( ColorRGB( 80, 0, 0 ), 1, 0 );
                        GfxMoveTo( x1, price );
                        GfxLineTo( x1 + relbar, price );
                    }
                }
            }

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

if( Status( "Action" ) == actionIndicator )
{
    Title = Name() + "   Volume area (%): " + volumeValuearea * 100;

    SetChartOptions( 0, chartShowDates );
    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, -2, 5 );

    if( showHL )
    {
        Plot( highOfDay, "", colorGreen, styleDots | styleNoLine | styleNoRescale, Null, Null, 0, 0, 1 );
        Plot( lowOfDay, "", colorRed, styleDots | styleNoLine | styleNoRescale, Null, Null, 0, 0, 1 );
    }

    calculateVolumeValueArea( fvb, lvb );

    if( showVal1 )
    {
        Plot( valueHigh1, "", ColorRGB( 0, 250, 250 ), styleDots | styleNoLine | styleNoRescale, Null, Null, 0, -3, 1 );
        Plot( valueLow1, "", ColorRGB( 0, 250, 250 ), styleDots | styleNoLine | styleNoRescale, Null, Null, 0, -3, 1 );
    }

    if( showVal0 )
    {
        Plot( valueHigh0, "", ColorRGB( 250, 250, 0 ), styleDots | styleNoLine | styleNoRescale, Null, Null, 0, -3, 1 );
        Plot( valueLow0, "", ColorRGB( 250, 250, 0 ), styleDots | styleNoLine | styleNoRescale, Null, Null, 0, -3, 1 );
        PlotOHLC( valueLow0, valueLow0, valueHigh0, valueHigh0, "", ColorRGB( vai, vai, 0 ), styleCloud | styleNoRescale, Null, Null, 0, -5, 1 );
    }

    if( showPOC )
    {
        Plot( pointOfControl, "", ColorRGB( 250, 0, 250 ), styleDots | styleNoLine | styleNoRescale, Null, Null, 0, -3, 1 );
    }
}

if( Status( "Action" ) == actionExplore )
{
    calculateVolumeValueArea( 0, BarCount - 1 );

    Filter = Nz( valueHigh0 ) OR Nz( valueLow0 );
    AddColumn( Nz( valueHigh0 ), "Upper Boundary Volume Value area", 1.2, colorWhite, colorRed, -1 );
    AddColumn( Nz( valueLow0 ), "Lower Boundary Volume Value area", 1.2, colorWhite, colorGreen, -1 );
}
2 Likes

TickSize = 0.25; // <<<<==== adjust yourself

oh yeah I commented that out because I set this in the Information Window, see "Contract Specification"

contr

there were still small errors in there. But also made a cool update where you can select a separator other then Day().

so up until now you could only (using my code) make a MP using intraday data. But will post code 2morrow where you can chose between Day/Week/Month and Year. And yourself can easily add Hour/15min etc all the way down to ticks.

I just have little issue left with Week since there is no Week() function in Amibroker. Thought I solved it but just found 1 more imperfection.

what I use now

if( sep == "Week" )
{
    dw = DayOfWeek();
    newWeek = dw < Ref( dw, -1 );;
    newYear = Year() != Ref( Year(), -1 );
    dn = weekNumber = Sum( newWeek, BarsSince( newYear ) + 1 );
    dn1 = inWeekly;
}

so weekNumber returns same as Day(), Month() etc functions. But not perfect yet. Why again is there no Week() function in Amibroker?

no issue just seems at cross of years in Weekly. And is due to H/L inWeekly. Not a big issue, will solve that tomorrow

so most of it works pretty good. So with code below try using 15min data and then set in the Parameter window “Separator Interval” to week, month or year

oh yeah, Ticksize is commented out in code. Set that correctly, else it will not work

cheers :beer:

// in reply to: http://forum.amibroker.com/t/how-to-get-the-most-traded-area-value-of-previous-day-intraday-data/2472
// code assumes your working with intraday data (e.g. 5min data)
// Value area calculation: http://onlinelibrary.wiley.com/doi/10.1002/9781118659724.app1/pdf
// !!!! TickSize is hardcoded in code. You need to adjust for, according to contract specifics.
// E.M.Pottasch (10/2017)

// possible strategies (did not test any myself)
// - 80% rule: https://marketdelta.com/wp-content/uploads/Strategy-80PercentRule.pdf
// -

//TickSize = 0.25; // <<<<==== adjust yourself

volumeValuearea = Param( "Volume Value area (%)", 0.7, 0, 1, 0.01 );
showVolume = ParamToggle( "Show Volume", "No|Yes", 1 );
showHL = ParamToggle( "Show High/Low boundaries", "No|Yes", 0 );
showVal1 = ParamToggle( "Show Value area inside same day", "No|Yes", 0 );
showVal0 = ParamToggle( "Show Value area projected into the next day", "No|Yes", 1 );
showPOC = ParamToggle( "Show Point Of Control (POC)", "No|Yes", 1 );
vai = Param( "Volume Value area Color Intensity", 10, 0, 254, 1 );
sep = ParamList( "Separator Interval", "Day|Week|Month|Year", 0 );

if( sep == "Day" )
{
    dn = Day();
    dn1 = inDaily;
}

if( sep == "Week" )
{
    dw = DayOfWeek();
    newWeek = dw < Ref( dw, -1 );;
    newYear = Year() != Ref( Year(), -1 );
    dn = weekNumber = Sum( newWeek, BarsSince( newYear ) + 1 );
    dn1 = inWeekly;
}

if( sep == "Month" )
{
    dn = Month();
    dn1 = inMonthly;
}

if( sep == "Year" )
{
    dn = Year();
    dn1 = inYearly;
}

"dn: " + dn;

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

bi = BarIndex();
fvb = Max( 0, FirstVisibleValue( bi ) );
lvb = Max( 0, LastVisibleValue( bi ) );

valueHigh1 = valueLow1 = Null;
valueHigh0 = valueLow0 = Null;
pointOfControl = Null;
highOfDay = TimeFrameGetPrice( "H", dn1 );
lowOfDay = TimeFrameGetPrice( "L", dn1 );

lbx2 = ValueWhen( separator, bi, 2 );
lbx1 = ValueWhen( separator, bi, 1 );
lbx0 = ValueWhen( separator, bi, 0 );

function calculateVolumeValueArea( fb, lb )
{
    GfxSetZOrder( -4 );
    GfxSetCoordsMode( 1 );

    cnt = 0; // count number of visible days

    for( i = lb; i > fb; i-- )
    {
        idx0 = lbx0[ i ];
        idx1 = lbx1[ i ];
        idx2 = lbx2[ i ];

        if( IsEmpty( idx1 ) ) break;

        bins = int( ( highOfDay[ idx1 - 1 ] - lowOfDay[ idx1 - 1 ] ) / TickSize );
        mx = PriceVolDistribution( H, L, V, bins, False, idx2, idx1 - 1 );
        //bins = MxGetSize( mx, 0 );
 
        dx = idx1 - idx2;

        mxVolBinIdx = 0;
        mxVol = 0;
        totVol = 0;

        for( j = 0; j < bins; j++ )
        {
            price = mx[ j ][ 0 ]; // price level
            relvolume = mx[ j ][ 1 ]; // relative volume 0..1
            relbar = relvolume * dx;

            if( showVolume )
            {
                GfxSelectPen( ColorRGB( 80, 0, 0 ), 1, 0 );
                GfxMoveTo( idx2, price );
                GfxLineTo( idx2 + relbar, price );
            }

            if( relvolume > mxVol )
            {
                mxVol = relvolume;
                mxVolBinIdx = j;
            }

            totVol = totVol + relvolume;
        }

        // calculate Volume Value area
        mxih = mxil = mxVolBinIdx;
        tvol = mx[ mxVolBinIdx ][ 1 ];
        pricePOC = mx[ mxVolBinIdx ][ 0 ];

        for( j = 0; j < bins; j++ )
        {
            if( mxih + 2 < bins AND mxil - 2 >= 0 )
            {
                relvolumeh = mx[ mxih + 1 ][ 1 ] + mx[ mxih + 2 ][ 1 ];
                relvolumel = mx[ mxil - 1 ][ 1 ] + mx[ mxil - 2 ][ 1 ];

                if( relvolumeh > relvolumel )
                {
                    mxih = mxih + 2;
                    tvol = tvol + relvolumeh;
                }
                else
                    if( relvolumeh < relvolumel )
                    {
                        mxil = mxil - 2;
                        tvol = tvol + relvolumel;
                    }
                    else
                        if( relvolumeh == relvolumel )
                        {
                            mxih = mxih + 2;
                            mxil = mxil - 2;
                            tvol = tvol + relvolumeh + relvolumel;
                        }
            }
            else
                if( mxih + 2 >= bins AND mxil - 2 >= 0 )
                {
                    relvolumel = mx[ mxil - 1 ][ 1 ] + mx[ mxil - 2 ][ 1 ];
                    mxil = mxil - 2;
                    tvol = tvol + relvolumel;
                }
                else
                    if( mxih + 2 < bins AND mxil - 2 < 0 )
                    {
                        relvolumeh = mx[ mxih + 1 ][ 1 ] + mx[ mxih + 2 ][ 1 ];
                        mxih = mxih + 2;
                        tvol = tvol + relvolumeh;
                    }

            // handle uneven bars left
            if( mxih + 2 >= bins AND mxil - 2 < 0 )
            {
                if( mxih + 1 < bins )
                {
                    relvolumeh = mx[ mxih + 1 ][ 1 ];
                    mxih = mxih + 1;
                    tvol = tvol + relvolumeh;
                }

                if( mxil - 1 >= 0 )
                {
                    relvolumel = mx[ mxil - 1 ][ 1 ];
                    mxil = mxil - 1;
                    tvol = tvol + relvolumel;
                }
            }

            if( ( tvol / totVol ) >= volumeValuearea ) break;
        }

        priceh = mx[ mxih ][ 0 ];
        pricel = mx[ mxil ][ 0 ];
        x1 = idx2;
        x2 = idx1;
        line = LineArray( x1, priceh, x2, priceh );
        valueHigh1 = IIf( line, line, valueHigh1 );
        line = LineArray( x1, pricel, x2, pricel );
        valueLow1 = IIf( line, line, valueLow1 );

        // draw into next day
        if( cnt > 0 )
        {
            x1 = idx1;
            x2 = idx0;
            line = LineArray( x1, priceh, x2, priceh );
            valueHigh0 = IIf( line, line, valueHigh0 );
            line = LineArray( x1, pricel, x2, pricel );
            valueLow0 = IIf( line, line, valueLow0 );

            line = LineArray( x1, pricePOC, x2, pricePOC );
            pointOfControl = IIf( line, line, pointOfControl );
        }
        else
            if( cnt == 0 )
            {
                x1 = idx1;
                x2 = BarCount - 1;
                line = LineArray( x1, priceh, x2, priceh );
                valueHigh0 = IIf( line, line, valueHigh0 );
                line = LineArray( x1, pricel, x2, pricel );
                valueLow0 = IIf( line, line, valueLow0 );

                line = LineArray( x1, pricePOC, x2, pricePOC );
                pointOfControl = IIf( line, line, pointOfControl );

                // draw volume current day
                if( showVolume )
                {
                    bins = int( ( highOfDay[ x2 ] - lowOfDay[ x2 ] ) / TickSize );
                    mx = PriceVolDistribution( H, L, V, bins, False, x1, x2 );
                    //bins = MxGetSize( mx, 0 );
                    //_trace( "bins: " + bins + " x1: " + x1 + " x2: " + x2  );

                    dx = x2 - x1;

                    for( j = 0; j < bins; j++ )
                    {
                        price = mx[ j ][ 0 ]; // price level
                        relvolume = mx[ j ][ 1 ]; // relative volume 0..1
                        relbar = relvolume * dx;

                        GfxSelectPen( ColorRGB( 80, 0, 0 ), 1, 0 );
                        GfxMoveTo( x1, price );
                        GfxLineTo( x1 + relbar, price );
                    }
                }
            }

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

if( Status( "Action" ) == actionIndicator )
{
    Title = Name() + "   >>|<<   Volume area (%): " + volumeValuearea * 100 + "   >>|<<   Separator Timeframe: " + sep;

    SetChartOptions( 0, chartShowDates );
    SetChartBkColor( ColorRGB( 0, 0, 0 ) );
    Plot( Close, "Price", colorDefault, styleCandle, Null, Null, 0, 0, 1 );
    Plot( separator, "", colorDarkBlue, styleHistogram | styleOwnScale | styleNoLabel | styleNoRescale, 0, 1, 0, -2, 5 );

    if( showHL )
    {
        Plot( highOfDay, "", colorGreen, styleDots | styleNoLine | styleNoRescale, Null, Null, 0, 0, 1 );
        Plot( lowOfDay, "", colorRed, styleDots | styleNoLine | styleNoRescale, Null, Null, 0, 0, 1 );
    }

    calculateVolumeValueArea( fvb, lvb );

    if( showVal1 )
    {
        Plot( valueHigh1, "", ColorRGB( 0, 250, 250 ), styleDots | styleNoLine | styleNoRescale, Null, Null, 0, -3, 1 );
        Plot( valueLow1, "", ColorRGB( 0, 250, 250 ), styleDots | styleNoLine | styleNoRescale, Null, Null, 0, -3, 1 );
    }

    if( showVal0 )
    {
        Plot( valueHigh0, "", ColorRGB( 250, 250, 0 ), styleDots | styleNoLine | styleNoRescale, Null, Null, 0, -3, 1 );
        Plot( valueLow0, "", ColorRGB( 250, 250, 0 ), styleDots | styleNoLine | styleNoRescale, Null, Null, 0, -3, 1 );
        PlotOHLC( valueLow0, valueLow0, valueHigh0, valueHigh0, "", ColorRGB( vai, vai, 0 ), styleCloud | styleNoRescale, Null, Null, 0, -5, 1 );
    }

    if( showPOC )
    {
        Plot( pointOfControl, "", ColorRGB( 250, 0, 250 ), styleDots | styleNoLine | styleNoRescale, Null, Null, 0, -3, 1 );
    }
}

if( Status( "Action" ) == actionExplore )
{
    calculateVolumeValueArea( 0, BarCount - 1 );

    Filter = Nz( valueHigh0 ) OR Nz( valueLow0 );
    AddColumn( Nz( valueHigh0 ), "Upper Boundary Volume Value area", 1.2, colorWhite, colorRed, -1 );
    AddColumn( Nz( valueLow0 ), "Lower Boundary Volume Value area", 1.2, colorWhite, colorGreen, -1 );
}
2 Likes

just looked into the exploration issue since for the backtest it is the same.

found simple solution that seems to work. Just replace the bottom actionExplore part with code below.

However this works only if you use “From- To Dates”.

But I am not too lazy to use it.

if( Status( "Action" ) == actionExplore )
{
	br = Status( "barinrange" );
	br = br - Ref( br, -1 );
	st = LastValue( ValueWhen( br == 1, bi ) );
	ed = LastValue( ValueWhen( br == (-1), bi ) );
	if( ed == 0 ) ed = BarCount - 1;
	
	//_Trace( "st: " + st + " ed: " + ed + " (Barcount - 1): " + (BarCount - 1 ) ); 
	
    calculateVolumeValueArea( st, ed );

    Filter = Nz( valueHigh0 ) OR Nz( valueLow0 );
    AddColumn( Nz( valueHigh0 ), "Upper Boundary Volume Value area", 1.2, colorWhite, colorRed, -1 );
    AddColumn( Nz( valueLow0 ), "Lower Boundary Volume Value area", 1.2, colorWhite, colorGreen, -1 );
}
1 Like

Since you asked...
Exploration can be used to output profile/footprint stats instead of outputting them on chart pane. Exploration is pretty flexible clean table environment. Below are two older sample pictures.

1
1

4 Likes

ok, yes my point was that I would prefer to see it in the chart, but your table looks nice.

I know little about the market profile but I always wanted to get hold of the volume value area in the form of arrays and that is now made easier with the PlotVolDistribution() function. As I understand it these market profile traders work with a “Volume Value Area” and a “Time Value Area”. With a POC (point of control => the price at with it stayed the max amount of time) and the VPOC, the volume point of control => the price at which the maximum amount of volume is traded.

So we still need a function PlotTimeDistribution() :wink: :wink:

your chart does not show a “time value area”, right?

Ed,
You are mixing things…market profile and volume profile are similar concepts but not the same.
Volume profiles (here by using PriceVolDistribution() function) are based on volume.
Market profiles are based on time, see time price opportunity (TPO).
The terms Value Area, VAH/VAL, POC are used in both profile versions.

It shows volume profiles.

1 Like

yes ok. I read that some mix the “time profile” with the “volume profile” chart and look for confluence between the two. But apparently the volume profile is the more powerful. I wanted to use the volume area high and low similar to how levels S4 and R4 are used in the Camarilla system. But so far I only managed to make a system that loses money. Buy above the volume area high and sell at the close, short below volume area low and cover at the close is not good enough.

How about Buy at the MidpPoint, if Volumes & Closes are Progressive , And Short if the Closes are lower and Volumes are Progressive ?