이것은 월별 수익 표시를 기반으로 한 양적 거래 전략입니다. 분석을 위해 차트에 있는 표에 전략의 월별 및 연간 수익률과 벤치마크 수익률을 계산하고 제시하기 위해 파인 스크립트를 사용합니다.
이 전략의 핵심 논리는 월간 및 연간 성과를 추적하고 계산하고 표 형식으로 표시하는 것입니다. 주요 단계는 다음과 같습니다.
자금의 변화에 기초하여 월 및 연간 수익을 계산합니다.
기준값의 월 및 연간 수익을 가격변화에 기초하여 계산합니다.
매월 및 연간 반환을 배열로 저장합니다.
바가 확인되면 매월 퍼프를 표시하기 위해 저장된 반환 배열을 사용하여 테이블을 채우십시오.
두 번째 줄에 기준값을 표시하고 세 번째 줄에 알파를 표시합니다.
이렇게 함으로써 이 스크립트는 매월 수익을 조직된 표와 함께 벤치마크 비교로 명확하게 제시할 수 있습니다. 이것은 성과를 분석하는 데 도움이 됩니다.
이 월간 수익 전략의 주요 장점은 다음과 같습니다.
직관적인 월별 수익 표시. 테이블 형식은 성과를 쉽게 분석합니다.
명확한 벤치마크 비교. 별도의 벤치마크 행을 표시하면 전략 대 시장 성과 분석이 가능합니다.
알파 계산. 알파 행은 전략이 벤치마크를 능가하거나 저하하는지를 보여줍니다.
유연성을 위해 사용자 지정 가능한 매개 변수. 사용자는 필요에 따라 색상, 날짜 범위, 벤치마크 기호 등을 설정할 수 있습니다.
이 전략에서 주목해야 할 몇 가지 위험은 다음과 같습니다.
트레이딩 논리가 없습니다. 이것은 단순히 수익을 표시합니다. 실제 거래를 포함하지 않습니다.
역사적인 성과가 계속되지 않을 수 있습니다. 모든 백테스트와 마찬가지로 과거의 수익은 미래의 성과를 보장하지 않습니다.
수익 계산에서 오류가 발생할 수 있습니다. 버그는 잘못된 월간 수익 수치로 이어질 수 있습니다.
전체적으로 이 스크립트는 주로 성능 시각화 도구로 사용됩니다. 수익 계산의 정확성을 보장함으로써 위험을 완화 할 수 있으며 백테스트에만 의존하지 않습니다.
이 월간 수익 전략이 개선될 수 있는 몇 가지 방법은 다음과 같습니다.
실제 거래 전략을 추가하고 성능을 표시합니다. 양성 전략과 결합합니다.
벤치마크 기호, 시간 프레임 등과 같은 벤치마크 사용자 정의 매개 변수를 추가합니다.
더 나은 시각을 위해 테이블 포맷을 향상 - 색상, 셀, 포맷 등
더 많은 분석을 위해 다른 수익 메트릭 - CAGR, 샤프 비율 등을 추가하십시오.
이 전략은 특히 더 쉬운 분석을 위해 테이블 형식으로 시스템 및 벤치마크의 월간 수익을 표시하는 데 초점을 맞추고 있습니다. 이의 장점은 직관적인 시각화 및 전략과 벤치마크의 비교입니다. 위험은 거래 논리 부족과 백테스트에 의존하는 것입니다. 양자 전략과 결합하여 추가 사용자 정의 옵션 및 더 많은 메트릭을 추가하여 향상시킬 수 있습니다.
/*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)