Untitled
unknown
plain_text
a year ago
29 kB
9
Indexable
//@version=5
strategy("CBA Grid Backtester", overlay=true, max_lines_count=500, initial_capital=1000)
int version = 1
// Input parameters
upper_limit = input.price(title="Upper Limit", defval=100.0)
lower_limit = input.price(title="Lower Limit", defval=60.0)
num_grids = input.int(title="Number of Grids", defval=20, minval=5, maxval=100)
START_DATE = input.time(timestamp("2019-01-01"), title="Start Date", group="Date Range", tooltip="Configure this date to the present day when enabling automation to receive the most recent alerts.")
END_DATE = input.time(timestamp("2029-01-01"), title="End Date", group="Date Range", tooltip="Until when the script should trade. This enables you to backtest until a cretain time period in the past.")
ENABLE_TAKE_PROFIT = input.bool(false, "Take Profit", tooltip = "Configure Take profit option to close the bot when the price moves in the market direction and reaches the specified price. If the price is reached, the bot sells all the Quote currency used and stops further operations.")
TAKE_PROFIT_PRICE = input.price(1000, " Take Profit Price")
ENABLE_TAKE_PROFIT_PERC = input.bool(false, "Take Profit Percentage", tooltip = "Configure Take profit option to close the bot when the price moves in the market direction and reaches the specified profit percentage. If the price is reached, the bot sells all the Quote currency used and stops further operations.")
TAKE_PROFIT_PERC = input.float(5, title=" Take Profit Percentage")
ENABLE_STOP_LOSS = input.bool(false, "Stop Loss", tooltip = "Configure Stop Loss options to close the bot when the price moves against the chosen direction. If the price reaches a specified Stop Loss level, the bot sells all the Quote currency used and stops further operations.")
STOP_LOSS_PRICE = input.price(500, " Stop Loss Price")
ENABLE_STOP_LOSS_PERC = input.bool(false, "Stop Loss Percentage", tooltip = "Configure Stop Loss options to close the bot when the price moves against the chosen direction. If the price reaches a specified Stop Loss level, the bot sells all the Quote currency used and stops further operations.")
STOP_LOSS_PERC = input.float(5, title=" Stop Loss Percentage")
ENABLE_TRAINLING_UP = input.bool(false, "Trailing Up", tooltip = "If enabled, the bot will move the Take Profit price up as the price increases. This option only works when the Take Profit option is enabled.")
ENABLE_TRAINLING_DOWN = input.bool(false, "Trailing Down", tooltip = "If enabled, the bot will move the Stop Loss price down as the price decreases. This option only works when the Stop Loss option is enabled.")
// Exchange fee (adjust as needed)
exchange_fee_pct = 0.001 // Assuming 0.1% fee
f_calculate_grid_step_perc(upper_limit, lower_limit, num_grids) =>
base_step = math.pow(upper_limit / lower_limit, 1 / num_grids) - 1
adjusted_step = base_step * (1 - 2 * exchange_fee_pct) // Adjusting by 2 * exchange_fee_pct
adjusted_step * 100 // Convert to percentage
// Calculate grid levels and sizes
grid_step_perc = f_calculate_grid_step_perc(upper_limit, lower_limit, num_grids)
var float grid_investment = na // will calculate later strategy.initial_capital / num_grids
// Define a custom type for grid levels
type GridLevel
float price
line level_line
string static_order_id
string dynamic_order_id
// Define a custom type for grid state
type GridState
float no_fee_zone_upper_level
float no_fee_zone_lower_level
int dynamic_order_counter
float upper_limit
float lower_limit
// New custom type to represent trades
type Trade
float entry_price
float quantity
// Initialize the GridState
var GridState grid_state = GridState.new(na, na, 0, upper_limit, lower_limit)
// Initialize variables
var GridLevel[] buy_levels = array.new<GridLevel>()
var GridLevel[] sell_levels = array.new<GridLevel>()
var bool is_initialized = false
var bool initial_buy_executed = false
var bool bot_ended = false
var int end_time = na
// Initialize variables for tracking dynamic order profits
var Trade[] open_trades = array.new<Trade>()
var float dynamic_order_profit = 0.0
// Function to generate lines for take profit and stop loss
f_generate_tp_sl_lines() =>
if ENABLE_TAKE_PROFIT
tp_line = line.new(bar_index, TAKE_PROFIT_PRICE, bar_index + 1, TAKE_PROFIT_PRICE,
extend=extend.both, color=color.green, width = 2)
if ENABLE_STOP_LOSS
sl_line = line.new(bar_index, STOP_LOSS_PRICE, bar_index + 1, STOP_LOSS_PRICE,
extend=extend.both, color=color.red, width = 2)
f_calculate_grid_levels() =>
if grid_step_perc <= 0.1
runtime.error("Unable to setup grid: Use less grid lines or increase the grid span.")
current_price = close
no_fee_zone_lower = current_price * (1 - exchange_fee_pct)
no_fee_zone_upper = current_price * (1 + exchange_fee_pct + grid_step_perc / 100)
//label.new(bar_index, high, "grid_step_perc: " + str.tostring(grid_step_perc, "#.##") + "%")
local_buy_levels = array.new<GridLevel>()
local_sell_levels = array.new<GridLevel>()
current_level = lower_limit
lower_grid_placed = false
for i = 0 to num_grids - 1
if current_level > no_fee_zone_lower and current_level < no_fee_zone_upper and lower_grid_placed
current_level := current_level * (1 + grid_step_perc / 100)
continue
level_line = line.new(bar_index, current_level, bar_index+1, current_level, extend=extend.both, color=current_level < close ? color.green : color.red)
new_level = GridLevel.new(current_level, level_line)
if close <= current_level
local_sell_levels.push(new_level)
else
local_buy_levels.unshift(new_level)
if current_level <= current_price
lower_grid_placed := true
current_level := math.min(upper_limit, current_level * (1 + grid_step_perc / 100))
total_levels = local_buy_levels.size() + local_sell_levels.size()
my_grid_investment = strategy.initial_capital / total_levels
// here set up the order
int j = 0
while j < local_buy_levels.size()
level = local_buy_levels.get(j)
level.static_order_id := "Initial Grid Buy " + str.tostring(j)
strategy.order(level.static_order_id, strategy.long, qty=my_grid_investment / level.price, limit=level.price)
j += 1
j := 0
while j < local_sell_levels.size()
level = local_sell_levels.get(j)
level.static_order_id := "Initial Grid Sell " + str.tostring(j)
strategy.order(level.static_order_id, strategy.short, qty=my_grid_investment / level.price, limit=level.price)
j += 1
if local_buy_levels.size() == 0 and local_sell_levels.size() == 0
runtime.error("Unable to setup grid: Use less grid lines or increase the grid span.")
local_no_fee_zone_lower_level = local_buy_levels.size() > 0 ? local_buy_levels.get(0).price : na
local_no_fee_zone_upper_level = local_sell_levels.size() > 0 ? local_sell_levels.get(0).price : na
[local_buy_levels, local_sell_levels, local_no_fee_zone_lower_level, local_no_fee_zone_upper_level, my_grid_investment]
if time >= START_DATE and not is_initialized
[new_buy_levels, new_sell_levels, new_no_fee_zone_lower, new_no_fee_zone_upper, my_grid_investment] = f_calculate_grid_levels()
buy_levels := new_buy_levels
sell_levels := new_sell_levels
grid_state.no_fee_zone_lower_level := new_no_fee_zone_lower
grid_state.no_fee_zone_upper_level := new_no_fee_zone_upper
grid_investment := my_grid_investment
f_generate_tp_sl_lines()
is_initialized := true
// Initial buy order
if is_initialized and not initial_buy_executed and not na(grid_state.no_fee_zone_lower_level) and not na(grid_state.no_fee_zone_upper_level)
sell_levels_count = sell_levels.size()
initial_buy_amount = grid_investment * sell_levels_count
entry_amount = initial_buy_amount / close
strategy.entry("Initial Buy", strategy.long, qty=entry_amount)
initial_buy_executed := true
f_is_outside_no_fee_zone(price1, price2, current_price) =>
no_fee_zone_lower = current_price * (1 - exchange_fee_pct)
no_fee_zone_upper = current_price * (1 + exchange_fee_pct + grid_step_perc / 100)
price_diff = math.abs(price1 - price2)
no_fee_zone_size = no_fee_zone_upper - no_fee_zone_lower
price_diff >= no_fee_zone_size
f_remove_grid_level(GridLevel level) =>
level.level_line.delete()
if not na(level.static_order_id)
strategy.cancel(level.static_order_id)
if not na(level.dynamic_order_id)
strategy.cancel(level.dynamic_order_id)
get_profit_from_sell_order(float sell_price, array<Trade> open_trades) =>
float trade_profit = 0.0
if open_trades.size() > 0
current_trade = open_trades.get(0)
trade_profit := (sell_price - current_trade.entry_price) * current_trade.quantity - (sell_price * exchange_fee_pct) - (current_trade.entry_price * exchange_fee_pct)
trade_profit
// Dynamic orders (moving with exchange fee zone)
f_update_dynamic_orders_high(GridState state, array<Trade> open_trades) =>
bool changed = false
float my_profit = 0.0
if high >= state.no_fee_zone_upper_level and sell_levels.size() > 0
changed := true
current_price = state.no_fee_zone_upper_level
f_remove_grid_level(sell_levels.get(0))
sell_levels.remove(0)
if sell_levels.size() > 0
state.no_fee_zone_upper_level := sell_levels.get(0).price
else
state.no_fee_zone_upper_level := na
state.no_fee_zone_lower_level := (1 - grid_step_perc / 100 - 1 * exchange_fee_pct) * current_price
state.no_fee_zone_lower_level := state.no_fee_zone_lower_level * (1 - exchange_fee_pct) // here we need to apply the exchange fee to the lower level again (because the fe is paid at the low level not the upper level)
if f_is_outside_no_fee_zone(na(state.no_fee_zone_upper_level) ? state.upper_limit : state.no_fee_zone_upper_level, na(state.no_fee_zone_lower_level) ? state.lower_limit : state.no_fee_zone_lower_level, current_price)
state.no_fee_zone_lower_level := na(state.no_fee_zone_lower_level) ? state.lower_limit : state.no_fee_zone_lower_level
GridLevel new_buy_level = GridLevel.new(state.no_fee_zone_lower_level, line.new(bar_index, state.no_fee_zone_lower_level, bar_index+1, state.no_fee_zone_lower_level, extend=extend.both, color=color.green))
new_buy_level.dynamic_order_id := "Dynamic Buy " + str.tostring(state.dynamic_order_counter)
buy_levels.unshift(new_buy_level)
strategy.order(new_buy_level.dynamic_order_id, strategy.long, qty=grid_investment / state.no_fee_zone_lower_level, limit=state.no_fee_zone_lower_level)
state.dynamic_order_counter += 1
else if na(state.no_fee_zone_upper_level)
if buy_levels.get(0).price < state.upper_limit
next_buy_level = (1 + grid_step_perc / 100 + exchange_fee_pct) * buy_levels.get(0).price
next_buy_level := next_buy_level * (1 + exchange_fee_pct)
new_buy_level = GridLevel.new(next_buy_level, line.new(bar_index, next_buy_level, bar_index+1, next_buy_level, extend=extend.both, color=color.green))
new_buy_level.dynamic_order_id := "Dynamic Buy " + str.tostring(state.dynamic_order_counter)
buy_levels.unshift(new_buy_level)
strategy.order(new_buy_level.dynamic_order_id, strategy.long, qty=grid_investment / next_buy_level, limit=next_buy_level)
state.dynamic_order_counter += 1
// else
// no_fee_zone_lower = current_price * (1 - exchange_fee_pct)
// no_fee_zone_upper = current_price * (1 + exchange_fee_pct + grid_step_perc / 100)
// no_fee_zone_size = no_fee_zone_upper - no_fee_zone_lower
// up_prc = na(state.no_fee_zone_upper_level) ? upper_limit : state.no_fee_zone_upper_level
// dn_prc = na(state.no_fee_zone_lower_level) ? state.lower_limit : state.no_fee_zone_lower_level
// label.new(bar_index, high, "price_diff: " + str.tostring(up_prc - dn_prc) +
// "\n no_fee_zone_size: " + str.tostring(no_fee_zone_size) + "\n\n\n\n")
my_profit := get_profit_from_sell_order(current_price, open_trades)
[changed, my_profit]
// Function to handle low price updates
f_update_dynamic_orders_low(GridState state, array<Trade> open_trades) =>
bool changed = false
if low <= state.no_fee_zone_lower_level and buy_levels.size() > 0
changed := true
current_price = state.no_fee_zone_lower_level
f_remove_grid_level(buy_levels.get(0))
buy_levels.remove(0)
if buy_levels.size() > 0
state.no_fee_zone_lower_level := buy_levels.get(0).price
else
state.no_fee_zone_lower_level := na
state.no_fee_zone_upper_level := (1 + grid_step_perc / 100 + 1 * exchange_fee_pct) * current_price
state.no_fee_zone_upper_level := state.no_fee_zone_upper_level * (1 + exchange_fee_pct)
if f_is_outside_no_fee_zone(na(state.no_fee_zone_upper_level) ? state.upper_limit : state.no_fee_zone_upper_level, na(state.no_fee_zone_lower_level) ? state.lower_limit : state.no_fee_zone_lower_level, current_price)
state.no_fee_zone_upper_level := na(state.no_fee_zone_upper_level) ? state.upper_limit : state.no_fee_zone_upper_level
GridLevel new_sell_level = GridLevel.new(state.no_fee_zone_upper_level, line.new(bar_index, state.no_fee_zone_upper_level, bar_index+1, state.no_fee_zone_upper_level, extend=extend.both, color=color.red))
new_sell_level.dynamic_order_id := "Dynamic Sell " + str.tostring(state.dynamic_order_counter)
sell_levels.unshift(new_sell_level)
strategy.order(new_sell_level.dynamic_order_id, strategy.short, qty=grid_investment/current_price, limit=state.no_fee_zone_upper_level)
state.dynamic_order_counter += 1
else if na(state.no_fee_zone_lower_level)
if sell_levels.get(0).price > state.lower_limit
next_sell_level = (1 - grid_step_perc / 100 - exchange_fee_pct) * sell_levels.get(0).price
next_sell_level := next_sell_level * (1 - exchange_fee_pct)
new_sell_level = GridLevel.new(next_sell_level, line.new(bar_index, next_sell_level, bar_index+1, next_sell_level, extend=extend.both, color=color.red))
new_sell_level.dynamic_order_id := "Dynamic Sell " + str.tostring(state.dynamic_order_counter)
sell_levels.unshift(new_sell_level)
strategy.order(new_sell_level.dynamic_order_id, strategy.short, qty=grid_investment / next_sell_level, limit=next_sell_level)
state.dynamic_order_counter += 1
//label.new(bar_index, high, "fill up")
// else
// no_fee_zone_lower = current_price * (1 - exchange_fee_pct)
// no_fee_zone_upper = current_price * (1 + exchange_fee_pct + grid_step_perc / 100)
// no_fee_zone_size = no_fee_zone_upper - no_fee_zone_lower
// up_prc = na(state.no_fee_zone_upper_level) ? upper_limit : state.no_fee_zone_upper_level
// dn_prc = na(state.no_fee_zone_lower_level) ? lower_limit : state.no_fee_zone_lower_level
// label.new(bar_index, high, "price_diff: " + str.tostring(up_prc - dn_prc) +
// "\n no_fee_zone_size: " + str.tostring(no_fee_zone_size) + "\n\n\n\n")
// Add new trade to open_trades array (because the low barreir was broken)
new_trade = Trade.new(current_price, grid_investment/current_price)
open_trades.unshift(new_trade)
changed
f_trailing_up(GridState state) =>
if ENABLE_TRAINLING_UP and sell_levels.size() <= 1 and buy_levels.size() > 0
float next_sell_level = na
if sell_levels.size() > 0
next_sell_level := sell_levels.get(0).price * (1 + grid_step_perc / 100)
else
next_sell_level := buy_levels.get(0).price * (1 + 2 * exchange_fee_pct + 2 * grid_step_perc / 100)
new_sell_level = GridLevel.new(next_sell_level, line.new(bar_index, next_sell_level, bar_index+1, next_sell_level, extend=extend.both, color=color.red))
new_sell_level.dynamic_order_id := "Dynamic Sell " + str.tostring(state.dynamic_order_counter)
sell_levels.push(new_sell_level)
strategy.order(new_sell_level.dynamic_order_id, strategy.short, qty=grid_investment / next_sell_level, limit=next_sell_level)
state.dynamic_order_counter += 1
last_elem = buy_levels.pop()
f_remove_grid_level(last_elem)
strategy.order("Trailing Up Buy " + str.tostring(state.dynamic_order_counter), strategy.long, qty=grid_investment / close)
state.dynamic_order_counter += 1
state.upper_limit := next_sell_level
state.lower_limit := last_elem.price
state.no_fee_zone_upper_level := next_sell_level
true
else
false
f_trailing_down(GridState state) =>
if ENABLE_TRAINLING_DOWN and buy_levels.size() <= 1 and sell_levels.size() > 0
float next_buy_level = na
if buy_levels.size() > 0
next_buy_level := buy_levels.get(0).price * (1 - grid_step_perc / 100)
else
next_buy_level := sell_levels.get(0).price * (1 - 2 * exchange_fee_pct - 2 * grid_step_perc / 100)
new_buy_level = GridLevel.new(next_buy_level, line.new(bar_index, next_buy_level, bar_index+1, next_buy_level, extend=extend.both, color=color.green))
new_buy_level.dynamic_order_id := "Dynamic Buy " + str.tostring(state.dynamic_order_counter)
buy_levels.unshift(new_buy_level)
strategy.order(new_buy_level.dynamic_order_id, strategy.long, qty=grid_investment / next_buy_level, limit=next_buy_level)
state.dynamic_order_counter += 1
last_elem = sell_levels.pop()
f_remove_grid_level(last_elem)
strategy.order("Trailing Down Sell " + str.tostring(state.dynamic_order_counter), strategy.short, qty=grid_investment / close)
state.dynamic_order_counter += 1
state.upper_limit := last_elem.price
state.lower_limit := next_buy_level
state.no_fee_zone_lower_level := next_buy_level
true
else
false
// DEBUGGING
// int bar_dir = 0
// int before_highs = 0
// int after_highs = 0
// int before_lows = 0
// int after_lows = 0
// int after_trailing_up = 0
// int after_trailing_down = 0
// Update dynamic orders on each bar
if is_initialized and not bot_ended
if close < open
// bar_dir := -1
// before_highs := grid_state.dynamic_order_counter
for i = 1 to 10
[changed, my_profit] = f_update_dynamic_orders_high(grid_state, open_trades)
dynamic_order_profit += my_profit
if not changed
break
// after_highs := grid_state.dynamic_order_counter
for i = 1 to 10
changed = f_update_dynamic_orders_low(grid_state, open_trades)
if not changed
break
// after_lows := grid_state.dynamic_order_counter
f_trailing_up(grid_state)
// after_trailing_up := grid_state.dynamic_order_counter
f_trailing_down(grid_state)
// after_trailing_down := grid_state.dynamic_order_counter
else
// bar_dir := 1
// before_lows := grid_state.dynamic_order_counter
for i = 1 to 10
changed = f_update_dynamic_orders_low(grid_state, open_trades)
if not changed
break
// after_lows := grid_state.dynamic_order_counter
for i = 1 to 10
[changed, my_profit] = f_update_dynamic_orders_high(grid_state, open_trades)
dynamic_order_profit += my_profit
if not changed
break
// after_highs := grid_state.dynamic_order_counter
f_trailing_up(grid_state)
// after_trailing_up := grid_state.dynamic_order_counter
f_trailing_down(grid_state)
// after_trailing_down := grid_state.dynamic_order_counter
// Add this function to check for Take Profit and Stop Loss conditions
f_check_tp_sl() =>
if ENABLE_TAKE_PROFIT and high >= TAKE_PROFIT_PRICE
strategy.cancel_all()
strategy.close_all("Take Profit")
true
else if ENABLE_STOP_LOSS and low <= STOP_LOSS_PRICE
strategy.cancel_all()
strategy.close_all("Stop Loss")
true
else
false
// Modify your main strategy logic to include the Take Profit and Stop Loss check
if is_initialized and initial_buy_executed and not bot_ended
if f_check_tp_sl()
bot_ended := true
end_time := time
else if ENABLE_TAKE_PROFIT_PERC and strategy.openprofit_percent >= TAKE_PROFIT_PERC
strategy.cancel_all()
strategy.close_all("Take Profit Perc")
bot_ended := true
end_time := time
else if ENABLE_STOP_LOSS_PERC and strategy.netprofit_percent <= (STOP_LOSS_PERC * -1)
strategy.cancel_all()
strategy.close_all("Stop Loss Perc")
bot_ended := true
end_time := time
if not bot_ended and time >= END_DATE
strategy.cancel_all()
strategy.close_all("End Date")
bot_ended := true
end_time := time
// DEBUG
// plot(grid_state.no_fee_zone_upper_level, title = "no_fee_zone_upper_level", color=color.new(color = color.blue , transp = 0), display=display.data_window)
// plot(grid_state.no_fee_zone_lower_level, title = "no_fee_zone_lower_level", color=color.new(color = color.blue , transp = 0), display=display.data_window)
// plot(buy_levels.size(), title = "buy_levels.size()", color=color.new(color = color.blue , transp = 0), display=display.data_window)
// plot(sell_levels.size(), title = "sell_levels.size()", color=color.new(color = color.blue , transp = 0), display=display.data_window)
// plot(upper_limit, title = "upper_limit", color=color.new(color = color.blue , transp = 0), display=display.data_window)
// plot(lower_limit, title = "lower_limit", color=color.new(color = color.blue , transp = 0), display=display.data_window)
// plot(grid_step_perc, title = "grid_step_perc", color=color.new(color = color.blue , transp = 0), display=display.data_window)
// plot(bot_ended? 1 : 0, title = "bot_ended", color=color.new(color = color.blue , transp = 0), display=display.data_window)
// plot(strategy.position_avg_price, title = "strategy.position_avg_price", color=color.new(color = color.blue , transp = 0), display=display.data_window)
// plot(grid_state.dynamic_order_counter, title = "dynamic_order_counter", color=color.new(color = color.red , transp = 0), display=display.data_window)
// plot(bar_dir, title = "bar_dir", color=color.new(color = color.red , transp = 0), display=display.data_window)
// plot(before_highs, title = "before_highs", color=color.new(color = color.red , transp = 0), display=display.data_window)
// plot(after_highs, title = "after_highs", color=color.new(color = color.red , transp = 0), display=display.data_window)
// plot(before_lows, title = "before_lows", color=color.new(color = color.red , transp = 0), display=display.data_window)
// plot(after_lows, title = "after_lows", color=color.new(color = color.red , transp = 0), display=display.data_window)
// plot(after_trailing_up, title = "after_trailing_up", color=color.new(color = color.green , transp = 0), display=display.data_window)
// plot(after_trailing_down, title = "after_trailing_down", color=color.new(color = color.green , transp = 0), display=display.data_window)
if barstate.islastconfirmedhistory
transparent = color.new(#131722, transp = 0)
color1 = color.white
quote = syminfo.currency
table_position = input.string(position.bottom_right, "Table Position", options = [position.top_left, position.top_center, position.top_right, position.middle_left, position.middle_center, position.middle_right, position.bottom_left, position.bottom_center, position.bottom_right])
var table tab1 = table.new(table_position, 15, 15, transparent, transparent,0,transparent,0)
table.cell(tab1, 0, 1, 'CBA Grid Backtester' , text_halign = text.align_left, text_size= size.normal, text_color=color1)
table.cell(tab1, 1, 1, str.tostring(version, '#.0') , text_halign = text.align_right, text_size= size.normal, text_color=color1)
table.cell(tab1, 0, 2, "Grid Step %", text_halign = text.align_left, text_size= size.normal, text_color=color1)
table.cell(tab1, 1, 2, str.tostring(grid_step_perc, "#.##") + "%", text_halign = text.align_right, text_size= size.normal, text_color=color1)
grid_range = ((upper_limit - lower_limit) / upper_limit) * 100
table.cell(tab1, 0, 3, "Grid Range", text_halign = text.align_left, text_size= size.normal, text_color=color1)
table.cell(tab1, 1, 3, str.tostring(grid_range, "#.##") + "%", text_halign = text.align_right, text_size= size.normal, text_color=color1)
current_value = strategy.equity
table.cell(tab1, 0, 4, "Current Value", text_halign = text.align_left, text_size= size.normal, text_color=color1)
table.cell(tab1, 1, 4, str.tostring(current_value, "#,###.##") + " " + quote, text_halign = text.align_right, text_size= size.normal, text_color=color1)
total_pnl = strategy.netprofit + strategy.openprofit
table.cell(tab1, 0, 5, "Total PNL", text_halign = text.align_left, text_size= size.normal, text_color=color1)
table.cell(tab1, 1, 5, str.tostring(total_pnl, "#,###.##") + " " + quote, text_halign = text.align_right, text_size= size.normal, text_color=color1)
portfolio_profit_pct = (total_pnl/ strategy.initial_capital) * 100
table.cell(tab1, 0, 6, "Total PNL %", text_halign = text.align_left, text_size= size.normal, text_color=color1)
table.cell(tab1, 1, 6, str.tostring(portfolio_profit_pct, "#.##") + "%", text_halign = text.align_right, text_size= size.normal, text_color=color1)
//bot_profit = strategy.netprofit
table.cell(tab1, 0, 7, "Bot Profit", text_halign = text.align_left, text_size= size.normal, text_color=color1)
table.cell(tab1, 1, 7, str.tostring(dynamic_order_profit, "#,###.##") + " " + quote, text_halign = text.align_right, text_size= size.normal, text_color=color1)
bot_profit_pct = (dynamic_order_profit / strategy.initial_capital) * 100
table.cell(tab1, 0, 8, "Bot Profit %", text_halign = text.align_left, text_size= size.normal, text_color=color1)
table.cell(tab1, 1, 8, str.tostring(bot_profit_pct, "#.##") + "%", text_halign = text.align_right, text_size= size.normal, text_color=color1)
days_elapsed = ((na(end_time) ? time : end_time) - START_DATE) / (1000 * 60 * 60 * 24)
avg_daily_profit = total_pnl / days_elapsed
table.cell(tab1, 0, 9, "Avg. Daily", text_halign = text.align_left, text_size= size.normal, text_color=color1)
table.cell(tab1, 1, 9, str.tostring(avg_daily_profit, "#,###.##") + " " + quote, text_halign = text.align_right, text_size= size.normal, text_color=color1)
avg_daily_percent = (math.pow(1 + portfolio_profit_pct / 100, 1 / days_elapsed) - 1) * 100
table.cell(tab1, 0, 10, "Avg. Daily %", text_halign = text.align_left, text_size= size.normal, text_color=color1)
table.cell(tab1, 1, 10, str.tostring(avg_daily_percent, "#.##") + "%", text_halign = text.align_right, text_size= size.normal, text_color=color1)
table.cell(tab1, 0, 11, "Total Days Traded", text_halign = text.align_left, text_size= size.normal, text_color=color1)
table.cell(tab1, 1, 11, str.tostring(days_elapsed, "#"), text_halign = text.align_right, text_size= size.normal, text_color=color1)
// Additional statistics
// total_trades = strategy.closedtrades
// table.cell(tab1, 0, 12, "Total Trades", text_halign = text.align_left, text_size= size.normal, text_color=color1)
// table.cell(tab1, 1, 12, str.tostring(total_trades), text_halign = text.align_right, text_size= size.normal, text_color=color1)
// win_rate = strategy.wintrades / total_trades * 100
// table.cell(tab1, 0, 13, "Win Rate", text_halign = text.align_left, text_size= size.normal, text_color=color1)
// table.cell(tab1, 1, 13, str.tostring(win_rate, "#.##") + "%", text_halign = text.align_right, text_size= size.normal, text_color=color1)
// profit_factor = strategy.grossprofit / math.abs(strategy.grossloss)
// table.cell(tab1, 0, 14, "Profit Factor", text_halign = text.align_left, text_size= size.normal, text_color=color1)
// table.cell(tab1, 1, 14, str.tostring(profit_factor, "#.##"), text_halign = text.align_right, text_size= size.normal, text_color=color1)
// max_drawdown = strategy.max_drawdown
// table.cell(tab1, 0, 15, "Max Drawdown", text_halign = text.align_left, text_size= size.normal, text_color=color1)
// table.cell(tab1, 1, 15, str.tostring(max_drawdown, "#,###.##") + " " + quote, text_halign = text.align_right, text_size= size.normal, text_color=color1)Editor is loading...
Leave a Comment