Trading range display with Box
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © potatoshop

//@version=5
strategy("Trading range display with Box","Box", overlay = true,process_orders_on_close=true,calc_on_every_tick=true, max_boxes_count=500, initial_capital=1000, default_qty_type=strategy.percent_of_equity,
  commission_type=strategy.commission.percent,default_qty_value=10,commission_value=0.04,slippage=2)

// Just simple strategy for test. Put your strategy here. 
a= ta.sma(close, 14)
b= ta.sma(close, 20)
plot(a,color=color.white)
plot(b,color=color.blue)

longCondition = ta.crossover(a,b)
if (longCondition)
    strategy.entry("L", strategy.long)

closeCondition = ta.crossunder(a,b)
if (closeCondition)
    strategy.close("L",comment = "CL")

// From here on, just Copy and Paste  
// 1.Making the trading signal to get the (left,right) for Box.     left, right 를 구하기 위한 시그널 만들기. 
is_trading = strategy.position_size != 0                     // 거래 포지션이 0이 아니면 거래중으로 판단하며, true를 리턴.
is_trading_L = strategy.position_size > 0
is_trading_S = strategy.position_size < 0

tradingstart = (is_trading == true and is_trading[1] == false)     
tradingstart_L =  (is_trading_L == true and is_trading_L[1] == false)  
tradingstart_S =  (is_trading_S == true and is_trading_S[1] == false)  
tradingend = (is_trading == false and is_trading[1] == true)           
tradingend_L =  (is_trading_L == false and is_trading_L[1] == true)    
tradingend_S =  (is_trading_S == false and is_trading_S[1] == true)    
// plotchar(tradingstart,text="start",textcolor = color.white) // check the signal 시그널 확인용.
// plotshape(tradingend,text="End",textcolor = color.white)   


// 2.Get the left, right.                        left, right 에 좌표 기준 만들어 주기. 
var left_L = bar_index , var left_S = bar_index 
var right_L = bar_index , var right_S = bar_index 

if tradingstart_L 
    left_L := bar_index -1                                       // 거래 시작이 확정된 봉이 진짜 시점보다 1봉 이후에 나오므로 일부러 -1을 했다.
if tradingend_L or (barstate.islast and is_trading_L)              // 과거데이타를 처리할때는 거래 종료 시점만 필요하지만, 현재 거래중일때는 지금의 정보를 계속 업데이트 시켜준다. 
    right_L := bar_index -1

if tradingstart_S
    left_S := bar_index -1                                       
if tradingend_S or (barstate.islast and is_trading_S)               
    right_S := bar_index -1

//3.We need two box to make body and wick.    body 와 wick 느낌으로 만들기 위해서 top, bottom을 각각 나누어 만들었다. 
entry = barstate.islast and is_trading? strategy.opentrades.entry_price(strategy.opentrades-1) : strategy.closedtrades.entry_price(strategy.closedtrades-1) // 진입한 가격을 두 상황에 나누어 정의해 준다.
exit = barstate.islast ? close : strategy.closedtrades.exit_price(strategy.closedtrades-1)                                              // 현재 거래중일때는 현재종가가 기준이다.

// body
top_body = math.max(entry,exit)            
bottom_body = math.min(entry,exit)
// wick
len_L = right_L and left_L ?  right_L - left_L +1 : 1   
high_session_L = ta.highest(high,len_L)
low_session_L = ta.lowest(low,len_L)
len_S = right_S and left_S ?  right_S - left_S +1 : 1   
high_session_S = ta.highest(high,len_S)
low_session_S = ta.lowest(low,len_S)
// Box color part.
DEFAULT_COLOR_GROWTH = color.rgb(0, 150, 136, 50)
DEFAULT_COLOR_FALL = color.rgb(244, 67, 54, 50)
color_growth = input.color(DEFAULT_COLOR_GROWTH, title='', inline='Body')
color_fall = input.color(DEFAULT_COLOR_FALL, title='Body', inline='Body')
color_border_growth = color.rgb(color.r(color_growth), color.g(color_growth), color.b(color_growth), 50)
color_border_fall = color.rgb(color.r(color_fall), color.g(color_fall), color.b(color_fall), 50)

past_profit = strategy.closedtrades.profit(strategy.closedtrades-1)
now_profit = strategy.opentrades.profit(strategy.opentrades-1)
colorBD =  barstate.islast and is_trading? (now_profit > 0 ? color_growth : color_fall) : (past_profit > 0 ? color_growth : color_fall)                               // Body color
colorBL =  barstate.islast and is_trading? (now_profit > 0 ? color_border_growth : color_border_fall) : (past_profit > 0 ? color_border_growth : color_border_fall)//  : (exit - entry > 0 ? color_border_fall : color_border_growth)  // wick color

// 4. Box part
var box last_box1_L = na
var box last_box2_L = na

// Long Position Box
if tradingend_L and not barstate.isrealtime // 1. 과거 데이타로 확인된 봉에서만 실행.
    box.delete(last_box1_L) , box.delete(last_box2_L)
    box.new(left_L,high_session_L,right_L,low_session_L, border_color = colorBL, bgcolor = colorBL)
    box.new(left_L,top_body,right_L,bottom_body, border_color = colorBD, bgcolor = colorBD)
    left_L := na
    right_L := na

if barstate.islast                         // 2. 현재봉에서 거래중인지 확인후 실행. 
    if tradingend_L
        last_box1_L := na
        last_box2_L := na        
    else if is_trading_L
        right_L := bar_index -1              
        box.delete(last_box1_L) , box.delete(last_box2_L)
        last_box1_L := box.new(left_L,high_session_L,right_L,low_session_L, border_color = colorBL, bgcolor = colorBL)
        last_box2_L := box.new(left_L,top_body,right_L,bottom_body, border_color = colorBD, bgcolor = colorBD)

// Short Position Box
var box last_box1_S = na
var box last_box2_S = na

if tradingend_S and not barstate.isrealtime 
    box.delete(last_box1_S) , box.delete(last_box2_S)
    box.new(left_S,high_session_S,right_S,low_session_S, border_color = colorBL, bgcolor = colorBL)
    box.new(left_S,top_body,right_S,bottom_body, border_color = colorBD, bgcolor = colorBD)
    left_S := na
    right_S := na

if barstate.islast                         
    if tradingend
        last_box1_S := na
        last_box2_S := na        
    else if is_trading_S
        right_S := bar_index -1              
        box.delete(last_box1_S) , box.delete(last_box2_S)
        last_box1_S := box.new(left_S,high_session_S,right_S,low_session_S, border_color = colorBL, bgcolor = colorBL)
        last_box2_S := box.new(left_S,top_body,right_S,bottom_body, border_color = colorBD, bgcolor = colorBD)
