# expected_move_cone_02_date
# expected move parabola , ver2
# cone starts on last bar or a date
# halcyonguy
# 22-05-19
# http://www.nishatrades.com/blog/mathematically-calculating-expected-move-using-a-probability-analysis-chart
# nisha trades , described std dev
# expected move = price * iv * ( sqrt( days to expire / 365))
#----------------------------------
def price = close;
def iv2 = imp_volatility();
def iv = round(iv2,2);
def na = double.nan;
def bn = barnumber();
def lastbn = HighestAll(If(IsNaN(price), 0, bn));
def endbn = highestall(bn);
def lastbar = if lastbn == bn then 1 else 0;
# def lastbar = !isnan(close[0]) and isnan(close[-1]);
# expansion area, bars after last bar to right edge of chart
def expan_bars = (endbn - lastbn );
def expan_area = if (bn >= lastbn and bn <= endbn) then 1 else 0;
def lastcls = if bn < lastbn then na else if bn == lastbn then price else lastcls[1];
# replace lastiv with siv
#def lastiv = if bn < lastbn then na else if bn == lastbn then iv else lastiv[1];
def newday = if getday() != getday()[1] then 1 else 0;
#--------------------------------------------
def chartagg = GetAggregationPeriod();
def chartmin = (chartagg / 1000) / 60;
def daybarqty = roundup(390 / chartmin, 0);
def daysperbar = 1/daybarqty;
# --------------------------------------------
input start_bar = { default last_bar, date };
# pick a start date
# cone starts on first bar of a day
#input start_date_yyyymmdd = 20220504;
input start_date_yyyymmdd = 20211123;
def sdat = start_date_yyyymmdd;
def is_start_date = if (GetYYYYMMDD() == sdat and newday) then 1 else 0;
def start_date_price = if is_start_date then close else start_date_price[1];
def syear = Round(sdat/10000, 0);
def smonth = Round((sdat % 10000) / 100, 0);
def sday = (sdat % 100);
# --------------------------
def big = 99999;
# cone start bar, price
def sbar;
def sprice;
def sbn;
switch(start_bar) {
case last_bar:
sbar = lastbar;
sprice = lastcls;
sbn = if bn == 1 then big else if lastbar then bn else sbn[1];
case date:
sbar = is_start_date;
sprice = start_date_price;
sbn = if bn == 1 then big else if is_start_date then bn else sbn[1];
}
def siv = if bn == 1 then na else if bn == sbn then iv else siv[1];
# --------------------------------------------
# date of a trading day
input target_date_yyyymmdd = 20220622;
def tdat = target_date_yyyymmdd;
def is_target_date = if (GetYYYYMMDD() == tdat and newday) then 1 else 0;
# mobius
def tyear = Round(tdat/10000, 0);
def tmonth = Round((tdat % 10000) / 100, 0);
def tday = (tdat % 100);
# this fixes the CountTradingDays() error , when it was in a normal if-then
def dayz5;
if GetYYYYMMDD() > tdat then {
dayz5 = 0;
#} else if lastbn == bn then {
# dayz5 = CountTradingDays(GetYYYYMMDD(), dat );
} else if sbar then {
dayz5 = CountTradingDays(GetYYYYMMDD(), tdat );
} else {
dayz5 = dayz5[1];
}
# -------------------------------------
input vertical_line_target_date = yes;
addverticalline(vertical_line_target_date and is_target_date, " " + (tmonth + " / " + tday), color.yellow);
# for EM formula, need a qty of days that starts at 0 and counts up to the qty of days to target date
#def cone_days_cnt_up = if bn == 1 then na else if lastbar then 0 else cone_days_cnt_up[1] + daysperbar;
def cone_days_cnt_up = if bn == 1 then na else if sbar then 0 else cone_days_cnt_up[1] + daysperbar;
input em_factor = 1.0;
#def em = round(em_factor * lastcls * lastiv * ( sqrt(cone_days_cnt_up/365)), 2);
#def em_per = round((em/lastcls)*100, 1);
#def em = round(em_factor * sprice * lastiv * ( sqrt(cone_days_cnt_up/365)), 2);
def em = round(em_factor * sprice * siv * ( sqrt(cone_days_cnt_up/365)), 2);
def em_per = round((em/sprice)*100, 1);
# get EM value on lastbar, so it will be displayed in a label
def em2b = if bn == 1 then 0 else if is_target_date then em else em2b[1];
def em2 = if isNaN(close[-1000]) then em2b[-1000] else Double.NaN;
# top half parabola
#plot ztop = if expan_area then (lastcls + em) else na;
#plot ztop = if expan_area then (sprice + em) else na;
plot ztop = if bn >= sbn then (sprice + em) else na;
ztop.setdefaultcolor(color.yellow);
# bottom half parabola
#plot zbot = if expan_area then (lastcls - em) else na;
#plot zbot = if expan_area then (sprice - em) else na;
plot zbot = if bn >= sbn then (sprice - em) else na;
zbot.setdefaultcolor(color.yellow);
input cone_horz_line = yes;
#plot z2 = if (cone_horz_line and expan_area) then lastcls else na;
#plot z2 = if (cone_horz_line and expan_area) then sprice else na;
plot z2 = if (cone_horz_line and bn > sbn) then sprice else na;
z2.setdefaultcolor(color.gray);
# -------------------------------------
# target date price bubbles
input show_price_bubbles = yes;
def vert = 0.99;
addchartbubble(show_price_bubbles and is_target_date, ztop, ztop , color.yellow, yes);
#addchartbubble(show_price_bubbles and is_target_date, lastcls * vert, "$" + em + "\n" + em_per + "%" , color.yellow, yes);
addchartbubble(show_price_bubbles and is_target_date, sprice * vert, "$" + em + "\n" + em_per + "%" , color.yellow, yes);
addchartbubble(show_price_bubbles and is_target_date, zbot, zbot, color.yellow, no);
input show_date_bubble = yes;
addchartbubble(show_date_bubble and is_target_date, ztop*0.99, (tmonth + "/" + tday) , color.yellow, no);
# ===========================================
# labels
addlabel(1, "IV " + iv, color.orange);
input iv_label = yes;
AddLabel(iv_label, " " , Color.black);
input chart_stats_labels = no;
AddLabel(chart_stats_labels, "chartmin " + chartmin, Color.MAGENTA);
AddLabel(chart_stats_labels, "bars per day " + daybarqty, Color.MAGENTA);
input show_labels = yes;
addLabel(show_labels, "start date: " + smonth + "/" + sday + "/" + AsPrice(syear), color.yellow);
addLabel(show_labels, "target date: " + tmonth + "/" + tday + "/" + AsPrice(tyear), color.yellow);
addlabel(show_labels, "trading days to target date " + dayz5, color.yellow);
addlabel(show_labels, "EM " + "$" + em2 , color.orange);
#