Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //@version=5
- strategy(title="thwlp Upgraded damn it-_-", overlay=true)
- import ZenAndTheArtOfTrading/ZenLibrary/2 as l_zen
- import HeWhoMustNotBeNamed/RecursiveAlerts/2 as ra
- // Step 1: Get inputs
- lookback = input.int(defval =2, title="Lookback", minval=2)
- tp_percent = input.float(defval =1, title="Take Profit (%)", minval=0.01,step = 0.5)*0.01
- sl_percent = input.float(defval =1, title="Stop Loss (%)", minval=0.001,step = 0.5)*0.01
- atr_bool = input.bool(false,title = "Atr use")
- atr_multi = input.float(defval = 1.5, title="ATR Multiplier", minval=0.01,step = 0.5)
- atr_len = input.int(defval =14,title = "ATR Length",minval = 1)
- var g_tester = 'Back tester table'
- i_startTime = input.time(title='Start Date', defval=timestamp('01 Jan 2020 00:00 +0100'), group=g_tester, tooltip='Date & time to begin trading from')
- i_endTime = input.time(title='End Date', defval=timestamp('1 Jan 2099 00:00 +0100'), group=g_tester, tooltip='Date & time to stop trading')
- var g_pause = "Pause trades"
- i_tradePause = input.int(title= "For how many bars?", defval=0, minval = 0, group= g_pause, tooltip="Pauses trades for X bars after a closed trade\n0 = OFF")
- i_tradePauseLoss = input.bool(title= "Only loosing trades", defval = true, inline = "4", group= g_pause)
- i_tradeLossNum = input.int(title= "| How much?", defval=1, minval = 1, group= g_pause, inline = "4", tooltip="Number of loosing trades in a row")
- i_drawTester = input.bool(title='Show back tester', defval=true, group=g_tester, tooltip='Turn on/off inbuilt backtester display', inline = "backtester1")
- i_testerPosition = input.string(title='', defval="Top right", options = ["Top right", "Top left", "Bottom right", "Bottom left"], group=g_tester, tooltip='Position of the backtester table', inline = "backtester1")
- i_rr = input.float(title='R:R', defval=1.0, group=g_tester, tooltip='Risk:Reward profile')
- startBalance = input.float(title='Starting Balance', defval=100.0, group=g_tester, tooltip='Your starting balance for the custom inbuilt tester system')
- riskPerTrade = input.float(title='Risk Per Trade', defval=1.0, group=g_tester, tooltip='Your desired % risk per trade (as a whole number)')
- atr = ta.atr(atr_len)
- entry = strategy.position_avg_price
- var int pos_bi = na
- // Step 2: Calculate TP and SL
- var atr_stop_loss_l = 0.0
- var atr_stop_loss_s = 0.0
- // sl_atr = 0.0
- float tp_s = entry * (1 - tp_percent)
- float sl_s = not atr_bool ? entry * (1 + sl_percent) : atr_stop_loss_s
- float tp_l = entry * (1 + tp_percent)
- float sl_l = not atr_bool ? entry * (1 - sl_percent) : atr_stop_loss_l
- //-------------------------
- //Alert Templates Creation
- keys = array.from("{entry}", "{stop}", "{target}")
- //Step 2. Create a default alert template for long trades
- long_template = '{\n
- \t"trade_type": "long",\n
- \t"entry": {entry},\n
- \t"stop_loss": {stop},\n
- \t"take_profit": {target}\n
- }'
- //Step 3. Create a default alert template for short trades
- short_template = '{\n
- \t"trade_type": "short",\n
- \t"entry": {entry},\n
- \t"stop_loss": {stop},\n
- \t"take_profit": {target}\n
- }'
- var alertme = '🔔 The Alerts Alertatron'
- alert_freq = input.string("Once per bar",title = "Alert Frequency",group = alertme,options = ["Once per bar","Once per close","All"])
- if alert_freq == "Once per bar"
- alert_freq := alert.freq_once_per_bar
- else if alert_freq =="Once per close"
- alert_freq := alert.freq_once_per_bar_close
- else if alert_freq == "All"
- alert_freq := alert.freq_all
- i_usemessage = input.bool(false, "Show Alertatron bot message", group = alertme)
- entry_long = input.text_area(title="API Entry - Long", defval=long_template, group = alertme)
- exit_long = input.text_area(title="API Exit - Long", defval=" ", group = alertme)
- entry_short = input.text_area(defval=short_template,title = "API Entry - Short",group = alertme)
- exit_short = input.text_area(defval=" ",title = "API Exit - Short",group = alertme)
- // Step 3: Entry condition for long
- long_condition = barstate.isconfirmed and close < low[1] and high[1] < high[lookback + 1] and strategy.position_size == 0
- // Step 4: Entry condition for short
- short_condition = barstate.isconfirmed and close > high[1] and low[1] > low[lookback + 1] and strategy.position_size == 0
- strategy.risk.allow_entry_in(strategy.direction.all)
- c_dateFilter = time >= i_startTime and time <= i_endTime
- c_sinceLastTrade = ta.barssince(strategy.closedtrades > strategy.closedtrades[1])
- c_sinceLastLossTrade = ta.barssince(strategy.losstrades > strategy.losstrades[1])
- var c_countLosstrades = 0
- switch
- strategy.losstrades > strategy.losstrades[1] => c_countLosstrades += 1
- strategy.wintrades > strategy.wintrades[1] => c_countLosstrades := 0
- c_countLosstrades == i_tradeLossNum and c_sinceLastLossTrade > i_tradePause => c_countLosstrades := 0
- long_condition or short_condition => c_countLosstrades := 0
- c_longCondition = c_dateFilter and (i_tradePauseLoss ? (i_tradePause != 0 ? c_countLosstrades < i_tradeLossNum : true) and
- (strategy.losstrades != 0 ? c_sinceLastLossTrade >= i_tradePause : true) : (strategy.closedtrades != 0 ? c_sinceLastTrade >= i_tradePause : true)) and
- long_condition
- c_shortCondition = c_dateFilter and (i_tradePauseLoss ? (i_tradePause != 0 ? c_countLosstrades < i_tradeLossNum : true) and
- (strategy.losstrades != 0 ? c_sinceLastLossTrade >= i_tradePause : true) : (strategy.closedtrades != 0 ? c_sinceLastTrade >= i_tradePause : true)) and
- short_condition
- if c_longCondition
- long_values = array.from(str.tostring(entry), str.tostring(sl_l), str.tostring(tp_l))
- long_alert_message = ra.updateAlertTemplate(entry_long, keys, long_values)
- strategy.entry("Long", strategy.long, alert_message = i_usemessage ? long_alert_message : "Enter Long")
- atr_stop_loss_l := close - (atr * atr_multi)
- alert(long_alert_message, alert_freq)
- if strategy.position_size > 0
- // tp_l := entry * (1 + tp_percent)
- // sl_l := not atr_bool ? entry * (1 - sl_percent) : atr_stop_loss_l
- strategy.exit("Take Profit", "Long", limit=tp_l, stop=sl_l, comment_profit="Take Profit", comment_loss="Stoploss", alert_message = i_usemessage ? exit_long : na)
- alert(exit_long, alert_freq)
- if c_shortCondition
- short_values = array.from(str.tostring(entry), str.tostring(sl_s), str.tostring(tp_s))
- short_alert_message = ra.updateAlertTemplate(entry_short, keys, short_values)
- strategy.entry("Short", strategy.short, alert_message = i_usemessage ? short_alert_message : "Enter Short")
- atr_stop_loss_s := close + (atr * atr_multi)
- alert(short_alert_message, alert_freq)
- if strategy.position_size < 0
- // tp_s := entry * (1 - tp_percent)
- // sl_s := not atr_bool ? entry * (1 + sl_percent) : atr_stop_loss_s
- strategy.exit("Short Exit", "Short", limit=tp_s, stop=sl_s, comment_profit="Take profit", comment_loss="Stoploss", alert_message = i_usemessage ? exit_short : na)
- alert(exit_short, alert_freq)
- //-----------------------------------------------------------------------------
- // Step 5: Exit strategy with take profit or stop loss
- //TP LONG AND SHORT
- // pos_bi := bar_index
- // pos_bi := bar_index
- //ATR sl for long and short
- if atr_bool == true and strategy.position_size > 0
- strategy.exit("ATR SL", "Long", stop=atr_stop_loss_l)
- alert(exit_long, alert_freq)
- // pos_bi := bar_index
- if atr_bool == true and strategy.position_size < 0
- strategy.exit("ATR SL", "Short", stop=atr_stop_loss_s)
- alert(exit_short, alert_freq)
- // pos_bi := bar_index
- // if not atr_bool
- // //Normal SL %
- // if strategy.position_size > 0
- // strategy.exit("Stop Loss", "Long", stop=sl_l, alert_message = i_usemessage ? exit_long : na)
- // alert(exit_long, alert_freq)
- // // pos_bi := bar_index
- // if strategy.position_size < 0
- // strategy.exit("Stop Loss", "Short", stop=sl_s, alert_message = i_usemessage ? exit_short : na)
- // alert(exit_short, alert_freq)
- //-----------------------------------------------------------------------------
- //Box
- // if strategy.position_size[1] != 0 and strategy.position_size == 0
- // tn = strategy.closedtrades - 1
- // penp = strategy.closedtrades.entry_price(tn)
- // pexp = strategy.closedtrades.exit_price(tn)
- // box.new(pos_bi, math.max(pexp, penp), bar_index, math.min(penp, pexp), border_color=penp < pexp ? color.green : color.red, bgcolor=penp < pexp ? color.new(color.green, 75) : color.new(color.red, 75))
- // Plot stop loss values for confirmation
- plot(series= sl_l, color=color.new(color.red, 0), style=plot.style_linebr, linewidth=2, title='Long Stop Loss')
- plot(series= sl_s, color=color.new(color.red, 0), style=plot.style_linebr, linewidth=2, title='Short Stop Loss')
- plot(series= tp_l, color=color.new(color.green, 0), style=plot.style_linebr, linewidth=2, title='Long Takeprofit')
- plot(series= tp_s, color=color.new(color.green, 0), style=plot.style_linebr, linewidth=2, title='Short Takeprofit')
- // // Used for debug and check the ATR SL value
- // plot(atr_bool ==true and strategy.position_size != 0 ? atr_stop_loss_l : na, color=color.new(color.red, 100), title='ATR Stop Value')
- // // Plot take profit values for confirmation
- // plot(series=strategy.position_size > 0 and useTakeProfit ? TP1longPrice : na, color=color.new(color.green, 0), style=plot.style_linebr, linewidth=3, title='Long Take Profit 1')
- // plot(series=strategy.position_size < 0 and useTakeProfit ? TP1shortPrice : na, color=color.new(color.red, 0), style=plot.style_linebr, linewidth=3, title='Short Take Profit 1')
- // // Used for debug and check the ATR TP value
- // plot(use_TP_ATR and strategy.position_size != 0 ? RR_TP1_ATR * rewardRatioATR1 : na, color=color.new(color.green, 100), title='ATR TP1 Value')
- // plot(strategy.position_size != 0 ? strategy.position_avg_price : na, title = "Entry Price", style = plot.style_linebr, linewidth = 2)
- // --- BEGIN TESTER CODE --- //
- // Declare performance tracking variables
- var balance = startBalance
- var maxBalance = 0.0
- var totalWins = 0
- var totalLoss = 0
- // Detect winning trades
- if strategy.wintrades != strategy.wintrades[1]
- balance := balance + riskPerTrade / 100 * balance * i_rr
- totalWins := totalWins + 1
- if balance > maxBalance
- maxBalance := balance
- maxBalance
- // Detect losing trades
- if strategy.losstrades != strategy.losstrades[1]
- balance := balance - riskPerTrade / 100 * balance
- totalLoss := totalLoss + 1
- // // Prepare stats table
- // var table testTable = table.new(i_testerPosition == "Top right" ? position.top_right : i_testerPosition == "Top left" ? position.top_left : i_testerPosition == "Bottom right" ? position.bottom_right :position.bottom_left, 5, 2, border_width=2)
- // f_fillCell(_table, _column, _row, _title, _value, _bgcolor, _txtcolor) =>
- // _cellText = _title + '\n' + _value
- // table.cell(_table, _column, _row, _cellText, bgcolor=_bgcolor, text_color=_txtcolor)
- // // Draw stats table
- // var bgcolor = color.new(color.black, 0)
- // if i_drawTester
- // if barstate.islastconfirmedhistory
- // // Update table
- // dollarReturn = balance - startBalance
- // f_fillCell(testTable, 0, 0, 'Total Trades:', str.tostring(strategy.closedtrades), bgcolor, color.white)
- // f_fillCell(testTable, 0, 1, 'Win Rate:', str.tostring(l_zen.truncate(strategy.wintrades / strategy.closedtrades * 100, 2)) + '%', (strategy.wintrades / strategy.closedtrades * 100) >= 50 ? color.green : bgcolor, color.white)
- // f_fillCell(testTable, 1, 0, 'Starting:', '$' + str.tostring(startBalance), bgcolor, color.white)
- // f_fillCell(testTable, 1, 1, 'Ending:', '$' + str.tostring(l_zen.truncate(balance, 2)), balance > startBalance ? color.green : bgcolor, color.white)
- // // --- END BACKTESTER CODE --- //
- // Dashboard Table Text Size
- i_tableTextSize = input.string(title="Dashboard Size", defval="Small", options=["Auto", "Huge", "Large", "Normal", "Small", "Tiny"], group="Dashboards")
- table_text_size(s) =>
- switch s
- "Auto" => size.auto
- "Huge" => size.huge
- "Large" => size.large
- "Normal" => size.normal
- "Small" => size.small
- => size.tiny
- tableTextSize = table_text_size(i_tableTextSize)
- /// Performance Summary Dashboard
- // â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘
- // Inspired by https://www.tradingview.com/script/uWqKX6A2/ - Thanks VertMT
- i_showDashboard = input.bool(title="Performance Summary", defval=true, group="Dashboards", inline="Show Dashboards")
- f_fillCell(_table, _column, _row, _title, _value, _bgcolor, _txtcolor) =>
- _cellText = _title + "\n" + _value
- table.cell(_table, _column, _row, _cellText, bgcolor=_bgcolor, text_color=_txtcolor, text_size=tableTextSize)
- // Draw dashboard table
- if i_showDashboard
- var bgcolor = color.new(color.black,0)
- // Keep track of Wins/Losses streaks
- newWin = (strategy.wintrades > strategy.wintrades[1]) and (strategy.losstrades == strategy.losstrades[1]) and (strategy.eventrades == strategy.eventrades[1])
- newLoss = (strategy.wintrades == strategy.wintrades[1]) and (strategy.losstrades > strategy.losstrades[1]) and (strategy.eventrades == strategy.eventrades[1])
- varip int winRow = 0
- varip int lossRow = 0
- varip int maxWinRow = 0
- varip int maxLossRow = 0
- if newWin
- lossRow := 0
- winRow := winRow + 1
- if winRow > maxWinRow
- maxWinRow := winRow
- if newLoss
- winRow := 0
- lossRow := lossRow + 1
- if lossRow > maxLossRow
- maxLossRow := lossRow
- // Prepare stats table
- var table dashTable = table.new(position.top_right, 1, 15, border_width=1)
- if barstate.islastconfirmedhistory
- // Update table
- dollarReturn = strategy.netprofit
- f_fillCell(dashTable, 0, 0, "Start:", str.format("{0,date,long}", strategy.closedtrades.entry_time(0)) , bgcolor, color.white) // + str.format(" {0,time,HH:mm}", strategy.closedtrades.entry_time(0))
- f_fillCell(dashTable, 0, 1, "End:", str.format("{0,date,long}", strategy.opentrades.entry_time(0)) , bgcolor, color.white) // + str.format(" {0,time,HH:mm}", strategy.opentrades.entry_time(0))
- _profit = (strategy.netprofit / strategy.initial_capital) * 100
- f_fillCell(dashTable, 0, 2, "Net Profit:", str.tostring(_profit, '##.##') + "%", _profit > 0 ? color.teal : color.maroon, color.white)
- _numOfDaysInStrategy = (strategy.opentrades.entry_time(0) - strategy.closedtrades.entry_time(0)) / (1000 * 3600 * 24)
- f_fillCell(dashTable, 0, 3, "Percent Per Day", str.tostring(_profit / _numOfDaysInStrategy, '#########################.#####')+"%", _profit > 0 ? color.teal : color.maroon, color.white)
- _winRate = ( strategy.wintrades / strategy.closedtrades ) * 100
- f_fillCell(dashTable, 0, 4, "Percent Profitable:", str.tostring(_winRate, '##.##') + "%", _winRate < 50 ? color.maroon : _winRate < 75 ? #999900 : color.teal, color.white)
- f_fillCell(dashTable, 0, 5, "Profit Factor:", str.tostring(strategy.grossprofit / strategy.grossloss, '##.###'), strategy.grossprofit > strategy.grossloss ? color.teal : color.maroon, color.white)
- f_fillCell(dashTable, 0, 6, "Total Trades:", str.tostring(strategy.closedtrades), bgcolor, color.white)
- f_fillCell(dashTable, 0, 8, "Max Wins In A Row:", str.tostring(maxWinRow, '######') , bgcolor, color.white)
- f_fillCell(dashTable, 0, 9, "Max Losses In A Row:", str.tostring(maxLossRow, '######') , bgcolor, color.white)
- // Monthly Table Performance Dashboard By @QuantNomad
- // â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘
- i_showMonthlyPerformance = input.bool(true, 'Monthly Performance', group='Dashboards', inline="Show Dashboards")
- i_monthlyReturnPercision = 2
- if i_showMonthlyPerformance
- new_month = month(time) != month(time[1])
- new_year = year(time) != year(time[1])
- eq = strategy.equity
- bar_pnl = eq / eq[1] - 1
- cur_month_pnl = 0.0
- cur_year_pnl = 0.0
- // Current Monthly P&L
- cur_month_pnl := new_month ? 0.0 :
- (1 + cur_month_pnl[1]) * (1 + bar_pnl) - 1
- // Current Yearly P&L
- cur_year_pnl := new_year ? 0.0 :
- (1 + cur_year_pnl[1]) * (1 + bar_pnl) - 1
- // Arrays to store Yearly and Monthly P&Ls
- var month_pnl = array.new_float(0)
- var month_time = array.new_int(0)
- var year_pnl = array.new_float(0)
- var year_time = array.new_int(0)
- last_computed = false
- if (not na(cur_month_pnl[1]) and (new_month or barstate.islastconfirmedhistory))
- if (last_computed[1])
- array.pop(month_pnl)
- array.pop(month_time)
- array.push(month_pnl , cur_month_pnl[1])
- array.push(month_time, time[1])
- if (not na(cur_year_pnl[1]) and (new_year or barstate.islastconfirmedhistory))
- if (last_computed[1])
- array.pop(year_pnl)
- array.pop(year_time)
- array.push(year_pnl , cur_year_pnl[1])
- array.push(year_time, time[1])
- last_computed := barstate.islastconfirmedhistory ? true : nz(last_computed[1])
- // Monthly P&L Table
- var monthly_table = table(na)
- if (barstate.islastconfirmedhistory)
- monthly_table := table.new(position.bottom_right, columns = 14, rows = array.size(year_pnl) + 1, border_width = 1)
- table.cell(monthly_table, 0, 0, "", bgcolor = #cccccc, text_size=tableTextSize)
- table.cell(monthly_table, 1, 0, "Jan", bgcolor = #cccccc, text_size=tableTextSize)
- table.cell(monthly_table, 2, 0, "Feb", bgcolor = #cccccc, text_size=tableTextSize)
- table.cell(monthly_table, 3, 0, "Mar", bgcolor = #cccccc, text_size=tableTextSize)
- table.cell(monthly_table, 4, 0, "Apr", bgcolor = #cccccc, text_size=tableTextSize)
- table.cell(monthly_table, 5, 0, "May", bgcolor = #cccccc, text_size=tableTextSize)
- table.cell(monthly_table, 6, 0, "Jun", bgcolor = #cccccc, text_size=tableTextSize)
- table.cell(monthly_table, 7, 0, "Jul", bgcolor = #cccccc, text_size=tableTextSize)
- table.cell(monthly_table, 8, 0, "Aug", bgcolor = #cccccc, text_size=tableTextSize)
- table.cell(monthly_table, 9, 0, "Sep", bgcolor = #cccccc, text_size=tableTextSize)
- table.cell(monthly_table, 10, 0, "Oct", bgcolor = #cccccc, text_size=tableTextSize)
- table.cell(monthly_table, 11, 0, "Nov", bgcolor = #cccccc, text_size=tableTextSize)
- table.cell(monthly_table, 12, 0, "Dec", bgcolor = #cccccc, text_size=tableTextSize)
- table.cell(monthly_table, 13, 0, "Year", bgcolor = #999999, text_size=tableTextSize)
- for yi = 0 to array.size(year_pnl) - 1
- table.cell(monthly_table, 0, yi + 1, str.tostring(year(array.get(year_time, yi))), bgcolor = #cccccc, text_size=tableTextSize)
- y_color = array.get(year_pnl, yi) > 0 ? color.new(color.teal, transp = 40) : color.new(color.gray, transp = 40)
- table.cell(monthly_table, 13, yi + 1, str.tostring(math.round(array.get(year_pnl, yi) * 100, i_monthlyReturnPercision)), bgcolor = y_color, text_color=color.new(color.white, 0),text_size=tableTextSize)
- for mi = 0 to array.size(month_time) - 1
- m_row = year(array.get(month_time, mi)) - year(array.get(year_time, 0)) + 1
- m_col = month(array.get(month_time, mi))
- m_color = array.get(month_pnl, mi) > 0 ? color.new(color.teal, transp = 40) : color.new(color.maroon, transp = 40)
- table.cell(monthly_table, m_col, m_row, str.tostring(math.round(array.get(month_pnl, mi) * 100, i_monthlyReturnPercision)), bgcolor = m_color, text_color=color.new(color.white, 0), text_size=tableTextSize)
Advertisement