-- More information about this indicator can be found at: -- http://fxcodebase.com/code/viewtopic.php?f=17&t=63071 --+------------------------------------------------------------------+ --| 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 | --+------------------------------------------------------------------+ --| Patreon : https://goo.gl/GdXWeN | --| BitCoin : 15VCJTLaz12Amr7adHSBtL9v8XomURo9RF | --| BitCoin Cash: 1BEtS465S3Su438Kc58h2sqvVvHK9Mijtg | --| Ethereum : 0x8C110cD61538fb6d7A2B47858F0c0AaBd663068D | --| LiteCoin : LLU8PSY2vsq7B9kRELLZQcKf5nJQrdeqwD | --+------------------------------------------------------------------+ -- The indicator corresponds to the Ichimoku Kinko Hyo indicator in MetaTrader. -- Indicator profile initialization routine -- Defines indicator profile properties and indicator parameters function Init() indicator:name(resources:get("name")); indicator:description(resources:get("description")); indicator:requiredSource(core.Bar); indicator:type(core.Indicator); indicator:setTag("group", "Trend"); indicator.parameters:addGroup("Calculation"); indicator.parameters:addInteger("X", resources:get("param_X_name"), resources:get("param_X_description"), 9, 1, 10000); indicator.parameters:addInteger("Y", resources:get("param_Y_name"), resources:get("param_Y_description"), 26, 1, 10000); indicator.parameters:addInteger("Z", resources:get("param_Z_name"), resources:get("param_Z_description"), 52, 1, 10000); indicator.parameters:addBoolean("ShowPeriod", resources:get("param_ShowPeriod_name"), resources:get("param_ShowPeriod_description"),true); indicator.parameters:addGroup("Style"); indicator.parameters:addColor("clrTS", string.format(resources:get("R_color_of_PARAM_name"), resources:get("param_TS_line_name")), string.format(resources:get("R_color_of_PARAM_description"), resources:get("param_TS_line_desc")), core.rgb(255, 255, 0)); indicator.parameters:addInteger("widthTS", string.format(resources:get("R_width_of_PARAM_name"), resources:get("param_TS_line_name")), string.format(resources:get("R_width_of_PARAM_description"), resources:get("param_TS_line_desc")), 1, 1, 5); indicator.parameters:addInteger("styleTS", string.format(resources:get("R_style_of_PARAM_name"), resources:get("param_TS_line_name")), string.format(resources:get("R_style_of_PARAM_description"), resources:get("param_TS_line_desc")), core.LINE_SOLID); indicator.parameters:setFlag("styleTS", core.FLAG_LEVEL_STYLE); indicator.parameters:addColor("clrKS", string.format(resources:get("R_color_of_PARAM_name"), resources:get("param_KS_line_name")), string.format(resources:get("R_color_of_PARAM_description"), resources:get("param_KS_line_desc")), core.rgb(0, 255, 255)); indicator.parameters:addInteger("widthKS", string.format(resources:get("R_width_of_PARAM_name"), resources:get("param_KS_line_name")), string.format(resources:get("R_width_of_PARAM_description"), resources:get("param_KS_line_desc")), 1, 1, 5); indicator.parameters:addInteger("styleKS", string.format(resources:get("R_style_of_PARAM_name"), resources:get("param_KS_line_name")), string.format(resources:get("R_style_of_PARAM_description"), resources:get("param_KS_line_desc")), core.LINE_SOLID); indicator.parameters:setFlag("styleKS", core.FLAG_LEVEL_STYLE); indicator.parameters:addColor("clrCS", string.format(resources:get("R_color_of_PARAM_name"), resources:get("param_CS_line_name")), string.format(resources:get("R_color_of_PARAM_description"), resources:get("param_CS_line_desc")), core.rgb(0, 255, 0)); indicator.parameters:addInteger("widthCS", string.format(resources:get("R_width_of_PARAM_name"), resources:get("param_CS_line_name")), string.format(resources:get("R_width_of_PARAM_description"), resources:get("param_CS_line_desc")), 1, 1, 5); indicator.parameters:addInteger("styleCS", string.format(resources:get("R_style_of_PARAM_name"), resources:get("param_CS_line_name")), string.format(resources:get("R_style_of_PARAM_description"), resources:get("param_CS_line_desc")), core.LINE_SOLID); indicator.parameters:setFlag("styleCS", core.FLAG_LEVEL_STYLE); indicator.parameters:addColor("clrSSA", string.format(resources:get("R_color_of_PARAM_name"), resources:get("param_SSA_line_name")), string.format(resources:get("R_color_of_PARAM_description"), resources:get("param_SSA_line_desc")), core.rgb(255, 0, 0)); indicator.parameters:addInteger("widthSSA", string.format(resources:get("R_width_of_PARAM_name"), resources:get("param_SSA_line_name")), string.format(resources:get("R_width_of_PARAM_description"), resources:get("param_SSA_line_desc")), 1, 1, 5); indicator.parameters:addInteger("styleSSA", string.format(resources:get("R_style_of_PARAM_name"), resources:get("param_SSA_line_name")), string.format(resources:get("R_style_of_PARAM_description"), resources:get("param_SSA_line_desc")), core.LINE_SOLID); indicator.parameters:setFlag("styleSSA", core.FLAG_LEVEL_STYLE); indicator.parameters:addColor("clrSSB", string.format(resources:get("R_color_of_PARAM_name"), resources:get("param_SSB_line_name")), string.format(resources:get("R_color_of_PARAM_description"), resources:get("param_SSB_line_desc")), core.rgb(0, 0, 255)); indicator.parameters:addInteger("widthSSB", string.format(resources:get("R_width_of_PARAM_name"), resources:get("param_SSB_line_name")), string.format(resources:get("R_width_of_PARAM_description"), resources:get("param_SSB_line_desc")), 1, 1, 5); indicator.parameters:addInteger("styleSSB", string.format(resources:get("R_style_of_PARAM_name"), resources:get("param_SSB_line_name")), string.format(resources:get("R_style_of_PARAM_description"), resources:get("param_SSB_line_desc")), core.LINE_SOLID); indicator.parameters:setFlag("styleSSB", core.FLAG_LEVEL_STYLE); indicator.parameters:addInteger("transp", resources:get("param_transp_name"), resources:get("param_transp_description"), 80, 0, 100); end -- Indicator instance initialization routine -- Processes indicator parameters and creates output streams -- Parameters block local Tenkan; local Kijun; local Senkou; local ShowPeriod; local firstPeriod; local source = nil; local TSp,KSp; local csFirst = nil; local tsFirst = nil; local ksFirst = nil; local saFirst = nil; local sbFirst = nil; local chFirst = nil; -- Streams block local TS = nil; local KS = nil; local CS = nil; local SA = nil; local SB = nil; local SA1 = nil; local SB2 = nil; local clrSSA, clrSSB; if ffi then local ffi_source; local ffi_TS; local ffi_KS; local ffi_CS; local ffi_SA; local ffi_SB; local ffi_SA1; local ffi_SB1; local ffi_TSp; local ffi_KSp; local ffi_source_close; end -- Routine function Prepare(nameOnly) Tenkan = instance.parameters.X; Kijun = instance.parameters.Y; Senkou = instance.parameters.Z; ShowPeriod = instance.parameters.ShowPeriod; source = instance.source; firstPeriod = source:first(); local name = profile:id() .. "(" .. source:name() .. ", " .. Tenkan .. ", " .. Kijun .. ", " .. Senkou .. ")"; instance:name(name); if (nameOnly) then return; end TS = instance:addStream("TS", core.Line, name .. ".TS", "TS", instance.parameters.clrTS, firstPeriod + Tenkan - 1) TS:setWidth(instance.parameters.widthTS); TS:setStyle(instance.parameters.styleTS); KS = instance:addStream("KS", core.Line, name .. ".KS", "KS", instance.parameters.clrKS, firstPeriod + Kijun - 1) KS:setWidth(instance.parameters.widthKS); KS:setStyle(instance.parameters.styleKS); CS = instance:addStream("CS", core.Line, name .. ".CS", "CS", instance.parameters.clrCS, firstPeriod, -Kijun) CS:setWidth(instance.parameters.widthCS); CS:setStyle(instance.parameters.styleCS); SA = instance:addStream("SA", core.Line, name .. ".SA", "SAA", instance.parameters.clrSSA, math.max(TS:first(), KS:first()), Kijun) SA:setWidth(instance.parameters.widthSSA); SA:setStyle(instance.parameters.styleSSA); SB = instance:addStream("SB", core.Line, name .. ".SB", "SBB", instance.parameters.clrSSB, firstPeriod + Senkou - 1, Kijun) SB:setWidth(instance.parameters.widthSSB); SB:setStyle(instance.parameters.styleSSB); --[[ label -> The short name of the stream. id -> The stream identifier. The identifier must contain only English letters or digits and must be unique within the instance of the indicator. font -> The name of the font which is used to draw the text labels. size -> The size of the font. The size is expressed in points (a point is 1/72 of inch). halign -> The horizontal alignment of the text labels. The possible values are: core.H_Left -> The text label is located at left of the data/time line. The right border of the text label touches the date/time line. core.H_Center -> The text label is centered against the date/time line. core.H_Right -> The text label is located at right of the data/time line. The left border of the text label touches the date/time line. valign -> The vertical alignment of the text labels. Can be core.V_Top, core.V_Center or core.V_Bottom core.V_Top -> The text label is located at above the price line. The bottom border of the text label touches the price line. core.V_Center -> The text label is centered against the price line. core.V_Bottom -> The text label is located below the price line. The top border of the text label touches the price line. color -> The color of the text label. extent -> Optional. The parameter specifies the difference between the source size and the output size. The positive number means that the output is longer than the source, the negative number means that the output is shorter than the source. The default value is 0. ]] TSp = instance:createTextOutput ("TSp", "TSp", "Wingdings", 9, core.H_Center, core.V_Top, instance.parameters.clrTS, 0); KSp = instance:createTextOutput ("KSp", "KSp", "Wingdings", 9, core.H_Center, core.V_Top, instance.parameters.clrKS, 0); csFirst = CS:first() + Kijun; tsFirst = TS:first(); ksFirst = KS:first(); saFirst = SA:first(); sbFirst = SB:first(); chFirst = math.max(saFirst, sbFirst); SA1 = instance:addInternalStream(chFirst, Kijun); SB1 = instance:addInternalStream(chFirst, Kijun); instance:createChannelGroup("SA-SB", "SA-SB", SA1, SB1, instance.parameters.clrSSA, 100 - instance.parameters.transp); clrSSA = instance.parameters.clrSSA; clrSSB = instance.parameters.clrSSB; if ffi then local pv = ffi.typeof("void *"); ffi_source = ffi.cast(pv, source.ffi_ptr); ffi_TS = ffi.cast(pv, TS.ffi_ptr); ffi_KS = ffi.cast(pv, KS.ffi_ptr); ffi_CS = ffi.cast(pv, CS.ffi_ptr); ffi_SA = ffi.cast(pv, SA.ffi_ptr); ffi_SB = ffi.cast(pv, SB.ffi_ptr); ffi_SA1 = ffi.cast(pv, SA1.ffi_ptr); ffi_SB1 = ffi.cast(pv, SB1.ffi_ptr); ffi_TSp = ffi.cast(pv, TSp.ffi_ptr); ffi_KSp = ffi.cast(pv, KSp.ffi_ptr); ffi_source_close = ffi.cast(pv, source.close.ffi_ptr); end end -- Indicator calculation routine if ffi then function mathex_minmax(stream, from, to) local maxVal = -1.7976931348623158e+308 local minVal = 1.7976931348623158e+308 local maxPos = -1; local minPos = -1; if indicore3_ffi.stream_isBar(stream) == true then for i = from , to, 1 do local high = indicore3_ffi.barstream_getHigh(stream, i); local low = indicore3_ffi.barstream_getLow(stream, i); if maxVal < high then maxVal = high; maxPos = i; end if minVal > low then minVal = low; minPos = i; end end else for i = from , to, 1 do local t= indicore3_ffi.stream_getPrice(stream, i); if maxVal < t then maxVal = t; maxPos = i; end if minVal > t then minVal = t; minPos = i; end end end return minVal, maxVal, minPos, maxPos end function Update(period) if (period >= csFirst) then indicore3_ffi.outputstreamimpl_set(ffi_CS, period - Kijun, indicore3_ffi.stream_getPrice(ffi_source_close, period)); end local p, hh, ll; if (period >= tsFirst) then ll, hh = mathex_minmax(ffi_source, period - Tenkan + 1, period); indicore3_ffi.outputstreamimpl_set(ffi_TS, period, (hh + ll) / 2); --[[ textoutputimpl_set stream - > The text output stream. index - > The index of the period. The index of the first period is 0. The index of the last period is indicore3_ffi.textoutput_size() - 1. price - > The numeric value of the level on the chart vertical scale at which the label is placed. text - > The text of the label. If the font of the text label is a windows symbol font such as "Wingdings", "Wingdings 2" or "Wingdings 3", the following notation must be used to put the character by its code: "\xxx" where xxx is decimal code of the character. tt - > The text of the tooltip. If the tooltip is not required the nil value must be specified. color - > The color of the label. The value can be created using the core.rgb function. The specified color overrides the color defined by the stream. To keep the stream color, the -1 value must be specified. ]] if ShowPeriod then indicore3_ffi.textoutputimpl_set(ffi_TSp, period - Tenkan + 1, indicore3_ffi.barstream_getHigh(ffi_source, period - Tenkan+1), "\117", "" .. indicore3_ffi.barstream_getHigh(ffi_source, period - Tenkan+1), -1); indicore3_ffi.textoutputimpl_setNoData(ffi_TSp, period - Tenkan); end end if (period >= ksFirst) then ll, hh = mathex_minmax(ffi_source, period - Kijun + 1, period); indicore3_ffi.outputstreamimpl_set(ffi_KS, period, (hh + ll) / 2); if ShowPeriod then indicore3_ffi.textoutputimpl_set(ffi_KSp, period - Kijun + 1, indicore3_ffi.barstream_getHigh(ffi_source, period - Kijun+1), "\117", "" .. indicore3_ffi.barstream_getHigh(ffi_source, period - Kijun+1), -1); indicore3_ffi.textoutputimpl_setNoData(ffi_KSp, period - Kijun); end end local p = period + Kijun; if (period >= saFirst) then indicore3_ffi.outputstreamimpl_set(ffi_SA, p, (indicore3_ffi.stream_getPrice(ffi_TS, period) + indicore3_ffi.stream_getPrice(ffi_KS, period)) / 2); end if (period >= sbFirst) then ll, hh = mathex_minmax(ffi_source, period - Senkou + 1, period); indicore3_ffi.outputstreamimpl_set(ffi_SB, p, (hh + ll) / 2); end if (period >= chFirst) then indicore3_ffi.outputstreamimpl_set(ffi_SA1, p, indicore3_ffi.stream_getPrice(ffi_SA, p)); indicore3_ffi.outputstreamimpl_set(ffi_SB1, p, indicore3_ffi.stream_getPrice(ffi_SB, p)); if (indicore3_ffi.stream_getPrice(ffi_SA, p) > indicore3_ffi.stream_getPrice(ffi_SB, p)) then indicore3_ffi.outputstreamimpl_setColor(ffi_SA1, p, clrSSB); else indicore3_ffi.outputstreamimpl_setColor(ffi_SA1, p, clrSSA); end end end else function Update(period) if (period >= csFirst) then CS[period - Kijun] = source.close[period]; end local p, hh, ll; if (period >= tsFirst) then ll, hh = mathex.minmax(source, period - Tenkan + 1, period); TS[period] = (hh + ll) / 2; if ShowPeriod then TSp:set(period - Tenkan+1, source.high[period - Tenkan+1], "\117", source.high[period - Tenkan+1]); TSp:setNoData(period - Tenkan); end end if (period >= ksFirst) then ll, hh = mathex.minmax(source, period - Kijun + 1, period); KS[period] = (hh + ll) / 2; if ShowPeriod then KSp:set(period - Kijun+1, source.high[period - Kijun+1], "\117", source.high[period - Kijun+1]); KSp:setNoData(period - Kijun); end end local p = period + Kijun; if (period >= saFirst) then SA[p] = (TS[period] + KS[period]) / 2; end if (period >= sbFirst) then ll, hh = mathex.minmax(source, period - Senkou + 1, period); SB[p] = (hh + ll) / 2; end if (period >= chFirst) then SA1[p] = SA[p]; SB1[p] = SB[p]; if (SA[p] > SB[p]) then SA1:setColor(p, clrSSB); else SA1:setColor(p, clrSSA); end end end end