Indicator · Pine Script v4 · On the chart

Divergence for Many Indicators v4

by Trade-Research· code credited to LonesomeTheBlue

This indicator detects regular and hidden divergences across multiple technical indicators including RSI, MACD, Stochastic, CCI, momentum, OBV, and others.

View on GitHub

GitHub stars2on the repository
Pine versionv4older, still runs
Lines of code930
Settings40inputs
LicenceMIT
Last update4 years ago26 Mar 2022

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

930 lines of Pine Script v4 from indicators_script/divergense_mlp_neural_network.pinescript, published under MIT. Keep the author's credit and licence lines when you reuse it.

divergense_mlp_neural_network.pinescript
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © LonesomeTheBlue

//@version=4
study("Divergence for Many Indicators v4", overlay = true, max_bars_back = 1000, max_lines_count = 400, max_labels_count = 400)
prd = input(defval = 5, title = "Pivot Period", minval = 1, maxval = 50)
source = input(defval = "Close", title = "Source for Pivot Points", options = ["Close", "High/Low"])
searchdiv = input(defval = "Regular", title = "Divergence Type", options = ["Regular", "Hidden", "Regular/Hidden"])
showindis = input(defval = "Full", title = "Show Indicator Names", options = ["Full", "First Letter", "Don't Show"])
showlimit = input(1, title="Minimum Number of Divergence", minval = 1, maxval = 11)
maxpp = input(defval = 10, title = "Maximum Pivot Points to Check", minval = 1, maxval = 20)
maxbars = input(defval = 100, title = "Maximum Bars to Check", minval = 30, maxval = 200)
shownum = input(defval = true, title = "Show Divergence Number")
showlast = input(defval = false, title = "Show Only Last Divergence")
dontconfirm = input(defval = false, title = "Don't Wait for Confirmation")
showlines = input(defval = true, title = "Show Divergence Lines")
showpivot = input(defval = false, title = "Show Pivot Points")
calcmacd = input(defval = true, title = "MACD")
calcmacda = input(defval = true, title = "MACD Histogram")
calcrsi = input(defval = true, title = "RSI")
calcstoc = input(defval = true, title = "Stochastic")
calccci = input(defval = true, title = "CCI")
calcmom = input(defval = false, title = "Momentum")
calcobv = input(defval = true, title = "OBV")
calcvwmacd = input(true, title = "VWmacd")
calccmf = input(true, title = "Chaikin Money Flow")
calcmfi = input(true, title = "Money Flow Index")
calcext = input(false, title = "Check External Indicator")
externalindi = input(defval = close, title = "External Indicator")
pos_reg_div_col = input(defval = color.yellow, title = "Positive Regular Divergence")
neg_reg_div_col = input(defval = color.navy, title = "Negative Regular Divergence")
pos_hid_div_col = input(defval = color.lime, title = "Positive Hidden Divergence")
neg_hid_div_col = input(defval = color.red, title = "Negative Hidden Divergence")
pos_div_text_col = input(defval = color.black, title = "Positive Divergence Text Color")
neg_div_text_col = input(defval = color.white, title = "Negative Divergence Text Color")
reg_div_l_style_ = input(defval = "Solid", title = "Regular Divergence Line Style", options = ["Solid", "Dashed", "Dotted"])
hid_div_l_style_ = input(defval = "Dashed", title = "Hdden Divergence Line Style", options = ["Solid", "Dashed", "Dotted"])
reg_div_l_width = input(defval = 2, title = "Regular Divergence Line Width", minval = 1, maxval = 5)
hid_div_l_width = input(defval = 1, title = "Hidden Divergence Line Width", minval = 1, maxval = 5)

// set line styles
var reg_div_l_style = reg_div_l_style_ == "Solid" ? line.style_solid : 
                       reg_div_l_style_ == "Dashed" ? line.style_dashed :
                       line.style_dotted
var hid_div_l_style = hid_div_l_style_ == "Solid" ? line.style_solid : 
                       hid_div_l_style_ == "Dashed" ? line.style_dashed :
                       line.style_dotted


// get indicators
rsi = rsi(close, 14) // RSI
[macd, signal, deltamacd] = macd(close, 12, 26, 9) // MACD
moment = mom(close, 10) // Momentum
cci = cci(close, 10) // CCI
Obv = obv // OBV
stk = sma(stoch(close, high, low, 14), 3) // Stoch
maFast = vwma(close, 12), maSlow = vwma(close, 26), vwmacd = maFast - maSlow // volume weighted macd
Cmfm = ((close-low) - (high-close)) / (high - low), Cmfv = Cmfm * volume, cmf = sma(Cmfv, 21) / sma(volume,21) // Chaikin money flow
Mfi = mfi(close, 14) // Moneyt Flow Index

// keep indicators names and colors in arrays
var indicators_name = array.new_string(11)
var div_colors = array.new_color(4)
if barstate.isfirst
    // names
    array.set(indicators_name, 0, showindis == "Full" ? "MACD" : "M")
    array.set(indicators_name, 1, showindis == "Full" ? "Hist" : "H")
    array.set(indicators_name, 2, showindis == "Full" ? "RSI" : "E")
    array.set(indicators_name, 3, showindis == "Full" ? "Stoch" : "S")
    array.set(indicators_name, 4, showindis == "Full" ? "CCI" : "C")
    array.set(indicators_name, 5, showindis == "Full" ? "MOM" : "M")
    array.set(indicators_name, 6, showindis == "Full" ? "OBV" : "O")
    array.set(indicators_name, 7, showindis == "Full" ? "VWMACD" : "V")
    array.set(indicators_name, 8, showindis == "Full" ? "CMF" : "C")
    array.set(indicators_name, 9, showindis == "Full" ? "MFI" : "M")
    array.set(indicators_name,10, showindis == "Full" ? "Extrn" : "X")
    //colors
    array.set(div_colors, 0, pos_reg_div_col)
    array.set(div_colors, 1, neg_reg_div_col)
    array.set(div_colors, 2, pos_hid_div_col)
    array.set(div_colors, 3, neg_hid_div_col)

// Check if we get new Pivot High Or Pivot Low
float ph = pivothigh((source == "Close" ? close : high), prd, prd)
float pl = pivotlow((source == "Close" ? close : low), prd, prd)
plotshape(ph and showpivot, text = "H",  style = shape.labeldown, color = color.new(color.white, 100), textcolor = color.red, location = location.abovebar, transp = 0, offset = -prd)
plotshape(pl and showpivot, text = "L",  style = shape.labelup, color = color.new(color.white, 100), textcolor = color.lime, location = location.belowbar, transp = 0, offset = -prd)

// keep values and positions of Pivot Highs/Lows in the arrays
var int maxarraysize = 20
var ph_positions = array.new_int(maxarraysize, 0)
var pl_positions = array.new_int(maxarraysize, 0)
var ph_vals = array.new_float(maxarraysize, 0.)
var pl_vals = array.new_float(maxarraysize, 0.)

// add PHs to the array
if ph
    array.unshift(ph_positions, bar_index)
    array.unshift(ph_vals, ph)
    if array.size(ph_positions) > maxarraysize
        array.pop(ph_positions)
        array.pop(ph_vals)

// add PLs to the array
if pl
    array.unshift(pl_positions, bar_index)
    array.unshift(pl_vals, pl)
    if array.size(pl_positions) > maxarraysize
        array.pop(pl_positions)
        array.pop(pl_vals)

// functions to check Regular Divergences and Hidden Divergences

// function to check positive regular or negative hidden divergence
// cond == 1 => positive_regular, cond == 2=> negative_hidden
positive_regular_positive_hidden_divergence(src, cond)=>
    divlen = 0
    prsc = source == "Close" ? close : low
    // if indicators higher than last value and close price is higher than las close 
    if dontconfirm or src > src[1] or close > close[1]
        startpoint = dontconfirm ? 0 : 1 // don't check last candle
        // we search last 15 PPs
        for x = 0 to maxpp - 1
            len = bar_index - array.get(pl_positions, x) + prd
            // if we reach non valued array element or arrived 101. or previous bars then we don't search more
            if array.get(pl_positions, x) == 0 or len > maxbars
                break
            if len > 5 and 
               ((cond == 1 and src[startpoint] > src[len] and prsc[startpoint] < nz(array.get(pl_vals, x))) or
               (cond == 2 and src[startpoint] < src[len] and prsc[startpoint] > nz(array.get(pl_vals, x))))
                slope1 = (src[startpoint] - src[len]) / (len - startpoint)
                virtual_line1 = src[startpoint] - slope1
                slope2 = (close[startpoint] - close[len]) / (len - startpoint)
                virtual_line2 = close[startpoint] - slope2
                arrived = true
                for y = 1 + startpoint to len - 1
                    if src[y] < virtual_line1 or nz(close[y]) < virtual_line2
                        arrived := false
                        break
                    virtual_line1 := virtual_line1 - slope1
                    virtual_line2 := virtual_line2 - slope2
                
                if arrived
                    divlen := len
                    break
    divlen

// function to check negative regular or positive hidden divergence
// cond == 1 => negative_regular, cond == 2=> positive_hidden
negative_regular_negative_hidden_divergence(src, cond)=>
    divlen = 0
    prsc = source == "Close" ? close : high
    // if indicators higher than last value and close price is higher than las close 
    if dontconfirm or src < src[1] or close < close[1]
        startpoint = dontconfirm ? 0 : 1 // don't check last candle
        // we search last 15 PPs
        for x = 0 to maxpp - 1
            len = bar_index - array.get(ph_positions, x) + prd
            // if we reach non valued array element or arrived 101. or previous bars then we don't search more
            if array.get(ph_positions, x) == 0 or len > maxbars
                break
            if len > 5 and 
               ((cond == 1 and src[startpoint] < src[len] and prsc[startpoint] > nz(array.get(ph_vals, x))) or 
               (cond == 2 and src[startpoint] > src[len] and prsc[startpoint] < nz(array.get(ph_vals, x))))
                slope1 = (src[startpoint] - src[len]) / (len - startpoint)
                virtual_line1 = src[startpoint] - slope1
                slope2 = (close[startpoint] - nz(close[len])) / (len - startpoint)
                virtual_line2 = close[startpoint] - slope2
                arrived = true
                for y = 1 + startpoint to len - 1
                    if src[y] > virtual_line1 or nz(close[y]) > virtual_line2
                        arrived := false
                        break
                    virtual_line1 := virtual_line1 - slope1
                    virtual_line2 := virtual_line2 - slope2
                
                if arrived
                    divlen := len
                    break
    divlen

// calculate 4 types of divergence if enabled in the options and return divergences in an array
calculate_divs(cond, indicator)=>
    divs = array.new_int(4, 0)
    array.set(divs, 0, cond and (searchdiv == "Regular" or searchdiv == "Regular/Hidden") ? positive_regular_positive_hidden_divergence(indicator, 1) : 0)
    array.set(divs, 1, cond and (searchdiv == "Regular" or searchdiv == "Regular/Hidden") ? negative_regular_negative_hidden_divergence(indicator, 1) : 0)
    array.set(divs, 2, cond and (searchdiv == "Hidden" or searchdiv == "Regular/Hidden")  ? positive_regular_positive_hidden_divergence(indicator, 2) : 0)
    array.set(divs, 3, cond and (searchdiv == "Hidden" or searchdiv == "Regular/Hidden")  ? negative_regular_negative_hidden_divergence(indicator, 2) : 0)
    divs

// array to keep all divergences
var all_divergences = array.new_int(44) // 11 indicators * 4 divergence = 44 elements
// set related array elements
array_set_divs(div_pointer, index)=>
    for x = 0 to 3
        array.set(all_divergences, index * 4 + x, array.get(div_pointer, x))

// set divergences array 
array_set_divs(calculate_divs(calcmacd, macd), 0)
array_set_divs(calculate_divs(calcmacda, deltamacd), 1)
array_set_divs(calculate_divs(calcrsi, rsi), 2)
array_set_divs(calculate_divs(calcstoc, stk), 3)
array_set_divs(calculate_divs(calccci, cci), 4)
array_set_divs(calculate_divs(calcmom, moment), 5)
array_set_divs(calculate_divs(calcobv, Obv), 6)
array_set_divs(calculate_divs(calcvwmacd, vwmacd), 7)
array_set_divs(calculate_divs(calccmf, cmf), 8)
array_set_divs(calculate_divs(calcmfi, Mfi), 9)
array_set_divs(calculate_divs(calcext, externalindi), 10)

// check minimum number of divergence, if less than showlimit then delete all divergence
total_div = 0
for x = 0 to array.size(all_divergences) - 1
    total_div := total_div + round(sign(array.get(all_divergences, x)))

if total_div < showlimit
    array.fill(all_divergences, 0)

// keep line in an array
var pos_div_lines = array.new_line(0)
var neg_div_lines = array.new_line(0)
var pos_div_labels = array.new_label(0)
var neg_div_labels = array.new_label(0) 

// MLP 구현부 삽입, 입력값
isMLP = input(true, title="단순 신경망 학습", group="학습")

var inode = 48  //다이버전스 개수 11 indicators * 4 divergence = 44 elements  에다 마지막에 가격기반을 두 개 추가해서 46개
var hnode = input(500, title="은닉층 노드 수", group="학습", tooltip="노드수 많으면 많을수록 좋지만 성능이 점점 수렴하고 계산이 느려짐")
var onode = 12 // 5미만 가격차이 1마다 2% 5초과 1마다 2%로 지정.
var lrate = input(0.1, "학습률", group="학습", minval=0.0001, maxval=0.5, step=0.01, tooltip="이번 신호에서 학습할 때 발생하는 오차에 얼마나 가중치를 적합시킬지를 정함")
var train_candle = input(14, "몇 캔들 전과의 가격차이로 학습하는 기준", minval=0, maxval=200, group="학습", tooltip="과거 종가 가격 차이, 고가 차이, 저가 차이 % 데이터들을 입력층 노드의 일부로 넣을건데 몇 캔들이나 과거로 넣을지 정하는거")
var std_candle = input(7, "몇 캔들 뒤를 예측?", minval=1, maxval=200, group="학습", tooltip="말그대로 신호 위치에서 몇 캔들이나 미래를 예측할지 정함. 학습 오차에 영향이 깊음")
var trainCnt = input(1, "중복학습 횟수", group="학습", tooltip="교차 학습을 구현 못해서 안쓰는게 나음.")
var isShowTrainLog = input(false, "학습 로그 표시", group="학습", tooltip="체크하면 학습된 위치 보여줌")
var isSecMaxView = input(true, "2번째로 큰 예상 강도도 표시", group="학습")
var signal_check = input(10, "신호 사라짐 확인 캔들 수", tooltip ="10이면 현재에서 10캔들 이전까지만 신호가 사라지지 않았는지 확인하고 학습한다는 뜻. 큰 시간대일수록 작은 수치 사용 추천", group="학습")
var diff_per = input(5.5, "변동 폭 최대 단위 -값% ~ +값% 를 총 12토막냄.", minval=5.5, maxval=99, step=5.5, tooltip ="예시) 5.5입력시-5.5% ~ +5.5% 단위까지 제대로 학습함.\n 큰 시간대에선 변동폭이 커지므로 제대로 학습할 수 있게 넣은 단위. 5.5%~99%까지 지원", group="학습")
var diff_val = diff_per / 5.5
// var is_success_check = input(false, "적중률 테이블 보기")
// var success_check_cnt = input(100, "범위 내 적중률 계산 개수", minval=10, maxval=1000, tooltip="최근 범위 내에서 얼마나 잘 맞았는지 테이블로 보기 위한 변수")
// var success_check_option = input("기간내 범위 달성", "정답 기준", options=["기간 마무리에 범위 달성", "기간내 범위 달성"])
// var sucess_option_flag = success_check_option == "기간내 범위 달성" ? true : false
// var success_cnt_option = input("#1", "예상강도별 적중률 체크", options=["#1", "#2", "#1+#2"])


var ml_learn_pos_div = array.new_string(0) 
var ml_past_pos_price = array.new_float(0) 
var ml_past_pos_high_price = array.new_float(0) 
var ml_past_pos_low_price = array.new_float(0) 
var ml_past_pos_mid_price = array.new_float(0) 
var add_after_pos_cnt = array.new_int(0) 

var ml_learn_neg_div = array.new_string(0) 
var ml_past_neg_price = array.new_float(0)
var ml_past_neg_high_price = array.new_float(0) 
var ml_past_neg_low_price = array.new_float(0) 
var ml_past_neg_mid_price = array.new_float(0)
var add_after_neg_cnt = array.new_int(0) 


get_input_node_datas() =>
    calc_per = 50.0/diff_per
    input_price_per = (close/close[train_candle]-1) * calc_per + 0.5
    if(input_price_per < 0.01) 
        input_price_per := 0.01
    if(input_price_per > 0.99) 
        input_price_per := 0.99
    if(na(input_price_per))
        input_price_per := 0.5
    hl_high_price_per = (close/highest(train_candle)-1) * calc_per + 0.5
    if(hl_high_price_per < 0.01) 
        hl_high_price_per := 0.01
    if(hl_high_price_per > 0.99) 
        hl_high_price_per := 0.99
    if(na(hl_high_price_per))
        hl_high_price_per := 0.5
    hl_low_price_per = (close/lowest(train_candle)-1) * calc_per + 0.5
    if(hl_low_price_per < 0.01) 
        hl_low_price_per := 0.01
    if(hl_low_price_per > 0.99) 
        hl_low_price_per := 0.99
    if(na(hl_low_price_per))
        hl_low_price_per := 0.5
    hl_mid_price_per = (close/avg(highest(train_candle), lowest(train_candle))-1) * calc_per + 0.5
    if(hl_mid_price_per < 0.01) 
        hl_mid_price_per := 0.01
    if(hl_mid_price_per > 0.99) 
        hl_mid_price_per := 0.99
    if(na(hl_mid_price_per))
        hl_mid_price_per := 0.5
    [input_price_per, hl_high_price_per, hl_low_price_per, hl_mid_price_per]

push_pos_ml_datas(text) =>
    array.push(ml_learn_pos_div, text)
    [input_price_per, hl_high_price_per, hl_low_price_per, hl_mid_price_per] = get_input_node_datas()
    array.push(ml_past_pos_price, input_price_per)
    array.push(ml_past_pos_high_price, hl_high_price_per)
    array.push(ml_past_pos_low_price, hl_low_price_per)
    array.push(ml_past_pos_mid_price, hl_mid_price_per)
    array.push(add_after_pos_cnt, 0)
    
push_neg_ml_datas(text) =>
    array.push(ml_learn_neg_div, text)
    [input_price_per, hl_high_price_per, hl_low_price_per, hl_mid_price_per] = get_input_node_datas()
    array.push(ml_past_neg_price, input_price_per)
    array.push(ml_past_neg_high_price, hl_high_price_per)
    array.push(ml_past_neg_low_price, hl_low_price_per)
    array.push(ml_past_neg_mid_price, hl_mid_price_per)
    array.push(add_after_neg_cnt, 0)

pop_pos_ml_datas() =>
    array.pop(add_after_pos_cnt)
    [array.pop(ml_learn_pos_div), array.pop(ml_past_pos_price), array.pop(ml_past_pos_high_price), array.pop(ml_past_pos_low_price), array.pop(ml_past_pos_mid_price)]
    
pop_neg_ml_datas() =>
    array.pop(add_after_neg_cnt)
    [array.pop(ml_learn_neg_div), array.pop(ml_past_neg_price), array.pop(ml_past_neg_high_price), array.pop(ml_past_neg_low_price), array.pop(ml_past_neg_mid_price)]
    
shift_pos_ml_datas() =>
    array.shift(add_after_pos_cnt)
    [array.shift(ml_learn_pos_div), array.shift(ml_past_pos_price), array.shift(ml_past_pos_high_price), array.shift(ml_past_pos_low_price), array.shift(ml_past_pos_mid_price)]
    
shift_neg_ml_datas() =>
    array.shift(add_after_neg_cnt)
    [array.shift(ml_learn_neg_div), array.shift(ml_past_neg_price), array.shift(ml_past_neg_high_price), array.shift(ml_past_neg_low_price), array.shift(ml_past_neg_mid_price)]
    
clear_pos_ml_datas() =>
    array.clear(add_after_pos_cnt)
    array.clear(ml_learn_pos_div)
    array.clear(ml_past_pos_price)
    array.clear(ml_past_pos_high_price)
    array.clear(ml_past_pos_low_price)
    array.clear(ml_past_pos_mid_price)
    
clear_neg_ml_datas() =>
    array.clear(add_after_neg_cnt)
    array.clear(ml_learn_neg_div)
    array.clear(ml_past_neg_price)
    array.clear(ml_past_neg_high_price)
    array.clear(ml_past_neg_low_price)
    array.clear(ml_past_neg_mid_price)


up_pos_cnt() =>
    if(array.size(add_after_pos_cnt) > 0)
        for i = 0 to array.size(add_after_pos_cnt) - 1
            array.set(add_after_pos_cnt, i, array.get(add_after_pos_cnt,i)+1)
        
up_neg_cnt() =>
    if(array.size(add_after_neg_cnt) > 0)
        for i = 0 to array.size(add_after_neg_cnt) - 1
            array.set(add_after_neg_cnt, i, array.get(add_after_neg_cnt,i)+1)

over_cnt_pos_check(cnt) =>
    if(array.size(add_after_pos_cnt)!=0)
        if array.get(add_after_pos_cnt, 0) > cnt
            [a, b, c, d, e] = shift_pos_ml_datas()
            [a, b, c, d, e]
        else
            ["", -1.0, -1.0, -1.0, -1.0]
            
over_cnt_neg_check(cnt) =>
    if(array.size(add_after_neg_cnt)!=0)
        if array.get(add_after_neg_cnt, 0) > cnt
            [a, b, c, d, e] = shift_neg_ml_datas()
            [a, b, c, d, e]
        else
            ["", -1.0, -1.0, -1.0, -1.0]

get_target_datas() =>
    train_std_close = std_candle < signal_check ? signal_check-std_candle : 0
    target = ((close[train_std_close] / close[train_std_close + std_candle]-1)*1000 + diff_val*55.0) / (10*diff_val) 
    if(target < 5.5) 
        target := floor(target)
    else
        target := ceil(target)
    if(target < 0) 
        target := 0
    if(target > 11) 
        target := 11
    target

// remove old lines and labels if showlast option is enabled
delete_old_pos_div_lines()=>
    if array.size(pos_div_lines) > 0    
        for j = 0 to array.size(pos_div_lines) - 1 
            line.delete(array.get(pos_div_lines, j))
        array.clear(pos_div_lines)

delete_old_neg_div_lines()=>
    if array.size(neg_div_lines) > 0    
        for j = 0 to array.size(neg_div_lines) - 1 
            line.delete(array.get(neg_div_lines, j))
        array.clear(neg_div_lines)

delete_old_pos_div_labels()=>
    if array.size(pos_div_labels) > 0 
        for j = 0 to array.size(pos_div_labels) - 1 
            label.delete(array.get(pos_div_labels, j))
        array.clear(pos_div_labels)

delete_old_neg_div_labels()=>
    if array.size(neg_div_labels) > 0    
        for j = 0 to array.size(neg_div_labels) - 1 
            label.delete(array.get(neg_div_labels, j))
        array.clear(neg_div_labels)

// delete last creted lines and labels until we met new PH/PV 
delete_last_pos_div_lines_label(n)=>
    if n > 0 and array.size(pos_div_lines) >= n    
        asz = array.size(pos_div_lines)
        for j = 1 to n
            line.delete(array.get(pos_div_lines, asz - j))
            array.pop(pos_div_lines)
        if array.size(pos_div_labels) > 0  
            label.delete(array.get(pos_div_labels, array.size(pos_div_labels) - 1))
            array.pop(pos_div_labels)
        if array.size(add_after_pos_cnt) > 0
            pop_pos_ml_datas()

delete_last_neg_div_lines_label(n)=>
    if n > 0 and array.size(neg_div_lines) >= n    
        asz = array.size(neg_div_lines)
        for j = 1 to n
            line.delete(array.get(neg_div_lines, asz - j))
            array.pop(neg_div_lines)
        if array.size(neg_div_labels) > 0  
            label.delete(array.get(neg_div_labels, array.size(neg_div_labels) - 1))
            array.pop(neg_div_labels)
        if array.size(add_after_neg_cnt) > 0
            pop_neg_ml_datas()
            
// variables for Alerts
pos_reg_div_detected = false
neg_reg_div_detected = false
pos_hid_div_detected = false
neg_hid_div_detected = false

// to remove lines/labels until we met new // PH/PL
var last_pos_div_lines = 0
var last_neg_div_lines = 0
var last_pos_ml_lines = 0
var last_neg_ml_lines = 0
var remove_last_pos_divs = false 
var remove_last_neg_divs = false
var remove_last_pos_ml = false 
var remove_last_neg_ml = false
if pl
    remove_last_pos_divs := false
    remove_last_pos_ml := false
    last_pos_div_lines := 0
    last_pos_ml_lines := 0
if ph
    remove_last_neg_divs := false
    remove_last_neg_ml := false
    last_neg_div_lines := 0
    last_neg_ml_lines := 0

// draw divergences lines and labels
divergence_text_top = ""
divergence_text_bottom = ""
distances = array.new_int(0)
dnumdiv_top = 0
dnumdiv_bottom = 0
top_label_col = color.white
bottom_label_col = color.white
old_pos_divs_can_be_removed = true
old_neg_divs_can_be_removed = true
startpoint = dontconfirm ? 0 : 1 // used for don't confirm option


range2(_src, _a, _b) =>
    _arr = array.new_float(0)
    for i = _a to _b - 1
        array.push(_arr, _src[i])
    _arr

divMasking = ""
remove_flag = false
for x = 0 to 10
    div_type = -1
    for y = 0 to 3
        if array.get(all_divergences, x * 4 + y) > 0 // any divergence?
            divMasking := divMasking + "1"
            div_type := y
            if (y % 2) == 1 
                dnumdiv_top := dnumdiv_top + 1
                top_label_col := array.get(div_colors, y)
            if (y % 2) == 0
                dnumdiv_bottom := dnumdiv_bottom + 1
                bottom_label_col := array.get(div_colors, y)
            if not array.includes(distances, array.get(all_divergences, x * 4 + y))  // line not exist ?
                array.push(distances, array.get(all_divergences, x * 4 + y))
                new_line = showlines ? line.new(x1 = bar_index - array.get(all_divergences, x * 4 + y), 
                          y1 = (source == "Close" ? close[array.get(all_divergences, x * 4 + y)] : 
                                           (y % 2) == 0 ? low[array.get(all_divergences, x * 4 + y)] : 
                                                          high[array.get(all_divergences, x * 4 + y)]),
                          x2 = bar_index - startpoint,
                          y2 = (source == "Close" ? close[startpoint] : 
                                           (y % 2) == 0 ? low[startpoint] : 
                                                          high[startpoint]),
                          color = array.get(div_colors, y),
                          style = y < 2 ? reg_div_l_style : hid_div_l_style,
                          width = y < 2 ? reg_div_l_width : hid_div_l_width
                          )
                          : na
                if (y % 2) == 0
                    if old_pos_divs_can_be_removed
                        old_pos_divs_can_be_removed := false
                        if not showlast and remove_last_pos_divs
                            remove_flag := true
                            delete_last_pos_div_lines_label(last_pos_div_lines)
                            last_pos_div_lines := 0
                        if showlast
                            delete_old_pos_div_lines()
                    array.push(pos_div_lines, new_line)
                    last_pos_div_lines := last_pos_div_lines + 1
                    remove_last_pos_divs := true
                    
                if (y % 2) == 1
                    if old_neg_divs_can_be_removed
                        old_neg_divs_can_be_removed := false
                        if not showlast and remove_last_neg_divs
                            remove_flag := true
                            delete_last_neg_div_lines_label(last_neg_div_lines)
                            last_neg_div_lines := 0
                        if showlast
                            delete_old_neg_div_lines()
                    array.push(neg_div_lines, new_line)
                    last_neg_div_lines := last_neg_div_lines + 1
                    remove_last_neg_divs := true
                    
            // set variables for alerts
            if y == 0
                pos_reg_div_detected := true
            if y == 1
                neg_reg_div_detected := true
            if y == 2
                pos_hid_div_detected := true
            if y == 3
                neg_hid_div_detected := true
        else 
            divMasking := divMasking + "0"
            na
    // get text for labels
    if div_type >= 0
        divergence_text_top    := divergence_text_top    + ((div_type % 2) == 1 ? (showindis != "Don't Show" ? array.get(indicators_name, x) + "\n" : "") : "")
        divergence_text_bottom := divergence_text_bottom + ((div_type % 2) == 0 ? (showindis != "Don't Show" ? array.get(indicators_name, x) + "\n" : "") : "")

// plot(remove_last_neg_divs?45000:40000, "변수테스트")
// plot(remove_flag?close+1000:close-1000, "remove테스트", color=color.red)

// draw labels
if showindis != "Don't Show" or shownum
    if shownum and dnumdiv_top > 0
        divergence_text_top := divergence_text_top + tostring(dnumdiv_top)
    if shownum and dnumdiv_bottom > 0
        divergence_text_bottom := divergence_text_bottom + tostring(dnumdiv_bottom)
    if divergence_text_top != ""
        if showlast
            delete_old_neg_div_labels()
        push_neg_ml_datas(divMasking)   //다이브 마스킹과 어레이 추가
        array.push(neg_div_labels, 
                      label.new( x = bar_index, 
                                 y = max(high, high[1]), 
                                 text = divergence_text_top,
                                 color = top_label_col,
                                 textcolor = neg_div_text_col,
                                 style = label.style_label_down
                                 ))
                                 
    if divergence_text_bottom != ""
        if showlast
            delete_old_pos_div_labels()
        push_pos_ml_datas(divMasking)
        array.push(pos_div_labels, 
                      label.new( x = bar_index, 
                                 y = min(low, low[1]), 
                                 text = divergence_text_bottom,
                                 color = bottom_label_col, 
                                 textcolor = pos_div_text_col,
                                 style = label.style_label_up
                                 ))
                                 
    
alertcondition(pos_reg_div_detected, title='Positive Regular Divergence Detected', message='Positive Regular Divergence Detected')
alertcondition(neg_reg_div_detected, title='Negative Regular Divergence Detected', message='Negative Regular Divergence Detected')
alertcondition(pos_hid_div_detected, title='Positive Hidden Divergence Detected', message='Positive Hidden Divergence Detected')
alertcondition(neg_hid_div_detected, title='Negative Hidden Divergence Detected', message='Negative Hidden Divergence Detected')
alertcondition(pos_reg_div_detected or pos_hid_div_detected, title='Positive Divergence Detected', message='Positive Divergence Detected')
alertcondition(neg_reg_div_detected or neg_hid_div_detected, title='Negative Divergence Detected', message='Negative Divergence Detected')


// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © yechankun, redniche

///////////////////////////////////// MLP구현부 //////////////////////////////
    
f_matrix_get_nr_of_rows(_m) =>
    _rows = int(array.get(_m, 0))
    _rows

f_matrix_get_nr_of_columns(_m) =>
    _columns = int(array.get(_m, 1))
    _columns
    
f_matrix_get_size(_m) =>
    _rows    = int(array.get(_m, 0))
    _columns = int(array.get(_m, 1))
    [_rows, _columns]

//가상 2차원 매트릭스 생성 함수 - 트뷰엔 실제론 1차원 배열만 있음.
f_matrix_init(_nr_of_rows, _nr_of_columns, _fill) =>
    _size = int(_nr_of_rows * _nr_of_columns)
    _m    = array.new_float(_size + 2, _fill)
    array.set(_m, 0, _nr_of_rows), array.set(_m, 1, _nr_of_columns)
    _m
//가상 2차원 매트릭스 행과 열로 값 세팅
f_matrix_set(_m, _row_index, _column_index, _val) =>
    _columns = f_matrix_get_nr_of_columns(_m)
    array.set(_m, 2 + int((_row_index * _columns) + _column_index), _val)
//행과 열로 값 가져오기
f_matrix_get(_m, _row_index, _column_index) =>
    _columns = f_matrix_get_nr_of_columns(_m)
    _val     = array.get(_m, 2 + int((_row_index * _columns) + _column_index))
    _val
    
f_matrix_print(_m) =>
    _text = "(" + tostring(array.get(_m, 0)) + "x" + tostring(array.get(_m, 1)) + ")"
    _text := _text + "\n" + "\n"+"["
    for i = 2 to array.size(_m) - 1
        _text := _text + (i == 2 ? "" : ((i - 2) % array.get(_m, 1)) == 0 ? "]" + "\n" + "[" : " ") + tostring(array.get(_m, i))
    _text := _text + "]"
    

    


//1차원 배열만 가능함. 시그모이드 활성화 함수 => Leaky RelU
Activation_function(arr) =>
    // result = array.new_float(array.size(arr), 0)
    // for i = 0 to array.size(result) - 1
    //     array.set(result, i ,1.0 / (1.0 + exp(-array.get(arr, i))))
    // result
    result = array.new_float(array.size(arr), 0)
    for i = 0 to array.size(result) - 1
        x = array.get(arr, i)
        array.set(result, i, max(0.01 * x, x))
    result


NextGaussian(mean, sd) =>
    u = 0.0
    v = 0.0
    for i=0 to 1000
        if(not u == 0)
            break
        u := random(seed = 213214215) //Converting [0,1) to (0,1)
    
    for i=0 to 1000
        if(not v == 0)
            break
        v := random(seed = 909090215)
    result = mean + sqrt( -2.0 * log( u ) ) * cos( 2.0 * math.pi * v ) * sd
    result

//가중치 행렬 세팅
var wih = f_matrix_init(inode, hnode, 0.0)
var who = f_matrix_init(hnode, onode, 0.0)

// s = f_matrix_get_nr_of_columns(wih)
// label.new(bar_index, close-100, tostring(s))
var flag = true
if(flag)
    flag := false
    for i=0 to inode-1
        for h=0 to hnode-1
            // f_matrix_set(wih, i, h, NextGaussian(0.0,  sqrt(2.0/hnode)))  // relu용 , he
            f_matrix_set(wih, i, h, NextGaussian(0.0, pow(hnode, -0.5))) // 가중치 초기화 sigmoid용 , xavier
            
            
    for h=0 to hnode-1
        for o=0 to onode-1
            // f_matrix_set(who, h, o, NextGaussian(0.0, sqrt(2.0/onode)))   // relu용 , he
            f_matrix_set(who, h, o, NextGaussian(0.0, pow(onode, -0.5))) // 가중치 초기화 sigmoid용 , xavier
            
//학습 함수
Train(input_list, target_list) =>
    //// 정전파
    // label.new(bar_index, close-50, tostring(hidden_outputs))
    hidden_inputs =  array.new_float(hnode, 0)
    for i=0 to inode-1
        for h=0 to hnode-1
            array.set(hidden_inputs, h, array.get(hidden_inputs, h) + f_matrix_get(wih, i, h) * array.get(input_list, i))
    // label.new(bar_index, close-50, tostring(f_matrix_get(wih, 0, 0)))
    hidden_outputs = Activation_function(hidden_inputs)
    
    final_inputs =  array.new_float(onode, 0)
    for h=0 to hnode-1
        for o=0 to onode-1
            array.set(final_inputs, o, array.get(final_inputs, o) + f_matrix_get(who, h, o) * array.get(hidden_outputs, h))
    final_outputs = Activation_function(final_inputs)
    
    
    ////역전파
    output_errors = target_list
    for o=0 to onode-1
        array.set(output_errors, o, array.get(output_errors, o) - array.get(final_outputs, o))
    // label.new(bar_index, close, tostring(target_list))
    // output_errors := Activation_derivative(output_errors)
    
    hidden_errors = array.new_float(hnode, 0)
    for o=0 to onode-1
        for h=0 to hnode-1
            array.set(hidden_errors, h, array.get(hidden_errors, h) + f_matrix_get(who, h, o) * array.get(output_errors, o))
    // hidden_errors := Activation_derivative(hidden_errors)
    
    //가중치 업데이트
    for h=0 to hnode-1
        for o=0 to onode-1
            f_matrix_set(who, h, o, f_matrix_get(who, h, o) + lrate * array.get(output_errors, o) * array.get(final_outputs,o) * (1 - array.get(final_outputs,o)) * array.get(hidden_outputs, h))
    
    for i=0 to inode-1
        for h=0 to hnode-1
            f_matrix_set(wih, i, h, f_matrix_get(wih, i, h) + lrate * array.get(hidden_errors, h) * array.get(hidden_outputs,h) * (1 - array.get(hidden_outputs,h)) * array.get(input_list, i))
    final_outputs

//질의 함수
Query(input_list) =>
    //질의는 정전파만 수행
    hidden_inputs =  array.new_float(hnode, 0)
    for i=0 to inode-1
        for h=0 to hnode-1
            array.set(hidden_inputs, h, array.get(hidden_inputs, h) + f_matrix_get(wih, i, h) * array.get(input_list, i))
    hidden_outputs = Activation_function(hidden_inputs)
    final_inputs =  array.new_float(onode, 0)
    for h=0 to hnode-1
        for o=0 to onode-1
            array.set(final_inputs, o, array.get(final_inputs, o) + f_matrix_get(who, h, o) * array.get(hidden_outputs, h))
    final_outputs = Activation_function(final_inputs)
    final_outputs



//학습을 위한 입력 리스트 타겟 리스트 설정
var isDivPast = false


if(isDivPast[1])
    isDivPast := false
for i=0 to 43
    if array.get(all_divergences, i) > 0   // 과거 다이버전스 발생을 저장하려면 이런 수를 써야함. 배열의 과거 접근은 지원을 안함.
        isDivPast := true
        divMasking := divMasking + "1"
    else
        divMasking := divMasking + "0"


var pos_ml_labels = array.new_label(0)
var neg_ml_labels = array.new_label(0) 

up_pos_cnt()    //다이버전스 등록된지 얼마나 됐는지 카운팅
up_neg_cnt()

if(isMLP)
    [div_mask, past_close_diff_per, past_high_diff_per, past_low_diff_per, past_mid_diff_per] = over_cnt_pos_check(std_candle < signal_check ? signal_check : std_candle)    // 등록된지 10이상이면 std_candle 캔들 기간 뒤에 뽑아짐. div_mask가 ""이거나 나머지가 false면 등록된지 std_candle캔들이 안지난것
    [div_mask2, past_close_diff_per2, past_high_diff_per2, past_low_diff_per2, past_mid_diff_per2] = over_cnt_neg_check(std_candle < signal_check ? signal_check : std_candle)
    //학습 결과값과 비교할 위치 기준임.
    train_std_close = std_candle < signal_check ? signal_check-std_candle : 0
    if(div_mask != "")   // 상다 학습 시키기
        inputs_list = array.new_float(inode, 0.01)
        pastDivCheck = str.split(div_mask, "")        
        for i=0 to inode - (inode - 44) - 1
            if array.get(pastDivCheck, i) == "1"
                array.set(inputs_list, i, 0.99)
                // label.new(bar_index, close, "1") //디버깅용 
        // train_std_close = std_candle < 7 ? 7-std_candle : 0 
        array.set(inputs_list, inode - 1, past_close_diff_per)
        array.set(inputs_list, inode - 2, past_high_diff_per)
        array.set(inputs_list, inode - 3, past_low_diff_per)
        array.set(inputs_list, inode - 4, past_mid_diff_per)
        // label.new(bar_index, high, tostring(inputs_list))
        
        targets_list = array.new_float(onode, 0.01) //-10 -8 -6 -4 -2 0 2 4 6 8 10 
        //현재가격/과거가격   
        target_idx = int(get_target_datas())
        array.set(targets_list, target_idx, 0.99)
        
        // label.new(bar_index, close, f_matrix_print(targets_list))
        if(isShowTrainLog) 
            label.new(bar_index, high, "학습했웡")
            line.new(x1 = bar_index[train_std_close + std_candle] ,y1= close[train_std_close + std_candle], x2 = bar_index, y2 = close, width=2)
        output = array.new_float(0)
        for i = 1 to trainCnt
            output := Train(inputs_list, targets_list)
    
    if(div_mask2 != "")   //하다 학습 시키기
        inputs_list = array.new_float(inode, 0.01)
        pastDivCheck = str.split(div_mask2, "")        
        for i=0 to inode - (inode - 44) - 1
            if array.get(pastDivCheck, i) == "1"
                array.set(inputs_list, i, 0.99)
                // label.new(bar_index, close, "1") //디버깅용 
        // train_std_close = std_candle < 7 ? 7-std_candle : 0 
        array.set(inputs_list, inode - 1, past_close_diff_per2)
        array.set(inputs_list, inode - 2, past_high_diff_per2)
        array.set(inputs_list, inode - 3, past_low_diff_per2)
        array.set(inputs_list, inode - 4, past_mid_diff_per2)
        
        targets_list = array.new_float(onode, 0.01) //-10 -8 -6 -4 -2 0 2 4 6 8 10 
        //현재가격/과거가격   =
        array.set(targets_list, int(get_target_datas()), 0.99)
        // label.new(bar_index, close*0.9, tostring(inputs_list))
        if(isShowTrainLog) 
            label.new(bar_index, high, "학습했웡")
            line.new(x1 = bar_index[train_std_close + std_candle] ,y1= close[train_std_close + std_candle], x2 = bar_index, y2 = close, width=2)

        for i = 1 to trainCnt
            Train(inputs_list, targets_list)
    
    
    if(isDivPast)   //[]가 아니면 현재임.
        inputs_list = array.new_float(inode, 0.01)
        pastDivCheck = str.split(divMasking, "")        
        for i=0 to inode - (inode - 44) - 1
            if array.get(pastDivCheck, i) == "1"
                array.set(inputs_list, i, 0.99)
                
        [input_price_per, hl_high_price_per, hl_low_price_per, hl_mid_price_per] = get_input_node_datas()
        array.set(inputs_list, inode - 1, input_price_per)
        array.set(inputs_list, inode - 2, hl_high_price_per)
        array.set(inputs_list, inode - 3, hl_low_price_per)
        array.set(inputs_list, inode - 4, hl_mid_price_per)
        ///////
        
        output = Query(inputs_list)
        
        
        max = array.max(output)
        max_index = array.indexof(output, max)
        output_max = -(diff_val/2.0*11.0) + max_index*diff_val
        if(output_max == -(diff_val/2*11.0) - 1.0)
            output_max := na
        else
            array.remove(output, max_index)
            array.insert(output, max_index, 0.0)
            na
        
        s_max = array.max(output)
        s_output_max = -(diff_val/2.0*11.0) + array.indexof(output, s_max)*diff_val
        if(s_output_max == -(diff_val/2.0*11.0) - 1.0)
            s_output_max := na
            
        // label.new(bar_index, close, f_matrix_print(output))
        // label.new(bar_index, close, "약"+tostring(qu)+"%__"+ tostring(floor(max*100))+"%")
    
        ml_text_top = ""
        ml_text_bot = ""
        old_pos_ml_can_be_removed = true
        old_neg_ml_can_be_removed = true
        distances_ml = array.new_int(0)
        
        for x = 0 to 10
            div_type = -1
            for y = 0 to 3
                if array.get(all_divergences, x * 4 + y) > 0 // any divergence?
                    div_type := y
                    if (y % 2) == 1 
                        // dnumdiv_top := dnumdiv_top + 1
                        top_label_col := array.get(div_colors, y)
                    if (y % 2) == 0
                        // dnumdiv_bottom := dnumdiv_bottom + 1
                        bottom_label_col := array.get(div_colors, y)
                    if not array.includes(distances_ml, array.get(all_divergences, x * 4 + y))  // line not exist ?
                        array.push(distances_ml, array.get(all_divergences, x * 4 + y))
                        if (y % 2) == 0
                            if old_pos_ml_can_be_removed
                                old_pos_ml_can_be_removed := false
                                if not showlast and remove_last_pos_ml
                                    if array.size(pos_ml_labels) > 0  and last_pos_ml_lines > 0
                                        label.delete(array.pop(pos_ml_labels))//여기서 라벨 
                                    last_pos_ml_lines := 0
                            last_pos_ml_lines := last_pos_ml_lines + 1
                            remove_last_pos_ml := true
                            
                        if (y % 2) == 1
                            if old_neg_ml_can_be_removed
                                old_neg_ml_can_be_removed := false
                                if not showlast and remove_last_neg_ml
                                    if array.size(neg_ml_labels) > 0 and last_neg_ml_lines > 0
                                        label.delete(array.pop(neg_ml_labels))
                                    last_neg_ml_lines := 0
                            last_neg_ml_lines := last_neg_ml_lines + 1
                            remove_last_neg_ml := true
                            
            // get text for labels
            if div_type >= 0
                ml_text_top    := (div_type % 2) == 1 ? "#1: 약 " + (output_max > 0 ? "+": "") + tostring(round(output_max,2))+"% 이내\n예측강도 " + tostring(floor(max*100))+"%" + (isSecMaxView? "\n#2: 약 " + (s_output_max > 0 ? "+": "") + tostring(round(s_output_max,2))+"% 이내\n예측강도 " + tostring(floor(s_max*100))+"%" : ""): ""
                ml_text_bot    := (div_type % 2) == 0 ? "#1: 약 " + (output_max > 0 ? "+": "") + tostring(round(output_max,2))+"% 이내\n예측강도 " + tostring(floor(max*100))+"%" + (isSecMaxView? "\n#2: 약 " + (s_output_max > 0 ? "+": "") + tostring(round(s_output_max,2))+"% 이내\n예측강도 " + tostring(floor(s_max*100))+"%" : ""): ""
                
        if showindis != "Don't Show" or shownum
            if ml_text_top != ""
                if showlast
                    if array.size(neg_ml_labels) > 0    
                        for j = 0 to array.size(neg_ml_labels) - 1 
                            label.delete(array.get(neg_ml_labels, j))
                        array.clear(neg_ml_labels) // ml 라벨 지우는걸로 바꿔야함.
                array.push(neg_ml_labels, 
                              label.new( x = bar_index, 
                                         y = min(low, low[1]), 
                                         text = ml_text_top,
                                         color = top_label_col,
                                         textcolor = neg_div_text_col,
                                         style = label.style_label_up
                                         ))
            if ml_text_bot != ""
                if showlast
                    if array.size(pos_ml_labels) > 0    
                        for j = 0 to array.size(pos_ml_labels) - 1 
                            label.delete(array.get(pos_ml_labels, j))
                        array.clear(pos_ml_labels) // ml 라벨 지우는걸로 바꿔야함.
                array.push(pos_ml_labels, 
                              label.new( x = bar_index, 
                                         y = max(high, high[1]), 
                                         text = ml_text_bot,
                                         color = bottom_label_col,
                                         textcolor = pos_div_text_col,
                                         style = label.style_label_down
                                         ))

Overview

Divergence for Many Indicators v4 calculates pivot points on a chosen source to identify bullish and bearish divergences, then plots colored lines and labels on the price chart to highlight them. Settings control the divergence type, which indicators to calculate, minimum divergence count, pivot limits, and display options such as line styles and colors. The script incorporates an MLP neural network for volatility prediction using prior price highs, lows, and divergence data as inputs. It draws exclusively on the price chart and supports various divergence detection parameters.

Details

Published by

Trade-Research on GitHub

Code credit

LonesomeTheBlue, as written in the script's header

Type

Indicator, Pine Script v4

Draws

On the price chart

Category

Divergence, Oscillators & momentum, Support & resistance

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
Pivot Periodint5prd
Source for Pivot PointsstringClosesource
Divergence TypestringRegularsearchdiv
Show Indicator NamesstringFullshowindis
Minimum Number of Divergenceint1showlimit
Maximum Pivot Points to Checkint10maxpp
Maximum Bars to Checkint100maxbars
Show Divergence Numberbooltrueshownum
Show Only Last Divergenceboolfalseshowlast
Don't Wait for Confirmationboolfalsedontconfirm
Show Divergence Linesbooltrueshowlines
Show Pivot Pointsboolfalseshowpivot
Show all 40 settings
SettingTypeDefaultVariable
MACDbooltruecalcmacd
MACD Histogrambooltruecalcmacda
RSIbooltruecalcrsi
Stochasticbooltruecalcstoc
CCIbooltruecalccci
Momentumboolfalsecalcmom
OBVbooltruecalcobv
VWmacdbooltruecalcvwmacd
Chaikin Money Flowbooltruecalccmf
Money Flow Indexbooltruecalcmfi
Check External Indicatorboolfalsecalcext
External Indicatorsourcecloseexternalindi
Positive Regular Divergencecolorcolor.yellowpos_reg_div_col
Negative Regular Divergencecolorcolor.navyneg_reg_div_col
Positive Hidden Divergencecolorcolor.limepos_hid_div_col
Negative Hidden Divergencecolorcolor.redneg_hid_div_col
Positive Divergence Text Colorcolorcolor.blackpos_div_text_col
Negative Divergence Text Colorcolorcolor.whiteneg_div_text_col
Regular Divergence Line StylestringSolidreg_div_l_style_
Hdden Divergence Line StylestringDashedhid_div_l_style_
Regular Divergence Line Widthint2reg_div_l_width
Hidden Divergence Line Widthint1hid_div_l_width
단순 신경망 학습booltrueisMLP
은닉층 노드 수int500hnode
학습률float0.1lrate
몇 캔들 전과의 가격차이로 학습하는 기준int14train_candle
몇 캔들 뒤를 예측?int7std_candle
중복학습 횟수int1trainCnt
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

23 stars

This indicator collection calculates and plots previous daily high and low price levels on the chart to identify potential supply and demand zones. It includes real-time intraday high and low calculations, RSI divergence detection across a customizable period

Indicator v4 Support & resistanceDivergence
Updated 3 years ago · None stated GitHub repository of Daily High and Low Strategy

This indicator implements a full Chanlun pipeline on the price chart. It merges contained bars, marks top and bottom fractals, and connects alternating fractals into strokes. Overlapping strokes form pivot boxes, and MACD area ratios flag trend or consolidatio

Indicator v6 Support & resistanceDivergence
Updated 2 months ago · GPL-3.0 GitHub repository of 缠论 - 分型与笔 [Chanlun Core]
5 stars

This indicator plots RSI(14) on the price chart along with regular and hidden bullish and bearish divergences. It detects divergences by comparing price highs and lows to RSI values using pivot points with configurable lookback bars. Signals appear as triangle

Indicator v4 Oscillators & momentumDivergence
Updated 2 years ago · None stated GitHub repository of CB RSI (Divergence and OB/OS)

This price-chart indicator finds swing highs and lows with a user-set pivot length and classifies them as higher high, lower high, higher low, or lower low. It tracks a trend state and the latest swing signal from those pivots. The same swing comparison is run

Indicator v5 Candlestick patternsSupport & resistance
Updated 5 months ago · None stated GitHub repository of Price Action Candles with Pivot Trendlines

SAB PRO Pivot Master

by IAMATOMIC001
3 stars

SAB PRO Pivot Master is a price-chart overlay that builds an RSX-style oscillator from a chosen source and length, then compares price extremes with that oscillator over a lookback window to mark pivots and bullish or bearish divergence. Overbought and oversol

Indicator v5 Oscillators & momentumVolatility & bands
Updated 12 months ago · None stated GitHub repository of SAB PRO Pivot Master
2 stars

Divergence-Support/Resistence combines dual Zigzag pivot detection with momentum oscillators to identify divergence patterns and plot support and resistance levels directly on the price chart. Users can select from various built-in oscillators, such as RSI, CC

Indicator v5 DivergenceSupport & resistance Repaints
Updated 8 months ago · None stated GitHub repository of Divergence-Support/Resistence

More indicators

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers