//@Name:MA Clouds //@Description:Fills the space between two MAs //Author: Richard Chiesa, ShareScope Support // 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. var maPeriod1 = 15; var maPeriod2 = 30; var maType1 = 0; var maType2 = 0; var maCol1 = Colour.Green; var maCol2 = Colour.Red; var fillCol1 = Colour.RGB(0,125,0); var fillCol2 = Colour.RGB(125,0,0); var maTitleList = ["SMA","EMA","WMA","TMA","VVHF","VCMO","VIDYA","HMA","TEMA"]; var maList = ["Simple","Exponential","Weighted","Triangular","VariableVHF","VariableCMO","VIDYA","Hull","TEMA"]; var dataList = ["Open","High","Low","Close","Typical","Median","Weighted"]; var dataSource1 = 3; var dataSource2 = 3; function init(status) { if (status == Loading || status == Editing) { maPeriod1 = storage.getAt(0); maPeriod2 = storage.getAt(1); maType1 = storage.getAt(2); maType2 = storage.getAt(3); maCol1 = storage.getAt(4); maCol2 = storage.getAt(5); fillCol1 = storage.getAt(6); fillCol2 = storage.getAt(7); dataSource1 = storage.getAt(8); dataSource2 = storage.getAt(9); } if(status == Adding|| status == Editing) { drawDialogBox(); } buttonHandle = createButton("Settings", onButton0); setInfoText(maPeriod1+" "+maTitleList[maType1]+"("+dataList[dataSource1]+") / "+maPeriod2+" "+maTitleList[maType2]+"("+dataList[dataSource2]+")"); }//"\n"+dataList[dataSource1]+" / " function onButton0() { maPeriod1 = storage.getAt(0); maPeriod2 = storage.getAt(1); maType1 = storage.getAt(2); maType2 = storage.getAt(3); maCol1 = storage.getAt(4); maCol2 = storage.getAt(5); fillCol1 = storage.getAt(6); fillCol2 = storage.getAt(7); dataSource = storage.getAt(8); dataSource = storage.getAt(9); drawDialogBox(); setInfoText(maPeriod1+" "+maTitleList[maType1]+"("+dataList[dataSource1]+") /"+maPeriod2+" "+maTitleList[maType2]+"("+dataList[dataSource2]+")"); draw(); } function drawDialogBox() { var dlg = new Dialog("Moving Average Clouds", 365, 140); dlg.addOkButton(); dlg.addCancelButton(); dlg.addGroupBox(10,5,280,35,"Moving Average 1"); dlg.addDropList("MA1Val1",35,20,-1,-1,maList,"Type","",maType1); dlg.addIntEdit("MA1Val3",155,20,-1,-1,"Period length","",maPeriod1,2,1000); dlg.addDropList("dataSource1",195,20,50,-1,dataList,"","",dataSource1); dlg.addColPicker("maColour1",255,20,-1,-1,"","",maCol1); dlg.addGroupBox(10,45,280,35,"Moving Average 2"); dlg.addDropList("MA2Val1",35,60,-1,-1,maList,"Type","",maType2); dlg.addIntEdit("MA2Val3",155,60,-1,-1,"Period length","",maPeriod2,2,1000); dlg.addDropList("dataSource2",195,60,50,-1,dataList,"","",dataSource2); dlg.addColPicker("maColour2",255,60,-1,-1,"","",maCol2); dlg.addGroupBox(10,85,100,50,"Cloud colours"); dlg.addColPicker("MA1Val2",20,95,-1,-1,"","MA1 above MA2",fillCol1); dlg.addColPicker("MA2Val2",20,115,-1,-1,"","MA1 below MA2 ",fillCol2); if (dlg.show() == Dialog.Cancel) return false; maPeriod1 = dlg.getValue("MA1Val3"); maPeriod2 = dlg.getValue("MA2Val3"); maType1 = dlg.getValue("MA1Val1"); maType2 = dlg.getValue("MA2Val1"); fillCol1= dlg.getValue("MA1Val2"); fillCol2 = dlg.getValue("MA2Val2"); maCol1 =dlg.getValue("maColour1"); maCol2 =dlg.getValue("maColour2"); dataSource1 = dlg.getValue("dataSource1"); dataSource2 = dlg.getValue("dataSource2"); storage.setAt(0, maPeriod1); storage.setAt(1, maPeriod2); storage.setAt(2, maType1); storage.setAt(3, maType2); storage.setAt(4, maCol1); storage.setAt(5, maCol2); storage.setAt(6, fillCol1); storage.setAt(7, fillCol2); storage.setAt(8, dataSource1); storage.setAt(9, dataSource2); } function onNewChart() { draw(); } function onNewBarUpdate() { draw() } function draw() { clearDisplay(); if (maType1==8) var ma1 = new TEMA(maPeriod1); else var ma1 = new MA(maPeriod1,maType1); if (maType2==8) var ma2 = new TEMA(maPeriod2); else var ma2 = new MA(maPeriod2,maType2); var maValues1 = []; var maValues2 = []; for (var i=0;iline2[i] && line1[i-1]line2[i-1])) { if (line1[i]line2[i-1]) setBrushColour(upCol3); else setBrushColour(downCol4); //x & y are the the coordinates of the exact crossing point of the two lines var x = (line1[i] - line2[i] + i * (line2[i]-line2[i-1]-line1[i]+line1[i-1])) / (line2[i]-line2[i-1]-line1[i]+line1[i-1]); var y = (line1[i]-line1[i-1]) * (x - i) + line1[i]; beginPath(); moveTo(startX,startY); for (var j=Math.floor(startX+1);j=Math.floor(startX+1);j--) lineTo(j,line2[j]); lineTo(startX,startY); fillPath(); //set x & y as the new starting point for the next cloud startX = x; startY = y; } } //fill the last, unfinished cloud if (line1[line1.length-1]>line2[line2.length-1]) setBrushColour(upCol3); else setBrushColour(downCol4); beginPath(); moveTo(startX,startY); for (var j=Math.floor(startX+1);j=Math.floor(startX+1);j--) lineTo(j,line2[j]); lineTo(startX,startY); fillPath(); } //returns the correct type of data to be used in the MA calculation function getData(x, type) { if (type == 0) return x.open; else if (type == 1) return x.high; else if (type == 2) return x.low; else if (type == 3) return x.close; else if (type == 4) return (x.high+x.low+x.close)/3; else if (type == 5) return (x.high+x.low)/2; else return (x.open+x.high+x.low+x.close)/4; } function TEMA(p) { this.period = p; this.emaVal1; this.emaVal2; this.emaVal3; } TEMA.prototype.getNext = function (price) { var ma1 = new MA(this.period, MA.Exponential); var ma2 = new MA(this.period, MA.Exponential); var ma3 = new MA(this.period, MA.Exponential) if (this.emaVal1 != undefined) this.emaVal1 = ma1.getNext(this.emaVal1); this.emaVal1 = ma1.getNext((price.high+price.low+price.close)/3); if (this.emaVal2 != undefined) this.emaVal2 = ma2.getNext(this.emaVal2); this.emaVal2 = ma2.getNext(this.emaVal1); if (this.emaVal3 != undefined) this.emaVal3 = ma3.getNext(this.emaVal3); this.emaVal3 = ma3.getNext(this.emaVal2); var tema = 3*this.emaVal1-3*this.emaVal2+this.emaVal3; return tema; }