Multiple Anchored VWAP

Hello! I have the following formula which produces an Anchored VWAP when you click anywhere on a chart. However, every other click deletes the previous VWAP. Is there a way to produce several VWAPs over multiple dates when clicking on the chart and maybe having a parameter to delete/reset them? How can this be achieved?

dn = DateTime();
sd = SelectedValue( dn );

start = dn == sd;

mp = C;

PV = mp * V;
CV = Cum( V );
VSS = CV - ValueWhen( start, CV );

denom = IIf( VSS == 0, 1, VSS );
num = Cum( PV ) - ValueWhen( start, Cum( PV ) );

M = IIf( BarsSince( start ), num/denom, mp );

Plot( C, Date() + " Close", colorYellow, styleBar );
Plot( M, "M" + _PARAM_VALUES(), colorYellow, styleThick );
1 Like

This might help . I am not the author . Available on net

_SECTION_BEGIN("VWAP");
/*
The VWAP for a stock is calculated by adding the dollars traded for every
transaction in that stock ("price" x "number of shares traded") and dividing the total shares traded. A VWAP is computed from the Open of the market to the market Close, AND is calculated by Volume weighting all transactions during this time period
*/
 
Bars_so_far_today = 1 + BarsSince( Day() != Ref(Day(), -1));
StartBar = ValueWhen(TimeNum() == 093000, BarIndex());
TodayVolume = Sum(V,Bars_so_far_today);
IIf (BarIndex() >= StartBar, VWAP = Sum (C * V, Bars_so_far_today  ) / TodayVolume,0);
Plot (VWAP,"VWAP",colorOrange, styleThick);
 
_SECTION_END();```

This would be the VWAP calculated from 930am every day until the daily close.

I’m looking for a way to place various VWAP starting points that would go until the latest bar.

here is 1 way:

Version( 6.21 );

dn = DateTime();
sd = SelectedValue( dn );

start = dn == sd;

mp = C;

PV = mp * V;
CV = Cum( V );
VSS = CV - ValueWhen( start, CV );

denom = IIf( VSS == 0, 1, VSS );
num = Cum( PV ) - ValueWhen( start, Cum( PV ) );

M = IIf( BarsSince( start ), num / denom, mp );

SetChartOptions( 0, chartShowDates );
SetChartBkColor( ColorRGB( 0, 0, 0 ) );
Plot( C, Date() + " Close", colorYellow, styleBar );
Plot( M, "M" + _PARAM_VALUES(), colorYellow, styleThick );

GuiSetFont( "Lucida Console", 10 );
GuiButton( "Store VWAP", 1, 10, 50, 120, 30, 7 );
GuiButton( "Reset VWAPs", 2, 10, 85, 120, 30, 7 );
GuiSetColors( 1, 2, 2, colorRed, colorBlack, colorRed, colorWhite, colorBlue, colorYellow, colorRed, colorBlack, colorYellow );

id = GuiGetEvent( 0, 0 );
event = GuiGetEvent( 0, 1 );

for( i = 1; i <= 2; i++ )
{
    if( id == 1 && event == 1 )
    {
        Say( "Store VWAP" );
        StaticVarSet( "cnt", Nz( StaticVarGet( "cnt" ) ) + 1, True );
        StaticVarSet( Name() + "M" + StaticVarGet( "cnt" ), M, True );
    }

    if( id == 2 && event == 1 )
    {
        Say( "Reset VWAPs" );
        StaticVarRemove( Name() + "M*" );
        StaticVarRemove( "cnt" );
    }
}

for( i = 1; i < Nz( StaticVarGet( "cnt" ) ); i++ )
{
    Plot( StaticVarGet( Name() + "M" + i ), "M" + i + _PARAM_VALUES(), colorYellow, styleThick );
}
6 Likes

Absolutely amazing! Thank you so much! This is only possible with the BETA? Is it stable enough?

version I just added because you at least need 6.21.

about stability. My code is just to give a general method how it can be done. I did not check it in detail if I implemented everything correctly. But with persistent static variables the stored VWAPs should still be there if you close Amibroker and start it back up again. Details you have to implement yourself

Instead of GUI buttons you may use keyboard key stroke plus mouse click. It is quicker workflow in addition.
Read the instructions in the chart title first.

dn = DateTime();
sd = SelectedValue( dn );

start = dn == sd;

mp = C;

PV = mp * V;
CV = Cum( V );
VSS = CV - ValueWhen( start, CV );

denom = IIf( VSS == 0, 1, VSS );
num = Cum( PV ) - ValueWhen( start, Cum( PV ) );

M = IIf( BarsSince( start ), num / denom, mp );

SetChartOptions( 0, chartShowDates );
SetChartBkColor( ColorRGB( 0, 0, 0 ) );
Plot( C, Date() + " Close", colorYellow, styleBar );
Plot( M, "M" + _PARAM_VALUES(), colorYellow, styleThick );

gcmb = GetCursorMouseButtons();
lmb = gcmb == 9;
mmb = gcmb == 12;
CTRL = GetAsyncKeyState(17) < 0;

if( lmb && CTRL )
{
	Say( "Store VWAP" );
	StaticVarSet( "cnt", Nz( StaticVarGet( "cnt" ) ) + 1, True );
	StaticVarSet( Name() + "M" + StaticVarGet( "cnt" ), M, True );
}

if( mmb && CTRL )
{
	Say( "Reset VWAPs" );
	StaticVarRemove( Name() + "M*" );
	StaticVarRemove( "cnt" );
}

for( i = 1; i < Nz( StaticVarGet( "cnt" ) ); i++ )
{
    Plot( StaticVarGet( Name() + "M" + i ), "M" + i + _PARAM_VALUES(), colorYellow, styleThick );
}

if( Nz( LastValue(StaticVarGet( Name() + "M1" ) )) == 0)
	Title = EncodeColor(colorRed) + "1. Hold CTRL key!\n2. Select a bar\n3. Then click Left mouse button to create lines\n4. Click CTRL +  Middle mouse button to delete lines\n{{VALUES}}"; 
6 Likes

thanks fx, will study it tomorrow

This is great! Thank you!

yes fx, this works great.

only thing with the current setup is that if a new bar comes in it will not recalculate the VWAP for the latest incoming data point. So this is something that needs to be added to the code still. Mañana maybe

The previous code was not working properly as I was editing it in editor without applying it to chart. Below is a better working one. In addition it updates all set static lines at latest incoming price data.

function NewBarJustArrived() {
    // function by T. Janeczko
    vname = "lbe" + GetChartID();
    prev = Nz( StaticVarGet( vname ) );
    curr = Status( "lastbarend" );
    StaticVarSet( vname, curr );
    return curr != prev;
}

/// VWAP-Multi-Storage AFL
/// by fxshrat
/// it uses CTRL + mouse button click toi set lines (read instructions in chart title
/// code updates lines on new incoming price data.
/// @link http://forum.amibroker.com/t/multiple-anchored-vwap/4739/10
/// modified from GUI version
/// @link http://forum.amibroker.com/t/multiple-anchored-vwap/4739/4

dt = DateTime();
sdt = SelectedValue(dt);
newbar = NewBarJustArrived();

gcmb = GetCursorMouseButtons();
lmb = gcmb == 9;
mmb = gcmb == 12;
CTRL = GetAsyncKeyState(17) < 0;

mp = C;
PV = mp * V;
CV = Cum( V );
CumPV = Cum( PV );

start = dt == sdt;
num = Cum( PV ) - ValueWhen( start, Cum( PV ) );
denom = CV - ValueWhen( start, CV );
vwap = IIf( BarsSince(start) > 0, num / Max(1, denom), mp );

nm = Name();
vwapstr = nm + "VWAP";
cntstr = nm + "VWAP_cnt";
dnstr = nm + "VWAP_DN";

if( CTRL && lmb ) {
	staticget = Nz( StaticVarGet( cntstr ) );
	Say( "Store V.W.A.P."+(staticget+1) );	
	StaticVarSet( cntstr, staticget+1, True );
	StaticVarSet( vwapstr + staticget, vwap, True );
	StaticVarSet(dnstr + staticget, sdt, True );	
}

if( CTRL && mmb ) {
	Say( "Reset VWAPs" );
	StaticVarRemove( vwapstr + "*" );
	StaticVarRemove( dnstr + "*" );
	StaticVarRemove( cntstr );
}

// Output
SetChartOptions( 0, chartShowDates | chartWrapTitle );
Plot( C, Date() + " - Close", colorYellow, styleBar );
Plot( vwap, "VWAPselect" + _PARAM_VALUES(), colorOrange, styleThick );

for( i = 0; i < Nz(StaticVarGet( cntstr )); i++ ) {
    if( newbar ) {
		Say( "This is new bar!" );
		staticsd = StaticVarGet( dnstr + i );
		staticstart = dt == staticsd;
		staticnum = CumPV - ValueWhen( staticstart, CumPV );
		staticdenom = CV - ValueWhen( staticstart, CV );
		static_vwap = IIf( BarsSince( staticstart ) > 0, staticnum / Max(1, staticdenom), mp );		
		StaticVarSet( vwapstr + i, static_vwap, True );
	}
   
    Plot( StaticVarGet(vwapstr + i ), "VWAP" + (i+1) + _PARAM_VALUES(), colorYellow, styleThick );
}

if( Nz( LastValue(StaticVarGet( vwapstr + "0" ) )) == 0)
	Title = EncodeColor(colorRed) + "1. Hold CTRL key!\n2. Click left mouse button to create lines\n3. Click CTRL + Middle mouse button to delete lines\n{{VALUES}}"; 
3 Likes

Changed NewBarJustArrived to check for new price data too. Renamed to NewDataJustArrived().

function NewDataJustArrived() {
    // function by T. Janeczko
    // mod. by fxshrat to check for new price data too
    vname = "lbe" + GetChartID();
    prev = Nz( StaticVarGet( vname ) );
    curr = Status( "lastbarend" );    
    StaticVarSet( vname, curr );  
    // 
    lastC = LastValue(C);
    prevC = Nz( StaticVarGet( vname + "_Close" ) ); 
    StaticVarSet( vname + "_Close", lastC );

    return curr != prev || lastc != prevC;
}

/// VWAP-Multi-Storage AFL
/// by fxshrat
/// it uses CTRL + mouse button click toi set lines (read instructions in chart title
/// code updates lines on new incoming price data.
/// @link http://forum.amibroker.com/t/multiple-anchored-vwap/4739/10
/// modified from GUI version
/// @link http://forum.amibroker.com/t/multiple-anchored-vwap/4739/4

dt = DateTime();
sdt = SelectedValue(dt);
newbar = NewDataJustArrived();

gcmb = GetCursorMouseButtons();
lmb = gcmb == 9;
mmb = gcmb == 12;
CTRL = GetAsyncKeyState(17) < 0;

mp = C;
PV = mp * V;
CV = Cum( V );
CumPV = Cum( PV );

start = dt == sdt;
num = Cum( PV ) - ValueWhen( start, Cum( PV ) );
denom = CV - ValueWhen( start, CV );
vwap = IIf( BarsSince(start) > 0, num / Max(1, denom), mp );

nm = Name();
vwapstr = nm + "VWAP";
cntstr = nm + "VWAP_cnt";
dnstr = nm + "VWAP_DN";

if( CTRL && lmb ) {
	staticget = Nz( StaticVarGet( cntstr ) );
	Say( "Store V.W.A.P."+(staticget+1) );	
	StaticVarSet( cntstr, staticget+1, True );
	StaticVarSet( vwapstr + staticget, vwap, True );
	StaticVarSet(dnstr + staticget, sdt, True );	
}

if( CTRL && mmb ) {
	Say( "Reset VWAPs" );
	StaticVarRemove( vwapstr + "*" );
	StaticVarRemove( dnstr + "*" );
	StaticVarRemove( cntstr );
}

// Output
SetChartOptions( 0, chartShowDates | chartWrapTitle );
Plot( C, Date() + " - Close", colorYellow, styleBar );
Plot( vwap, "VWAPselect" + _PARAM_VALUES(), colorOrange, styleThick );

for( i = 0; i < Nz(StaticVarGet( cntstr )); i++ ) {
    if( newbar ) {
		Say( "This is new bar or new data!" );
		staticsd = StaticVarGet( dnstr + i );
		staticstart = dt == staticsd;
		staticnum = CumPV - ValueWhen( staticstart, CumPV );
		staticdenom = CV - ValueWhen( staticstart, CV );
		static_vwap = IIf( BarsSince( staticstart ) > 0, staticnum / Max(1, staticdenom), mp );		
		StaticVarSet( vwapstr + i, static_vwap, True );
	}
   
    Plot( StaticVarGet(vwapstr + i ), "VWAP" + (i+1) + _PARAM_VALUES(), colorYellow, styleThick );
}

if( Nz( LastValue(StaticVarGet( vwapstr + "0" ) )) == 0)
	Title = EncodeColor(colorRed) + "1. Hold CTRL key!\n2. Click left mouse button to create lines\n3. Click CTRL + Middle mouse button to delete lines\n{{VALUES}}"; 
10 Likes

i had the idea to just store the start array and draw the VWAP at every refresh. Then you need not to worry about new bars coming in. I wanted to check that out so therefore I updated my button code.

You can also remove a single VWAP when you stand on the curve you want to remove and then press "Remove single VWAP"

// afl Code by E.M.Pottasch 2/2018
Version( 6.21 );

dn = DateTime();
sd = SelectedValue( dn );

start0 = dn == sd;
idx0 = LastValue( ValueWhen( start0, BarIndex() ) );

mp = C;

PV = mp * V;
CV = Cum( V );
VSS = CV - ValueWhen( start0, CV );

denom = IIf( VSS == 0, 1, VSS );
num = Cum( PV ) - ValueWhen( start0, Cum( PV ) );

M = IIf( BarsSince( start0 ), num / denom, mp );

SetChartOptions( 0, chartShowDates );
SetChartBkColor( ColorRGB( 0, 0, 0 ) );
Plot( C, Date() + " No.VWAPs: " + Nz( StaticVarGet( "cnt" ) ) + " Close: ", colorYellow, styleCandle );
Plot( M, "M", colorBlue, styleLine, Null, Null, 0, 0, 2 );

GuiSetFont( "Lucida Console", 10 );
GuiButton( "Store VWAP", 1, 10, 50, 155, 30, 7 );
GuiButton( "Remove single VWAP", 2, 10, 85, 155, 30, 7 );
GuiButton( "Reset all VWAPs", 3, 10, 120, 155, 30, 7 );
GuiSetColors( 1, 3, 2, colorRed, colorBlack, colorRed, colorWhite, colorBlue, colorYellow, colorRed, colorBlack, colorYellow );

id = GuiGetEvent( 0, 0 );
event = GuiGetEvent( 0, 1 );

if( id == 1 && event == 1 )
{
    Say( "Store VWAP" );
    StaticVarSet( "cnt", Nz( StaticVarGet( "cnt" ) ) + 1, True );
    StaticVarSet( Name() + "M" + StaticVarGet( "cnt" ), start0, True );
}

if( id == 2 && event == 1 )
{
    Say( "Remove single VWAPs" );

    idx = 0;
    cnt = Nz( StaticVarGet( "cnt" ) );

    for( i = 1; i <= cnt; i++ )
    {
        start1 = StaticVarGet( Name() + "M" + i );
        idx1 = LastValue( ValueWhen( start1, BarIndex() ) );

        if( idx0 == idx1 )
        {
            idx = i;
            StaticVarSet( Name() + "M" + i, 0, True );
        }
    }

    if( idx != 0 )
    {
        for( i = 1; i <= cnt; i++ )
        {
            if( i > idx )
            {
                start1 = StaticVarGet( Name() + "M" + i );
                StaticVarSet( Name() + "M" + ( i - 1 ), start1, True );
            }
        }

        StaticVarSet( "cnt", Nz( StaticVarGet( "cnt" ) ) - 1, True );
    }
}

if( id == 3 && event == 1 )
{
    Say( "Reset all VWAPs" );
    StaticVarRemove( Name() + "M*" );
    StaticVarRemove( "cnt" );
}

for( i = 1; i <= Nz( StaticVarGet( "cnt" ) ); i++ )
{
    start = StaticVarGet( Name() + "M" + i );
    VSS = CV - ValueWhen( start, CV );
    denom = IIf( VSS == 0, 1, VSS );
    num = Cum( PV ) - ValueWhen( start, Cum( PV ) );
    M = IIf( BarsSince( start ), num / denom, mp );
    Plot( M, "M" + i, colorYellow, styleLine | styleNoRescale, Null, Null, 0, 0, 5 );
}
14 Likes

Updating loop calculation of multiple static lines on every chart refresh
is little bit overkill as only incoming data change will change plot
result. The point is to (re-)store at data change only.

1 Like

Hi all,...I'm interesting with this discussion since I am trying to find out how if I want to calculate vwap from x-given date to y-given date. From this discussion it's already half way that we can select any starting date/bar and always end at current bar. I have one afl code for fibonacci that can select start-bar and end-bar...is it ok if I post it here as an example?

Hi and thanks so much for your efforts. Any chance this AFL can be used to work on Ami 6.0 as I currently have that version only.

i think i added "version" because it uses the GuiButtons. I think they are only available in higher versions

I had similar goals and from similar code created a function.
You can also use this function to draw VWAP based on an array. You set the array named "VWAPStart" to 1 in the Dates that you like.

SetChartOptions(0,chartShowArrows|chartShowDates);
_N(Title = StrFormat("{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ));
Plot( C, "Close", ParamColor("Color", colorDefault ), styleNoTitle | ParamStyle("Style") | GetPriceStyle() ); 

function VWAP_Anchored(AnchoredArray) {
//Anchored VWAP
//AnchoredArray = when array=1 then VWAP is anchored
	start = AnchoredArray;
	mp = C;
	PV = mp * V;
	CV = Cum( V );
	CumPV = Cum( PV );

	num = Cum( PV ) - ValueWhen( start, Cum( PV ) );
	denom = CV - ValueWhen( start, CV );
	vwap = IIf( BarsSince(start) > 0, num / Max(1, denom), mp );
	return vwap;
}

//put any array to VWAPStart, when array=1 then VWAP is recalculated
//here recalculates VWAP on every Wednesday 
VWAPStart = (DayOfWeek()==3);
vwap = VWAP_Anchored(VWAPStart);
Plot( vwap, "VWAPselect" + _PARAM_VALUES(), colorOrange, styleThick );


//extar code - to Mark when recalculates VWAP
Value1=0;
Value1 = ValueWhen(VWAPStart, C);
Value1 = IIf(Value1!=0,Value1,Ref(Value1,-1));
Plot (Value1,"",colorWhite, styleline);
1 Like

Here is the updated "VWAP_Anchored" function:
Based on
https://www.amibroker.com/members/library/formula.php?id=853

function VWAP_Anchored(AnchoredArray) {
//Anchored VWAP
//AnchoredArray = when array=1 then VWAP is anchored
	Bars_so_far_today = 1 + BarsSince( AnchoredArray);
	TodayVolume = Sum(V,Bars_so_far_today);
	VWAP = Sum (C * V, Bars_so_far_today  ) / TodayVolume;

	return vwap;
}
3 Likes