asset-rotation-system-investorunknown.pine
Copy
// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © InvestorUnknown
// {||}
// , {||}
// ,,,,, {||}
// ,,,,, , ,, {||}
// , ,,,, , ,, ,,, {||}
// . , , ,,,, , ,,,, .,, {||} ╔╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╗
// ,, , ,, ,,,,,,, , , , {||} ╠╬╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╬╣
// ,, ,, , ,, ,,,,,, ,,,, , , {||} ╠╣ /$$$$$$ /$$ ╠╣
// ., , ,,, ,,,,,,,,,,,,,, ,, ,, , , ,, {||} ╠╣ |_ $$_/ | $$ ╠╣
// , . ,, ,,,,,,,,,,,,, , ,,, , ,, , , {||} ╠╣ | $$ /$$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ ╠╣
// ,, ,,, ,,,,,,,,,,,,,,,,,,,,,, ,,, ,, {||} ╠╣ | $$ | $$__ $$| $$ /$$//$$__ $$ /$$_____/|_ $$_/ /$$__ $$ /$$__ $$ ╠╣
// , , ,,, .,,,,,,,,,,,, ,,, ,,,,,,,, ,,, ,, {||} ╠╣ | $$ | $$ \ $$ \ $$/$$/| $$$$$$$$| $$$$$$ | $$ | $$ \ $$| $$ \__/ ╠╣
// ., , ,, ,, ,,, ,,,,,,, ,, ,,, ,,,,, ,,, , ,, ,, {||} ╠╣ | $$ | $$ | $$ \ $$$/ | $$_____/ \____ $$ | $$ /$$| $$ | $$| $$ ╠╣
// , ,,,,, , ,,,, ,, , ,,,,,,,,,,,,,,,,,,,,,, ,, ,, {||} ╠╣ /$$$$$$| $$ | $$ \ $/ | $$$$$$$ /$$$$$$$/ | $$$$/| $$$$$$/| $$ ╠╣
// . //./ /// ,,,,,,,,,,,,,,,. ,,,,,,,,,,,,,,,,,, {||} ╠╣ |______/|__/ |__/ \_/ \_______/|_______/ \___/ \______/ |__/ ╠╣
// , / ,., ,,,,,,,,,,, ,,,,,,, ,,,,,,, {||} ╠╣ ╠╣
// . ,,, ,/ ///./ ,,,.,,,,,,,,,,,,,,, ,, , , {||} ╠╣ ╠╣
// ,,,,,, //./ , / .,,.,,, ,,,,,, ,. ,,,,,,, {||} ╠╣ ╠╣
// ,,,, // *, / / ,,,,,,,,,,,, ,, ,,,,, {||} ╠╣ /$$ /$$ /$$ ╠╣
// ,, // ////.*/// / ,.,,,,,.,, ,, ,,,, ,,,,,, {||} ╠╣ | $$ | $$ | $$ ╠╣
// , ///// // , ,,,,,, ,,,, ,,,,, ,,, / /. {||} ╠╣ | $$ | $$ /$$$$$$$ | $$ /$$ /$$$$$$$ /$$$$$$ /$$ /$$ /$$ /$$$$$$$ ╠╣
// ,, , ////// ,,,,,,,,, ,,,,,,,,/ /// / // {||} ╠╣ | $$ | $$| $$__ $$| $$ /$$/| $$__ $$ /$$__ $$| $$ | $$ | $$| $$__ $$ ╠╣
// ///// .// ,,,,,, ,, ,,,, ,,, ///* //*/// {||} ╠╣ | $$ | $$| $$ \ $$| $$$$$$/ | $$ \ $$| $$ \ $$| $$ | $$ | $$| $$ \ $$ ╠╣
// // . ,, .// ,, ///, /// {||} ╠╣ | $$ | $$| $$ | $$| $$_ $$ | $$ | $$| $$ | $$| $$ | $$ | $$| $$ | $$ ╠╣
// ////// ,,,, ///// ,. , {||} ╠╣ | $$$$$$/| $$ | $$| $$ \ $$| $$ | $$| $$$$$$/| $$$$$/$$$$/| $$ | $$ ╠╣
// *///////. // / */////* {||} ╠╣ \______/ |__/ |__/|__/ \__/|__/ |__/ \______/ \_____/\___/ |__/ |__/ ╠╣
// .,, // ,,,,,,,,,, //* ,,, ////// {||} ╠╬╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╦╬╣
// ,,,,, ,,,,,, ,.,,,,,,, {||} ╚╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╩╝
// ,,,,,,,,,,,, ,, {||}
// ,,,,,,,,, {||}
// {||}
// {||}
//@version=6
indicator("Asset Rotation System [InvestorUnknown]", "Asset Rotation System", max_bars_back = 5000)
// ╔════════════════════════════╗
// ║ IMPORTS ║
// ╚════════════════════════════╝
//{
import TradingView/ta/9
//}
// ╔════════════════════════════╗
// ║ FUNCTIONS ║
// ╚════════════════════════════╝
//{
// Fuction to remove parts of the ticker
f_remove_exchange_name(string name) =>
string[] parts = str.split(name, ":")
string result = array.size(parts) > 1 ? array.get(parts, 1) : name
result
// Function to get color based on the value of the signal
f_trend_col(series int x) =>
x > 0 ? color.green : color.red
// RSI
f_rsi(series float src, simple int len) =>
rsi = ta.rsi(src, len)
sig = rsi > 50 ? 1 : 0
// CCI
f_cci(series float src, simple int len) =>
cci = ta.cci(src, len)
sig = cci > 0 ? 1 : 0
// SuperTrend
f_supertrend(simple float factor, simple int len) =>
[st, dir] = ta.supertrend(factor, len)
sig = -dir > 0 ? 1 : 0
// DMI
f_dmi(simple int len) =>
[dip, dim, adx] = ta.dmi(len, 1)
sig = dip > dim ? 1 : 0
// Parabolic Sar
f_psar(simple float start, simple float increment, simple float max) =>
sar = ta.sar(start, increment, max)
sig = sar < close ? 1 : 0
// Mini trend system
f_all(series float rsi_src, simple int rsi_len,
series float cci_src, simple int cci_len,
simple float st_factor, simple int st_len,
simple int dmi_len,
simple float sar_start, simple float sar_inc, simple float sar_max) =>
rsi = f_rsi(rsi_src, rsi_len)
cci = f_cci(cci_src, cci_len)
st = f_supertrend(st_factor, st_len)
dmi = f_dmi(dmi_len)
sar = f_psar(sar_start, sar_inc, sar_max)
sig = (rsi + cci + st + dmi + sar) > 0 ? 1 : 0
// Function to return opposite of the signal
f_oppose(series int x) =>
x == 1 ? (0) : (x == 0 ? 1 : 0)
// Function to perfrom trend analysis
f_trend(simple string clas,
series float rsi_src, simple int rsi_len,
series float cci_src, simple int cci_len,
simple float st_factor, simple int st_len,
simple int dmi_len,
simple float sar_start, simple float sar_inc, simple float sar_max) =>
sig = switch clas
"RSI" => f_rsi(rsi_src, rsi_len)
"CCI" => f_cci(cci_src, cci_len)
"SuperTrend" => f_supertrend(st_factor, st_len)
"DMI" => f_dmi(dmi_len)
"PSAR" => f_psar(sar_start, sar_inc, sar_max)
"All" => f_all(rsi_src, rsi_len, cci_src, cci_len, st_factor, st_len, dmi_len, sar_start, sar_inc, sar_max)
[sig, f_oppose(sig)]
// Function to calculate the age of the ticker
f_age() =>
// Calculate number of bars since the beginning of the chart
bars = bar_index + 1
// Limit the age to 5000 if it exceeds
math.min(bars, 5000)
// Function to return the daily return as decimal number
f_roc() =>
roc = ta.roc(close, 1)
r = roc/100
// Function to find the ticker with the highest value among 7 pairs (ticker, value)
f_BestPerformingAsset(simple string ticker1, series int v1, simple string ticker2, series int v2, simple string ticker3, series int v3,
simple string ticker4, series int v4, simple string ticker5, series int v5, simple string ticker6, series int v6, simple string ticker7, series int v7) =>
// Create arrays for tickers and values
var array<string> tickers = array.new_string(7, "")
var array<float> values = array.new_float(7, 0.0)
array.set(tickers, 0, ticker1), array.set(values, 0, v1)
array.set(tickers, 1, ticker2), array.set(values, 1, v2)
array.set(tickers, 2, ticker3), array.set(values, 2, v3)
array.set(tickers, 3, ticker4), array.set(values, 3, v4)
array.set(tickers, 4, ticker5), array.set(values, 4, v5)
array.set(tickers, 5, ticker6), array.set(values, 5, v6)
array.set(tickers, 6, ticker7), array.set(values, 6, v7)
// Find index of highest value
var int highestIndex = 0
for i = 0 to 6
if array.get(values, i) > array.get(values, highestIndex)
highestIndex := i
// Return the ticker at the highest value's index
array.get(tickers, highestIndex)
// Function to calculate strategy equity, with maximum drawdown - holding only the best performing asset
f_equity(simple string ticker1, simple string ticker2, simple string ticker3, simple string ticker4, simple string ticker5, simple string ticker6,
series string best_asset, series float r1, series float r2, series float r3, series float r4, series float r5, series float r6, series bool backtest) =>
var float equity = na
var float peak_equity = na
var float max_drawdown = 0.0
if backtest
a = switch best_asset[1]
ticker1 => r1
ticker2 => r2
ticker3 => r3
ticker4 => r4
ticker5 => r5
ticker6 => r6
"USD" => 0
equity := na(equity[1]) ? 1 : equity[1] * (1 + a)
// Calculate max drawdown
peak_equity := math.max(na(peak_equity) ? equity : peak_equity, equity)
current_drawdown = peak_equity > 0 ? (peak_equity - equity) / peak_equity : 0
if current_drawdown > max_drawdown
max_drawdown := current_drawdown
if equity > peak_equity
peak_equity := equity
else
equity := 1
[equity, math.round(max_drawdown, 4)]
// Function to calculate buy and hold equity of an asset, with maximum drawdown
f_buy_and_hold(series float r, series bool backtest) =>
var float equity = na
var float peak_equity = na
var float max_drawdown = 0.0
if backtest
// Calculate equity
equity := na(equity[1]) ? 1 : equity[1] * (1 + r)
// Calculate max drawdown
peak_equity := math.max(na(peak_equity) ? equity : peak_equity, equity)
current_drawdown = peak_equity > 0 ? (peak_equity - equity) / peak_equity : 0
if current_drawdown > max_drawdown
max_drawdown := current_drawdown
if equity > peak_equity
peak_equity := equity
else
equity := 1
[equity, math.round(max_drawdown, 4)]
// Function to return color for equity curve for visualizing the best performing asset
f_best_asset_col(simple string ticker1, simple string ticker2, simple string ticker3, simple string ticker4,
simple string ticker5, simple string ticker6, series string best_asset, series bool backtest, color[] colors) =>
if backtest
col = switch best_asset[1]
ticker1 => array.get(colors, 0)
ticker2 => array.get(colors, 1)
ticker3 => array.get(colors, 2)
ticker4 => array.get(colors, 3)
ticker5 => array.get(colors, 4)
ticker6 => array.get(colors, 5)
"USD" => array.get(colors, 6)
else
col = color.new(color.white, 100)
// Function to calculate performance metrics from equity curve ("base" - is the equity curve)
f_PerformanceMetrics(series float base, series int Lookback, series bool backtest, series float max_drawdown) =>
// Initialize variables for positive and negative returns
pos_sum = 0.0
neg_sum = 0.0
pos_count = 0
neg_count = 0
returns_sum = 0.0
returns_squared_sum = 0.0
pos_returns_squared_sum = 0.0
neg_returns_squared_sum = 0.0
lookback = Lookback
if Lookback > 4999
lookback := 4998
// Loop through the past 'Lookback' bars to calculate sums, counts, and drawdown
if backtest
for i = 0 to lookback - 1
r = (base[i] - base[i + 1]) / base[i + 1]
returns_sum += r
returns_squared_sum += r * r
if r > 0
pos_sum += r
pos_count += 1
pos_returns_squared_sum += r * r
else if r < 0
neg_sum += r
neg_count += 1
neg_returns_squared_sum += r * r
float[] export_array = array.new_float(10)
// Calculate means
mean_all = math.round(returns_sum / lookback, 4)
mean_pos = pos_count != 0 ? math.round(pos_sum / pos_count, 4) : na
mean_neg = neg_count != 0 ? math.round(neg_sum / neg_count, 4) : na
// Calculate standard deviations
stddev_all = math.round(math.sqrt((returns_squared_sum - (returns_sum * returns_sum) / lookback) / lookback), 4)
stddev_pos = pos_count != 0 ? math.round(math.sqrt((pos_returns_squared_sum - (pos_sum * pos_sum) / pos_count) / pos_count), 4) : na
stddev_neg = neg_count != 0 ? math.round(math.sqrt((neg_returns_squared_sum - (neg_sum * neg_sum) / neg_count) / neg_count), 4) : na
// Calculate ratios
sharpe_ratio = math.round((mean_all / stddev_all) * math.sqrt(255), 3)
sortino_ratio = math.round((mean_all / stddev_neg) * math.sqrt(255), 3)
omega_ratio = math.round(pos_sum / math.abs(neg_sum), 3)
// Set values in the array
array.set(export_array, 0, mean_all * 100)
array.set(export_array, 1, mean_pos * 100)
array.set(export_array, 2, mean_neg * 100)
array.set(export_array, 3, stddev_all * 100)
array.set(export_array, 4, stddev_pos * 100)
array.set(export_array, 5, stddev_neg * 100)
array.set(export_array, 6, sharpe_ratio)
array.set(export_array, 7, sortino_ratio)
array.set(export_array, 8, omega_ratio)
array.set(export_array, 9, max_drawdown * 100)
// Export the array
export_array
// Function to plot Perfomance Metrics Table
f_PerfMetricTable(simple string ticker1, simple string ticker2, simple string ticker3, simple string ticker4, simple string ticker5, simple string ticker6,
float[] strategy, float[] a1, float[] a2, float[] a3, float[] a4, float[] a5, float[] a6, color[] colors) =>
var table p = table.new(position.top_left, 8, 15, border_width = 1, frame_width = 1, frame_color = color.white)
// Header
table.cell(p, 0, 0, "Performance Metrics", text_color = color.white, bgcolor = color.gray)
table.merge_cells(p, 0, 0, 7, 0)
// Column headers
table.cell(p, 1, 1, "Strategy", text_color = array.get(colors, 7))
table.cell(p, 2, 1, str.tostring(f_remove_exchange_name(ticker1)), text_color = array.get(colors, 0))
table.cell(p, 3, 1, str.tostring(f_remove_exchange_name(ticker2)), text_color = array.get(colors, 1))
table.cell(p, 4, 1, str.tostring(f_remove_exchange_name(ticker3)), text_color = array.get(colors, 2))
table.cell(p, 5, 1, str.tostring(f_remove_exchange_name(ticker4)), text_color = array.get(colors, 3))
table.cell(p, 6, 1, str.tostring(f_remove_exchange_name(ticker5)), text_color = array.get(colors, 4))
table.cell(p, 7, 1, str.tostring(f_remove_exchange_name(ticker6)), text_color = array.get(colors, 5))
// Metrics labels
for i = 0 to array.size(strategy) - 1
metric = switch i
0 => "Mean (All Returns) %"
1 => "Mean (Positive Returns) %"
2 => "Mean (Negative Returns) %"
3 => "STDEV (All Returns) %"
4 => "STDEV (Positive Returns) %"
5 => "STDEV (Negative Returns) %"
6 => "Sharpe Ratio"
7 => "Sortino Ratio"
8 => "Omega Ratio"
9 => "Maximum Drawdown %"
table.cell(p, 0, i + 2, metric, text_color = array.get(colors, 7))
table.cell(p, 1, i + 2, str.tostring(array.get(strategy, i)), text_color = array.get(colors, 7))
table.cell(p, 2, i + 2, str.tostring(array.get(a1, i)), text_color = array.get(colors, 0))
table.cell(p, 3, i + 2, str.tostring(array.get(a2, i)), text_color = array.get(colors, 1))
table.cell(p, 4, i + 2, str.tostring(array.get(a3, i)), text_color = array.get(colors, 2))
table.cell(p, 5, i + 2, str.tostring(array.get(a4, i)), text_color = array.get(colors, 3))
table.cell(p, 6, i + 2, str.tostring(array.get(a5, i)), text_color = array.get(colors, 4))
table.cell(p, 7, i + 2, str.tostring(array.get(a6, i)), text_color = array.get(colors, 5))
p
// Function to return "lookaback" period as count of bars from certain event
f_since(series bool active) =>
var count = 0
if active
count += 1
output = count > 2 ? count - 1 : count
output
//}
// ╔════════════════════════════╗
// ║ STRINGS ║
// ╚════════════════════════════╝
//{
var string tic = "Tickers"
var string GS = "General Settings"
var string CS = "Colo Settings"
var string I1 = "RSI Settings"
var string I2 = "CCI Settings"
var string I3 = "SuperTrend Settings"
var string I4 = "DMI Settings"
var string I5 = "Parabolic SAR Settings"
//}
// ╔════════════════════════════╗
// ║ INPUTS ║
// ╚════════════════════════════╝
//{
// Tickers
simple string ticker1 = input.symbol("INDEX:BTCUSD", "Asset 1", group = tic, display = display.none)
simple string ticker2 = input.symbol("INDEX:ETHUSD", "Asset 2", group = tic, display = display.none)
simple string ticker3 = input.symbol("CRYPTO:SOLUSD", "Asset 3", group = tic, display = display.none)
simple string ticker4 = input.symbol("CRYPTO:XRPUSD", "Asset 4", group = tic, display = display.none)
simple string ticker5 = input.symbol("CRYPTO:BNBUSD", "Asset 5", group = tic, display = display.none)
simple string ticker6 = input.symbol("CRYPTO:DOGEUSD", "Asset 6", group = tic, display = display.none)
// General Settings
simple string trend_classification = input.string("All", "Trend Classification Method", options = ["RSI", "CCI", "SuperTrend", "DMI", "PSAR", "All"], group = GS, display = display.none)
simple bool use_custom_startdate = input.bool(false, "Use Custom Starting Date for Backtest", group = GS, inline = "CC")
simple float custom_startdate = input.time(timestamp("2023-1-1"), "", group = GS, inline = "CC", display = display.none)
simple bool plot_metric_table = input.bool(true, "Plot Perf. Metrics Table", group = GS)
// Color Settings
simple color asset1_col = input.color(color.aqua, "Asset 1", group = CS, inline = "C1")
simple color asset2_col = input.color(color.red, "Asset 2", group = CS, inline = "C1")
simple color asset3_col = input.color(color.green, "Asset 3", group = CS, inline = "C1")
simple color asset4_col = input.color(color.purple, "Asset 4", group = CS, inline = "C2")
simple color asset5_col = input.color(color.orange, "Asset 5", group = CS, inline = "C2")
simple color asset6_col = input.color(color.yellow, "Asset 6", group = CS, inline = "C2")
simple color usd_col = input.color(color.white, "USD", group = CS, inline = "C3")
simple color tab_lab_text_col = input.color(color.white, "Table & Lable Text", group = CS, inline = "C3")
// RSI
series float rsi_src = input.source(close, "RSI Source", group = I1, display = display.none)
simple int rsi_len = input.int(14, "RSI Length", group = I1, display = display.none)
// CCI
series float cci_src = input.source(close, "CCI Source", group = I2, display = display.none)
simple int cci_len = input.int(20, "CCI Length", group = I2, display = display.none)
// SuperTrend
simple float st_factor = input.float(2.0, "SuperTrend Factor", group = I3, display = display.none, step = 0.1)
simple int st_len = input.int(14, "SuperTrend Length", group = I3, display = display.none)
// DMI
simple int dmi_len = input.int(14, "DMI Length", group = I4, display = display.none)
// Parabolic SAR
simple float sar_start = input.float(0.02, "PSAR Start", group = I5, display = display.none, step = 0.001)
simple float sar_inc = input.float(0.02, "PSAR Increment", group = I5, display = display.none, step = 0.001)
simple float sar_max = input.float(0.2, "PSAR Max Value", group = I5, display = display.none, step = 0.001)
//}
// ╔════════════════════════════╗
// ║ TREND ANALYSIS ║
// ╚════════════════════════════╝
//{
// Asset 1 against all assets
[c1_2, c2_1] = request.security(str.tostring(ticker1 + "/" + ticker2), "", f_trend(trend_classification, rsi_src, rsi_len, cci_src, cci_len, st_factor, st_len, dmi_len, sar_start, sar_inc, sar_max))
[c1_3, c3_1] = request.security(str.tostring(ticker1 + "/" + ticker3), "", f_trend(trend_classification, rsi_src, rsi_len, cci_src, cci_len, st_factor, st_len, dmi_len, sar_start, sar_inc, sar_max))
[c1_4, c4_1] = request.security(str.tostring(ticker1 + "/" + ticker4), "", f_trend(trend_classification, rsi_src, rsi_len, cci_src, cci_len, st_factor, st_len, dmi_len, sar_start, sar_inc, sar_max))
[c1_5, c5_1] = request.security(str.tostring(ticker1 + "/" + ticker5), "", f_trend(trend_classification, rsi_src, rsi_len, cci_src, cci_len, st_factor, st_len, dmi_len, sar_start, sar_inc, sar_max))
[c1_6, c6_1] = request.security(str.tostring(ticker1 + "/" + ticker6), "", f_trend(trend_classification, rsi_src, rsi_len, cci_src, cci_len, st_factor, st_len, dmi_len, sar_start, sar_inc, sar_max))
[c1_usd, cusd_1] = request.security(ticker1, "", f_trend(trend_classification, rsi_src, rsi_len, cci_src, cci_len, st_factor, st_len, dmi_len, sar_start, sar_inc, sar_max))
[c1_age, r1] = request.security(ticker1, "", [f_age(), f_roc()])
// Asset 2 against all remaining assets
[c2_3, c3_2] = request.security(str.tostring(ticker2 + "/" + ticker3), "", f_trend(trend_classification, rsi_src, rsi_len, cci_src, cci_len, st_factor, st_len, dmi_len, sar_start, sar_inc, sar_max))
[c2_4, c4_2] = request.security(str.tostring(ticker2 + "/" + ticker4), "", f_trend(trend_classification, rsi_src, rsi_len, cci_src, cci_len, st_factor, st_len, dmi_len, sar_start, sar_inc, sar_max))
[c2_5, c5_2] = request.security(str.tostring(ticker2 + "/" + ticker5), "", f_trend(trend_classification, rsi_src, rsi_len, cci_src, cci_len, st_factor, st_len, dmi_len, sar_start, sar_inc, sar_max))
[c2_6, c6_2] = request.security(str.tostring(ticker2 + "/" + ticker6), "", f_trend(trend_classification, rsi_src, rsi_len, cci_src, cci_len, st_factor, st_len, dmi_len, sar_start, sar_inc, sar_max))
[c2_usd, cusd_2] = request.security(ticker2, "", f_trend(trend_classification, rsi_src, rsi_len, cci_src, cci_len, st_factor, st_len, dmi_len, sar_start, sar_inc, sar_max))
[c2_age, r2] = request.security(ticker2, "", [f_age(), f_roc()])
// Asset 3 against all remaining assets
[c3_4, c4_3] = request.security(str.tostring(ticker3 + "/" + ticker4), "", f_trend(trend_classification, rsi_src, rsi_len, cci_src, cci_len, st_factor, st_len, dmi_len, sar_start, sar_inc, sar_max))
[c3_5, c5_3] = request.security(str.tostring(ticker3 + "/" + ticker5), "", f_trend(trend_classification, rsi_src, rsi_len, cci_src, cci_len, st_factor, st_len, dmi_len, sar_start, sar_inc, sar_max))
[c3_6, c6_3] = request.security(str.tostring(ticker3 + "/" + ticker6), "", f_trend(trend_classification, rsi_src, rsi_len, cci_src, cci_len, st_factor, st_len, dmi_len, sar_start, sar_inc, sar_max))
[c3_usd, cusd_3] = request.security(ticker3, "", f_trend(trend_classification, rsi_src, rsi_len, cci_src, cci_len, st_factor, st_len, dmi_len, sar_start, sar_inc, sar_max))
[c3_age, r3] = request.security(ticker3, "", [f_age(), f_roc()])
// Asset 4 against all remaining assets
[c4_5, c5_4] = request.security(str.tostring(ticker4 + "/" + ticker5), "", f_trend(trend_classification, rsi_src, rsi_len, cci_src, cci_len, st_factor, st_len, dmi_len, sar_start, sar_inc, sar_max))
[c4_6, c6_4] = request.security(str.tostring(ticker4 + "/" + ticker6), "", f_trend(trend_classification, rsi_src, rsi_len, cci_src, cci_len, st_factor, st_len, dmi_len, sar_start, sar_inc, sar_max))
[c4_usd, cusd_4] = request.security(ticker4, "", f_trend(trend_classification, rsi_src, rsi_len, cci_src, cci_len, st_factor, st_len, dmi_len, sar_start, sar_inc, sar_max))
[c4_age, r4] = request.security(ticker4, "", [f_age(), f_roc()])
// Asset 5 against all remaining assets
[c5_6, c6_5] = request.security(str.tostring(ticker5 + "/" + ticker6), "", f_trend(trend_classification, rsi_src, rsi_len, cci_src, cci_len, st_factor, st_len, dmi_len, sar_start, sar_inc, sar_max))
[c5_usd, cusd_5] = request.security(ticker5, "", f_trend(trend_classification, rsi_src, rsi_len, cci_src, cci_len, st_factor, st_len, dmi_len, sar_start, sar_inc, sar_max))
[c5_age, r5] = request.security(ticker5, "", [f_age(), f_roc()])
// Asset 6 against remaining asset (USD)
[c6_usd, cusd_6] = request.security(ticker6, "", f_trend(trend_classification, rsi_src, rsi_len, cci_src, cci_len, st_factor, st_len, dmi_len, sar_start, sar_inc, sar_max))
[c6_age, r6] = request.security(ticker6, "", [f_age(), f_roc()])
// Calculation of Final Score for each asset (number of assets it is currently outperforming)
series int a1_score = c1_2 + c1_3 + c1_4 + c1_5 + c1_6 + c1_usd
series int a2_score = c2_1 + c2_3 + c2_4 + c2_5 + c2_6 + c2_usd
series int a3_score = c3_1 + c3_2 + c3_4 + c3_5 + c3_6 + c3_usd
series int a4_score = c4_1 + c4_2 + c4_3 + c4_5 + c4_6 + c4_usd
series int a5_score = c5_1 + c5_2 + c5_3 + c5_4 + c5_6 + c5_usd
series int a6_score = c6_1 + c6_2 + c6_3 + c6_4 + c6_5 + c6_usd
series int usd_score = cusd_1 + cusd_2 + cusd_3 + cusd_4 + cusd_5 + cusd_6
// Determining "Optimal" Asset
series string best_asset = f_BestPerformingAsset(ticker1, a1_score, ticker2, a2_score, ticker3, a3_score, ticker4, a4_score, ticker5, a5_score, ticker6, a6_score, "USD", usd_score)
// Calculation of equity curves and maximum drawdown for Strategy and Buy and Hold for each asset
bool backtest = c1_age > 1 and c2_age > 1 and c3_age > 1 and c4_age > 1 and c5_age > 1 and c6_age > 1 and (not use_custom_startdate or time > custom_startdate)
[eq, dd_eq] = f_equity(ticker1, ticker2, ticker3, ticker4, ticker5, ticker6, best_asset, r1, r2, r3, r4, r5, r6, backtest)
[bah1, dd1] = f_buy_and_hold(r1, backtest)
[bah2, dd2] = f_buy_and_hold(r2, backtest)
[bah3, dd3] = f_buy_and_hold(r3, backtest)
[bah4, dd4] = f_buy_and_hold(r4, backtest)
[bah5, dd5] = f_buy_and_hold(r5, backtest)
[bah6, dd6] = f_buy_and_hold(r6, backtest)
// Calculating of Performance metrics of Strategy and Buy and Hold for each asset (returned in an array)
since = f_since(backtest)
float[] a_strategy = f_PerformanceMetrics(eq, since, backtest, dd_eq)
float[] a1 = f_PerformanceMetrics(bah1, since, backtest, dd1)
float[] a2 = f_PerformanceMetrics(bah2, since, backtest, dd2)
float[] a3 = f_PerformanceMetrics(bah3, since, backtest, dd3)
float[] a4 = f_PerformanceMetrics(bah4, since, backtest, dd4)
float[] a5 = f_PerformanceMetrics(bah5, since, backtest, dd5)
float[] a6 = f_PerformanceMetrics(bah6, since, backtest, dd6)
//}
// ╔════════════════════════════╗
// ║ PLOTS AND TABLES ║
// ╚════════════════════════════╝
//{
// Place all colors into an array for table and functions
color[] colors = array.new_color(8)
array.set(colors, 0, asset1_col), array.set(colors, 1, asset2_col)
array.set(colors, 2, asset3_col), array.set(colors, 3, asset4_col)
array.set(colors, 4, asset5_col), array.set(colors, 5, asset6_col)
array.set(colors, 6, usd_col), array.set(colors, 7, tab_lab_text_col)
// Plotting equity curves
plot(eq, "Best Asset Equity", color = f_best_asset_col(ticker1, ticker2, ticker3, ticker4, ticker5, ticker6, best_asset, backtest, colors), linewidth = 3)
plot(bah1, "Buy and Hold Asset1", color = backtest ? color.new(asset1_col, 30) : color.new(color.white, 100))
plot(bah2, "Buy and Hold Asset2", color = backtest ? color.new(asset2_col, 30) : color.new(color.white, 100))
plot(bah3, "Buy and Hold Asset3", color = backtest ? color.new(asset3_col, 30) : color.new(color.white, 100))
plot(bah4, "Buy and Hold Asset4", color = backtest ? color.new(asset4_col, 30) : color.new(color.white, 100))
plot(bah5, "Buy and Hold Asset5", color = backtest ? color.new(asset5_col, 30) : color.new(color.white, 100))
plot(bah6, "Buy and Hold Asset6", color = backtest ? color.new(asset6_col, 30) : color.new(color.white, 100))
// Labels
if backtest and barstate.islast
label.new(bar_index + 5, eq, "Strategy", color = color.gray, textcolor = tab_lab_text_col, style = label.style_label_left)
label.new(bar_index + 5, bah1, str.tostring(f_remove_exchange_name(ticker1)), color = asset1_col, textcolor = tab_lab_text_col, style = label.style_label_left)
label.new(bar_index + 5, bah2, str.tostring(f_remove_exchange_name(ticker2)), color = asset2_col, textcolor = tab_lab_text_col, style = label.style_label_left)
label.new(bar_index + 5, bah3, str.tostring(f_remove_exchange_name(ticker3)), color = asset3_col, textcolor = tab_lab_text_col, style = label.style_label_left)
label.new(bar_index + 5, bah4, str.tostring(f_remove_exchange_name(ticker4)), color = asset4_col, textcolor = tab_lab_text_col, style = label.style_label_left)
label.new(bar_index + 5, bah5, str.tostring(f_remove_exchange_name(ticker5)), color = asset5_col, textcolor = tab_lab_text_col, style = label.style_label_left)
label.new(bar_index + 5, bah6, str.tostring(f_remove_exchange_name(ticker6)), color = asset6_col, textcolor = tab_lab_text_col, style = label.style_label_left)
// Barcolor
barcolor(f_best_asset_col(ticker1, ticker2, ticker3, ticker4, ticker5, ticker6, best_asset, backtest, colors))
// Tables
table t = table.new(position.bottom_right, 9, 8, bgcolor = color.new(color.gray, 80), frame_color = color.white, frame_width = 2)
table b = table.new(position.bottom_center, 1, 2, bgcolor = color.new(color.gray, 80), frame_color = color.white, frame_width = 2)
if barstate.islast
// Table with Trend Scores //
// Table Headers
t.cell(0, 0, text = "")
t.cell(0, 1, text = str.tostring(f_remove_exchange_name(ticker1)), text_color = asset1_col)
t.cell(0, 2, text = str.tostring(f_remove_exchange_name(ticker2)), text_color = asset2_col),
t.cell(0, 3, text = str.tostring(f_remove_exchange_name(ticker3)), text_color = asset3_col),
t.cell(0, 4, text = str.tostring(f_remove_exchange_name(ticker4)), text_color = asset4_col),
t.cell(0, 5, text = str.tostring(f_remove_exchange_name(ticker5)), text_color = asset5_col),
t.cell(0, 6, text = str.tostring(f_remove_exchange_name(ticker6)), text_color = asset6_col),
t.cell(0, 7, "USD", text_color = usd_col)
t.cell(1, 0, text = str.tostring(f_remove_exchange_name(ticker1)), text_color = tab_lab_text_col)
t.cell(2, 0, text = str.tostring(f_remove_exchange_name(ticker2)), text_color = tab_lab_text_col),
t.cell(3, 0, text = str.tostring(f_remove_exchange_name(ticker3)), text_color = tab_lab_text_col),
t.cell(4, 0, text = str.tostring(f_remove_exchange_name(ticker4)), text_color = tab_lab_text_col),
t.cell(5, 0, text = str.tostring(f_remove_exchange_name(ticker5)), text_color = tab_lab_text_col),
t.cell(6, 0, text = str.tostring(f_remove_exchange_name(ticker6)), text_color = tab_lab_text_col),
t.cell(7, 0, "USD", text_color = tab_lab_text_col)
// Trend Scores
t.cell(2, 1, text = str.tostring(c1_2[1]), text_color = f_trend_col(c1_2[1])), t.cell(1, 2, text = str.tostring(c2_1[1]), text_color = f_trend_col(c2_1[1]))
t.cell(3, 1, text = str.tostring(c1_3[1]), text_color = f_trend_col(c1_3[1])), t.cell(1, 3, text = str.tostring(c3_1[1]), text_color = f_trend_col(c3_1[1]))
t.cell(4, 1, text = str.tostring(c1_4[1]), text_color = f_trend_col(c1_4[1])), t.cell(1, 4, text = str.tostring(c4_1[1]), text_color = f_trend_col(c4_1[1]))
t.cell(5, 1, text = str.tostring(c1_5[1]), text_color = f_trend_col(c1_5[1])), t.cell(1, 5, text = str.tostring(c5_1[1]), text_color = f_trend_col(c5_1[1]))
t.cell(6, 1, text = str.tostring(c1_6[1]), text_color = f_trend_col(c1_6[1])), t.cell(1, 6, text = str.tostring(c6_1[1]), text_color = f_trend_col(c6_1[1]))
t.cell(7, 1, text = str.tostring(c1_usd[1]), text_color = f_trend_col(c1_usd[1])), t.cell(1, 7, text = str.tostring(cusd_1[1]), text_color = f_trend_col(cusd_1[1]))
t.cell(3, 2, text = str.tostring(c2_3[1]), text_color = f_trend_col(c2_3[1])), t.cell(2, 3, text = str.tostring(c3_2[1]), text_color = f_trend_col(c3_2[1]))
t.cell(4, 2, text = str.tostring(c2_4[1]), text_color = f_trend_col(c2_4[1])), t.cell(2, 4, text = str.tostring(c4_2[1]), text_color = f_trend_col(c4_2[1]))
t.cell(5, 2, text = str.tostring(c2_5[1]), text_color = f_trend_col(c2_5[1])), t.cell(2, 5, text = str.tostring(c5_2[1]), text_color = f_trend_col(c5_2[1]))
t.cell(6, 2, text = str.tostring(c2_6[1]), text_color = f_trend_col(c2_6[1])), t.cell(2, 6, text = str.tostring(c6_2[1]), text_color = f_trend_col(c6_2[1]))
t.cell(7, 2, text = str.tostring(c2_usd[1]), text_color = f_trend_col(c2_usd[1])), t.cell(2, 7, text = str.tostring(cusd_2[1]), text_color = f_trend_col(cusd_2[1]))
t.cell(4, 3, text = str.tostring(c3_4[1]), text_color = f_trend_col(c3_4[1])), t.cell(3, 4, text = str.tostring(c4_3[1]), text_color = f_trend_col(c4_3[1]))
t.cell(5, 3, text = str.tostring(c3_5[1]), text_color = f_trend_col(c3_5[1])), t.cell(3, 5, text = str.tostring(c5_3[1]), text_color = f_trend_col(c5_3[1]))
t.cell(6, 3, text = str.tostring(c3_6[1]), text_color = f_trend_col(c3_6[1])), t.cell(3, 6, text = str.tostring(c6_3[1]), text_color = f_trend_col(c6_3[1]))
t.cell(7, 3, text = str.tostring(c3_usd[1]), text_color = f_trend_col(c3_usd[1])), t.cell(3, 7, text = str.tostring(cusd_3[1]), text_color = f_trend_col(cusd_3[1]))
t.cell(5, 4, text = str.tostring(c4_5[1]), text_color = f_trend_col(c4_5[1])), t.cell(4, 5, text = str.tostring(c5_4[1]), text_color = f_trend_col(c5_4[1]))
t.cell(6, 4, text = str.tostring(c4_6[1]), text_color = f_trend_col(c4_6[1])), t.cell(4, 6, text = str.tostring(c6_4[1]), text_color = f_trend_col(c6_4[1]))
t.cell(7, 4, text = str.tostring(c4_usd[1]), text_color = f_trend_col(c4_usd[1])), t.cell(4, 7, text = str.tostring(cusd_4[1]), text_color = f_trend_col(cusd_4[1]))
t.cell(6, 5, text = str.tostring(c5_6[1]), text_color = f_trend_col(c5_6[1])), t.cell(5, 6, text = str.tostring(c6_5[1]), text_color = f_trend_col(c6_5[1]))
t.cell(7, 5, text = str.tostring(c5_usd[1]), text_color = f_trend_col(c5_usd[1])), t.cell(5, 7, text = str.tostring(cusd_5[1]), text_color = f_trend_col(cusd_5[1]))
t.cell(7, 6, text = str.tostring(c6_usd[1]), text_color = f_trend_col(c6_usd[1])), t.cell(6, 7, text = str.tostring(cusd_6[1]), text_color = f_trend_col(cusd_6[1]))
// Final Scores
t.cell(8, 0, "Score", text_color = tab_lab_text_col)
t.cell(8, 1, text = str.tostring(a1_score[1]), text_color = tab_lab_text_col)
t.cell(8, 2, text = str.tostring(a2_score[1]), text_color = tab_lab_text_col)
t.cell(8, 3, text = str.tostring(a3_score[1]), text_color = tab_lab_text_col)
t.cell(8, 4, text = str.tostring(a4_score[1]), text_color = tab_lab_text_col)
t.cell(8, 5, text = str.tostring(a5_score[1]), text_color = tab_lab_text_col)
t.cell(8, 6, text = str.tostring(a6_score[1]), text_color = tab_lab_text_col)
t.cell(8, 7, text = str.tostring(usd_score[1]), text_color = tab_lab_text_col)
// Separators
for x = 1 to 7
t.cell(x, x, "", bgcolor = color.new(color.gray, 50))
// Table B //
b.cell(0, 0, "Best Performing Asset:", text_color = tab_lab_text_col)
b.cell(0, 1, text = str.tostring(f_remove_exchange_name(best_asset[1])), text_color = tab_lab_text_col)
// Performance Metrics Table //
if plot_metric_table
f_PerfMetricTable(ticker1, ticker2, ticker3, ticker4, ticker5, ticker6, a_strategy, a1, a2, a3, a4, a5, a6, colors)
//}
// ╔════════════════════════════╗
// ║ ALETRS ║
// ╚════════════════════════════╝
//{
bool alert = not (best_asset[2] == best_asset[1]) // Using indexes ensures candle close confirmation
alertcondition(alert, "New Optimal Asset", message = "A new optimal asset has been detected. Check chart for details")
//}
Show all 614 lines