//@Name:Two Colour MA //@Description: Draws an MA with an optional down colour // 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: Phil Tolhurst, ShareScope Support // Modified: Phil Tolhurst, ShareScope Support - 20-07-18 - Allowed for intraday data where the data exists but the OHLC is Undefined. //Globals - accessable by any part of the script. var settingsArray = new Array(); var settingsFile; var maTitleList = ["SMA","EMA","WMA","TMA","VVHF","VCMO","VIDYA","TEMA","HMA"]; var maList = ["Simple","Exponential","Weighted","Triangular","VariableVHF","VariableCMO","VIDYA","TEMA","Hull"]; var MA1choice = 1; var MA1type = 0; var MA1period = 25; var MA1colour1 = Colour.RGB(0,255,0); var MA1pen1 = 0; var MA1width1 = 1; var MA1downColour = 1; var MA1colour2 = Colour.RGB(255,0,0); var channelList = ["Envelopes","Bolinger Bands"]; var MA1channelChoice = 0; var MA1channelType = 0; var MA1channelValue = 2.5; var MA1channelColour = Colour.RGB(0,0,255); var MA1channelPen = 2; var MA1channelWidth = 0; var MA1channelFill = 1; var MA1channelFillColour = Colour.RGB(198,198,255); var setMA = 0; var dataList = ["Open","High","Low","Close","Typical","Median","Weighted"]; var dataSource = 3; var initCycle = 0; function init(status) { if (status == Loading || status == Editing) { MA1choice = storage.getAt(0); MA1type = storage.getAt(1); MA1period = storage.getAt(2); MA1colour1 = storage.getAt(3); MA1pen1 = storage.getAt(4); MA1width1 = storage.getAt(5); MA1downColour = storage.getAt(6); MA1colour2 = storage.getAt(7); MA1channelChoice = storage.getAt(8); MA1channelType = storage.getAt(9); MA1channelValue = storage.getAt(10); MA1channelColour = storage.getAt(11); MA1channelPen = storage.getAt(12); MA1channelWidth = storage.getAt(13); MA1channelFill = storage.getAt(14); MA1channelFillColour = storage.getAt(15); dataSource = storage.getAt(16); } if(status == Adding|| status == Editing) { var dlg = new Dialog("Moving Averages", 250, 127); dlg.addOkButton(); dlg.addCancelButton(); dlg.addGroupBox(15,5,175,50,""); dlg.addTickBox("MA1Val1",20,5,65,-1,"Moving Average",MA1choice); dlg.addDropList("MA1Val2",40,20,-1,-1,maList,"Type","",MA1type); dlg.addColLinePicker("MA1Val3",155,20,-1,-1,"","",MA1colour1,MA1pen1,MA1width1); dlg.addTickBox("MA1Val4",125,38,30,-1,"Down",MA1downColour); dlg.addColPicker("MA1Val5",155,35,-1,-1,"","",MA1colour2); dlg.addIntEdit("MA1Val6",40,38,-1,-1,"","MA period",MA1period,2,1000); dlg.addGroupBox(15,55,175,50,""); dlg.addTickBox("MA1Val7",20,55,40,-1,"Channel",MA1channelChoice); dlg.addDropList("MA1Val8",40,70,-1,-1,channelList,"Type","",MA1channelType); dlg.addColLinePicker("MA1Val9",155,70,-1,-1,"","",MA1channelColour,MA1channelPen,MA1channelWidth); dlg.addNumEdit("MA1Val10",40,85,-1,-1,"","%/devs",MA1channelValue,0.01,100); dlg.addTickBox("MA1Val11",125,88,30,-1,"Fill",MA1channelFill); dlg.addColPicker("MA1Val12",155,85,-1,-1,"","",MA1channelFillColour); dlg.addDropList("MA1Val13",60,110,-1,-1,dataList,"Data Source","",dataSource); if (dlg.show() == Dialog.Cancel) return false; MA1choice = dlg.getValue("MA1Val1")==true?1:0; MA1type = dlg.getValue("MA1Val2"); MA1width1 = dlg.getValue("MA1Val3").width; MA1colour1 = dlg.getValue("MA1Val3").colour; MA1pen1 = dlg.getValue("MA1Val3").pen; MA1downColour = dlg.getValue("MA1Val4")==true?1:0; MA1colour2= dlg.getValue("MA1Val5"); MA1period = dlg.getValue("MA1Val6"); MA1channelChoice = dlg.getValue("MA1Val7")==true?1:0; MA1channelType = dlg.getValue("MA1Val8"); MA1channelColour = dlg.getValue("MA1Val9").colour; MA1channelWidth = dlg.getValue("MA1Val9").width; MA1channelPen = dlg.getValue("MA1Val9").pen; MA1channelValue = dlg.getValue("MA1Val10"); MA1channelFill = dlg.getValue("MA1Val11")==true?1:0; MA1channelFillColour = dlg.getValue("MA1Val12"); dataSource = dlg.getValue("MA1Val13"); storage.setAt(0, MA1choice); storage.setAt(1, MA1type); storage.setAt(2, MA1period); storage.setAt(3, MA1colour1); storage.setAt(4, MA1pen1); storage.setAt(5, MA1width1); storage.setAt(6, MA1downColour); storage.setAt(7, MA1colour2); storage.setAt(8, MA1channelChoice); storage.setAt(9, MA1channelType); storage.setAt(10, MA1channelValue); storage.setAt(11, MA1channelColour); storage.setAt(12, MA1channelPen); storage.setAt(13, MA1channelWidth); storage.setAt(14, MA1channelFill); storage.setAt(15, MA1channelFillColour); storage.setAt(16, dataSource); } buttonHandle = createButton("Set", onButton0); setInfoText(MA1period+" "+maTitleList[MA1type]+"("+dataList[dataSource]+")"+(MA1channelChoice?"\n"+channelList[MA1channelType]+" "+MA1channelValue+(MA1channelType==0?"%":" Devs"):"")); } //What happens if the set button is clicked: function onButton0() { MA1choice = storage.getAt(0); MA1type = storage.getAt(1); MA1period = storage.getAt(2); MA1colour1 = storage.getAt(3); MA1pen1 = storage.getAt(4); MA1width1 = storage.getAt(5); MA1downColour = storage.getAt(6); MA1colour2 = storage.getAt(7); MA1channelChoice = storage.getAt(8); MA1channelType = storage.getAt(9); MA1channelValue = storage.getAt(10); MA1channelColour = storage.getAt(11); MA1channelPen = storage.getAt(12); MA1channelWidth = storage.getAt(13); MA1channelFill = storage.getAt(14); MA1channelFillColour = storage.getAt(15); dataSource = storage.getAt(16); var dlg = new Dialog("Moving Averages", 250, 125); dlg.addOkButton(); dlg.addCancelButton(); dlg.addGroupBox(15,5,175,50,""); dlg.addTickBox("MA1Val1",20,5,65,-1,"Moving Average",MA1choice); dlg.addDropList("MA1Val2",40,20,-1,-1,maList,"Type","",MA1type); dlg.addColLinePicker("MA1Val3",155,20,-1,-1,"","",MA1colour1,MA1pen1,MA1width1); dlg.addTickBox("MA1Val4",125,38,30,-1,"Down",MA1downColour); dlg.addColPicker("MA1Val5",155,35,-1,-1,"","",MA1colour2); dlg.addIntEdit("MA1Val6",40,38,-1,-1,"","MA period",MA1period,2,1000); dlg.addGroupBox(15,55,175,50,""); dlg.addTickBox("MA1Val7",20,55,40,-1,"Channel",MA1channelChoice); dlg.addDropList("MA1Val8",40,70,-1,-1,channelList,"Type","",MA1channelType); dlg.addColLinePicker("MA1Val9",155,70,-1,-1,"","",MA1channelColour,MA1channelPen,MA1channelWidth); dlg.addNumEdit("MA1Val10",40,85,-1,-1,"","%/devs",MA1channelValue,0.01,100); dlg.addTickBox("MA1Val11",125,88,30,-1,"Fill",MA1channelFill); dlg.addColPicker("MA1Val12",155,85,-1,-1,"","",MA1channelFillColour); dlg.addDropList("MA1Val13",60,110,-1,-1,dataList,"Data Source","",dataSource); if (dlg.show() == Dialog.Cancel) return false; MA1choice = dlg.getValue("MA1Val1")==true?1:0; MA1type = dlg.getValue("MA1Val2"); MA1width1 = dlg.getValue("MA1Val3").width; MA1colour1 = dlg.getValue("MA1Val3").colour; MA1pen1 = dlg.getValue("MA1Val3").pen; MA1downColour = dlg.getValue("MA1Val4")==true?1:0; MA1colour2= dlg.getValue("MA1Val5"); MA1period = dlg.getValue("MA1Val6"); MA1channelChoice = dlg.getValue("MA1Val7")==true?1:0; MA1channelType = dlg.getValue("MA1Val8"); MA1channelColour = dlg.getValue("MA1Val9").colour; MA1channelWidth = dlg.getValue("MA1Val9").width; MA1channelPen = dlg.getValue("MA1Val9").pen; MA1channelValue = dlg.getValue("MA1Val10"); MA1channelFill = dlg.getValue("MA1Val11")==true?1:0; MA1channelFillColour = dlg.getValue("MA1Val12"); dataSource = dlg.getValue("MA1Val13"); storage.setAt(0, MA1choice); storage.setAt(1, MA1type); storage.setAt(2, MA1period); storage.setAt(3, MA1colour1); storage.setAt(4, MA1pen1); storage.setAt(5, MA1width1); storage.setAt(6, MA1downColour); storage.setAt(7, MA1colour2); storage.setAt(8, MA1channelChoice); storage.setAt(9, MA1channelType); storage.setAt(10, MA1channelValue); storage.setAt(11, MA1channelColour); storage.setAt(12, MA1channelPen); storage.setAt(13, MA1channelWidth); storage.setAt(14, MA1channelFill); storage.setAt(15, MA1channelFillColour); storage.setAt(16, dataSource); setInfoText(MA1period+" "+maTitleList[MA1type]+"("+dataList[dataSource]+")"+(MA1channelChoice?"\n"+channelList[MA1channelType]+" "+MA1channelValue+(MA1channelType==0?"%":" Devs"):"")); draw(); } //This defines what happens when he study is added to a chart or we select a new share. function onNewChart() { draw(); } //Updates the graph if the data is updated. function onNewBarUpdate() { draw(); } //Updates the graph if the data is updated. function onZoom() { draw(); } //Draws a new line depending which button has been clicked on function draw() { if (bars != undefined && bars.length>=1 && bars[0].close!=undefined) { clearDisplay(); var mainMAarray = new Array(); var goodData = 0; if (MA1type == 8) { var sqrtperiod1 = Math.round(Math.sqrt(MA1period)); var ma1 = new MA(MA1period/2, MA.Weighted); var ma2 = new MA(MA1period, MA.Weighted); var ma3 = new MA(sqrtperiod1, MA.Weighted); for (var i=0; i=0;j--) { lineTo(j,mainMAarray[j]*(1-(MA1channelValue/100))); } lineTo(0,mainMAarray[0]*(1-(MA1channelValue/100))); endPath(); fillPath(); } } //draw bolinger bands if (MA1channelType==1) { var upBB = new Array(); var downBB = new Array(); var sumPmMA=0 setPenStyle(MA1channelPen,MA1channelWidth,MA1channelColour); { for(var i=0;i=MA1period-1;j--) { lineTo(j,downBB[j]); } lineTo(MA1period-1,upBB[MA1period-1]); endPath(); fillPath(); } } } } } 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; } //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; }