Message
Message
// Input parameters
i_upperBound = input.float(group='Grid Bounds', title='Upper Range', defval=50) //
manual upper bound
i_lowerBound = input.float(group='Grid Bounds', title='Lower Range', defval=0.225)
// manual lower bound
i_gridQty = input.int(group='Grid Lines', title='Grid Line Quantity', defval=60,
maxval=300, minval=3) // number of grid lines
/////////////////////////////////////////////////////////////////////////////////
// RSI
////////////////////////////////////////////////////////////////////////////////
// RSI Settings
rsiLengthInput = input.int(14, title='RSI Length', minval=1, group='RSI Settings')
rsiSourceInput = input.source(close, title='Source', group='RSI Settings')
//No_RSI_Use = input.bool (false, title = 'No RSI confirmation')
rsi_OB = 70 // not needed for long only grid bot.
rsi_OS = input.int(30, title='RSI Oversold', minval=1, group='RSI Settings')
signalPeriod = 1 // Signal Decay, not a useful factor a grid bot.
// RSI Calculation
change = ta.change(rsiSourceInput)
up = ta.rma(math.max(change, 0), rsiLengthInput)
down = ta.rma(-math.min(change, 0), rsiLengthInput)
rsi = down == 0 ? 100 : up == 0 ? 0 : 100 - 100 / (1 + up / down)
// Signal Tracking
var int activeSignal = 0
var int barsRemaining = 0
// Signal Conditions
buyTrigger = ta.crossover(rsi, rsi_OS)
sellTrigger = ta.crossunder(rsi, rsi_OB)
if buyTrigger
activeSignal := 1
barsRemaining := signalPeriod
barsRemaining
else if sellTrigger
activeSignal := -1
barsRemaining := signalPeriod
barsRemaining
else if barsRemaining > 0
barsRemaining -= 1
barsRemaining
else
activeSignal := 0
activeSignal
// Active Signals
buyRSIActive = activeSignal == 1 and barsRemaining > 0
//sellRSIActive = activeSignal == -1 and barsRemaining > 0
plotshape(buyRSIActive, title='RSI Buy', location=location.belowbar,
style=shape.diamond, size=size.small, color=color.new(color.green, 0))
//plotshape(sellRSIActive, title='RSI_Sell', location=location.abovebar,
style=shape.diamond, size=size.small, color=color.new(color.red, 0))
/////////////////////////////////////////////////////////////////////////////////
// T3
////////////////////////////////////////////////////////////////////////////////
useT3 = true
crossT3 = input.bool(true, 'Cross confirmation? - T3')
inverseT3 = input.bool(false, 'Inverse? - T3')
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Grid calculations
var upperBound = i_upperBound
var lowerBound = i_lowerBound
var gridWidth = (upperBound - lowerBound) / (i_gridQty - 1)
var gridLineArr = f_buildGrid(lowerBound, gridWidth, i_gridQty)
var orderArr = array.new_bool(i_gridQty, false)
// 1) BUY LOGIC: When the basic long condition is true, loop through all grid
levels
// and send an entry for every level that qualifies but has not yet been used.
if (buyRSIActive or basicLongCondition)
// Loop over all grid levels in your grid array
for i = 0 to array.size(gridLineArr) - 1
gridPrice = array.get(gridLineArr, i)
// Check if current price is below this grid level AND if we have not
already bought here.
if close < gridPrice and not array.get(orderArr, i)
// Mark this grid level as used
array.set(orderArr, i, true)
// Place the buy order.
strategy.entry(id = "GridBuy#" + str.tostring(i), direction =
strategy.long, qty = strategy.initial_capital / (i_gridQty - 1) / close, comment =
"#" + str.tostring(i))
// ------------------------------------
// 2) EXIT LOGIC
// Loop through each grid line except the very last
// because we'll check index+1 below.
for i = 0 to array.size(gridLineArr) - 2
// If we have an active buy from grid i
if array.get(orderArr, i)
// Next line above it is i + 1
nextLineIndex = i + 1
nextLinePrice = array.get(gridLineArr, nextLineIndex ) //I added in a -1 to
correct for the fact its closing orders 2 above instead of 1
//---------------------------------------------------------------------------------
-----------------------------------------------------------------------
// DASHBOARD PERFORMANCE TABLE/
//---------------------------------------------------------------------------------
-----------------------------------------------------------------------
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)
if newWin
lossRow := 0
winRow := winRow + 1
if winRow > maxWinRow
maxWinRow := winRow
if newLoss
winRow := 0
lossRow := lossRow + 1
if lossRow > maxLossRow
maxLossRow := lossRow
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)
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
last_computed = false
array.push(month_pnl , cur_month_pnl[1])
array.push(month_time, time[1])
array.push(year_pnl , cur_year_pnl[1])
array.push(year_time, time[1])
if (barstate.islastconfirmedhistory)
monthly_table := table.new(position.bottom_right, columns = 14, rows =
array.size(year_pnl) + 1, border_width = 1)
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)
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)