Квартальные линии с плавающими таймфреймами
Индикатор квартальных линий "Kvartal Line ".
: ( Auto ) Линии Условных Кварталов в году :
(Start) День . Месяц - (End) День . Месяц 1я пара линий ( High, Low ) : в пятницу 2й недели . 03 - 5 . 06 2я пара линий ( High, Low ) : в пятницу 2й недели . 06 - 4 . 09 3я пара линий ( High, Low ) : в пятницу 2й недели . 09 - 4 . 12 4я пара линий ( High, Low ) : в пятницу 2й недели . 12 - 6 . 03
Линии ( High, Low ) последнего квартала по соответствию формулы : от последнего завершенного квартала присутствие баров являющийся будущим кварталом. И далее, в случае присутствия текущих параметров, формула линий (из баров) : на графике (tikerid) присутствие 2й пятницы ( ~ присутствие 12 баров от последнего завершенного квартала до last_bar_index )
90 ( квартал ) - 12 ( 2я пятница ) = 78 ( будущих баров, от текущего бара - last_bar_index ) .
( Auto ) Годовая разметка ( вертикальная линия, color.gray (default) ) .
( Auto ) Квартальный разделитель ( вертикальная линия, color.silver (default) ) .
Квартальный разделитель для текущего ( последнего ) квартала . ( current values - от последнего завершенного квартала присутствие баров являющийся будущим кварталом ). И далее, в случае присутствия текущих параметров, вертикальная линия на основании формулы : на графике (tikerid) присутствие 2й пятницы ( ~ присутствие 12 баров от последнего завершенного квартала до last_bar_index )
90 ( квартал ) - 12 ( 2я пятница ) = 78 ( после будущих баров, в присутствии, от текущего бара ) .
Timeframe :
4 H -> YTD 1 D -> YTD 1 W -> YTD 1 M -> YTD
2е версии кода : в 1й (через bar_index) - все идеально, но Timeframe функционирует только " 1 D -> YTD "; во 2й (для улучшения Timeframe позиций по условию, через time) - все идеально, но не так работает скрипт pine, как надо. Не судите молодого студента, если что-то не то в скрипте. За ранее благодарен.
1я версия кода :
//@version=5
indicator(" Kvartal line ", overlay=true, max_lines_count=500)
//
//
//---- I ----------- User values -----------------------------------------------------------------------------------------
//
//
string group_1 = "---------- ГОРИЗОНТАЛЬНЫЕ линии High и Low, цвета и толщина ----------"
//
color clr_High = input.color(color.green, "Color High ", group=group_1) // " Color High "
color clr_Low = input.color(color.red, "Color Low ", group=group_1) // " Color Low "
//
int width_High = input.int(1, " width line, High ", group=group_1) // color.navy, "Color Low")
int width_Low = input.int(1, " width line, Low ", group=group_1) // color.navy, "Color Low")
//
//
string group_2 = "---------- ВЕРТИКАЛЬНЫЕ линии ----------"
//
color clr_Year = input.color(color.gray, "Color year ", group=group_2) // year line
color clr_3M = input.color(#81c385, "Color 3M ", group=group_2) // квартальная line
//
int width_Year = input.int(2, " width line, Year ", group=group_2)
int width_3M = input.int(1, " width line, 3M ", group=group_2)
//
//
//
//---- II ------------- Structuring ---------------------------------------------------------------------
//
//
int current_bar = bar_index // Определие текущего бара
//
//
// >>>>>>>>>>>>>>>> дорисовать будущий квартал (FK) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//
// Устанавка условия для сохраненного обновления current Kvartal (current_K)
// при следующей прорисовке добавления нового бара
var int current_K = na // Определие бара последнего прошлого квартала ( ... _end), чтобы дорисовать будущий
int period_Index = 10 // Разница (last_bar_index - current_K) , чтобы дорисовать будущий квартал
//
// Определие количества баров будущего квартала ( n ... last_bar_index )
int bars_before = last_bar_index - current_K // ! ( to last_bar_index = ) 28 ... last_bar_index
int _bars_in_K = 90 // Бары будущего квартала = min = 90 баров
//
bool is_FK = ( bars_before < _bars_in_K ) // Присутствие Будущего квартала
//
//
if is_FK // Определие количества баров будущего квартала (n ... last_bar_index)
period_Index := bars_before - 5 // из 2й пятницы месяца ( 2nd friday )
//
float Price_H_period = ta.highest(period_Index)
float Price_L_period = ta.lowest(period_Index)
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< дорисовать будущий квартал <<<<<<<<<<<<<
//
//
//
//
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Годовая разметка >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//
is_year_start = year != year[1]
//
if is_year_start
line.new(bar_index, low, bar_index, high, extend=extend.both, width= width_Year, color=clr_Year) //, style=line.style_dotted)
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Годовая разметка <<<<<<<<<<<
//
//
// Функция для получения даты второй пятницы месяца
//
second_friday(y, m) =>
first_day_of_month = timestamp(y, m, 1)
first_day_of_month_dow = dayofweek(first_day_of_month)
second_friday_day = 1 + (5 - first_day_of_month_dow + 7) % 7 + 7
timestamp(y, m, second_friday_day)
//
//
// Определение временных интервалов кварталов
//
// 1я пара линий ( High, Low ) : в пятницу 2й недели . 03 - 5 . 06
sec_friday_1 = second_friday(year, 3)
Q_1_start = sec_friday_1
Q_1_end = timestamp(year, 6, 5, 23, 59)
//
// 2я пара линий ( High, Low ) : в пятницу 2й недели . 06 - 4 . 09
sec_friday_2 = second_friday(year, 6)
Q_2_start = sec_friday_2
Q_2_end = timestamp(year, 9, 4, 23, 59)
//
// 3я пара линий ( High, Low ) : в пятницу 2й недели . 09 - 4 . 12
sec_friday_3 = second_friday(year, 9)
Q_3_start = sec_friday_3
Q_3_end = timestamp(year, 12, 4, 23, 59)
//
// 4я пара линий ( High, Low ) : в пятницу 2й недели . 12 - 6 . 03
sec_friday_4 = second_friday(year, 12)
Q_4_start = sec_friday_4
Q_4_end = timestamp(year, 3, 6, 23, 59)
//
//
// Функция для получения индекса бара по времени
//
F_Get_BarIndexAtTime(_time) =>
var int barIndex = na
if (_time <= time and (_time > time[1] or bar_index == 0))
barIndex := bar_index
barIndex
//
//
// Получение индексов баров для каждого квартала
//
int inBar_q1_start = request.security(syminfo.tickerid, "D", F_Get_BarIndexAtTime(Q_1_start))
int inBar_q1_end = request.security(syminfo.tickerid, "D", F_Get_BarIndexAtTime(Q_1_end))
//
int inBar_q2_start = request.security(syminfo.tickerid, "D", F_Get_BarIndexAtTime(Q_2_start))
int inBar_q2_end = request.security(syminfo.tickerid, "D", F_Get_BarIndexAtTime(Q_2_end))
//
int inBar_q3_start = request.security(syminfo.tickerid, "D", F_Get_BarIndexAtTime(Q_3_start))
int inBar_q3_end = request.security(syminfo.tickerid, "D", F_Get_BarIndexAtTime(Q_3_end))
//
int inBar_q4_start = request.security(syminfo.tickerid, "D", F_Get_BarIndexAtTime(Q_4_start))
int inBar_q4_end = request.security(syminfo.tickerid, "D", F_Get_BarIndexAtTime(Q_4_end))
//
//
// Функция для определения High и Low за квартал
//
F_Get_High_Low( startMonth, startDay, endMonth, endDay ) =>
var float highPrice = na
var float lowPrice = na
if (month == startMonth and dayofmonth == startDay)
highPrice := high
lowPrice := low
if (month >= startMonth and month <= endMonth)
highPrice := math.max(highPrice, high)
lowPrice := math.min(lowPrice, low)
else
if (month == endMonth and dayofmonth > endDay)
na
else
highPrice := math.max(highPrice, high)
lowPrice := math.min(lowPrice, low)
[highPrice, lowPrice]
//
//
//
// Определение квартальных периодов - [highPrice, lowPrice]
//
[q1_High, q1_Low] = F_Get_High_Low( 3, dayofmonth(Q_1_start), 6, dayofmonth(Q_1_end) )
[q2_High, q2_Low] = F_Get_High_Low( 6, dayofmonth(Q_2_start), 9, dayofmonth(Q_2_end) )
[q3_High, q3_Low] = F_Get_High_Low( 9, dayofmonth(Q_3_start), 12, dayofmonth(Q_3_end) )
[q4_High, q4_Low] = F_Get_High_Low( 12, dayofmonth(Q_4_start), 3, dayofmonth(Q_4_end) )
//
//
//
// Отрисовка линий и меток
//
if not ( barstate.islast ) // if timeframe.change('3M') // Определяем бары
// if not ( current_bar == last_bar_index )
if current_bar == inBar_q1_end // if bar_index == inBar_q1_end
line.new(inBar_q1_start, q1_High, inBar_q1_end, q1_High, width= width_High, color=clr_High) //, style=line.style_arrow_both)
line.new(inBar_q1_start, q1_Low, inBar_q1_end, q1_Low, width= width_Low, color=clr_Low) //, style=line.style_arrow_both)
// label.new(bar_index, high*1.4, text="Q1 start=" + str.tostring(inBar_q1_start) +"\n" +
// " inBar_q1_ end =" + str.tostring(inBar_q1_end) +"\n" +
// " High=" + str.tostring(q1_High) + " Low=" + str.tostring(q1_Low) +"\n" +
// " current_bar = " + str.tostring(current_bar) +"\n" +
// " current_K = " + str.tostring(current_K)
// )
//
line.new(bar_index, low, bar_index, high, extend=extend.both, width= width_3M, color=clr_3M, style=line.style_dotted ) // line.style_dashed )
current_K := current_bar +1
//
if current_bar == inBar_q2_end // if bar_index == inBar_q2_end
line.new(inBar_q2_start, q2_High, inBar_q2_end, q2_High, width= width_High, color= clr_High) //, style=line.style_arrow_both)
line.new(inBar_q2_start, q2_Low, inBar_q2_end, q2_Low, width= width_Low, color= clr_Low) //, style=line.style_arrow_both)
// label.new(inBar_q2_end, high * 1.95, text="Q2 start=" + str.tostring(inBar_q2_start) + " end=" + str.tostring(inBar_q2_end) + "\n High=" + str.tostring(q2_High) + " Low=" + str.tostring(q2_Low))
line.new(bar_index, low, bar_index, high, extend=extend.both, width= width_3M, color=clr_3M, style=line.style_dotted ) // line.style_dotted)
current_K := current_bar +1
//
if current_bar == inBar_q3_end // if bar_index == inBar_q3_end
line.new(inBar_q3_start, q3_High, inBar_q3_end, q3_High, width= width_High, color= clr_High) //, style=line.style_arrow_both)
line.new(inBar_q3_start, q3_Low, inBar_q3_end, q3_Low, width= width_Low, color= clr_Low) //, style=line.style_arrow_both)
// label.new(bar_index, high * 0.9, text="Q3 start=" + str.tostring(inBar_q3_start) + " end=" + str.tostring(inBar_q3_end) + " High=" + str.tostring(q3_High) + " Low=" + str.tostring(q3_Low))
line.new(bar_index, low, bar_index, high, extend=extend.both, width= width_3M, color=clr_3M, style=line.style_dotted) // line.style_dotted)
current_K := current_bar +1
//
if current_bar == inBar_q4_end // if bar_index == inBar_q4_end
line.new(inBar_q4_start, q4_High, inBar_q4_end, q4_High, width= width_High, color= clr_High) //, style=line.style_arrow_both)
line.new(inBar_q4_start, q4_Low, inBar_q4_end, q4_Low, width= width_Low, color= clr_Low) //, style=line.style_arrow_both)
// label.new(bar_index, high * 0.85, text="Q4 start=" + str.tostring(inBar_q4_start) + " end=" + str.tostring(inBar_q4_end) + " High=" + str.tostring(q4_High) + " Low=" + str.tostring(q4_Low))
line.new(bar_index, low, bar_index, high, extend=extend.both, width= width_3M, color=clr_3M, style=line.style_dotted) // line.style_dotted)
current_K := current_bar +1
//
else
//
// ( from last_bar_index )
//
// Определяю бары : bar_before [ ... ] last_bar_index [ ... ] bar_after
//
//
// Присутствие Будущего квартала и оптимально - 2й пятницы после последнего прошлого квартала
is_FK := ( bars_before >= 13 )
//
//
if is_FK
//
bar_before = current_K // ! to last_bar_index = 28 ... last_bar_index [ bar_index-_bars_in_K +1 ]
//
bars_after = 90 - bars_before // ! from last_bar_index = last_bar_index ... 68
bar_after = current_bar + bars_after // ! from last_bar_index = last_bar_index ... 68
//
// label.new(current_bar, high*1.2, textcolor=color.white , text= " bar_before= " + str.tostring(bar_before) +"\n" +
// " bar_after =" + str.tostring(bar_after) +"\n" +
// " period_Index =" + str.tostring(period_Index) +"\n" +
// " last_bar_index =" + str.tostring(last_bar_index) +"\n" +
// " bar_index =" + str.tostring(bar_index) +"\n" +
// " current_bar = " + str.tostring(current_bar) +"\n"+
// " bars_before =" + str.tostring(bars_before) +"\n" +
// " bars_after =" + str.tostring(bars_after) +"\n"
// )
// paint -> горизонтальные линии High и Low из 2й пятницы
line.new(x1=bar_before + 6, y1=Price_H_period, x2=bar_after, y2=Price_H_period, color=clr_High, width= width_High )
line.new(x1=bar_before + 6, y1=Price_L_period, x2=bar_after, y2=Price_L_period, color=clr_Low, width= width_Low )
//
line.new(x1=bar_after, y1=high, x2=bar_after, y2=high, extend=extend.both, width= width_3M, color = clr_3M, style=line.style_dotted) // line.style_dashed)
//
//
// // // // // // // // "Year Start Lines with Future Line" // // // // // // // //
//
// Количество дней в году
days_in_year = 365 + (year % 4 == 0 ? 1 : 0) // Учитываю високосные годы
current_date = timestamp(year, month, dayofmonth) // Текущая дата
start_of_year = timestamp(year, 1, 1) // Первый день текущего года
current_day_of_year = ( (current_date - start_of_year) / 86400000 ) // Текущий день года
days_left_in_year = days_in_year - current_day_of_year // Определение оставшихся дней до конца года
bars_in_future = days_left_in_year // Определение смещения в барах
//
// Рисование линии на оставшееся количество дней до конца года от последнего бара
var line future_line = na
//
// bool is_LastK = (is_FK) and ( ( bar_after - last_bar_index ) <= 89 ) // прорисовка годовой линии в присутствии последнего квартала в году
//
// прорисовка годовой линии в приближающемся последнем квартале из 2й пятницы в текущем году
bool is_LastK = ( bars_in_future <= (_bars_in_K - 12) )
//
// if ( bar_index == last_bar_index )
if is_LastK
if na(future_line)
future_line := line.new(bar_index + bars_in_future, low, bar_index + bars_in_future, high, extend=extend.both, width= width_Year, color=clr_Year)
else
line.set_xy1(future_line, bar_index + bars_in_future, low)
line.set_xy2(future_line, bar_index + bars_in_future, high)
// END
2я версия кода :
//@version=5
indicator("Kvartal line", overlay=true)
// Установка цветов для линий High и Low
color clr_High = input.color(color.green, "Color High")
color clr_Low = input.color(color.red, "Color Low")
int current_Bar = bar_index // Определение текущнго bar
int current_Time = time // Определение текущнго time
//
int _1D = 86400000 // 86400000 - количество миллисекунд в 1 торговом дне
//
var float current_K = na // Определение баров последнего прошлого квартала ( ... _end), чтобы дорисовать будущий
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Годовая разметка >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//
is_year_start = year != year[1]
//
if is_year_start
line.new(bar_index, low, bar_index, high, extend=extend.both, width= width_Year, color=color.gray) //, style=line.style_dotted)
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Годовая разметка <<<<<<<
//
//
// Функция для получения даты второй пятницы месяца
//
second_friday(y, m) =>
first_day_of_month = timestamp(y, m, 1)
first_day_of_month_dow = dayofweek(first_day_of_month)
second_friday_day = 1 + (5 - first_day_of_month_dow + 7) % 7 + 7
timestamp(y, m, second_friday_day)
//
// Определение временных интервалов кварталов
//
//
// 1я пара линий ( High, Low ) : в пятницу 2й недели . 03 - 5 . 06
sec_friday_1 = second_friday(year, 3)
Q_1_start = sec_friday_1
Q_1_end = timestamp(year, 6, 5, 23, 59)
// 2я пара линий ( High, Low ) : в пятницу 2й недели . 06 - 4 . 09
sec_friday_2 = second_friday(year, 6)
Q_2_start = sec_friday_2
Q_2_end = timestamp(year, 9, 4, 23, 59)
// 3я пара линий ( High, Low ) : в пятницу 2й недели . 09 - 4 . 12
sec_friday_3 = second_friday(year, 9)
Q_3_start = sec_friday_3
Q_3_end = timestamp(year, 12, 4, 23, 59)
// 4я пара линий ( High, Low ) : в пятницу 2й недели . 12 - 6 . 03
sec_friday_4 = second_friday(year, 12)
Q_4_start = sec_friday_4
Q_4_end = timestamp(year + 1, 3, 6, 23, 59)
//
// Определение максимумов и минимумов за квартал
//
F_Get_High_Low(start, end) =>
var float highPrice = na
var float lowPrice = na
period = (end - start) / _1D // 86400000 - количество миллисекунд в дне
highPrice := ta.highest(high, period)
lowPrice := ta.lowest(low, period)
[highPrice, lowPrice]
//
// Получение максимумов и минимумов для каждого квартала
//
[q1_High, q1_Low] = F_Get_High_Low(Q_1_start, Q_1_end)
// [q1_High, q1_Low] = request.security(syminfo.tickerid, "D", [Q_1_start,Q_1_end], lookahead = barmerge.lookahead_off)
[q2_High, q2_Low] = F_Get_High_Low(Q_2_start, Q_2_end)
[q3_High, q3_Low] = F_Get_High_Low(Q_3_start, Q_3_end)
[q4_High, q4_Low] = F_Get_High_Low(Q_4_start, Q_4_end)
//
// Отрисовка линий и меток
//
// bool is_Q_1 = (time == Q_1_end)
bool is_Q_1 = (current_Time >= Q_1_start and current_Time <= Q_1_end )
bool is_Q_2 = (current_Time >= Q_2_start and current_Time <= Q_2_end ) // - if (time == Q_2_end)
bool is_Q_3 = (current_Time >= Q_3_start and current_Time <= Q_3_end ) // - if (time == Q_3_end)
bool is_Q_4 = (current_Time >= Q_4_start and current_Time <= Q_4_end ) // - if (time == Q_4_end)
// if not ( bar_time.islast ) // if timeframe.change('3M') // Определяем бары
if not ( barstate.islast )
// if current_Time >= Q_1_end // - if (time == Q_1_end)
// if (current_Time >= Q_1_start and current_Time <= Q_1_end ) // - if (time == Q_1_end)
if is_Q_1
// if not ( current_bar == last_bar_index )
// if current_bar == inBar_q1_end // if bar_index == inBar_q1_end
line.new(x1=Q_1_start, y1=q1_High, x2=Q_1_end, y2=q1_High, width=2, color=clr_High, style=line.style_arrow_both, xloc=xloc.bar_time)
line.new(x1=Q_1_start, y1=q1_Low, x2=Q_1_end, y2=q1_Low, width=2, color=clr_Low, style=line.style_arrow_both, xloc=xloc.bar_time)
// квартальные разделители :
line.new(bar_index, low, bar_index, high, extend=extend.both, width= 2, color=color.gray, style= line.style_dashed ) // line.style_dotted )
// для прорисовки последнего квартала
// current_K := current_Time + 1 // _1D
current_K := current_Bar + 1 // _1D
// if (time >= Q_2_end)
// if (time == Q_2_end)
// if (current_Time >= Q_2_start and current_Time <= Q_2_end ) // - if (time == Q_1_end)
// if is_Q_2
// line.new(x1=Q_2_start, y1=q2_High, x2=Q_2_end, y2=q2_High, width=2, color=clr_High, style=line.style_arrow_both, xloc=xloc.bar_time)
// line.new(x1=Q_2_start, y1=q2_Low, x2=Q_2_end, y2=q2_Low, width=2, color=clr_Low, style=line.style_arrow_both, xloc=xloc.bar_time)
// квартальные разделители :
// line.new(bar_index, low, bar_index, high, extend=extend.both, width= 2, color=color.gray, style= line.style_dashed ) // line.style_dotted )
// current_K := current_Bar +1 // для прорисовки последнего квартала
// if (time >= Q_3_end)
// if (time == Q_3_end)
// if (current_Time >= Q_3_start and current_Time <= Q_3_end ) // - if (time == Q_1_end)
// if is_Q_3
// line.new(x1=Q_3_start, y1=q3_High, x2=Q_3_end, y2=q3_High, width=2, color=clr_High, style=line.style_arrow_both, xloc=xloc.bar_time)
// line.new(x1=Q_3_start, y1=q3_Low, x2=Q_3_end, y2=q3_Low, width=2, color=clr_Low, style=line.style_arrow_both, xloc=xloc.bar_time)
// квартальные разделители :
// line.new(bar_index, low, bar_index, high, extend=extend.both, width= 2, color=color.gray, style= line.style_dashed ) // line.style_dotted )
// current_K := current_Bar +1 // для прорисовки последнего квартала
// if (time >= Q_4_end)
// if (time == Q_4_end)
// if (current_Time >= Q_4_start and current_Time <= Q_4_end ) // - if (time == Q_1_end)
// if is_Q_4
// line.new(x1=Q_4_start, y1=q4_High, x2=Q_4_end, y2=q4_High, width=2, color=clr_High, style=line.style_arrow_both, xloc=xloc.bar_time)
// line.new(x1=Q_4_start, y1=q4_Low, x2=Q_4_end, y2=q4_Low, width=2, color=clr_Low, style=line.style_arrow_both, xloc=xloc.bar_time)
// квартальные разделители :
// line.new(bar_index, low, bar_index, high, extend=extend.both, width= 2, color=color.gray, style= line.style_dashed ) // line.style_dotted )
// current_K:= current_Bar +1 // для прорисовки последнего квартала
// END