-- More information about this indicator can be found at: -- http://fxcodebase.com/code/viewtopic.php?f=28&t=61403&start=30 --+------------------------------------------------------------------+ --| Copyright © 2018, Gehtsoft USA LLC | --| http://fxcodebase.com | --+------------------------------------------------------------------+ --| Developed by : Mario Jemic | --| mario.jemic@gmail.com | --+------------------------------------------------------------------+ --| Support our efforts by donating | --| Paypal: https://goo.gl/9Rj74e | --| BitCoin : 15VCJTLaz12Amr7adHSBtL9v8XomURo9RF | --| BitCoin Cash: 1BEtS465S3Su438Kc58h2sqvVvHK9Mijtg | --| Ethereum : 0x8C110cD61538fb6d7A2B47858F0c0AaBd663068D | --| LiteCoin : LLU8PSY2vsq7B9kRELLZQcKf5nJQrdeqwD | --+------------------------------------------------------------------+ -- Indicator profile initialization routine -- Defines indicator profile properties and indicator parameters function Init() indicator:name("MTF MCP Dashboard template"); indicator:description(""); indicator:requiredSource(core.Bar); indicator:type(core.Oscillator); indicator.parameters:addGroup("Calculation"); indicator.parameters:addInteger("K", "K Period","", 5, 2, 1000); indicator.parameters:addInteger("SD", "SD Period","", 3, 2, 1000); indicator.parameters:addInteger("D", "D Period","", 3, 2, 1000); indicator.parameters:addString("MVAT_K", "K smoothing","", "MVA"); indicator.parameters:addStringAlternative("MVAT_K", "MVA","", "MVA"); indicator.parameters:addStringAlternative("MVAT_K", "EMA","", "EMA"); indicator.parameters:addStringAlternative("MVAT_K", "FS","", "FS"); indicator.parameters:addString("MVAT_D", "D smoothing","", "MVA"); indicator.parameters:addStringAlternative("MVAT_D", "MVA","", "MVA"); indicator.parameters:addStringAlternative("MVAT_D", "EMA", "", "EMA"); indicator.parameters:addDouble("OB", "OB Level","", 80); indicator.parameters:addDouble("OS", "OS Level","", 20); indicator.parameters:addBoolean("Cross", "Cross Only", "", true); Parameters (1 , "D1", true ); Parameters (2 , "H4", true ); Parameters (3 , "H1", true ); for i= 1 ,20, 1 do indicator.parameters:addGroup(i..". Currency Pair "); Add(i); end indicator.parameters:addGroup( "Style"); indicator.parameters:addInteger("Size", "Label Size as percentage", "", 8); indicator.parameters:addColor("Color", "Label Color", "Label Color", core.COLOR_LABEL ); indicator.parameters:addColor("Up", "Up Color", "Label Color", core.rgb(0, 255, 0)); indicator.parameters:addColor("Down", "Down Color", "Label Color", core.rgb(255, 0, 0)); indicator.parameters:addColor("Zone", "OB/OS Color", "Label Color", core.rgb(0, 0, 255)); end function getInstrumentList() local list={}; local point={}; local count = 0; local row, enum; enum = core.host:findTable("offers"):enumerator(); row = enum:next(); while row ~= nil do count = count + 1; list[count] = row.Instrument; point[count] = row.PointSize; row = enum:next(); end return list, count,point; end function Add(id) local Init={"EUR/USD","USD/JPY", "GBP/USD","USD/CHF", "EUR/CHF" , "AUD/USD","USD/CAD", "NZD/USD", "EUR/GBP", "EUR/JPY" , "GBP/JPY", "CHF/JPY","GBP/CHF", "EUR/AUD", "EUR/CAD" , "AUD/CAD", "AUD/JPY","CAD/JPY", "NZD/JPY", "GBP/CAD" }; if id <= 5 then indicator.parameters:addBoolean("Dodaj"..id, "Use This Slot", "", true); else indicator.parameters:addBoolean("Dodaj"..id, "Use This Slot", "", true); end indicator.parameters:addString("Pair" .. id, "Pair", "", Init[id]); indicator.parameters:setFlag("Pair" .. id, core.FLAG_INSTRUMENTS); end function Parameters (id , FRAME, flag ) indicator.parameters:addGroup(id ..". Time Frame"); indicator.parameters:addBoolean("On"..id , "Show This Time Frame", "", flag); indicator.parameters:addString("TF"..id, "Time frame", "", FRAME); indicator.parameters:setFlag("TF"..id, core.FLAG_PERIODS); end -- Indicator instance initialization routine -- Processes indicator parameters and creates output streams -- TODO: Refine the first period calculation for each of the output streams. -- TODO: Calculate all constants, create instances all subsequent indicators and load all required libraries -- Parameters block local Size; local first; local source = nil; local Color, Up, Down,Neutral; local Indicator={}; local Num; local loading={}; local SourceData={}; local Point={}; local Pair={}; local Count; local TF={}; local Zone; local id; local Dodaj={}; local OB, OS; local K, SD, D, MVAT_K, MVAT_D; local Cross; -- Routine function Prepare(nameOnly) local name = profile:id() .. "(" .. instance.source:name() .. ")"; instance:name(name); if (nameOnly) then return; end source = instance.source; first = source:first(); Size=instance.parameters.Size; Color=instance.parameters.Color; Up=instance.parameters.Up; Down=instance.parameters.Down; Zone= instance.parameters.Zone; Cross= instance.parameters.Cross; K= instance.parameters.K; SD= instance.parameters.SD; D= instance.parameters.D; MVAT_K= instance.parameters.MVAT_K; MVAT_D= instance.parameters.MVAT_D; OB= instance.parameters.OB; OS= instance.parameters.OS; Num=0; for i = 1 , 13 , 1 do if instance.parameters:getBoolean ("On"..i) then Num = Num+1; TF[Num]= instance.parameters:getString ("TF"..i); end end Count=0; for i= 1,20 , 1 do Dodaj[i]=instance.parameters:getBoolean("Dodaj" .. i); if Dodaj[i] then Count=Count+1; Pair[Count]= instance.parameters:getString ("Pair"..i); Point[Count]= core.host:findTable("offers"):find("Instrument", Pair[Count]).PointSize; end end Id=0; local Test; for j = 1, Count, 1 do SourceData[j] = {}; Indicator[j] = {}; loading[j] = {}; for i = 1, Num, 1 do Test = core.indicators:create("STOCHASTIC", source ,K, SD, D, MVAT_K, MVAT_D); first= Test.DATA:first()*2; Id=Id+1; SourceData[j][i] = core.host:execute("getSyncHistory", Pair[j], TF[i], source:isBid(), math.min(first*2, 300) , 2000 + Id , 1000 + Id); loading[j][i] = true; Indicator[j][i] = core.indicators:create("STOCHASTIC", SourceData[j][i], K, SD, D, MVAT_K, MVAT_D ); end end instance:setLabelColor(Color); instance:ownerDrawn(true); core.host:execute ("setTimer", 1, 1); end function ReleaseInstance() core.host:execute ("killTimer", 1); end function getInstrumentList() local list={}; local point={}; local count = 0; local row, enum; enum = core.host:findTable("offers"):enumerator(); row = enum:next(); while row ~= nil do count = count + 1; list[count] = row.Instrument; point[count] = row.PointSize; row = enum:next(); end return list, count,point; end -- Indicator calculation routine -- TODO: Add your code for calculation output values function Update(period) end function AsyncOperationFinished(cookie) local i,j; local Id=0; for j = 1, Count, 1 do for i = 1, Num, 1 do Id=Id+1; if cookie == (1000 + Id) then loading[j][i] = true; elseif cookie == (2000 + Id) then loading[j][i] = false; end end end local FLAG=false; local Number=0; for j = 1, Count, 1 do for i = 1, Num, 1 do if loading[j][i] then FLAG= true; Number=Number+1; end end end if cookie== 1 and not FLAG then for j = 1, Count, 1 do for i = 1, Num, 1 do Indicator[j][i]:update(core.UpdateLast); end end end if FLAG then core.host:execute ("setStatus", " Loading "..((Count*Num) - Number) .. " / " .. (Count*Num) ); else core.host:execute ("setStatus", "") instance:updateFrom(0); end return core.ASYNC_REDRAW ; end function round(num, idp) if idp and idp>0 then local mult = 10^idp return math.floor(num * mult + 0.5) / mult end return math.floor(num + 0.5) end local initDraw = false; function Draw(stage, context) if stage ~= 2 then return ; end local FLAG=false; local Number=0; for j = 1, Count, 1 do for i = 1, Num, 1 do if loading[j][i] then FLAG= true; Number=Number+1; end end end if FLAG then return; end core.host:execute ("setStatus", " Loaded "); top, bottom = context:top(), context:bottom(); left, right = context:left(), context:right(); local Y=5; local X=5; if round(Count/5, 0) *5 < Count then Y=round(Count/5, 0)+1; else Y=round(Count/5, 0); end xGap= (right-left)/(X); yGap= (bottom-top)/(Y); context:createFont (2, "Arial",(xGap/100)*Size, (yGap/100)*Size , 0); context:createFont (3, "Wingdings",(xGap/100)*Size, (yGap/100)*Size , 0); context:createPen (1, context.SOLID, 1, Color); --context:createFont (objid, faceName, width, height, style) local Row=1; local Loop=0; local Column=1; local Cell=0; for i = 1, Y, 1 do context:drawLine (1, context:left () + xGap *i,context:top (), context:left ()+ xGap *i, context:bottom ()); -- v Line for j = 1, X, 1 do Cell=Cell+1; --Count == Cell context:drawLine (1, context:left (),context:top()+(j)*yGap, context:right (), context:top()+(j)*yGap); -- H Line width, height = context:measureText (2, Pair[Cell], context.CENTER ); context:drawText (2, Pair[Cell], Color, -1, context:left () + xGap *(j)-width , context:top()+(i-1)*yGap , context:left () + xGap *(j), context:top()+(i-1)*yGap+height, context.CENTER, 0); for k= 1, Num, 1 do width, height = context:measureText (2, TF[k], context.CENTER ); context:drawText (2, TF[k], Color, -1, context:left () + xGap *(j-1)+(xGap/Num)*(k-1)+(xGap/Num)/2-width/2 , context:top()+(i)*yGap-height , context:left () + xGap *(j-1)+(xGap/Num)*(k-1)+(xGap/Num)/2+width/2, context:top()+(i)*yGap, context.CENTER, 0); --end -- for k= 1, Num, 1 do local Signal=0; local Value=0; local Bottom=(yGap/100)*Size; local Top=yGap -(yGap/100)*Size; local Correction; local iZone=-1; if Indicator[Cell][k]~= nil and Indicator[Cell][k].D:hasData(Indicator[Cell][k].D:size()-1) and Indicator[Cell][k].D:hasData(Indicator[Cell][k].D:size()-2) then Value= Indicator[Cell][k].D[Indicator[Cell][k].D:size()-1]; Correction=Bottom -((Bottom -Top )/100)*Value; if Indicator[Cell][k].K[Indicator[Cell][k].K:size()-1] >Indicator[Cell][k].D[Indicator[Cell][k].D:size()-1] and (( Indicator[Cell][k].K[Indicator[Cell][k].K:size()-2] <= Indicator[Cell][k].D[Indicator[Cell][k].D:size()-2]and Cross )or not Cross ) then Signal=1; elseif Indicator[Cell][k].K[Indicator[Cell][k].K:size()-1] < Indicator[Cell][k].D[Indicator[Cell][k].D:size()-1] and (( Indicator[Cell][k].K[Indicator[Cell][k].K:size()-2] >= Indicator[Cell][k].D[Indicator[Cell][k].D:size()-2] and Cross )or not Cross ) then Signal=-1; end if Value> OB or Value < OS then iZone=Zone; end if Signal ~= 0 then width, height = context:measureText (3, "\225", context.CENTER ); if Signal== 1 then context:drawText (3, "\225", Up, iZone, context:left () + xGap *(j-1)+(xGap/Num)*(k-1)+(xGap/Num)/2-width/2 , context:top()+(i)*yGap-height/2 - Correction, context:left () + xGap *(j-1)+(xGap/Num)*(k-1)+(xGap/Num)/2+width/2, context:top()+(i)*yGap+height/2 - Correction , context.CENTER, 0); else context:drawText (3, "\226", Down, iZone, context:left () + xGap *(j-1)+(xGap/Num)*(k-1)+(xGap/Num)/2-width/2 , context:top()+(i)*yGap-height/2 - Correction , context:left () + xGap *(j-1)+(xGap/Num)*(k-1)+(xGap/Num)/2+width/2, context:top()+(i)*yGap+height/2 - Correction , context.CENTER, 0); end end end end end end end