Стратегия направления с несколькими столбцами

Автор:Чао Чжан, Дата: 2023-10-18 12:20:59
Тэги:

img

Обзор

Стратегия Multi-Bar Direction идентифицирует сигналы обратного тренда, рассчитывая вероятность того, что несколько панелей движутся в одном направлении.

Логика стратегии

Стратегия сначала устанавливает время начала и окончания для извлечения исторических данных. Часы торговли настраиваются для идентификации квалифицированных свечей. Она рассчитывает вероятность последовательных подъемов или падений в пределах 2 до 7 свечей. Торговые сигналы генерируются, когда соотношение вверх или вниз превышает порог.

Например, если вероятность нисходящего тренда в 3 свечах ниже 50%, то текущие 3 свечи соответствуют условию и генерируется сигнал покупки.

Конкретная логика такова:

  1. Установите временной диапазон обратного тестирования, включая дату начала, дату окончания, часы торговли.

  2. Подсчитайте количество подъемов или падений в одном направлении в пределах от 2 до 7 свечей.

  3. Вычислить вероятность продолжения движения вверх или вниз между соседними светильниками.

  4. Если вероятность ниже 50%, то текущие свечи соответствуют обратной схеме.

  5. Создавать сигналы покупки или продажи в течение рабочего времени.

  6. Проверка для подтверждения стратегии.

Преимущества

  • Избегайте ложных сигналов, рассматривая вероятность множества свечей.

  • Настраиваемое количество строк для идентификации сигналов обратного движения в разные временные рамки.

  • Четкие торговые часы избегают несвоевременных сигналов.

  • Интуитивное отображение статистики для оценки производительности.

  • Много оптимизируемых параметров, подходящих для разных рынков.

Риски

  • Счет строк не может полностью определить точки переворота тренда.

  • Долгая продолжительность статистики может лишить краткосрочных торговых возможностей.

  • Статический порог зависит от волатильности рынка, поэтому требуется динамическая корректировка.

  • Выбор периода обратного испытания может привести к переустановке.

Возможные решения:

  1. Оптимизируйте количество строк для разных временных рамок.

  2. Включить другие показатели.

  3. Принять динамические пороги, основанные на волатильности рынка.

  4. Расширить период обратных тестов и запустить несколько обратных тестов.

Руководство по оптимизации

Стратегия может быть оптимизирована в следующих аспектах:

  1. Оптимизируйте количество строк от 2 до 10 и выберите оптимальный параметр.

  2. Порог отмены испытаний с 40% до 60% с учетом изменений на рынке.

  3. Добавьте стоп-лосс после генерации сигнала, чтобы ограничить риск.

  4. Включите другие индикаторы, такие как RSI, для проверки сигналов.

  5. Добавьте больше продуктов, таких как фьючерсы и форекс для тестирования параметров.

  6. Инкрементальная настройка параметров для поиска оптимальных комбинаций.

  7. Применять модели машинного обучения для автоматического поиска оптимальных параметров.

Заключение

Стратегия Multi-Bar Direction идентифицирует потенциальные сигналы обратного движения путем статистического анализа вероятности свечей. Но производительность зависит от настройки параметров на основе достаточных оптимизаций. Кроме того, сигналы обратного движения имеют риски ошибочного суждения и нуждаются в проверке. В целом, это простая и эффективная статистическая стратегия, полезная для дальнейших исследований и оптимизации.


/*backtest
start: 2023-10-16 00:00:00
end: 2023-10-17 00:00:00
period: 5m
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// BO - Bar's direction Signal - Backtesting
//anch.v43
// © inno14
//@version=4

strategy("BO - Bar's direction Signal - Backtesting", pyramiding=15)
// === INPUT PERIOD OF TIME ===
Date   = input(true, title = "=== Periods Counting ===")
FromDay   = input(defval = 1, title = "From Day", minval = 1, maxval = 31)
FromMonth = input(defval = 1, title = "From Month", minval = 1, maxval = 12)
FromYear  = input(defval = 2020, title = "From Year", minval = 2017)

ToDay     = input(defval = 1, title = "To Day", minval = 1, maxval = 31)
ToMonth   = input(defval = 1, title = "To Month", minval = 1, maxval = 12)
ToYear    = input(defval = 9999, title = "To Year", minval = 2017)

// === DATE RANGE ===
start     = timestamp(FromYear, FromMonth, FromDay, 00, 00)  // backtest start window
finish    = timestamp(ToYear, ToMonth, ToDay, 23, 59)        // backtest finish window
window()  => time >= start and time <= finish ? true : false // create function "within window of time"

// === Trading Time ===
CTimeDvM   = input(true, title = "=== Trading Time ===")
Time_zone = input(7,title="Time Zone")
FromHourDvM   = input(defval = 05, title = "From Hour", minval = 00, maxval = 23)
FromMinuteDvM = input(defval = 00, title = "From Minute", minval = 00, maxval = 59)
ToHourDvM   = input(defval = 04, title = "To Hour", minval = 00, maxval = 23)
ToMinuteDvM = input(defval = 59, title = "To Minute", minval = 00, maxval = 59)

GMT_FHDvM=FromHourDvM<Time_zone?FromHourDvM-Time_zone+24:FromHourDvM-Time_zone
GMT_THDvM=ToHourDvM<Time_zone?ToHourDvM-Time_zone+24:ToHourDvM-Time_zone
fhDvM= (GMT_FHDvM<10?"0"+tostring(GMT_FHDvM):tostring(GMT_FHDvM))
fmDvM= (FromMinuteDvM<10?"0"+tostring(FromMinuteDvM):tostring(FromMinuteDvM))
thDvM= (GMT_THDvM<10?"0"+tostring(GMT_THDvM):tostring(GMT_THDvM))
tmDvM= (ToMinuteDvM<10?"0"+tostring(ToMinuteDvM):tostring(ToMinuteDvM))
WorkingHourDvM = fhDvM+fmDvM+"-"+thDvM+tmDvM
t0_DvM = time(timeframe.period, WorkingHourDvM)
htrtime = input(true,title="Highlight Tradingtime")
bgcolor(htrtime? t0_DvM? color.gray : na:na, title="Trading Time", transp=90)

// === Date Backtesting ===
Date1   = input(true, title = "=== Date Backtesting ===")
FromDay1   = input(defval = 1, title = "From Day", minval = 1, maxval = 31)
FromMonth1 = input(defval = 1, title = "From Month", minval = 1, maxval = 12)
FromYear1  = input(defval = 2020, title = "From Year", minval = 2017)

ToDay1     = input(defval = 1, title = "To Day", minval = 1, maxval = 31)
ToMonth1   = input(defval = 1, title = "To Month", minval = 1, maxval = 12)
ToYear1    = input(defval = 9999, title = "To Year", minval = 2017)

// === DATE RANGE ===
start1     = timestamp(FromYear1, FromMonth1, FromDay1, 00, 00)  // backtest start window
finish1    = timestamp(ToYear1, ToMonth1, ToDay1, 23, 59)        // backtest finish window
window1()  => time >= start1 and time <= finish1 ? true : false // create function "within window of time"

// === Setup ===
Setup   = input(true, title = "=== Setup Options ===")
set1 = input(true, title = "Reversal after 2 bars same direction")
set2 = input(true, title = "Reversal after 3 bars same direction")
set3 = input(true, title = "Reversal after 4 bars same direction")
set4 = input(true, title = "Reversal after 5 bars same direction")
set5 = input(true, title = "Reversal after 6 bars same direction")


// Calculate hours, minutes, and seconds till close
timeLeft = barstate.isrealtime ?
     (time_close - timenow) / 1000 :
     na

minutesLeft = floor((timeLeft % 3600) / 60)
secondsLeft = timeLeft % 60
// truncate() truncates a given number
// to a certain number of decimals
truncate(number, decimals) =>
    factor = pow(10, decimals)
    int(number * factor) / factor
//count 2
redv2=window()?1:0
bluev2=window()?1:0
mchange2 = close[0]<open[0] and close[1]<open[1] and t0_DvM?-1:0
pchange2 = close[0]>open[0] and close[1]>open[1] and t0_DvM?1:0
blue2 = cum(pchange2 > 0 ? bluev2 : 0 * bluev2)
red2 = cum(mchange2 < 0 ? redv2 : 0 * redv2)

//count 3
redv3=window()?1:0
bluev3=window()?1:0
mchange3 = close[0]<open[0] and close[1]<open[1] and close[2]<open[2] and t0_DvM?-1:0
pchange3 = close[0]>open[0] and close[1]>open[1] and close[2]>open[2] and t0_DvM?1:0
blue3 = cum(pchange3 > 0 ? bluev3 : 0 * bluev3)
red3 = cum(mchange3 < 0 ? redv3 : 0 * redv3)

//count 4
redv4=window()?1:0
bluev4=window()?1:0
mchange4 = close[0]<open[0] and close[1]<open[1] and close[2]<open[2] and close[3]<open[3] and t0_DvM?-1:0
pchange4 = close[0]>open[0] and close[1]>open[1] and close[2]>open[2] and close[3]>open[3] and t0_DvM?1:0
blue4 = cum(pchange4 > 0 ? bluev4 : 0 * bluev4)
red4 = cum(mchange4 < 0 ? redv4 : 0 * redv4)

//count 5
redv5=window()?1:0
bluev5=window()?1:0
mchange5 = close[0]<open[0] and close[1]<open[1] and close[2]<open[2] and close[3]<open[3] and close[4]<open[4] and t0_DvM?-1:0
pchange5 = close[0]>open[0] and close[1]>open[1] and close[2]>open[2] and close[3]>open[3] and close[4]>open[4] and t0_DvM?1:0
blue5 = cum(pchange5 > 0 ? bluev5 : 0 * bluev5)
red5 = cum(mchange5 < 0 ? redv5 : 0 * redv5)

//count 6
redv6=window()?1:0
bluev6=window()?1:0
mchange6 = close[0]<open[0] and close[1]<open[1] and close[2]<open[2] and close[3]<open[3] and close[4]<open[4] and close[5]<open[5] and t0_DvM?-1:0
pchange6 = close[0]>open[0] and close[1]>open[1] and close[2]>open[2] and close[3]>open[3] and close[4]>open[4] and close[5]>open[5] and t0_DvM?1:0
blue6 = cum(pchange6 > 0 ? bluev6 : 0 * bluev6)
red6 = cum(mchange6 < 0 ? redv6 : 0 * redv6)

//count 7
redv7=window()?1:0
bluev7=window()?1:0
mchange7 = close[0]<open[0] and close[1]<open[1] and close[2]<open[2] and close[3]<open[3] and close[4]<open[4] and close[5]<open[5] and close[6]<open[6] and t0_DvM?-1:0
pchange7 = close[0]>open[0] and close[1]>open[1] and close[2]>open[2] and close[3]>open[3] and close[4]>open[4] and close[5]>open[5] and close[6]>open[6] and t0_DvM?1:0
blue7 = cum(pchange7 > 0 ? bluev7 : 0 * bluev7)
red7 = cum(mchange7 < 0 ? redv7 : 0 * redv7)

//Percent 3rd bar has same direction
pred3=(red3/red2)*100
pblue3=(blue3/blue2)*100

//2->3
p23_blue_xloc=0
p23_red_xloc=2
p23_lable_xloc=round((p23_blue_xloc+p23_red_xloc)/2)
p23_label_yloc=1.0*100
blue2_100=100
red2_100=100

plot(blue2_100, style=plot.style_columns, offset=p23_blue_xloc, color=color.blue, transp=60, show_last=1)
plot(red2_100, style=plot.style_columns, offset=-p23_red_xloc, color=color.red, transp=60, show_last=1)
plot(pblue3, style=plot.style_columns, offset=p23_blue_xloc, color=color.blue, transp=40, show_last=1)
plot(pred3, style=plot.style_columns, offset=-p23_red_xloc, color=color.red, transp=40, show_last=1)
// label_pred_23=label.new(bar_index[p23_red_xloc],pred3,style=label.style_none,text=tostring(truncate(pred3,2))+"%")
// label.delete(label_pred_23[1])
//label_2dn=label.new(bar_index[p23_red_xloc],red2,style=label.style_none,text="2 bars downward: "+tostring(red2))
//label.delete(label_2dn[1])
// label_pblue_23=label.new(bar_index[p23_blue_xloc],pblue3,style=label.style_none,text=tostring(truncate(pblue3,2))+"%")
// label.delete(label_pblue_23[1])
//label_2up=label.new(bar_index[p23_blue_xloc],blue2,style=label.style_none,text="2 bars upward: "+tostring(blue2))
//label.delete(label_2up[1])
// label_23=label.new(bar_index[p23_lable_xloc],p23_label_yloc,style=label.style_labeldown,text="3 bars same direction", color=color.orange)
// label.delete(label_23[1])

//Percent 4th bar has same direction
pred4=(red4/red3)*100
pblue4=(blue4/blue3)*100

//3->4
p34_blue_xloc=4
p34_red_xloc=6
p34_lable_xloc=round((p34_blue_xloc+p34_red_xloc)/2)
p34_label_yloc=1.0*100
blue3_100=100
red3_100=100

plot(blue3_100, style=plot.style_columns, offset=-p34_blue_xloc, color=color.blue, transp=60, show_last=1)
plot(red3_100, style=plot.style_columns, offset=-p34_red_xloc, color=color.red, transp=60, show_last=1)
plot(pblue4, style=plot.style_columns, offset=-p34_blue_xloc, color=color.blue, transp=40, show_last=1)
plot(pred4, style=plot.style_columns, offset=-p34_red_xloc, color=color.red, transp=40, show_last=1)
// label_pred_34=label.new(bar_index[p34_red_xloc],pred4,style=label.style_none,text=tostring(truncate(pred4,2))+"%")
// label.delete(label_pred_34[1])
// //label_3dn=label.new(bar_index[p34_red_xloc],red3,style=label.style_none,text="3 bars downward: "+tostring(red3))
// //label.delete(label_3dn[1])
// label_pblue_34=label.new(bar_index[p34_blue_xloc],pblue4,style=label.style_none,text=tostring(truncate(pblue4,2))+"%")
// label.delete(label_pblue_34[1])
// //label_3up=label.new(bar_index[p34_blue_xloc],blue3,style=label.style_none,text="3 bars upward: "+tostring(blue3))
// //label.delete(label_3up[1])
// label_34=label.new(bar_index[p34_lable_xloc],p34_label_yloc,style=label.style_labeldown,text="4 bars same direction", color=color.orange)
// label.delete(label_34[1])

//Percent 5th bar has same direction
pred5=(red5/red4)*100
pblue5=(blue5/blue4)*100

//4->5
p45_blue_xloc=8
p45_red_xloc=10
p45_lable_xloc=round((p45_blue_xloc+p45_red_xloc)/2)
p45_label_yloc=1.0*100
blue4_100=100
red4_100=100

plot(blue4_100, style=plot.style_columns, offset=-p45_blue_xloc, color=color.blue, transp=60, show_last=1)
plot(red4_100, style=plot.style_columns, offset=-p45_red_xloc, color=color.red, transp=60, show_last=1)
plot(pblue5, style=plot.style_columns, offset=-p45_blue_xloc, color=color.blue, transp=40, show_last=1)
plot(pred5, style=plot.style_columns, offset=-p45_red_xloc, color=color.red, transp=40, show_last=1)
// label_pred_45=label.new(bar_index[p45_red_xloc],pred5,style=label.style_none,text=tostring(truncate(pred5,2))+"%")
// label.delete(label_pred_45[1])
// //label_4dn=label.new(bar_index[p45_red_xloc],red4,style=label.style_none,text="4 bars downward: "+tostring(red4))
// //label.delete(label_4dn[1])
// label_pblue_45=label.new(bar_index[p45_blue_xloc],pblue5,style=label.style_none,text=tostring(truncate(pblue5,2))+"%")
// label.delete(label_pblue_45[1])
// //label_4up=label.new(bar_index[p45_blue_xloc],blue4,style=label.style_none,text="4 bars upward: "+tostring(blue4))
// //label.delete(label_4up[1])
// label_45=label.new(bar_index[p45_lable_xloc],p45_label_yloc,style=label.style_labeldown,text="5 bars same direction", color=color.orange)
// label.delete(label_45[1])

//Percent 6th bar has same direction
pred6=(red6/red5)*100
pblue6=(blue6/blue5)*100

//5->6
p56_blue_xloc=12
p56_red_xloc=14
p56_lable_xloc=round((p56_blue_xloc+p56_red_xloc)/2)
p56_label_yloc=1.0*100
blue5_100=100
red5_100=100

plot(blue5_100, style=plot.style_columns, offset=-p56_blue_xloc, color=color.blue, transp=60, show_last=1)
plot(red5_100, style=plot.style_columns, offset=-p56_red_xloc, color=color.red, transp=60, show_last=1)
plot(pblue6, style=plot.style_columns, offset=-p56_blue_xloc, color=color.blue, transp=40, show_last=1)
plot(pred6, style=plot.style_columns, offset=-p56_red_xloc, color=color.red, transp=40, show_last=1)
// label_pred_56=label.new(bar_index[p56_red_xloc],pred6,style=label.style_none,text=tostring(truncate(pred6,2))+"%")
// label.delete(label_pred_56[1])
// //label_5dn=label.new(bar_index[p56_red_xloc],red5,style=label.style_none,text="5 bars downward: "+tostring(red5))
// //label.delete(label_5dn[1])
// label_pblue_56=label.new(bar_index[p56_blue_xloc],pblue6,style=label.style_none,text=tostring(truncate(pblue6,2))+"%")
// label.delete(label_pblue_56[1])
// //label_5up=label.new(bar_index[p56_blue_xloc],blue5,style=label.style_none,text="5 bars upward: "+tostring(blue5))
// //label.delete(label_5up[1])
// label_56=label.new(bar_index[p56_lable_xloc],p56_label_yloc,style=label.style_labeldown,text="6 bars same direction", color=color.orange)
// label.delete(label_56[1])

//Percent 7th bar has same direction
pred7=(red7/red6)*100
pblue7=(blue7/blue6)*100

//6->7
p67_blue_xloc=16
p67_red_xloc=18
p67_lable_xloc=round((p67_blue_xloc+p67_red_xloc)/2)
p67_label_yloc=1.0*100
blue6_100=100
red6_100=100

plot(blue6_100, style=plot.style_columns, offset=-p67_blue_xloc, color=color.blue, transp=60, show_last=1)
plot(red6_100, style=plot.style_columns, offset=-p67_red_xloc, color=color.red, transp=60, show_last=1)
plot(pblue7, style=plot.style_columns, offset=-p67_blue_xloc, color=color.blue, transp=40, show_last=1)
plot(pred7, style=plot.style_columns, offset=-p67_red_xloc, color=color.red, transp=40, show_last=1)
// label_pred_67=label.new(bar_index[p67_red_xloc],pred7,style=label.style_none,text=tostring(truncate(pred7,2))+"%")
// label.delete(label_pred_67[1])
// //label_6dn=label.new(bar_index[p67_red_xloc],red6,style=label.style_none,text="6 bars downward: "+tostring(red6))
// //label.delete(label_6dn[1])
// label_pblue_67=label.new(bar_index[p67_blue_xloc],pblue7,style=label.style_none,text=tostring(truncate(pblue7,2))+"%")
// label.delete(label_pblue_67[1])
// //label_6up=label.new(bar_index[p67_blue_xloc],blue6,style=label.style_none,text="6 bars upward: "+tostring(blue6))
// //label.delete(label_6up[1])
// label_67=label.new(bar_index[p67_lable_xloc],p67_label_yloc,style=label.style_labeldown,text="7 bars same direction", color=color.orange)
// label.delete(label_67[1])

//Plot Time Label
time_label_yloc=1.4*100
time_lable_xloc=round((p67_red_xloc+p23_blue_xloc)/2)
time_label_text="Bar's Direction Info From: "+tostring(FromDay)+"/"+tostring(FromMonth)+"/"+tostring(FromYear)+" To: "+tostring(ToDay)+"/"+tostring(ToMonth)+"/"+tostring(ToYear)
// label_time=label.new(bar_index[time_lable_xloc],time_label_yloc,style=label.style_none,text=time_label_text, color=color.aqua)
// label.delete(label_time[1])

//Signal
//Put signal
x1=
       pblue3<50?blue2[0]>blue2[1] and blue3[0]==blue3[1]:false
x2=
       pblue4<50?blue3[0]>blue3[1] and blue4[0]==blue4[1]:false
x3=
       pblue5<50?blue4[0]>blue4[1] and blue5[0]==blue5[1]:false
x4=
       pblue6<50?blue5[0]>blue5[1] and blue6[0]==blue6[1]:false
x5=
       pblue7<50?blue6[0]>blue6[1] and blue7[0]==blue7[1]:false

//Call signal
y1=
       pred3<50?red2[0]>red2[1] and red3[0]==red3[1]:false
y2=
       pred4<50?red3[0]>red3[1] and red4[0]==red4[1]:false
y3=
       pred5<50?red4[0]>red4[1] and red5[0]==red5[1]:false
y4=
       pred6<50?red5[0]>red5[1] and red6[0]==red6[1]:false
y5=
       pred7<50?red6[0]>red6[1] and red7[0]==red7[1]:false

//Function
xTech=
       set1?x1:false
       or set2?x2:false
       or set3?x3:false
       or set4?x4:false
       or set5?x5:false
       

yTech=
       set1?y1:false
       or set2?y2:false
       or set3?y3:false
       or set4?y4:false
       or set5?y5:false
       

//Plot Analyzing Signals
hline1=hline(-100)
hline2=hline(-1.6*100)
hline0=hline(0)
sigtext=xTech?"Put signal":yTech?"Call signal":"Analyzing Signals - Bar's Time left:"+tostring(minutesLeft)+":"+tostring(secondsLeft)
sig_col=xTech?color.new(color.red,0):yTech?color.new(color.blue,0):color.new(color.navy,0)
// label_sig_text = label.new(bar_index[0], -1.5*100, text=sigtext, style=label.style_none, textcolor=sig_col, size=size.large)
// label.delete(label_sig_text[1])

//plot Signal

putcol = xTech? color.red : na
callcol = yTech? color.blue : na
PutSignal= xTech and window1() and t0_DvM?-100:na
CallSignal= yTech and window1() and t0_DvM?-100:na

plot(PutSignal, title='Put Signal', style=plot.style_columns, color=color.red, offset=1, transp=0)
plot(CallSignal, title='Call Signal', style=plot.style_columns, color=color.blue, offset=1, transp=0)
plotshape(PutSignal, title='Put', text="Put", style=shape.labeldown, location=location.bottom, color=color.orange, textcolor=color.black, offset=1, transp=0)
plotshape(CallSignal, title='Call', text="Call", style=shape.labelup, location=location.bottom, color=color.orange, textcolor=color.black, offset=1, transp=0)

//Backtesting
strategy.entry("Call", strategy.long, when=yTech and window1() and t0_DvM)
strategy.entry("Put", strategy.short, when=xTech and window1() and t0_DvM)
strategy.close_all(when=barstate.isnew)
//EOF

Больше