libHTF[without request.security()]
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © nazomobile
//@version=5
//@description this is libHTF under development.
//@description libHTF: use HTF values without request.security()
// This library enables to use HTF candles without request.security().
//
//@description Basic data structure
// Using <array> to access values in the same manner as series variable.
//The last member of HTF array is always latest current TF's data.
//If new bar in HTF(same as last bar closes), new member is pushed to HTF array.
//2nd from the last member of HTF array is latest fixed(closed) bar.
//
//@description HTF: How to use
//1. set TF
// tf_higher() function selects higher TF. TF steps are ()"1","5","15","60","240","D","W","M","3M","6M","Y").
// example:
//      tfChart = timeframe.period
//      htf1 = tf_higher(tfChart)
//
//2. set HTF matrix
// htf_candle() function returns 1 bool and 1 matrix.
//bool is a flag for start of new candle in HTF context.
//matrix is HTF candle data(0:open,1:time_open,2:close,3:time_close,4:high,5:time:high,6:low,7:time_low).
// example:
//      [b_new_bar1,m1]=htf_candle(htf1)
//
//3. how to access HTF candle data
// you can get values using <matrix>.lastx() method. 
// please be careful, return value is always float evenif it is "time". you need to cast to int time value when using for xloc.bartime.
//  example:
//      htf1open=m1.lastx("open")
//      htf1close=m1.lastx("close")
//      //if you need to use histrical value.
//      lastopen=open[1]
//      lasthtf1open=m1.lastx("open",1)
//
//4. how to store Data of HTF context
// you have to use array to store data of HTF context.
// array.htf_push() method handles the last member of array. if new_bar in HTF, it push new member. otherwise it set value to the last member.
// example:
//      array a_close=array.new<float>(1,na)
//      a_close.htf_push(b_new_bar1,m1.lastx("close"))
//
//@description HTFsrc: How to use
//1. how to setup src.
//set_src() function is set current tf's src from string(open/high/low/close/hl2/hlc3/ohlc4/hlcc4).
//set_htfsrc() function returns src array of HTF candle.
//
// example:
//      _src="ohlc4"
//      src=set_src(_src)
//      htf1src=set_htfsrc(_src,b_new_bar1,m1)
//      (if you need to use HTF src in series float)
//      s_htf1src=htf1src.lastx()
//
//@description HighLow: How to use
//1. set HTF arrays
// highlow() and htfhighlow() function calculates high/low and return high/low prices and time.
//the functions return 1 int and 8arrays.
//int is a flag for new high(1) or new low(-1).
//arrays are high/low and return high/low data. float for price, int for time.
// example
//      [i_renew,a_high,a_time_high,a_return_high,a_time_return_high,a_low,a_time_low,a_return_low,a_time_return_low] =
//        highlow()
//      [i_renew1,a_high1,a_time_high1,a_return_high1,a_time_return_high1,a_low1,a_time_low1,a_return_low1,a_time_return_low1] =
//        htfhighlow(m1)
//
//2. how to access HighLow data
// you can get values using <array>.lastx() method.
//  example:
//      if i_renew==1
//          myhigh=a_high.lastx()
//      //if you need to use histrical value.
//      myhigh=a_high.lastx(1)
//
//@description other functions
// functions for HTF candle matrix or HTF src array in this script are
//  htf_sma()/htf_ema()/htf_rma()
//  htf_rsi()/htf_rci()/htf_dmi()
//
library("libHTFwoRS",overlay=true)
var group_libHTF='libHTF'

// @function    method like array.last. it returns lastindex from the last member, if parameter is set.
// @param       lastindex (int) default value is "0"(the last member). if you need to access historical value, increment it(same manner as series vars).
// @returns     float value of lastindex from the last member of the array. returns na, if fail.
export method lastx(array<float> arrayid,int lastindex=0)=> arrayid.size()>=lastindex+1?arrayid.get(arrayid.size()-lastindex-1):na

// @function    method like array.last. it returns lastindex from the last member, if parameter is set.
// @param       lastindex (int) default value is "0"(the last member). if you need to access historical value, increment it(same manner as series vars).
// @returns     int value of lastindex from the last member of the array. returns na, if fail.
export method lastx(array<int> arrayid,int lastindex=0)=> arrayid.size()>=lastindex+1?arrayid.get(arrayid.size()-lastindex-1):na

// @function    method to set a value of the last member of the array. it sets value to the last member.
// @param       val (float) value to set.
// @returns     nothing
export method set_last(array<float> arrayid,float val)=>
    if arrayid.size()>0
        arrayid.set(arrayid.size()-1,val)

// @function    method to push new member to htf context. if new bar in htf, it works as push. else it works as set_last.
// @param       b (bool) true:push,false:set_last
// @param       val (float) _f the value to set.
// @returns     nothing
export method htf_push(array<float> arrayid,bool b,float val)=>
    if b
        arrayid.push(val)
    else if arrayid.size()>0
        arrayid.set(arrayid.size()-1,val)

method tftype(string tf) =>
    if na(tf)
        na
    else
        _last = str.substring(tf,str.length(tf)-1)
        _x = switch _last
            "Y"=>"Y"
            "M"=>"M"
            "W"=>"W"
            "D"=>"D"
            "H"=>"H"
            "S"=>"S"
            =>"min"

method multiplier(string tf)=>
    _x = switch tf.tftype()
        "Y" => str.length(tf)==1?"1":str.replace(tf,"Y","")
        "M" => str.length(tf)==1?"1":str.replace(tf,"M","")
        "W" => str.length(tf)==1?"1":str.replace(tf,"W","")
        "D" => str.length(tf)==1?"1":str.replace(tf,"D","")
        "H" => str.length(tf)==1?"1":str.replace(tf,"H","")
        "S" => str.length(tf)==1?"1":str.replace(tf,"S","")
        =>tf
    int(str.tonumber(_x))

// @function    method to set higher tf from tf string. TF steps are ["1","5","15","60","240","D","W","M","3M","6M","Y"].
// @param       tf (string) tf string
// @returns     (string) string of higher tf.
export method tf_higher(string tf)=>
    _m = tf.multiplier()
    _x = switch tf.tftype()
        "Y" => na
        "M" => _m<3?"3M": _m<6?"6M": _m<12?"12M":na
        "W" => "M"
        "D" => "W"
        "H" => "D"
        "S" => "1"
        "min" => _m<5?"5": _m<15?"15": _m<60?"60":  _m<240?"240": "D"
        => na

method tfseq(string _tf,int _time,string _TZ="GMT+3")=>
    _mul = _tf.multiplier()
    _year=year(_time,_TZ),_month=month(_time,_TZ),_week=weekofyear(_time,_TZ),_day=dayofmonth(_time,_TZ)
    _hour=hour(_time,_TZ),_minute=minute(_time,_TZ),_second=second(_time,_TZ)
    switch _tf.tftype()
        "Y"=>int(_year/_mul)
        "M"=>int(_month/_mul)
        "W"=>int(_week/_mul)
        "D"=>int(_day/_mul)
        "H"=>int(_hour/_mul)
        "S"=>int(_second/_mul)
        "min"=>str.tonumber(_tf)>=60?int(_hour/(_mul/60)): int(_minute/_mul)
        =>na

method time_close (string _tf,int _time_open,string _TZ="GMT+3") =>
    _mul = _tf.multiplier()
    _year=year(_time_open,_TZ),_month=month(_time_open,_TZ),_week=weekofyear(_time_open,_TZ),_day=dayofmonth(_time_open,_TZ)
    _hour=hour(_time_open,_TZ),_minute=minute(_time_open,_TZ)
    _time_close = switch _tf.tftype()
        "Y"=>timestamp(_TZ,_year+_mul,1,1)-1
        "M"=>timestamp(_TZ,_month+_mul>=12?_year+1:_year,_month+_mul>=12?_month+_mul-12:_month+_mul,1)-1
        "W"=>_time_open+timeframe.in_seconds(_tf)*1000*_mul-1
        "D"=>_time_open+timeframe.in_seconds(_tf)*1000*_mul-1
        "H"=>_time_open+timeframe.in_seconds(_tf)*1000*_mul-1
        "S"=>_time_open+(timeframe.in_seconds(_tf)*1000)-1
        "min"=> _time_open+(timeframe.in_seconds(_tf)*1000)-1
        =>na
    int(_time_close)

//*****
//HTF setup
//*****
//htf matrix rows; 0:open,1:time_open,2:close,3:time_close,4:high,5:time:high,6:low,7:time_low
method to_htfrow(string type) =>
    switch type
        "open" =>0
        "time_open"=>1
        "close" =>2
        "time_close"=>3
        "high" =>4
        "time_high"=>5
        "low" =>6
        "time_low"=>7

// @function    method for handling htf matrix.
// @param       m (matrix<float>) matrix for htf candle.
// @param       _type (string) value type of htf candle:["open","time_open","close","time_close","high","time_high","low","time_low"]
// @param       lastindex (int) default value is "0"(the last member).
// @returns     (float) value of htf candle. (caution: need to cast float to int to use time values!)
export method lastx(matrix<float> m,string _type,int lastindex=0)=>
    if m.columns()>=lastindex+1
        m.get(_type.to_htfrow(),m.columns()-lastindex-1)
    else
        na

method set_last(matrix<float> _m,string _type,float _x)=>
    if _m.columns()>0
        _m.set(_type.to_htfrow(),_m.columns()-1,_x)

// @function    build htf candles
// @param       _m (matrix<float>) matrix for htf candle. rows must be >=8.
// @param       _tf (string) tf string.
// @param       _TZ [optional string] of timezone. default value is "GMT+3".
// @returns     [bool,(matrix<float>)] bool for new bar@htf and matrix for snapshot of htf candle
export htf_candle(string _tf,string _TZ="GMT+3")=>
    var _m=matrix.new<float>(8,1,na)
    var i_htf=0

    i_htf:=_tf.tfseq(time,_TZ)
    b_new_bar=ta.change(i_htf)
    if b_new_bar
    //closing
        if high[1]>_m.lastx("high")
            _m.set_last("high",high[1])
        if low[1]<_m.lastx("low")
            _m.set_last("low",low[1])
        _m.set_last("close",close[1])
        _m.set_last("time_close",time_close[1])
    //push new bar
        _m.add_col()
        _m.set_last("open",open)
        _m.set_last("time_open",time)
        _m.set_last("close",close)
        _m.set_last("time_close",_tf.time_close(time,_TZ))
        _m.set_last("high",high)
        _m.set_last("time_high",timenow)
        _m.set_last("low",low)
        _m.set_last("time_low",timenow)
    else//update values
        if high>=_m.lastx("high")
            _m.set_last("high",high)
            _m.set_last("time_high",timenow)
        if low<=_m.lastx("low")
            _m.set_last("low",low)
            _m.set_last("time_low",timenow)
        _m.set_last("close",close)

    [b_new_bar,_m]

//src
//open/high/low/close/hl2/hlc3/ohlc4/hlcc4
sr0="open",sr1="high",sr2="low",sr3="close",sr4="hl2",sr5="hlc3",sr6="ohlc4",sr7="hlcc4"
// @function    set src.
// @param _src_type   (string) type of source:["open","high","low","close","hl2","hlc3","ohlc4","hlcc4"]
// @returns     (series float) src value
export set_src(string _src_type) =>
    switch _src_type
        sr0 => open
        sr1 => high
        sr2 => low
        sr3 => close
        sr4 => hl2
        sr5 => hlc3
        sr6 => ohlc4
        sr7 => hlcc4

f_htf_open (_m) =>
    _m.lastx("open")
f_htf_high (_m) =>
    _m.lastx("high")
f_htf_low (_m) =>
    _m.lastx("low")
f_htf_hl2 (_m) =>
    math.avg(_m.lastx("high"),_m.lastx("low"))
f_htf_hlc3 (_m) =>
    math.avg(_m.lastx("high"),_m.lastx("low"),_m.lastx("close"))
f_htf_ohlc4 (_m) =>
    math.avg(_m.lastx("open"),_m.lastx("high"),_m.lastx("low"),_m.lastx("close"))
f_htf_hlcc4 (_m) =>
    math.avg(_m.lastx("high"),_m.lastx("low"),_m.lastx("close"),_m.lastx("close"))

// @function    set htf src.
// @param       _src_type (string) type of source:["open","high","low","close","hl2","hlc3","ohlc4","hlcc4"]
// @param       _nb (bool) flag of new bar
// @param       _m (matrix<float>) matrix for htf candle.
// @returns     (array<float>) array of src value
export set_htfsrc (string _src_type,bool _nb, matrix<float> _m) =>
    var _a_htfsrc=array.new<float>(0,na)
    _s = switch _src_type
        sr0 => f_htf_open(_m)
        sr1 => f_htf_high(_m)
        sr2 => f_htf_low(_m)
        sr3 => close
        sr4 => f_htf_hl2(_m)
        sr5 => f_htf_hlc3(_m)
        sr6 => f_htf_ohlc4(_m)
        sr7 => f_htf_hlcc4(_m)
    if not(_a_htfsrc.size()>0)
        _a_htfsrc.push(_s)
    else if _nb
        _a_htfsrc.push(_s)
    else
        _a_htfsrc.set_last(_s)
    _a_htfsrc

//highlow
f_renew_high_low(_peak_bottom,_last_renew,
 _high,_time_high,_low,_time_low,
 _a_high,_a_time_high,_a_return_high,_a_time_return_high,
 _a_low,_a_time_low,_a_return_low,_a_time_return_low)
 =>
    _i_renew=0
    if _peak_bottom ==1
        if _a_return_high.size()>0
            if na(_a_return_high.last())
                _a_return_high.set_last(_high)
                _a_time_return_high.set_last(_time_high)
            else
                while(_a_return_high.size()>0)
                    if _a_return_high.lastx()<=_high
                        _a_return_high.pop()
                        _a_time_return_high.pop()
                    else
                        break
                _a_return_high.push(_high)
                _a_time_return_high.push(_time_high)
        else
            _a_return_high.push(_high)
            _a_time_return_high.push(_time_high)

        if _a_high.size()>0
            if na(_a_high.last())
                _i_renew:=1
                _a_high.set_last(_a_return_high.lastx())
                _a_time_high.set_last(_a_time_return_high.lastx())
            else if _a_high.lastx()<_a_return_high.lastx()
                _i_renew:=1
                if _i_renew==_last_renew
                    _a_high.set_last(_a_return_high.lastx())
                    _a_time_high.set_last(_a_time_return_high.lastx())
                else
                    _a_high.push(_a_return_high.lastx())
                    _a_time_high.push(_a_time_return_high.lastx())
        else
            _i_renew:=1
            _a_high.push(_a_return_high.lastx())
            _a_time_high.push(_a_time_return_high.lastx())

        if _i_renew==1 and array.size(_a_return_low)>0
            array.push(_a_low,array.last(_a_return_low))
            array.push(_a_time_low,array.last(_a_time_return_low))

    else if _peak_bottom==-1
        if _a_return_low.size()>0
            if na(_a_return_low.last())
                _a_return_low.set_last(_low)
                _a_time_return_low.set_last(_time_low)
            else
                while(_a_return_low.size()>0)
                    if _a_return_low.lastx()>=_low
                        _a_return_low.pop()
                        _a_time_return_low.pop()
                    else
                        break
                _a_return_low.push(_low)
                _a_time_return_low.push(_time_low)
        else
            _a_return_low.push(_low)
            _a_time_return_low.push(_time_low)
    
        if _a_low.size()>0
            if na(_a_low.last())
                _i_renew:=-1
                _a_low.set_last(_a_return_low.lastx())
                _a_time_low.set_last(_a_time_return_low.lastx())
            else if _a_low.lastx()>_a_return_low.lastx()
                _i_renew:=-1
                if _i_renew==_last_renew
                    _a_low.set_last(_a_return_low.lastx())
                    _a_time_low.set_last(_a_time_return_low.lastx())
                else
                    _a_low.push(_a_return_low.lastx())
                    _a_time_low.push(_a_time_return_low.lastx())
        else
            _i_renew:=-1
            _a_low.push(_a_return_low.lastx())
            _a_time_low.push(_a_time_return_low.lastx())
        
        if _i_renew==-1 and array.size(_a_return_high)>0
            array.push(_a_high,array.last(_a_return_high))
            array.push(_a_time_high,array.last(_a_time_return_high))

    [_i_renew,
     _a_high,_a_time_high,_a_return_high,_a_time_return_high,
     _a_low,_a_time_low,_a_return_low,_a_time_return_low
     ]

// @function    bool for latest bar is up.
// @returns     (bool) latest bar is up.
export is_up()=>open<close
// @function    bool for last bar is up.
// @returns     (bool) last bar is up.
export last_is_up()=>open[1]<close[1]
// @function    int for peak:1 or bottom:-1
// @param _latest (bool) latest bar is up.
// @param _last (bool) last bar is up.
// @returns     (int) peak:1 or bottom:-1 or 0
export peak_bottom(bool _latest,bool _last)=> _last and not _latest?1: not _last and _latest?-1: 0

// @function    bool for latest bar is up in htf.
// @param       _m (matrix<float>) matrix for htf candle.
// @returns     (bool) latest bar is up in htf.
export htf_is_up(matrix<float> _m)=>_m.lastx("open",1)<_m.lastx("close",1)
// @function    bool for last bar is up in htf.
// @param       _m (matrix<float>) matrix for htf candle.
// @returns     (bool) last bar is up in htf.
export htf_last_is_up(matrix<float> _m)=>_m.lastx("open",2)<_m.lastx("close",2)

// @function    highlow for current tf
// @param       _b_bar_time_price (bool) default is "true":The price of peak/bottom is set by price of latest bar. "false": The price of peak/bottom is set by comparison of "last close" and "current open".
// @returns     [int,array<float>,array<int>,array<float>,array<int>,array<float>,array<int>,array<float>,array<int>)] int for renew price(1:renew high,0:no renew,-1:renew low) and snapshot of highlow&return-highlow price&time.
export highlow(bool _b_bartime_price=true) =>
    i_renew=0
    var i_last_renew=i_renew
    var _a_high=array.new<float>(1,na)
    var _a_time_high=array.new<int>(1,na)
    var _a_return_high=array.new<float>(1,na)
    var _a_time_return_high=array.new<int>(1,na)
    var _a_low=array.new<float>(1,na)
    var _a_time_low=array.new<int>(1,na)
    var _a_return_low=array.new<float>(1,na)
    var _a_time_return_low=array.new<int>(1,na)

    pb =peak_bottom(is_up(),last_is_up())
    if pb!=0
        _high=_b_bartime_price?open: close[1]>=open?close[1]:open
        _time_high=_b_bartime_price?time: close[1]>=open?time_close[1]:time
        _low=_b_bartime_price?open: close[1]<=open?close[1]:open
        _time_low=_b_bartime_price?time: close[1]<=open?time_close[1]:time

        [tmp_i_renew,
         tmp_a_high,tmp_a_time_high,tmp_a_return_high,tmp_a_time_return_high,
         tmp_a_low,tmp_a_time_low,tmp_a_return_low,tmp_a_time_return_low
         ] =
         f_renew_high_low(pb,i_last_renew,_high,_time_high,_low,_time_low,
          _a_high,_a_time_high,_a_return_high,_a_time_return_high,
          _a_low,_a_time_low,_a_return_low,_a_time_return_low)
        i_renew:=tmp_i_renew
        _a_high:=tmp_a_high
        _a_time_high:=tmp_a_time_high
        _a_return_high:=tmp_a_return_high
        _a_time_return_high:=tmp_a_time_return_high
        _a_low:=tmp_a_low
        _a_time_low:=tmp_a_time_low
        _a_return_low:=tmp_a_return_low
        _a_time_return_low:=tmp_a_time_return_low

    i_last_renew:=i_renew!=0?i_renew:i_last_renew

    [i_renew,
     _a_high,_a_time_high,_a_return_high,_a_time_return_high,
     _a_low,_a_time_low,_a_return_low,_a_time_return_low]

// @function    highlow for htf
// @param       _m (matrix<float>) htf candle matrix.
// @param       _b_bar_time_price (bool) default is "true":The price of peak/bottom is set by price of latest bar. "false": The price of peak/bottom is set by comparison of "last close" and "current open".
// @returns     [int,array<float>,array<int>,array<float>,array<int>,array<float>,array<int>,array<float>,array<int>)] int for renew price(1:renew high,0:no renew,-1:renew low) and snapshot of highlow&return-highlow price&time.
export htfhighlow(matrix<float> _m,bool _b_bartime_price=true) =>
    i_renew=0
    var i_last_renew=i_renew
    var _a_high=array.new<float>(1,na)
    var _a_time_high=array.new<int>(1,na)
    var _a_return_high=array.new<float>(1,na)
    var _a_time_return_high=array.new<int>(1,na)
    var _a_low=array.new<float>(1,na)
    var _a_time_low=array.new<int>(1,na)
    var _a_return_low=array.new<float>(1,na)
    var _a_time_return_low=array.new<int>(1,na)
    pb =peak_bottom(htf_is_up(_m),htf_last_is_up(_m))
    if pb!=0
        float _high=_b_bartime_price?_m.lastx("open",1): _m.lastx("close",2)>_m.lastx("open",1)?_m.lastx("close",2):_m.lastx("open",1)
        int _time_high=_b_bartime_price?int(_m.lastx("time_open",1)): _m.lastx("close",2)>_m.lastx("open",1)?int(_m.lastx("time_close",2)):int(_m.lastx("time_open",1))
        float _low=_b_bartime_price?_m.lastx("open",1): _m.lastx("close",2)<_m.lastx("open",1)?_m.lastx("close",2):_m.lastx("open",1)
        int _time_low=_b_bartime_price?int(_m.lastx("time_open",1)): _m.lastx("close",2)<_m.lastx("open",1)?int(_m.lastx("time_close",2)):int(_m.lastx("time_open",1))

        [tmp_i_renew,
         tmp_a_high,tmp_a_time_high,tmp_a_return_high,tmp_a_time_return_high,
         tmp_a_low,tmp_a_time_low,tmp_a_return_low,tmp_a_time_return_low
         ] = f_renew_high_low(pb,i_last_renew,_high,_time_high,_low,_time_low,
          _a_high,_a_time_high,_a_return_high,_a_time_return_high,
          _a_low,_a_time_low,_a_return_low,_a_time_return_low)
        i_renew:=tmp_i_renew
        _a_high:=tmp_a_high
        _a_time_high:=tmp_a_time_high
        _a_return_high:=tmp_a_return_high
        _a_time_return_high:=tmp_a_time_return_high
        _a_low:=tmp_a_low
        _a_time_low:=tmp_a_time_low
        _a_return_low:=tmp_a_return_low
        _a_time_return_low:=tmp_a_time_return_low

    i_last_renew:=i_renew!=0?i_renew:i_last_renew

    [i_renew,
     _a_high,_a_time_high,_a_return_high,_a_time_return_high,
     _a_low,_a_time_low,_a_return_low,_a_time_return_low]

//MA
// @function    sma for htf
// @param       _a_src (array<float>) htf src array
// @param       _len (int) lengh
// @returns     (series float) sma value
export htf_sma(array<float> _a_src,int _len) =>
    _a_slice =array.new_float(0,na)
    if array.size(_a_src)>_len
        _last=array.size(_a_src)-1
        _a_slice:=array.slice(_a_src,_last-_len+1,_last)
    array.avg(_a_slice)

// @function    rma for htf
// @param       _a_src (array<float>) htf src array
// @param       _new_bar (bool) bool for htf new bar
// @param       _len (int) lengh
// @returns     (series float) rma value
export htf_rma(array<float> _a_src,bool _new_bar, int _len) =>
	_alpha = 1/_len
    var _a_rma=array.new_float(0,na)
    _rma=_a_src.size()>_len? na(_a_rma.lastx(1))? htf_sma(_a_src, _len) : _alpha * _a_src.lastx() + (1 - _alpha) * _a_rma.lastx(1) :na
    if _new_bar
        _a_rma.push(_rma)
    else
        _a_rma.set_last(_rma)
    _rma

// @function    ema for htf
// @param       _a_src (array<float>) htf src array
// @param       _new_bar (bool) bool for htf new bar
// @param       _len (int) lengh
// @returns     (series float) ema value
export htf_ema(array<float> _a_src,bool _new_bar,int _len) =>
	_alpha = 2/(_len+1)
    var _a_ema =array.new_float(0,na)
    _ema = _a_src.size()>_len? na(_a_ema.lastx(1))? htf_sma(_a_src, _len) : _alpha * _a_src.lastx() + (1 - _alpha) * _a_ema.lastx(1) :na
    if _new_bar
        _a_ema.push(_ema)
    else
        _a_ema.set_last(_ema)
    _ema

// @function    rsi for htf
// @param       _a_src (array<float>) htf src array.
// @param       _new_bar (bool) bool for htf new bar.
// @param       _len (int) lengh.
// @returns     (series float) rsi value.
export htf_rsi(array<float> _a_src,bool _new_bar,int _len) =>
    var _a_rsi_a=array.new<float>(0,na)
    var _a_rsi_b=array.new<float>(0,na)
    _alpha=_a_rsi_a.lastx(1)
    _beta=_a_rsi_b.lastx(1)
    if na(_alpha)
        if array.size(_a_src)>_len
            _alpha:=0.0,_beta:=0.0
            for i = 0 to _len-1
                _diff=_a_src.lastx(i)-_a_src.lastx(i+1)
                _alpha+=_diff>0?_diff:0
                _beta+=_diff<0?_diff:0
            _alpha/=_len
            _beta/=_len
    else
        _alpha*=_len-1
        _beta*=_len-1
        _diff=_a_src.lastx()-_a_src.lastx(1)
        _alpha+=_diff>0?_diff:0
        _beta+=_diff<0?_diff:0
        _alpha/=_len
        _beta/=_len
    if _new_bar
        _a_rsi_a.push(_alpha)
        _a_rsi_b.push(_beta)
    else
        _a_rsi_a.set_last(_alpha)
        _a_rsi_b.set_last(_beta)
    _alpha/(_alpha+math.abs(_beta)) * 100

// @function    rci for htf
// @param       _a_src (float) src array
// @param       _len (int) lengh
// @returns     (series float) rci value
export rci(float _src,int _len) =>
    d = 0.0
    for i = 0 to _len -1
        v = _src[i]
        s = -1
        o = 1
        for j = 0 to _len -1
            s+= v==_src[j]?1:0
            o+= v<_src[j]?1:0
        o:= (2*o+s)/2
        d+= math.pow((i+1-o),2)
    (1.0 - 6.0 * d / (math.pow(_len,3) - _len - 1.0)) * 100.0

// @function    rci for htf
// @param       _a_src (array<float>) htf src array
// @param       _len (int) lengh
// @returns     (series float) rci value
export htf_rci(array<float> _a_src,int _len) =>
    d = 0.0
    if array.size(_a_src)>=_len
        for i = 0 to _len-1
            v = _a_src.lastx(i)
            s = -1
            o = 1
            for j = 0 to _len-1
                s+= v==_a_src.lastx(j)?1:0
                o+= v<_a_src.lastx(j)?1:0
            o:= (2*o+s)/2
            d+= math.pow((i+1-o),2)
        (1.0 - 6.0 * d / (math.pow(_len,3) - _len - 1.0)) * 100.0
    else
        na

// @function    dmi for htf
// @param       _m (matrix<float>) htf candle matrix.
// @param       _new_bar (bool) bool for htf new bar.
// @param       _len (int) lengh.
// @param       _ma_type (string) type of ma for adx.(default:"rma",["sma","ema","rma"])
// @returns     [(float) adx,(float) +DI,(float) -DI]
export htf_dmi(matrix<float> _m,bool _new_bar,int _len,string _ma_type="rma") =>
    var _a_plus_dm = array.new_float(0,na)
    var _a_minus_dm = array.new_float(0,na)
    var _a_tr =array.new_float(0,na)
    var _a_plus_di = array.new_float(0,na)
    var _a_minus_di = array.new_float(0,na)
    var _a_dx = array.new_float(0,na)
    _dm1 =_m.lastx("high")-_m.lastx("high",1)
    _dm1:=_dm1<0?0:_dm1
    _dm2 =_m.lastx("low",1)-_m.lastx("low")
    _dm2:=_dm2<0?0:_dm2
    _tr =math.max(_m.lastx("high")-_m.lastx("low"),_m.lastx("high")-_m.lastx("close",1),_m.lastx("close")-_m.lastx("low"))
    if na(_a_tr.lastx()) or _new_bar
        _a_plus_dm.push(_dm1)
        _a_minus_dm.push(_dm2)
        _a_tr.push(_tr)
    else
        _a_plus_dm.set_last(_dm1)
        _a_minus_dm.set_last(_dm2)
        _a_tr.set_last(_tr)
    if _a_tr.size()>_len
        _a_plus_dm_sum = array.sum(_a_plus_dm.slice(_a_plus_dm.size()-_len,_a_plus_dm.size()-1))
        _a_minus_dm_sum = array.sum(_a_minus_dm.slice(_a_minus_dm.size()-_len,_a_minus_dm.size()-1))
        _a_tr_sum = array.sum(_a_tr.slice(_a_tr.size()-_len,_a_tr.size()-1))
        _di1= _a_plus_dm_sum/_a_tr_sum *100
        _di2= _a_minus_dm_sum/_a_tr_sum *100
        _dx=math.abs(_di1-_di2)/(_di1+_di2) *100
        if na(_a_dx.lastx()) or _new_bar
            _a_plus_di.push(_di1)
            _a_minus_di.push(_di2)
            _a_dx.push(_dx)
        else
            _a_plus_di.set_last(_di1)
            _a_minus_di.set_last(_di2)
            _a_dx.set_last(_dx)
    switch _ma_type
        "sma" => [_a_plus_di.lastx(),_a_minus_di.lastx(),htf_sma(_a_dx,_len)]
        "ema" => [_a_plus_di.lastx(),_a_minus_di.lastx(),htf_ema(_a_dx,_new_bar,_len)]
        "rma" => [_a_plus_di.lastx(),_a_minus_di.lastx(),htf_rma(_a_dx,_new_bar,_len)]
        =>na
//

//tf_higher() sample
var tfChart=timeframe.period
var htf1=tf_higher(tfChart)
var htf2=tf_higher(htf1)
var htf3=tf_higher(htf2)
var htf4=tf_higher(htf3)

//htf_candle() sample
[b_new_bar1,m1]=htf_candle(htf1)
[b_new_bar2,m2]=htf_candle(htf2)
[b_new_bar3,m3]=htf_candle(htf3)
[b_new_bar4,m4]=htf_candle(htf4)

//highlow() and htfhighlow() sample
[i_renew,a_high,a_time_high,a_return_high,a_time_return_high,a_low,a_time_low,a_return_low,a_time_return_low] =
 highlow()

[i_renew1,a_high1,a_time_high1,a_return_high1,a_time_return_high1,a_low1,a_time_low1,a_return_low1,a_time_return_low1] =
 htfhighlow(m1)

[i_renew2,a_high2,a_time_high2,a_return_high2,a_time_return_high2,a_low2,a_time_low2,a_return_low2,a_time_return_low2] =
 htfhighlow(m2)

[i_renew3,a_high3,a_time_high3,a_return_high3,a_time_return_high3,a_low3,a_time_low3,a_return_low3,a_time_return_low3] =
 htfhighlow(m3)

[i_renew4,a_high4,a_time_high4,a_return_high4,a_time_return_high4,a_low4,a_time_low4,a_return_low4,a_time_return_low4] =
 htfhighlow(m4)

//
//draw HighLowBox
//
colorBoxT=color.new(color.white,5)
colorBoxU=color.new(#aaffaa,5)
colorBoxD=color.new(#ffaaaa,5)

var mybox=box.new(na,na,na,na,xloc=xloc.bar_time,bgcolor=na,border_color=na)

if i_renew!=0
    top= a_high.lastx()
    top_time=  a_time_high.lastx()
    bottom= a_low.lastx()
    bottom_time= a_time_low.lastx()

    c_box=bottom_time<top_time?colorBoxU:colorBoxD

    _h = array.from(int(top_time),int(bottom_time))
    _v = array.from(top,bottom)
    _t = array.max(_v)
    _b = array.min(_v)
    _l = array.min(_h)

    mybox:=box.new(_l,na,na,na,xloc=xloc.bar_time,border_width=1,text_halign=text.align_center,text_size=size.normal,
     border_color=c_box,text_color=colorBoxT,bgcolor=na,border_style=line.style_dashed)

    box.set_bottom(mybox,_b)
    box.set_top(mybox,_t)
    box.set_text(mybox,tfChart)

box.set_right(mybox,time_close)

var mybox1=box.new(na,na,na,na,xloc=xloc.bar_time,bgcolor=na,border_color=na)

if i_renew1!=0
    top1= a_high1.lastx()
    top_time1=  a_time_high1.lastx()
    bottom1= a_low1.lastx()
    bottom_time1= a_time_low1.lastx()

    c_box=bottom_time1<top_time1?colorBoxU:colorBoxD
    va1=bottom_time1<top_time1?text.align_top:text.align_bottom

    _h1 = array.from(int(top_time1),int(bottom_time1))
    _v1 = array.from(top1,bottom1)
    _t1 = array.max(_v1)
    _b1 = array.min(_v1)
    _l1 = array.min(_h1)

    mybox1:=box.new(_l1,na,na,na,xloc=xloc.bar_time,border_width=2,text_halign=text.align_right,text_size=size.normal,
     text_valign=va1,border_color=c_box,text_color=colorBoxT,bgcolor=na,border_style=line.style_solid)

    box.set_bottom(mybox1,_b1)
    box.set_top(mybox1,_t1)
    box.set_text(mybox1,htf1)

box.set_right(mybox1,int(m1.lastx("time_close")))

var mybox2=box.new(na,na,na,na,xloc=xloc.bar_time,bgcolor=na,border_color=na)

if i_renew2!=0
    top2= a_high2.lastx()
    top_time2=  a_time_high2.lastx()
    bottom2= a_low2.lastx()
    bottom_time2= a_time_low2.lastx()

    c_box=bottom_time2<top_time2?colorBoxU:colorBoxD
    va2=bottom_time2<top_time2?text.align_top:text.align_bottom

    _h2 = array.from(int(top_time2),int(bottom_time2))
    _v2 = array.from(top2,bottom2)
    _t2 = array.max(_v2)
    _b2 = array.min(_v2)
    _l2 = array.min(_h2)

    mybox2:=box.new(_l2,na,na,na,xloc=xloc.bar_time,border_width=4,text_halign=text.align_right,text_size=size.normal,
     text_valign=va2,border_color=c_box,text_color=colorBoxT,bgcolor=na,border_style=line.style_dashed)

    box.set_bottom(mybox2,_b2)
    box.set_top(mybox2,_t2)
    box.set_text(mybox2,htf2)

box.set_right(mybox2,int(m2.lastx("time_close")))

//set_src() and set_htfsrc sample
mysrc="hlcc4"

src=set_src(mysrc)

sma20=ta.sma(src,20)

plot(sma20,color=color.aqua)
l20=label.new(bar_index+4,sma20,text=tfChart+":sma20",style=label.style_none,textcolor=color.aqua)
label.delete(l20[1])

a_htfsrc1=set_htfsrc(mysrc,b_new_bar1,m1)

//htf_sma(), htf_rma(), htf_ema() sample
sma20htf1=htf_sma(a_htfsrc1,20)
rma20htf1=htf_rma(a_htfsrc1,b_new_bar1,20)
ema20htf1=htf_ema(a_htfsrc1,b_new_bar1,20)

plot(sma20htf1,color=color.aqua,linewidth=2)
l20_1=label.new(bar_index+4,sma20htf1,text=htf1+":sma20",style=label.style_none,textcolor=color.aqua)
label.delete(l20_1[1])
plot(rma20htf1,color=color.orange,linewidth=2)
l20r_1=label.new(bar_index+4,rma20htf1,text=htf1+":rma20",style=label.style_none,textcolor=color.orange)
label.delete(l20r_1[1])
plot(ema20htf1,color=color.yellow,linewidth=2)
l20e_1=label.new(bar_index+4,ema20htf1,text=htf1+":ema20",style=label.style_none,textcolor=color.yellow)
label.delete(l20e_1[1])

a_htfsrc2=set_htfsrc(mysrc,b_new_bar2,m2)
sma20htf2=htf_sma(a_htfsrc2,20)

plot(sma20htf2,color=color.aqua,linewidth=3)
l20_2=label.new(bar_index+4,sma20htf2,text=htf2+":sma20",style=label.style_none,textcolor=color.aqua)
label.delete(l20_2[1])
