Price - TP/SL
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © DinGrogu

//@version=5

library('price')

// ############################################################
// # FUNCTIONS
// ############################################################

// Get the limit or stop loss price.
f_limit_stop_price(_price, _percentage, _bars_minimum=0, _bars_since_entry=0) =>
    price = 0.0
    if (_percentage > 0)
        if (_bars_minimum == 0)
            price := _price
        else if (_bars_minimum > 0)
            if (_bars_since_entry > _bars_minimum)
                price := _price
            else
                price := na
        else
            price := na
    else
        price := na

    response = price

// @function - Get the take profit price.
f_take_profit_price(_entry_price, _take_profit_percentage, _atr_length=0) =>
    atr_enabled = _atr_length > 0
    atr = atr_enabled ? ta.sma(ta.tr, _atr_length) : 0
    _take_profit_percentage > 0 ? atr_enabled ? _entry_price + (atr * _take_profit_percentage) : _entry_price + (_entry_price * (_take_profit_percentage / 100)) : na

// @function - Get the stop loss price.
f_stop_loss_price(_entry_price, _stop_loss_percentage, _atr_length=0) =>
    atr_enabled = _atr_length > 0
    atr = atr_enabled ? ta.sma(ta.tr, _atr_length) : 0
    _stop_loss_percentage > 0 ? atr_enabled ? _entry_price - (atr * _stop_loss_percentage) : _entry_price - (_entry_price * (_stop_loss_percentage / 100)) : na

// Calculate the difference between 2 assets in percentage.
f_difference(_src_1, _src_2) =>
    math.abs(((_src_1 - _src_2) / _src_2) * 100)

// A condition for percentage differences.
f_difference_condition(_src_1, _src_2, _percentage) =>
    _src_2 > _src_1 and f_difference(_src_1, _src_2) > _percentage

// Price change up.
f_up(_length, _percentage, _src=close, _low=low, _high=high) =>
    _lowest = _low[_length]
    change = _lowest < _src and math.abs((_high - _lowest) / _lowest * 100) > _percentage

// Price change down.
f_down(_length, _percentage, _src=close, _low=low, _high=high) =>
    _highest = _high[_length]
    change = _highest > _src and math.abs((_low - _highest) / _highest * 100) > _percentage

// Get the latest price from lower timeframe.
f_lower_timeframe(_prices, _last=false) =>
    price = 0.0
    if (array.size(_prices) > 0)
        if (_last)
            price := array.last(_prices)
        else
            price := array.first(_prices)
    price

// Get the order size from properties tab.
f_strategy_order_size() =>
    if (strategy.closedtrades > 0)
        order_size = strategy.initial_capital / strategy.closedtrades.entry_price(0)
        math.round(strategy.closedtrades.size(0) / order_size, 2) * 100
    else
        order_size = 100

// Get the commission from properties tab.
f_strategy_commission() =>
    strategy.closedtrades > 0 ? math.round(strategy.closedtrades.commission(0) / strategy.initial_capital * 100, 2) / 2 : 0

// ############################################################
// # EXPORT FUNCTIONS
// ############################################################

// function - Calculate the limit or stop price.
//
// usage example:
// limit_price = price.take_profit_price(take_profit_price, take_profit_percentage, take_profit_atr_length, take_profit_bars, bars_since_opened)
// stop_price = price.stop_loss_price(stop_loss_price, stop_loss_percentage, stop_loss_atr_length, stop_loss_bars, bars_since_opened)
// strategy.exit(id='TP/SL', comment='TP', from_entry='LONG', limit=limit_price, stop=stop_price)

// @param _price <float> - The source input.
// @param _percentage <float> - The percentage.
// @param _atr_length <int> - ATR length (0 to use percentage).
// @param _bars_minimum <int> - The number of bars to compare with elapsed bars.
// @param _bars_since_entry <int> - The number of bars elapsed.
export take_profit_price(series float _price, float _percentage, int _atr_length=0, int _bars_minimum=0, int _bars_since_entry=0) =>
    price = f_take_profit_price(_price, _percentage, _atr_length)
    f_limit_stop_price(price, _percentage, _bars_minimum, _bars_since_entry)

// @param _price <float> - The source input.
// @param _percentage <float> - The percentage.
// @param _atr_length <int> - ATR length (0 to use percentage).
// @param _bars_minimum <int> - The number of bars to compare with elapsed bars.
// @param _bars_since_entry <int> - The number of bars elapsed.
export stop_loss_price(series float _price, float _percentage, int _atr_length=0, int _bars_minimum=0, int _bars_since_entry=0) =>
    price = f_stop_loss_price(_price, _percentage, _atr_length)
    f_limit_stop_price(price, _percentage, _bars_minimum, _bars_since_entry)

// function - Get the difference in percentage between 2 prices.
// @param _src_1 <series float> - Source 1.
// @param _src_2 <series float> - Source 2.
export difference(series float _src_1, series float _src_2) =>
    f_difference(_src_1, _src_2)

// @param _length <simple int> - Lookback length.
// @param _percentage <simple float> - The percentage.
// @param _src <series float> - Source.
// @param _low <series float> - Low.
// @param _high <series float> - High
export up(simple int _length, simple float _percentage, series float _src=close, series float _low=low, series float _high=high) =>
    f_up(_length, _percentage, _src, _low, _high)

// @param _length <simple int> - Lookback length.
// @param _percentage <simple float> - The percentage.
// @param _src <series <series float> - Source.
// @param _low <series float> - Low.
// @param _high <series float> - High.
export down(simple int _length, simple float _percentage, series float _src=close, series float _low=low, series float _high=high) =>
    f_down(_length, _percentage, _src, _low, _high)

// function - Get lower timeframe price.
//
// usage example:
// price.ltf(request.security_lower_tf(ticker, '1', close))
//
// @param _prices <array float> - timeframe.
// @param _last <bool> - Show the last bar close instead of first.
export ltf(array<float> _prices, bool _last=false) =>
    f_lower_timeframe(_prices, _last)

// function - Get the strategy position size price.
export position() =>
    math.round_to_mintick(strategy.position_avg_price)

// function - Get the order size from the properties tab.
export order_size() =>
    f_strategy_order_size()

// function - Get the commission from the properties tab.
export commission() =>
    f_strategy_commission()
