Estrategia de rendimientos mensuales con referencia

El autor:¿ Qué pasa?, Fecha: 2024-01-30 17:40:05
Las etiquetas:

img

Resumen general

Esta es una estrategia de negociación cuantitativa basada en la visualización de rendimientos mensuales. Utiliza Pine Script para calcular y presentar los rendimientos mensuales y anuales de la estrategia, así como los rendimientos de referencia, en una tabla en el gráfico para análisis.

Estrategia lógica

La lógica central de esta estrategia es realizar un seguimiento y calcular el rendimiento mensual y anual, y mostrarlo en un formato de tabla.

  1. Calcular el rendimiento mensual y anual basado en el cambio de capital.

  2. Calcular los rendimientos mensuales y anuales de referencia basados en la variación de precios.

  3. Almacenar las declaraciones mensuales y anuales en matrices.

  4. Cuando el bar está confirmado, rellene una tabla utilizando las matrices de retorno almacenadas para presentar la perf mensual.

  5. Muestra el punto de referencia en la segunda fila de la tabla. Muestra alfa en la tercera fila.

Al hacerlo, este script puede presentar claramente los rendimientos mensuales en una tabla organizada, junto con la comparación de referencia.

Ventajas

Las principales ventajas de esta estrategia de rentabilidad mensual son:

  1. Display intuitivo de los rendimientos mensuales El formato de la tabla hace que el rendimiento sea fácil de analizar.

  2. Comparación clara de los índices de referencia: la visualización de una fila de índices de referencia separada permite el análisis de la estrategia frente al rendimiento del mercado.

  3. Calculo alfa: la fila alfa muestra si la estrategia tiene un rendimiento superior o inferior al del índice de referencia.

  4. Los parámetros personalizables para la flexibilidad. El usuario puede establecer colores, rango de fecha, símbolo de referencia, etc. según sea necesario.

Los riesgos

Algunos riesgos a tener en cuenta con esta estrategia son:

  1. No hay lógica de negociación. Esto sólo muestra los rendimientos, no incluye las operaciones reales.

  2. El rendimiento histórico puede no continuar. Como con cualquier prueba posterior, los rendimientos pasados no garantizan el rendimiento futuro.

  3. Errores potenciales en el cálculo de la rentabilidad.

En general, este guión sirve principalmente como una herramienta de visualización de rendimiento. Los riesgos pueden mitigarse al garantizar la precisión de los cálculos de rendimiento y no depender únicamente de las pruebas de retroceso.

Oportunidades de mejora

Algunas maneras en que esta estrategia de retorno mensual podría mejorarse son:

  1. Añadir una estrategia de trading real cuyo rendimiento se muestra.

  2. Añadir más parámetros de personalización de referencia como el símbolo de referencia, el marco de tiempo, etc.

  3. Mejorar el formato de la tabla para obtener mejores imágenes: colores, celdas, formato, etc.

  4. Añadir otras métricas de retorno - CAGR, ratio Sharpe, etc. para más análisis.

Conclusión

Esta es una estrategia enfocada específicamente en mostrar los rendimientos mensuales del sistema y el índice de referencia en formato de tabla para un análisis más fácil. Sus ventajas son la visualización intuitiva y la comparación de la estrategia vs índice de referencia. Los riesgos son la falta de lógica de negociación y la dependencia de las pruebas de retroceso. Se puede mejorar combinando con la estrategia de cantidad, agregando más opciones de personalización y más métricas.


/*backtest
start: 2023-12-01 00:00:00
end: 2023-12-31 23:59:59
period: 2h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=5
strategy('Monthly Returns with Benchmark', overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=25, commission_type=strategy.commission.percent, commission_value=0.1)

////////////
// Inputs //

// Pivot points inputs
leftBars   = input(2, group = "Pivot Points")
rightBars  = input(1, group = "Pivot Points")

// Styling inputs
prec       = input(2, title='Return Precision',                            group = "Monthly Table")
from_date  = input(timestamp("01 Jan 2000 00:00 +0000"), "From Date", group = "Monthly Table")
prof_color = input.color(color.green, title = "Gradient Colors", group = "Monthly Table", inline = "colors")
loss_color = input.color(color.red,   title = "",                group = "Monthly Table", inline = "colors")

// Benchmark inputs
use_cur    = input.bool(true,        title = "Use current Symbol for Benchmark", group = "Benchmark")
symb_bench = input('BTC_USDT:swap', title = "Benchmark",                        group = "Benchmark")
disp_bench = input.bool(true,        title = "Display Benchmark?",               group = "Benchmark")
disp_alpha = input.bool(true,        title = "Display Alpha?",                   group = "Benchmark")

// Pivot Points Strategy
swh = ta.pivothigh(leftBars, rightBars)
swl = ta.pivotlow(leftBars, rightBars)

hprice = 0.0
hprice := not na(swh) ? swh : hprice[1]

lprice = 0.0
lprice := not na(swl) ? swl : lprice[1]

le = false
le := not na(swh) ? true : le[1] and high > hprice ? false : le[1]

se = false
se := not na(swl) ? true : se[1] and low < lprice ? false : se[1]

if le
    strategy.entry('PivRevLE', strategy.long, comment='PivRevLE', stop=hprice + syminfo.mintick)

if se
    strategy.entry('PivRevSE', strategy.short, comment='PivRevSE', stop=lprice - syminfo.mintick)

plot(hprice, color=color.new(color.green, 0), linewidth=2)
plot(lprice, color=color.new(color.red, 0), linewidth=2)

///////////////////
// MONTHLY TABLE //

new_month = month(time) != month(time[1])
new_year  = year(time)  != year(time[1])

eq       = strategy.equity
bench_eq = close

// benchmark eq
bench_eq_htf = request.security(symb_bench, timeframe.period, close)

if (not use_cur)
    bench_eq := bench_eq_htf

bar_pnl   = eq / eq[1] - 1
bench_pnl = bench_eq / bench_eq[1] - 1

cur_month_pnl = 0.0
cur_year_pnl  = 0.0

// Current Monthly P&L
cur_month_pnl := bar_index == 0 ? 0 : 
                 time >= from_date and (time[1] < from_date or new_month) ? bar_pnl : 
                 (1 + cur_month_pnl[1]) * (1 + bar_pnl) - 1

// Current Yearly P&L
cur_year_pnl  := bar_index == 0 ? 0 : 
                 time >= from_date and (time[1] < from_date or new_year) ? bar_pnl : 
                 (1 + cur_year_pnl[1]) * (1 + bar_pnl) - 1

bench_cur_month_pnl = 0.0
bench_cur_year_pnl  = 0.0

// Current Monthly P&L - Bench
bench_cur_month_pnl := bar_index == 0 or (time[1] < from_date and time >= from_date) ? 0 : 
                       time >= from_date and new_month ? bench_pnl : 
                       (1 + bench_cur_month_pnl[1]) * (1 + bench_pnl) - 1 

// Current Yearly P&L - Bench
bench_cur_year_pnl :=  bar_index == 0 ? 0 : 
                       time >= from_date and (time[1] < from_date  or new_year) ? bench_pnl : 
                       (1 + bench_cur_year_pnl[1]) * (1 + bench_pnl) - 1

var month_time = array.new_int(0)
var year_time  = array.new_int(0)

var month_pnl = array.new_float(0)
var year_pnl  = array.new_float(0)

var bench_month_pnl = array.new_float(0)
var bench_year_pnl  = array.new_float(0)

// Filling monthly / yearly pnl arrays
if array.size(month_time) > 0
    if month(time) == month(array.get(month_time, array.size(month_time) - 1))
        array.pop(month_pnl)
        array.pop(bench_month_pnl)
        array.pop(month_time)

if array.size(year_time) > 0
    if year(time) == year(array.get(year_time, array.size(year_time) - 1))
        array.pop(year_pnl)
        array.pop(bench_year_pnl)
        array.pop(year_time)

if (time >= from_date)
    array.push(month_time, time)
    array.push(year_time,  time)
    
    array.push(month_pnl, cur_month_pnl)
    array.push(year_pnl,  cur_year_pnl)
    
    array.push(bench_year_pnl,  bench_cur_year_pnl)
    array.push(bench_month_pnl, bench_cur_month_pnl)

// Monthly P&L Table    
var monthly_table = table(na)

if array.size(year_pnl) > 0 and barstate.islastconfirmedhistory

    monthly_table := table.new(position.bottom_right, columns=15, rows=array.size(year_pnl) * 3 + 5, border_width=1)

    // Fill monthly performance

    table.cell(monthly_table, 0, 0,  'Perf', bgcolor = #999999)
    table.cell(monthly_table, 1, 0,  'Jan',  bgcolor = #999999)
    table.cell(monthly_table, 2, 0,  'Feb',  bgcolor = #999999)
    table.cell(monthly_table, 3, 0,  'Mar',  bgcolor = #999999)
    table.cell(monthly_table, 4, 0,  'Apr',  bgcolor = #999999)
    table.cell(monthly_table, 5, 0,  'May',  bgcolor = #999999)
    table.cell(monthly_table, 6, 0,  'Jun',  bgcolor = #999999)
    table.cell(monthly_table, 7, 0,  'Jul',  bgcolor = #999999)
    table.cell(monthly_table, 8, 0,  'Aug',  bgcolor = #999999)
    table.cell(monthly_table, 9, 0,  'Sep',  bgcolor = #999999)
    table.cell(monthly_table, 10, 0, 'Oct',  bgcolor = #999999)
    table.cell(monthly_table, 11, 0, 'Nov',  bgcolor = #999999)
    table.cell(monthly_table, 12, 0, 'Dec',  bgcolor = #999999)
    table.cell(monthly_table, 13, 0, ' ', bgcolor = #999999)
    table.cell(monthly_table, 14, 0, 'Year', bgcolor = #999999)

    max_abs_y = math.max(math.abs(array.max(year_pnl)),  math.abs(array.min(year_pnl)))
    max_abs_m = math.max(math.abs(array.max(month_pnl)), math.abs(array.min(month_pnl)))

    for yi = 0 to array.size(year_pnl) - 1 by 1
        table.cell(monthly_table, 0,  yi + 1, str.tostring(year(array.get(year_time, yi))), bgcolor=#cccccc)
        table.cell(monthly_table, 13, yi + 1, ' ',   bgcolor=#999999)
        y_color = color.from_gradient(array.get(year_pnl, yi), -max_abs_y, max_abs_y, loss_color, prof_color) 
        table.cell(monthly_table, 14, yi + 1, str.tostring(math.round(array.get(year_pnl, yi) * 100, prec)), bgcolor=y_color)

    for mi = 0 to array.size(month_time) - 1 by 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 = color.from_gradient(array.get(month_pnl, mi), -max_abs_m, max_abs_m, loss_color, prof_color)

        table.cell(monthly_table, m_col, m_row, str.tostring(math.round(array.get(month_pnl, mi) * 100, prec)), bgcolor=m_color)
    
    // Fill benchmark performance
    next_row =  array.size(year_pnl) + 1  
    
    if (disp_bench)
    
        table.cell(monthly_table, 0,  next_row, 'Bench', bgcolor=#999999)
        table.cell(monthly_table, 1,  next_row, 'Jan',   bgcolor=#999999)
        table.cell(monthly_table, 2,  next_row, 'Feb',   bgcolor=#999999)
        table.cell(monthly_table, 3,  next_row, 'Mar',   bgcolor=#999999)
        table.cell(monthly_table, 4,  next_row, 'Apr',   bgcolor=#999999)
        table.cell(monthly_table, 5,  next_row, 'May',   bgcolor=#999999)
        table.cell(monthly_table, 6,  next_row, 'Jun',   bgcolor=#999999)
        table.cell(monthly_table, 7,  next_row, 'Jul',   bgcolor=#999999)
        table.cell(monthly_table, 8,  next_row, 'Aug',   bgcolor=#999999)
        table.cell(monthly_table, 9,  next_row, 'Sep',   bgcolor=#999999)
        table.cell(monthly_table, 10, next_row, 'Oct',   bgcolor=#999999)
        table.cell(monthly_table, 11, next_row, 'Nov',   bgcolor=#999999)
        table.cell(monthly_table, 12, next_row, 'Dec',   bgcolor=#999999)
        table.cell(monthly_table, 13, next_row, ' ',     bgcolor = #999999)
        table.cell(monthly_table, 14, next_row, 'Year',  bgcolor=#999999)
    
        max_bench_abs_y = math.max(math.abs(array.max(bench_year_pnl)),  math.abs(array.min(bench_year_pnl)))
        max_bench_abs_m = math.max(math.abs(array.max(bench_month_pnl)), math.abs(array.min(bench_month_pnl)))
    
        for yi = 0 to array.size(year_time) - 1 by 1
            table.cell(monthly_table, 0,  yi + 1 + next_row + 1, str.tostring(year(array.get(year_time, yi))), bgcolor=#cccccc)
            table.cell(monthly_table, 13, yi + 1 + next_row + 1, ' ',   bgcolor=#999999)
            y_color = color.from_gradient(array.get(bench_year_pnl, yi), -max_bench_abs_y, max_bench_abs_y, loss_color, prof_color)
            table.cell(monthly_table, 14, yi + 1 + next_row + 1, str.tostring(math.round(array.get(bench_year_pnl, yi) * 100, prec)), bgcolor=y_color)
     
        for mi = 0 to array.size(month_time) - 1 by 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 = color.from_gradient(array.get(bench_month_pnl, mi), -max_bench_abs_m, max_bench_abs_m, loss_color, prof_color)
    
            table.cell(monthly_table, m_col, m_row  + next_row + 1, str.tostring(math.round(array.get(bench_month_pnl, mi) * 100, prec)), bgcolor=m_color)
    
    // Fill Alpha
    if (disp_alpha)
    
        next_row :=  array.size(year_pnl) * 2 + 3   
        table.cell(monthly_table, 0,  next_row, 'Alpha', bgcolor=#999999)
        table.cell(monthly_table, 1,  next_row, 'Jan',   bgcolor=#999999)
        table.cell(monthly_table, 2,  next_row, 'Feb',   bgcolor=#999999)
        table.cell(monthly_table, 3,  next_row, 'Mar',   bgcolor=#999999)
        table.cell(monthly_table, 4,  next_row, 'Apr',   bgcolor=#999999)
        table.cell(monthly_table, 5,  next_row, 'May',   bgcolor=#999999)
        table.cell(monthly_table, 6,  next_row, 'Jun',   bgcolor=#999999)
        table.cell(monthly_table, 7,  next_row, 'Jul',   bgcolor=#999999)
        table.cell(monthly_table, 8,  next_row, 'Aug',   bgcolor=#999999)
        table.cell(monthly_table, 9,  next_row, 'Sep',   bgcolor=#999999)
        table.cell(monthly_table, 10, next_row, 'Oct',   bgcolor=#999999)
        table.cell(monthly_table, 11, next_row, 'Nov',   bgcolor=#999999)
        table.cell(monthly_table, 12, next_row, 'Dec',   bgcolor=#999999)
        table.cell(monthly_table, 13, next_row, '',      bgcolor=#999999)
        table.cell(monthly_table, 14, next_row, 'Year',  bgcolor=#999999)
        
        max_alpha_abs_y = 0.0
        for yi = 0 to array.size(year_time) - 1 by 1
            if (math.abs(array.get(year_pnl, yi)  - array.get(bench_year_pnl, yi)) > max_alpha_abs_y)
                max_alpha_abs_y := math.abs(array.get(year_pnl, yi)  - array.get(bench_year_pnl, yi))
    
        max_alpha_abs_m = 0.0
        for mi = 0 to array.size(month_pnl) - 1 by 1
            if (math.abs(array.get(month_pnl, mi) - array.get(bench_month_pnl, mi)) > max_alpha_abs_m)
                max_alpha_abs_m := math.abs(array.get(month_pnl, mi) - array.get(bench_month_pnl, mi))
                
        for yi = 0 to array.size(year_time) - 1 by 1
            table.cell(monthly_table, 0,  yi + 1 + next_row + 1, str.tostring(year(array.get(year_time, yi))), bgcolor=#cccccc)
            table.cell(monthly_table, 13, yi + 1 + next_row + 1, ' ',   bgcolor=#999999)
            y_color = color.from_gradient(array.get(year_pnl, yi)  - array.get(bench_year_pnl, yi), -max_alpha_abs_y, max_alpha_abs_y, loss_color, prof_color)
            table.cell(monthly_table, 14, yi + 1 + next_row + 1, str.tostring(math.round((array.get(year_pnl, yi)  - array.get(bench_year_pnl, yi)) * 100, prec)), bgcolor=y_color)
     
        for mi = 0 to array.size(month_time) - 1 by 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 = color.from_gradient(array.get(month_pnl, mi) - array.get(bench_month_pnl, mi), -max_alpha_abs_m, max_alpha_abs_m, loss_color, prof_color)
    
            table.cell(monthly_table, m_col, m_row  + next_row + 1, str.tostring(math.round((array.get(month_pnl, mi) - array.get(bench_month_pnl, mi)) * 100, prec)), bgcolor=m_color)


Más.