
이 전략은 양방향 가격 변동의 돌파구를 기반으로 한 양적 거래 전략이다. 그것은 Pivot High/Low을 가격의 핵심 지지부수로서 사용하고, Pivot High을 돌파할 때 더 많이 하고, Pivot Low을 돌파할 때 더 많이 하고, 양방향 작업을 수행한다.
이 전략의 핵심 논리는 양방향 가격의 핵심 점 돌파를 기반으로 합니다. 구체적으로 다음과 같은 몇 가지 단계가 있습니다:
지정된 주기에서의 Pivot 하위/하위를 계산한다. 여기서는 ta.pivothigh() 와 ta.pivotlow() 함수를 사용하여 최근 2일간의 최고 가격을 최고점으로, 최근 1일간의 최저 가격을 최저점으로 계산한다.
가격이 위에서 계산한 중요한 고점을 넘었을 때, 더 많은 입찰을하십시오. 가격이 중요한 낮은 점을 넘었을 때, 적폐 입찰을하십시오.
스포드 단위 스포드를 사용한다. 초과할 때, 스포드 가격은 최고점 + 최소 가격 변화 단위이다. 공백할 때, 스포드 가격은 최저점 - 최소 가격 변화 단위이다.
중요한 점들의 높고 낮은 점들을 그려서 직관적으로 판단하기 쉽다.
이렇게 하면 가격의 흔들림이 있을 때, 중요한 지점을 돌파할 때 적시에 진입할 수 있고, 빠르게 멈춰서 수익을 얻을 수 있다. 가격이 계속해서 새로운 높이를 돌파하거나 새로운 낮은 것을 돌파할 때, 전략은 여러 번 누적 수익을 달성할 수 있다.
이 두 가지 전략은 다음과 같은 장점을 가지고 있습니다.
간단하고 이해하기 쉽고 실행하기 쉽다. 이 전략은 단지 Pivot 하위점 (high/low) 을 뚫고 진출하는 것만으로 매우 간단하다.
손해를 쉽게 설정할 수 있다. 더 많은 코카이드를 할 때 높은 점과 낮은 점 + 최소 변화 거리를 손해 지점으로 삼아 신속하게 손해를 멈추고 위험을 효과적으로 제어할 수 있다.
양방향으로 작동할 수 있다. 시장이 오르락 내리락 하락하더라도 이 전략은 순차적으로 작동하여 수익을 누릴 수 있다.
위기 상황에 적합하다. 가격이 자주 오르락 내리락할 때, 전략은 자주 현장에 들어가 수익을 얻을 수 있다.
이러한 장점들에도 불구하고, 몇 가지 위험도 있습니다.
핵심 포인트를 잘못 설정하면 손실이 증가할 수 있다. 핵심 높고 낮은 포인트를 잘못 설정하면, 극단적인 경우 최고를 추격할 수 있다.
흔들림이 끝난 후 손실이 시작될 수 있다. 가격이 흔들림이 아닌 일방적인 돌파구가 나타나기 시작하면 이 전략은 수익을 내기 어렵다.
브레이크는 단기적인 가짜 브레이크일 수 있다. 단기간에 가짜 브레이크가 발생할 수도 있고, 전략은 잘못된 거래를 하게 된다.
전체적으로 이 전략은 충격적인 상황에서 사용하기에 더 적합하다. 투자자는 상황을 판단하는 데 주의를 기울여야 하며, 트렌드 상황에서 이 전략을 사용하는 것을 피해야 한다. 동시에, 핵심점을 확인하는 오류, 가짜 돌파구 등의 문제로 인한 손실을 방지하는 데 주의를 기울여야 한다.
위와 같은 위험들을 고려하여, 이 전략의 최적화 공간은 다음과 같은 부분들에 있습니다.
지능형 선택 키 높고 낮은 점 매개 변수. 기계 학습과 같은 방법을 통해 시스템이 자동으로 최적화하여 적절한 키 포인트 매개 변수를 선택하도록 할 수 있습니다.
결합된 트렌드 판단. 전략의 기초에 트렌드에 대한 판단 논리를 추가하고, 흔들리는 상황에서 전략을 사용하며, 일방적인 추세에서 전략을 종료하여 손실을 줄인다.
더 많은 스톱 전략. 이동 스톱, 간격 브레이크 스톱과 같은 더 정교한 스톱 전략을 설계하여 위험을 더욱 제어 할 수 있습니다.
이 전략은 간단하고 실용적인 양방향의 돌파구 전략이다. 그것은 가격의 중요한 지점의 돌파구에 의존하여 진입하고, 손해 방지 위험을 조절할 수 있도록 설정한다. 이 전략은 충격적인 상황에 적합하며, 양방향 거래에서 수익을 얻을 수 있다. 그러나 이 전략은 또한 위험이 있으며, 투자자는 신중하게 사용해야하며, 최적화 공간은 지능적인 선택 파라미터, 추세 판단과 더 정교한 손해 방지 전략을 설계하는 것과 같은 측면에 있다.
/*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)