//@Name:Ord Volume //@Description:Draws the Ord Volume indicator on the graph using a zig-zag line. Volume flags are coloured if they rise above or fall below the set percentage. //@Type:Historical //@Env:Production // Care has been taken in preparing this code but it is provided without guarantee. // You are welcome to modify and extend it. Please add your name as a modifier if you distribute it. //Coded by: Richard Chiesa, ShareScript Support var zigzagPerc = 15; //zig-zag percentage var volDiff = 50; var zigzagCol = Colour.LightBlue; var zigzagStyle = 0; var zigzagWidth = 1; var textCol = Colour.Black; var riseCol = Colour.LightGreen; var fallCol = Colour.LightRed; var rounding = 2; var zz; function init(status) { if (status == Loading || status == Editing) { zigzagPerc = storage.getAt(0); volDiff = storage.getAt(1); zigzagCol = storage.getAt(2); zigzagStyle = storage.getAt(3); zigzagWidth = storage.getAt(4); riseCol = storage.getAt(5); fallCol = storage.getAt(6); rounding = storage.getAt(7); } if (status == Adding || status == Editing) { dlg = new Dialog("Select Period Length", 180, 170); dlg.addOkButton(); dlg.addCancelButton(); dlg.addNumEdit("NUM1",8,-1,-1,-1,"","% Zig-Zag",zigzagPerc,1,100); dlg.addNumEdit("NUM2",8,-1,-1,-1,"","% Vol.Diff.",volDiff,1,200); dlg.addColLinePicker("CL1",8,-1,-1,-1,"","Zig-Zag Line",zigzagCol,zigzagStyle,zigzagWidth); dlg.addColPicker("COL1",8,-1,-1,-1,"","Rise Colour",riseCol); dlg.addColPicker("COL2",8,-1,-1,-1,"","Fall Colour",fallCol); dlg.addIntEdit("INT1",40,-1,-1,-1,"Round to","decimal places.",rounding,0,5); dlg.addText(8,110,160,56,"The % Zig-Zag determines the size of the swings: a new swing will be drawn only when the price"+ " reverses by the set percentage from the previous high or low.\nThe volume labels will be coloured if the"+ " swing's average volume is higher or lower than any one of the two previous swings."); if (dlg.show()==Dialog.Cancel) return false; zigzagPerc = dlg.getValue("NUM1"); volDiff = dlg.getValue("NUM2"); zigzagCol = dlg.getValue("CL1").colour; zigzagStyle = dlg.getValue("CL1").pen; zigzagWidth = dlg.getValue("CL1").width; riseCol = dlg.getValue("COL1"); fallCol = dlg.getValue("COL2"); rounding = dlg.getValue("INT1"); storage.setAt(0, zigzagPerc); storage.setAt(1, volDiff); storage.setAt(2, zigzagCol); storage.setAt(3, zigzagStyle); storage.setAt(4, zigzagWidth); storage.setAt(5, riseCol); storage.setAt(6, fallCol); storage.setAt(7, rounding); } } function onNewChart() { clearDisplay(); var share = getCurrentShare(); if (getBarLength()=="1d") var data = share.getPriceArray(); else if (getBarLength()=="1w") var data = share.getWeeklyBarArray(); else if (getBarLength()=="1m") var data = share.getMonthlyBarArray(); else return; zz = zigZagCalcHighLow(data,zigzagPerc/100); draw(); } function draw() { clearDisplay(); setLayer(Layer.Top); //start drawing the zig-zag line setPenStyle(zigzagStyle,zigzagWidth,zigzagCol); setBrushColour(Colour.Gray); setFontStyle("Arial",12,textCol); moveTo(zz[0].index, zz[0].value); for (var i=1;izz[i-1].value)?BoxAlign.Above:BoxAlign.Below),TextAlign.Centre); if (i>1 && zz[i-1].avVol && zz[i-2].avVol && (zz[i].avVol/zz[i-1].avVol-1>volDiff/100 || zz[i].avVol/zz[i-2].avVol-1>volDiff/100)) setBrushColour(riseCol); else if (i>1 && zz[i-1].avVol && zz[i-2].avVol && (zz[i].avVol/zz[i-1].avVol-1<-volDiff/100 || zz[i].avVol/zz[i-2].avVol-1<-volDiff/100)) setBrushColour(fallCol); else setBrushColour(Colour.Gray); lineTo(zz[i].index, zz[i].value); setFontColour(Colour.Black); drawText((zz[i].index+zz[i-1].index)/2,(zz[i].value+zz[i-1].value)/2,(zz[i].avVol/1000000).toFixed(rounding),BoxAlign.Centre|BoxAlign.VCentre,TextAlign.Centre,1,1); moveTo(zz[i].index, zz[i].value); } } function zigZagCalcHighLow(data,zzPerc) { var zz = []; var hh,ll; //start loop to calculate zig-zag line values zz[0] = {index:0,value:data[0].close,avVol:0}; for (var i=0;idata[i].low) ll = data[i].low; if (hh/zz[0].value-1>=zzPerc) { zz[1] = {index:i,value:data[i].high,avVol:0}; continue; } else if (1-ll/zz[0].value>=zzPerc) { zz[1] = {index:i,value:data[i].low,avVol:0}; continue; } } else { //if the line is moving up if (zz[zz.length-1].value>zz[zz.length-2].value) { if (1-data[i].low/zz[zz.length-1].value>=zzPerc) //check for reversals { for (var j=zz[zz.length-2].index+1;j<=zz[zz.length-1].index;j++) zz[zz.length-1].avVol += data[j].volume; zz[zz.length-1].avVol /= (zz[zz.length-1].index - zz[zz.length-2].index); zz[zz.length] = {index:i,value:data[i].low,avVol:0}; continue; } else if (data[i].high>zz[zz.length-1].value) //otherwise check for higher highs { zz[zz.length-1].value = data[i].high; zz[zz.length-1].index = i; } } else //if the line is moving down { if (data[i].high/zz[zz.length-1].value-1>=zzPerc) //check for reversals { for (var j=zz[zz.length-2].index+1;j<=zz[zz.length-1].index;j++) zz[zz.length-1].avVol += data[j].volume; zz[zz.length-1].avVol /= (zz[zz.length-1].index - zz[zz.length-2].index); zz[zz.length] = {index:i,value:data[i].high,avVol:0}; continue; } else if (data[i].low